From 1c82e21ac936241bf56109e7fff87446b0b6a131 Mon Sep 17 00:00:00 2001
From: 陈昶聿 <chychen@nbjetron.com>
Date: 星期一, 19 十月 2026 15:31:22 +0800
Subject: [PATCH] 【丽水】新增接口 修复Sys_User_Dept数据缺失问题

---
 ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml                  |    1 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java |  192 ++++++++++++++++++++++++++++++++++++++
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserDeptMapper.java        |   12 ++
 ruoyi-system/src/main/resources/mapper/system/SysUserDeptMapper.xml              |   11 ++
 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                  |   20 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java         |   10 ++
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java            |    9 +
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java |   12 ++
 8 files changed, 267 insertions(+), 0 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
index d6aa16b..c681538 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -283,6 +283,18 @@
     }
 
     /**
+     * 鏍规嵁 sys_user.hosp_info锛堢瀹わ級鍜� sys_user.dept_info锛堢梾鍖猴級琛ュ叏 sys_user_dept 鏁版嵁
+     */
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+    @AddOrgId
+    @PostMapping("/repairUserDept")
+    public AjaxResult repairUserDept(@RequestBody(required = false) SysUser user) {
+        String orgid = user == null ? null : user.getOrgid();
+        Long userId = user == null ? null : user.getUserId();
+        return success(userService.repairUserDeptByHospAndDeptInfo(orgid, userId));
+    }
+
+    /**
      * 鑾峰彇閮ㄩ棬鏍戝垪琛�
      */
     //@PreAuthorize("@ss.hasPermi('system:user:list')")
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserDeptMapper.java
index 88562e9..fc14677 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserDeptMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserDeptMapper.java
@@ -3,6 +3,7 @@
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysUserDept;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
@@ -77,4 +78,15 @@
     public int deleteSysUserDeptByUserId(SysUserDept sysUserDept);
 
     public int updateSysUserDeptForSync(SysUserDept sysUserDept);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID銆侀儴闂ㄧ紪鐮佹煡璇㈢敤鎴烽儴闂ㄥ叧绯伙紙鍖呭惈宸查�昏緫鍒犻櫎鐨勬暟鎹級
+     * 涓� hosp_info / dept_info 鐨勭敓鎴愰�昏緫淇濇寔涓�鑷达紝閮ㄩ棬缂栫爜鏄敤鎴烽儴闂ㄥ叧绯荤殑涓氬姟鍞竴閿�
+     *
+     * @param userId   鐢ㄦ埛ID
+     * @param deptCode 閮ㄩ棬缂栫爜
+     * @param orgid    鏈烘瀯ID锛屽彲涓虹┖
+     * @return 鐢ㄦ埛閮ㄩ棬鍏崇郴
+     */
+    public SysUserDept selectSysUserDeptByUserAndCode(@Param("userId") Long userId, @Param("deptCode") String deptCode, @Param("orgid") String orgid);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
index 8ae32f4..3b0c841 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -24,6 +24,15 @@
     public List<SysUser> getUserList(SysUser sysUser);
 
     /**
+     * 鏌ヨ闇�瑕佹牴鎹� hosp_info / dept_info 琛ュ叏閮ㄩ棬鍏崇郴鐨勭敤鎴�
+     *
+     * @param orgid  鏈烘瀯ID锛屽彲涓虹┖
+     * @param userId 鐢ㄦ埛ID锛屽彲涓虹┖
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎
+     */
+    public List<SysUser> selectUsersForRepairUserDept(@Param("orgid") String orgid, @Param("userId") Long userId);
+
+    /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸查厤鐢ㄦ埛瑙掕壊鍒楄〃
      *
      * @param user 鐢ㄦ埛淇℃伅
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
index 16cad1c..5718202 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import java.util.List;
+import java.util.Map;
 import com.ruoyi.common.core.domain.entity.SysUser;
 
 /**
@@ -214,4 +215,13 @@
      * @return 缁撴灉
      */
     public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
+
+    /**
+     * 鏍规嵁 sys_user.hosp_info锛堢瀹わ級鍜� sys_user.dept_info锛堢梾鍖猴級琛ュ叏 sys_user_dept 鏁版嵁
+     *
+     * @param orgid  鏈烘瀯ID锛屼负绌烘椂澶勭悊鍏ㄩ儴鏈烘瀯
+     * @param userId 鐢ㄦ埛ID锛屼负绌烘椂澶勭悊鍏ㄩ儴鐢ㄦ埛
+     * @return 澶勭悊缁撴灉缁熻
+     */
+    Map<String, Object> repairUserDeptByHospAndDeptInfo(String orgid, Long userId);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
index be0b93a..f403771 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -19,6 +19,8 @@
 import com.ruoyi.system.service.ISysUserService;
 import com.ruoyi.common.core.service.IUserExtInfoService;
 import com.ruoyi.system.mapper.SysUserDeptMapper;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -44,6 +46,8 @@
 @Service
 public class SysUserServiceImpl implements ISysUserService {
     private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
+
+    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
     @Autowired
     private SysUserMapper userMapper;
@@ -996,4 +1000,192 @@
         }
         return list;
     }
+
+    /**
+     * 鏍规嵁 sys_user.hosp_info锛堢瀹わ級鍜� sys_user.dept_info锛堢梾鍖猴級琛ュ叏 sys_user_dept 鏁版嵁
+     *
+     * @param orgid  鏈烘瀯ID锛屼负绌烘椂澶勭悊鍏ㄩ儴鏈烘瀯
+     * @param userId 鐢ㄦ埛ID锛屼负绌烘椂澶勭悊鍏ㄩ儴鐢ㄦ埛
+     * @return 澶勭悊缁撴灉缁熻
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> repairUserDeptByHospAndDeptInfo(String orgid, Long userId) {
+        List<SysUser> users = userMapper.selectUsersForRepairUserDept(orgid, userId);
+        int processedUsers = 0;
+        int inserted = 0;
+        int updated = 0;
+        int restored = 0;
+        int deptNotFound = 0;
+        Set<String> missingDeptCodes = new LinkedHashSet<>();
+
+        for (SysUser user : users) {
+            if (user.getUserId() == null) {
+                continue;
+            }
+            List<String> hospCodes = parseDeptCodes(user.getHospInfo());
+            List<String> wardCodes = parseDeptCodes(user.getDeptInfo());
+            if (hospCodes.isEmpty() && wardCodes.isEmpty()) {
+                continue;
+            }
+            processedUsers++;
+
+            int[] hospStat = repairUserDept(user, hospCodes, "1", missingDeptCodes);
+            int[] wardStat = repairUserDept(user, wardCodes, "2", missingDeptCodes);
+            inserted += hospStat[0] + wardStat[0];
+            updated += hospStat[1] + wardStat[1];
+            restored += hospStat[2] + wardStat[2];
+            deptNotFound += hospStat[3] + wardStat[3];
+        }
+
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("scannedUsers", users.size());
+        result.put("processedUsers", processedUsers);
+        result.put("inserted", inserted);
+        result.put("updated", updated);
+        result.put("restored", restored);
+        result.put("deptMetaNotFound", deptNotFound);
+        result.put("missingDeptCodes", missingDeptCodes);
+        log.info("鏍规嵁hosp_info/dept_info琛ュ叏鐢ㄦ埛閮ㄩ棬鍏崇郴瀹屾垚锛岀粨鏋滐細{}", result);
+        return result;
+    }
+
+    /**
+     * 琛ュ叏鍗曚釜鐢ㄦ埛鎸囧畾绫诲瀷鐨勯儴闂ㄥ叧绯汇��
+     * hosp_info / dept_info 鐢� Gson 搴忓垪鍖� List&lt;List&lt;String&gt;&gt; 鐢熸垚锛�
+     * 姣忎釜鍏冪礌褰㈠ [["code"]]锛屽洜姝や互閮ㄩ棬缂栫爜浣滀负琛ュ叏渚濇嵁锛屼笌鍘熷閲囬泦閫昏緫涓�鑷淬��
+     *
+     * @param user             鐢ㄦ埛
+     * @param deptCodes        閮ㄩ棬缂栫爜闆嗗悎
+     * @param expectedDeptType 閮ㄩ棬绫诲瀷锛�1绉戝 2鐥呭尯锛屽搴� hosp_info / dept_info锛�
+     * @param missingDeptCodes sys_dept 涓湭鍖归厤鍒扮殑閮ㄩ棬缂栫爜
+     * @return [鏂板鏁�, 鏇存柊鏁�, 鎭㈠鏁�, sys_dept鏈尮閰嶆暟]
+     */
+    private int[] repairUserDept(SysUser user, List<String> deptCodes, String expectedDeptType, Set<String> missingDeptCodes) {
+        int[] stat = new int[4];
+        for (String deptCode : deptCodes) {
+            // sys_dept 鍙敤浜庤ˉ鍏� dept_id銆乨ept_name 绛変俊鎭紝鏌ヤ笉鍒颁篃缁х画鎸夌紪鐮佽ˉ鍏�
+            SysDept sysDept = sysDeptMapper.selectDeptByCode(expectedDeptType, user.getOrgid(), deptCode);
+            if (ObjectUtils.isEmpty(sysDept)) {
+                // dept_type 鍙兘瀛樺湪鍘嗗彶鑴忔暟鎹紝鎸夌紪鐮佸厹搴曞啀鏌ヤ竴娆�
+                sysDept = sysDeptMapper.selectDeptByCode(null, user.getOrgid(), deptCode);
+            }
+            if (ObjectUtils.isEmpty(sysDept)) {
+                stat[3]++;
+                if (missingDeptCodes.size() < 100) {
+                    missingDeptCodes.add(deptCode);
+                }
+            }
+
+            String userDeptOrgid = StringUtils.isNotEmpty(user.getOrgid()) ? user.getOrgid()
+                    : (sysDept == null ? null : sysDept.getOrgid());
+            String campusid = sysDept != null && StringUtils.isNotEmpty(sysDept.getCampusid())
+                    ? sysDept.getCampusid() : user.getCampusid();
+            Date now = new Date();
+
+            // 涓庡師濮嬬敓鎴愰�昏緫淇濇寔涓�鑷达紝user_id + dept_code + orgid 浣滀负涓氬姟鍞竴閿�
+            SysUserDept sysUserDept = sysUserDeptMapper.selectSysUserDeptByUserAndCode(user.getUserId(), deptCode, user.getOrgid());
+            if (ObjectUtils.isEmpty(sysUserDept)) {
+                sysUserDept = new SysUserDept();
+                sysUserDept.setUserId(user.getUserId());
+                sysUserDept.setDeptCode(deptCode);
+                sysUserDept.setDeptType(expectedDeptType);
+                sysUserDept.setOrgid(userDeptOrgid);
+                sysUserDept.setCampusid(campusid);
+                if (sysDept != null) {
+                    sysUserDept.setDeptId(sysDept.getDeptId());
+                    sysUserDept.setDeptName(sysDept.getDeptName());
+                }
+                sysUserDept.setDelFlag(0L);
+                sysUserDept.setCreateTime(now);
+                sysUserDept.setUpdateTime(now);
+                sysUserDeptMapper.insertSysUserDept(sysUserDept);
+                stat[0]++;
+                continue;
+            }
+
+            boolean wasDeleted = !Long.valueOf(0L).equals(sysUserDept.getDelFlag());
+            sysUserDept.setDeptCode(deptCode);
+            sysUserDept.setDeptType(expectedDeptType);
+            sysUserDept.setOrgid(userDeptOrgid);
+            sysUserDept.setCampusid(campusid);
+            if (sysDept != null) {
+                sysUserDept.setDeptId(sysDept.getDeptId());
+                sysUserDept.setDeptName(sysDept.getDeptName());
+            }
+            sysUserDept.setDelFlag(0L);
+            sysUserDept.setUpdateTime(now);
+            sysUserDeptMapper.updateSysUserDept(sysUserDept);
+            if (wasDeleted) {
+                stat[2]++;
+            } else {
+                stat[1]++;
+            }
+        }
+        return stat;
+    }
+
+    /**
+     * 瑙f瀽 hosp_info / dept_info 涓殑閮ㄩ棬缂栫爜銆�
+     * 鍘熷鐢熸垚閫昏緫浣跨敤 Gson 搴忓垪鍖� List&lt;List&lt;String&gt;&gt;锛屾牸寮忓 [["code1"],["code2"]]锛�
+     * 杩欓噷鍏煎璇ユ牸寮忥紝鍚屾椂鍏煎 ["code"]銆乕{"deptCode":"code"}] 绛夊巻鍙叉牸寮忋��
+     */
+    private List<String> parseDeptCodes(String json) {
+        if (StringUtils.isEmpty(json)) {
+            return Collections.emptyList();
+        }
+        List<String> codes = new ArrayList<>();
+        try {
+            collectDeptCodes(OBJECT_MAPPER.readTree(json), codes);
+        } catch (Exception e) {
+            log.warn("瑙f瀽鐢ㄦ埛绉戝/鐥呭尯淇℃伅澶辫触锛屽唴瀹癸細{}", json, e);
+        }
+        return codes.stream().filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
+    }
+
+    private void collectDeptCodes(JsonNode node, List<String> codes) {
+        if (node == null || node.isNull()) {
+            return;
+        }
+        if (node.isArray()) {
+            for (JsonNode item : node) {
+                collectDeptCodes(item, codes);
+            }
+            return;
+        }
+        if (node.isObject()) {
+            JsonNode codeNode = node.get("deptCode");
+            if (codeNode == null) {
+                codeNode = node.get("code");
+            }
+            if (codeNode == null) {
+                codeNode = node.get("deptId");
+            }
+            if (codeNode == null) {
+                codeNode = node.get("hisDeptId");
+            }
+            if (codeNode != null) {
+                collectDeptCodes(codeNode, codes);
+                return;
+            }
+            Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
+            while (fields.hasNext()) {
+                JsonNode value = fields.next().getValue();
+                if (value != null && value.isValueNode() && !value.isNull()) {
+                    collectDeptCodes(value, codes);
+                    return;
+                }
+            }
+            return;
+        }
+        if (node.isValueNode()) {
+            String code = node.asText();
+            if (StringUtils.isNotEmpty(code)) {
+                code = code.trim();
+                if (StringUtils.isNotEmpty(code) && !"null".equalsIgnoreCase(code)) {
+                    codes.add(code);
+                }
+            }
+        }
+    }
 }
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
index 1b37417..225eac3 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -135,6 +135,7 @@
         select d.dept_id,
                d.parent_id,
                d.campusid,
+               d.orgid,
                d.dept_code,
                d.dept_type,
                d.ancestors,
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserDeptMapper.xml
index 4795ebc..88c3340 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserDeptMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserDeptMapper.xml
@@ -82,6 +82,17 @@
         where id = #{id}
     </select>
 
+    <select id="selectSysUserDeptByUserAndCode" resultMap="SysUserDeptResult">
+        <include refid="selectSysUserDeptVo"/>
+        where user_id = #{userId}
+          and dept_code = #{deptCode}
+        <if test="orgid != null and orgid != ''">
+            and orgid = #{orgid}
+        </if>
+        order by del_flag asc, id asc
+        limit 1
+    </select>
+
     <insert id="insertSysUserDept" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept"
             useGeneratedKeys="true" keyProperty="id">
         insert into sys_user_dept
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index f85b5ab..ac40ec5 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -245,6 +245,26 @@
         <if test="pageSize != null  and pageNum != null">limit ${pageSize} OFFSET ${pageNum}</if>
     </select>
 
+    <select id="selectUsersForRepairUserDept" resultMap="SysUserResult">
+        select u.user_id,
+               u.user_name,
+               u.orgid,
+               u.campusid,
+               u.hosp_info,
+               u.dept_info
+        from sys_user u
+        where u.del_flag = '0'
+          and ((u.hosp_info is not null and u.hosp_info != '' and u.hosp_info != '[]')
+            or (u.dept_info is not null and u.dept_info != '' and u.dept_info != '[]'))
+        <if test="orgid != null and orgid != ''">
+            AND u.orgid = #{orgid}
+        </if>
+        <if test="userId != null">
+            AND u.user_id = #{userId}
+        </if>
+        order by u.user_id
+    </select>
+
     <select id="selectAllocatedList" parameterType="com.ruoyi.common.core.domain.entity.SysUser"
             resultMap="SysUserResult">
         select distinct u.user_id,u.his_user_id,u.title,u.hosp_info,u.dept_info, u.searchscope, u.dept_id, u.user_name,

--
Gitblit v1.9.3