From f350465db70d6f9db9494483ee0cec7793a9007b Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 19 八月 2026 17:47:57 +0800
Subject: [PATCH] feat(approve): 实现审批流程或签会签功能并优化数据库配置

---
 src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java |  357 +++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 246 insertions(+), 111 deletions(-)

diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
index 63eb8ac..2ac1bae 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -16,6 +16,8 @@
 import com.ruoyi.approve.service.ApproveProcessConfigNodeService;
 import com.ruoyi.approve.service.IApproveNodeService;
 import com.ruoyi.approve.service.IApproveProcessService;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.common.utils.SecurityUtils;
@@ -50,6 +52,7 @@
 @RequiredArgsConstructor
 public class ApproveProcessServiceImpl extends ServiceImpl<ApproveProcessMapper, ApproveProcess> implements IApproveProcessService {
     private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
+    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
     private final SysDeptMapper sysDeptMapper;
     private final IApproveNodeService approveNodeService;
@@ -65,13 +68,18 @@
     private final ApproveProcessConfigNodeService approveProcessConfigNodeService;
 
     @Override
-    public void addApprove(ApproveProcessVO approveProcessVO) throws Exception {
+    public Long addApprove(ApproveProcessVO approveProcessVO) throws Exception {
         SysUser sysUser = SecurityUtils.getLoginUser().getUser();
         SysDept sysDept = sysDeptMapper.selectDeptById(SecurityUtils.getLoginUser().getCurrentDeptId());
-        List<ApproveProcessConfigNodeVo> list = approveProcessConfigNodeService.listNode( approveProcessVO.getApproveType());
+        List<ApproveProcessConfigNodeVo> list = approveProcessConfigNodeService.listNode(approveProcessVO.getApproveType());
+        // 鎸夎妭鐐归『搴忓垎缁勶紙鍚岃妭鐐瑰瀹℃壒浜猴級
+        List<List<ApproveProcessConfigNodeVo>> groups = groupByOrder(list);
+        if (groups.isEmpty()) throw new RuntimeException("娣诲姞瀹℃壒鑺傜偣鍜屼汉鍛�");
+        List<ApproveProcessConfigNodeVo> firstGroup = groups.get(0);
         List<Long> nodeIds = list.stream()
                 .map(ApproveProcessConfigNodeVo::getApproverId)
                 .collect(Collectors.toList());
+        if (nodeIds.isEmpty()) throw new RuntimeException("娣诲姞瀹℃壒鑺傜偣鍜屼汉鍛�");
         List<SysUser> sysUsers = sysUserMapper.selectUserByIds(nodeIds);
         if (CollectionUtils.isEmpty(sysUsers)) throw new RuntimeException("瀹℃牳鐢ㄦ埛涓嶅瓨鍦�");
         if (sysDept == null) throw new RuntimeException("閮ㄩ棬涓嶅瓨鍦�");
@@ -83,7 +91,7 @@
 //        String approveID = today + formattedCount;
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         ApproveProcess approveProcess = new ApproveProcess();
-        String no = OrderUtils.countTodayByCreateTime(approveProcessMapper, "approve_id");
+        String no = OrderUtils.countAfterServiceTodayByCreateTime(approveProcessMapper, "CGSP");
         approveProcess.setApproveId(no);
         approveProcess.setApproveUser(sysUser.getUserId());
         approveProcess.setApproveUserName(sysUser.getNickName());
@@ -103,40 +111,23 @@
         approveProcess.setApproveType(approveProcessVO.getApproveType());
         approveProcess.setCreateTime(LocalDateTime.now());
         approveProcess.setTenantId(approveProcessVO.getApproveDeptId());
-        approveProcess.setApproveUserCurrentId(nodeIds.get(0));
-        approveProcess.setApproveUserCurrentName(sysUsers
-                .stream()
-                .filter(SysUser -> SysUser.getUserId().equals(nodeIds.get(0)))
-                .collect(Collectors.toList())
-                .get(0)
-                .getNickName());
+        setFirstNodeApprovers(approveProcess, firstGroup, sysUsers);
         // 璁剧疆鐘舵�佷负閲嶆柊鎻愪氦
         if (approveProcessVO.getId() != null) {
             ApproveProcess approveProcess1 = approveProcessMapper.selectById(approveProcessVO.getId());
             approveProcess1.setApproveStatus(4);
             approveProcessMapper.updateById(approveProcess1);
         }
+        // 鑺傜偣缁撴瀯蹇収锛堜緵缂栬緫閲嶅缓瀹℃壒鑺傜偣鏃朵繚鍒嗙粍涓庢ā寮忥級
+        approveProcess.setApproveNodeConfig(buildNodeConfig(list));
         save(approveProcess);
-        //鍒濆鍖栧鎵硅妭鐐�
-        String nodeIdStr = nodeIds.stream()
-                .map(String::valueOf)
-                .collect(Collectors.joining(","));
-        approveNodeService.initApproveNodes(nodeIdStr, no, approveProcessVO.getApproveDeptId());
+        //鍒濆鍖栧鎵硅妭鐐癸紙鎸夐厤缃妭鐐瑰垎缁勶紝鏀寔鍚岃妭鐐瑰瀹℃壒浜�/鎴栫浼氱锛�
+        approveNodeService.initApproveNodes(list, no, approveProcessVO.getApproveDeptId());
         // 闄勪欢缁戝畾
         tempFileService.migrateTempFilesToFormal(approveProcess.getId(), approveProcessVO.getTempFileIds(), FileNameType.ApproveProcess.getValue());
-        /*娑堟伅閫氱煡*/
-        Long id = nodeIds.get(0);
-        if (approveProcess.getApproveType()==8){
-            sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
-                    approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Collections.singletonList(id),
-                    "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
-        }else {
-            sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
-                    approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Collections.singletonList(id),
-                    "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
-        }
+        /*娑堟伅閫氱煡锛堥�氱煡绗竴鑺傜偣鍏ㄩ儴瀹℃壒浜猴級*/
+        notifyApproveUsers(approveProcess, firstGroupUserIds(approveProcess));
+        return approveProcess.getId();
     }
 
     @Override
@@ -240,8 +231,8 @@
     }
 
     @Override
-    public void delApprove(List<Long> ids) {
-        for (Long approveId : ids) {
+    public void delApprove(List<String> ids) {
+        for (String approveId : ids) {
             ApproveProcess approveProcess = approveProcessMapper.selectOne(new LambdaQueryWrapper<ApproveProcess>()
                     .eq(ApproveProcess::getApproveId, approveId)
                     .eq(ApproveProcess::getApproveDelete, 0)
@@ -254,7 +245,7 @@
             // 鍒犻櫎瀵瑰簲鐨勯檮浠�
             commonFileService.deleteByBusinessId(approveProcess.getId(), FileNameType.ApproveProcess.getValue());
             //  鍒犻櫎瀹℃壒鑺傜偣
-            approveNodeService.delApproveNodeByApproveId(approveId.toString());
+            approveNodeService.delApproveNodeByApproveId(approveId);
 
             //  鍙煡鏈�鏂颁竴鏉″鎵规祦绋�
             ApproveProcess latestProcess = approveProcessMapper.selectOne(
@@ -296,112 +287,254 @@
                 .last("limit 1");
         ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper);
         if (approveProcess == null) throw new RuntimeException("璇烽�夋嫨瀹℃壒浜�");
-        String[] split = approveGetAndUpdateVo.getApproveUserIds().split(",");
-        if (split.length == 0) {
+        String newIds = approveGetAndUpdateVo.getApproveUserIds();
+        if (newIds == null || newIds.trim().isEmpty()) {
             throw new RuntimeException("璇烽�夋嫨瀹℃壒浜�");
         }
-        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(Arrays.asList(split).stream().map(Long::parseLong).collect(Collectors.toList()));
+        List<Long> newIdList = parseUserIds(newIds);
+        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(newIdList);
         if (CollectionUtils.isEmpty(sysUsers)) throw new RuntimeException("璇烽�夋嫨瀹℃壒浜�");
-        //瀹℃牳涓笉鍙互缂栬緫瀹℃牳浜�
-        if (approveProcess.getApproveStatus() != 1) {
-            approveProcess.setApproveUserCurrentId(Long.parseLong(split[0]));
-            approveProcess.setApproveUserCurrentName(sysUsers.stream().filter(user -> user.getUserId().equals(Long.parseLong(split[0]))).collect(Collectors.toList()).get(0).getNickName());
-        }
+        approveProcess.setApproveUserIds(newIds);
+        approveProcess.setApproveUserNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(",")));
         if (approveGetAndUpdateVo.getApproveStatus() != null) {
             approveProcess.setApproveStatus(approveGetAndUpdateVo.getApproveStatus());
         }
-        approveProcess.setApproveUserIds(approveGetAndUpdateVo.getApproveUserIds());
-        updateById(approveProcess);
-        //淇敼瀹℃壒浜�
-        // 鍏堝垹闄� 鍚庢柊澧�
-        LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId())
-                .eq(ApproveNode::getDeleteFlag, 0)
-//                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
-                .orderByAsc(ApproveNode::getApproveNodeOrder);
-        approveNodeMapper.delete(approveNodeLambdaQueryWrapper);
-        approveNodeService.initApproveNodes(approveGetAndUpdateVo.getApproveUserIds(), approveProcess.getApproveId(), approveProcess.getTenantId());
-        /*娑堟伅閫氱煡*/
-        String id = approveProcess.getApproveUserIds().split(",")[0];
-        if (approveProcess.getApproveType()==8){
-            sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
-                    approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Arrays.asList(Long.valueOf(id)),
-                    "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
-        }else {
-            sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
-                    approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Arrays.asList(Long.valueOf(id)),
-                    "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
+        // 鍏堝垹闄� 鍚庢柊澧烇紙浼樺厛鎸� approve_node_config 蹇収淇濆垎缁勪笌妯″紡锛�
+        approveNodeMapper.delete(new LambdaQueryWrapper<ApproveNode>()
+                .eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId())
+                .eq(ApproveNode::getDeleteFlag, 0));
+        rebuildApproveNodes(approveProcess, newIds);
+        // 瀹℃牳涓笉鍙互缂栬緫瀹℃牳浜�
+        if (approveProcess.getApproveStatus() != 1) {
+            refreshCurrentApprovers(approveProcess);
+        } else {
+            approveProcessMapper.updateById(approveProcess);
         }
+        /*娑堟伅閫氱煡锛堥�氱煡绗竴鑺傜偣鍏ㄩ儴瀹℃壒浜猴級*/
+        notifyApproveUsers(approveProcess, firstGroupUserIds(approveProcess));
     }
 
 
     @Override
     public void updateByApproveId(ApproveGetAndUpdateVo approveGetAndUpdateVo) throws IOException {
         ApproveProcess approve = approveProcessMapper.selectById(approveGetAndUpdateVo.getId());
+        Integer oldStatus = approve.getApproveStatus();
         BeanUtils.copyProperties(approveGetAndUpdateVo, approve);
-        approve.setApproveUserIds(approveGetAndUpdateVo.getApproveUserIds());
+        // BeanUtils 浼氭嫹璐� null锛岄槻姝㈡妸瀹℃壒鐘舵�佽鐩栦负绌�
+        if (approveGetAndUpdateVo.getApproveStatus() == null) {
+            approve.setApproveStatus(oldStatus);
+        }
         approve.setApproveReason(approveGetAndUpdateVo.getApproveReason());
-        SysUser sysUser = sysUserMapper.selectUserById(approveGetAndUpdateVo.getApproveUser());
-        String[] split = approveGetAndUpdateVo.getApproveUserIds().split(",");
-        if (split.length == 0) {
+        String newIds = approveGetAndUpdateVo.getApproveUserIds();
+        if (newIds == null || newIds.trim().isEmpty()) {
             throw new RuntimeException("璇烽�夋嫨瀹℃壒浜�");
         }
-        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(Arrays.asList(split).stream().map(Long::parseLong).collect(Collectors.toList()));
+        List<Long> newIdList = parseUserIds(newIds);
+        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(newIdList);
         if (CollectionUtils.isEmpty(sysUsers)) throw new RuntimeException("璇烽�夋嫨瀹℃壒浜�");
+        SysUser sysUser = sysUserMapper.selectUserById(approveGetAndUpdateVo.getApproveUser());
         if (sysUser == null) throw new RuntimeException("鐢宠浜轰笉瀛樺湪");
         approve.setApproveUserName(sysUser.getNickName());
         approve.setApproveUser(sysUser.getUserId());
-        //瀹℃牳涓笉鍙互缂栬緫瀹℃牳浜�
+        approve.setApproveUserIds(newIds);
+        approve.setApproveUserNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(",")));
+        //淇敼瀹℃壒浜猴細鍏堝垹闄ゅ悗鏂板锛堜紭鍏堟寜 approve_node_config 蹇収淇濆垎缁勪笌妯″紡锛�
+        approveNodeMapper.delete(new LambdaQueryWrapper<ApproveNode>()
+                .eq(ApproveNode::getApproveProcessId, approve.getApproveId())
+                .eq(ApproveNode::getDeleteFlag, 0));
+        rebuildApproveNodes(approve, newIds);
+        // 瀹℃牳涓笉鍙互缂栬緫瀹℃牳浜�
         if (approve.getApproveStatus() != 1) {
-            approve.setApproveUserCurrentId(Long.parseLong(split[0]));
-            approve.setApproveUserCurrentName(sysUsers.stream().filter(user -> user.getUserId().equals(Long.parseLong(split[0]))).collect(Collectors.toList()).get(0).getNickName());
+            refreshCurrentApprovers(approve);
+        } else {
+            approveProcessMapper.updateById(approve);
         }
-        updateById(approve);
-        //淇敼瀹℃壒浜�
-        // 鍏堝垹闄� 鍚庢柊澧�
-        LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approve.getApproveId())
-                .eq(ApproveNode::getDeleteFlag, 0)
-//                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
-                .orderByAsc(ApproveNode::getApproveNodeOrder);
-        approveNodeMapper.delete(approveNodeLambdaQueryWrapper);
-        approveNodeService.initApproveNodes(approveGetAndUpdateVo.getApproveUserIds(), approve.getApproveId(), approve.getTenantId());
-
-//        int i = 0;
-//        for (ApproveNode approveNode : list) {
-//            int finalI = i;
-//            if(i >= split.length){
-//                approveNode.setDeleteFlag(1);
-//            }else{
-//                List<SysUser> collect = sysUsers.stream().filter(user -> user.getUserId().equals(Long.parseLong(split[finalI]))).collect(Collectors.toList());
-//                if(CollectionUtils.isEmpty(collect)){
-//                    throw new RuntimeException("璇烽�夋嫨姝g‘鐨勫鎵逛汉");
-//                }
-//                approveNode.setApproveNodeUserId(collect.get(0).getUserId());
-//                approveNode.setApproveNodeUser(collect.get(0).getNickName());
-//            }
-//            approveNodeMapper.updateById(approveNode);
-//            i++;
-//        }
         tempFileService.migrateTempFilesToFormal(approve.getId(), approveGetAndUpdateVo.getTempFileIds(), FileNameType.ApproveProcess.getValue());
-        /*娑堟伅閫氱煡*/
-        String id = approve.getApproveUserIds().split(",")[0];
-        if (approve.getApproveType()==8){
-            sysNoticeService.simpleNoticeByUser(approveProcessType(approve.getApproveType()),
-                    approve.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Arrays.asList(Long.valueOf(id)),
-                    "/safeProduction/safeWorkApproval?approveType=" + approve.getApproveType() + "&approveId=" + approve.getApproveId());
-        }else {
-            sysNoticeService.simpleNoticeByUser(approveProcessType(approve.getApproveType()),
-                    approve.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Arrays.asList(Long.valueOf(id)),
-                    "/collaborativeApproval/approvalProcess?approveType=" + approve.getApproveType() + "&approveId=" + approve.getApproveId());
-        }
-
+        /*娑堟伅閫氱煡锛堥�氱煡绗竴鑺傜偣鍏ㄩ儴瀹℃壒浜猴級*/
+        notifyApproveUsers(approve, firstGroupUserIds(approve));
     }
 
+
+    /**
+     * 鎸夎妭鐐归『搴忓垎缁勶紙淇濆簭锛夛紝鍚岃妭鐐瑰瀹℃壒浜哄綊鍏ヤ竴缁�
+     */
+    private List<List<ApproveProcessConfigNodeVo>> groupByOrder(List<ApproveProcessConfigNodeVo> list) {
+        Map<Integer, List<ApproveProcessConfigNodeVo>> map = new LinkedHashMap<>();
+        for (ApproveProcessConfigNodeVo vo : list) {
+            if (vo.getApproverId() == null) {
+                continue;
+            }
+            int order = vo.getNodeOrder() == null ? map.size() + 1 : vo.getNodeOrder();
+            map.computeIfAbsent(order, k -> new ArrayList<>()).add(vo);
+        }
+        return new ArrayList<>(map.values());
+    }
+
+    /**
+     * 璁剧疆娴佺▼棣栬妭鐐瑰緟瀹′汉锛堝鍊奸�楀彿鍒嗛殧锛屽吋瀹规棫鐨勫崟鍊煎瓧娈碉級
+     */
+    private void setFirstNodeApprovers(ApproveProcess approveProcess, List<ApproveProcessConfigNodeVo> firstGroup, List<SysUser> sysUsers) {
+        List<Long> ids = firstGroup.stream()
+                .map(ApproveProcessConfigNodeVo::getApproverId)
+                .distinct()
+                .collect(Collectors.toList());
+        Map<Long, String> nameMap = sysUsers.stream()
+                .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName, (a, b) -> a));
+        List<String> names = ids.stream().map(nameMap::get).filter(Objects::nonNull).collect(Collectors.toList());
+        approveProcess.setApproveUserCurrentIds(ids.stream().map(String::valueOf).collect(Collectors.joining(",")));
+        approveProcess.setApproveUserCurrentNames(String.join(",", names));
+        if (!ids.isEmpty()) {
+            approveProcess.setApproveUserCurrentId(ids.get(0));
+            approveProcess.setApproveUserCurrentName(names.isEmpty() ? null : names.get(0));
+        }
+    }
+
+    /**
+     * 鑺傜偣缁撴瀯蹇収JSON锛歔{nodeOrder,mode,userIds,userNames}]锛屼緵缂栬緫閲嶅缓瀹℃壒鑺傜偣
+     */
+    private String buildNodeConfig(List<ApproveProcessConfigNodeVo> list) {
+        try {
+            List<Map<String, Object>> nodes = new ArrayList<>();
+            for (List<ApproveProcessConfigNodeVo> group : groupByOrder(list)) {
+                String mode = group.get(0).getApproveMode();
+                if (mode == null || mode.isEmpty()) {
+                    mode = "or";
+                }
+                List<Long> ids = group.stream().map(ApproveProcessConfigNodeVo::getApproverId).distinct().collect(Collectors.toList());
+                List<SysUser> users = sysUserMapper.selectUserByIds(ids);
+                Map<String, Object> node = new LinkedHashMap<>();
+                node.put("nodeOrder", group.get(0).getNodeOrder());
+                node.put("mode", mode);
+                node.put("userIds", ids.stream().map(String::valueOf).collect(Collectors.joining(",")));
+                node.put("userNames", users.stream().map(SysUser::getNickName).collect(Collectors.joining(",")));
+                nodes.add(node);
+            }
+            return OBJECT_MAPPER.writeValueAsString(nodes);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    private List<String> splitIds(String ids) {
+        if (ids == null || ids.trim().isEmpty()) {
+            return new ArrayList<>();
+        }
+        return Arrays.stream(ids.split(",")).map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toList());
+    }
+
+    private List<Long> parseUserIds(String ids) {
+        return splitIds(ids).stream().map(Long::parseLong).collect(Collectors.toList());
+    }
+
+    /**
+     * 閲嶅缓瀹℃壒鑺傜偣锛氫紭鍏堟寜 approve_node_config 蹇収淇濆垎缁勪笌妯″紡閲嶅缓锛�
+     * 鏂伴�夌殑鎵佸钩瀹℃壒浜轰覆鎸夎妭鐐规Ы浣嶉『搴忎緷娆″~鍏咃紱鏃犲揩鐓у垯鍥為��鎵佸钩閫昏緫锛堜竴鑺傜偣涓�浜� or锛�
+     */
+    private void rebuildApproveNodes(ApproveProcess approveProcess, String approveUserIds) {
+        List<ApproveProcessConfigNodeVo> config = null;
+        if (StringUtils.hasText(approveProcess.getApproveNodeConfig())) {
+            config = buildConfigFromSnapshot(approveProcess.getApproveNodeConfig(), approveUserIds);
+        }
+        if (config == null) {
+            approveNodeService.initApproveNodes(approveUserIds, approveProcess.getApproveId(), approveProcess.getTenantId());
+        } else {
+            approveNodeService.initApproveNodes(config, approveProcess.getApproveId(), approveProcess.getTenantId());
+        }
+    }
+
+    private List<ApproveProcessConfigNodeVo> buildConfigFromSnapshot(String snapshotJson, String approveUserIds) {
+        List<String> newIds = splitIds(approveUserIds);
+        try {
+            List<Map<String, Object>> nodes = OBJECT_MAPPER.readValue(snapshotJson,
+                    new TypeReference<List<Map<String, Object>>>() {});
+            List<ApproveProcessConfigNodeVo> config = new ArrayList<>();
+            int cursor = 0;
+            for (Map<String, Object> node : nodes) {
+                Object orderObj = node.get("nodeOrder");
+                int nodeOrder = orderObj instanceof Number ? ((Number) orderObj).intValue() : 0;
+                String mode = node.get("mode") == null ? "or" : String.valueOf(node.get("mode"));
+                List<String> snapshotIds = splitIds(node.get("userIds") == null ? null : String.valueOf(node.get("userIds")));
+                int slot = Math.max(1, snapshotIds.size());
+                for (int j = 0; j < slot; j++) {
+                    String uid = cursor < newIds.size() ? newIds.get(cursor++) : (j < snapshotIds.size() ? snapshotIds.get(j) : null);
+                    if (uid == null) {
+                        continue;
+                    }
+                    ApproveProcessConfigNodeVo vo = new ApproveProcessConfigNodeVo();
+                    vo.setNodeOrder(nodeOrder);
+                    vo.setApproverId(Long.parseLong(uid));
+                    vo.setApproveMode(mode);
+                    config.add(vo);
+                }
+            }
+            // 鏂伴�夊鎵逛汉鑻ュ浜庡揩鐓фЫ浣嶏紝杩藉姞鍒版渶鍚庝竴涓妭鐐�
+            while (cursor < newIds.size()) {
+                ApproveProcessConfigNodeVo vo = new ApproveProcessConfigNodeVo();
+                vo.setNodeOrder(nodes.isEmpty() ? 1 : ((Number) nodes.get(nodes.size() - 1).get("nodeOrder")).intValue());
+                vo.setApproverId(Long.parseLong(newIds.get(cursor++)));
+                vo.setApproveMode("or");
+                config.add(vo);
+            }
+            return config;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * 鍒锋柊娴佺▼褰撳墠瀹℃壒浜轰负绗竴鑺傜偣寰呭浜猴紙鐢ㄤ簬缂栬緫鍚庨噸寤猴級
+     */
+    private void refreshCurrentApprovers(ApproveProcess approveProcess) {
+        List<ApproveNode> first = approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>()
+                .eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId())
+                .eq(ApproveNode::getApproveNodeOrder, 1)
+                .eq(ApproveNode::getDeleteFlag, 0)
+                .orderByAsc(ApproveNode::getId));
+        if (first.isEmpty()) {
+            approveProcess.setApproveUserCurrentIds(null);
+            approveProcess.setApproveUserCurrentNames(null);
+            approveProcess.setApproveUserCurrentId(null);
+            approveProcess.setApproveUserCurrentName(null);
+        } else {
+            approveProcess.setApproveUserCurrentIds(first.stream()
+                    .map(n -> String.valueOf(n.getApproveNodeUserId())).collect(Collectors.joining(",")));
+            approveProcess.setApproveUserCurrentNames(first.stream()
+                    .map(ApproveNode::getApproveNodeUser).collect(Collectors.joining(",")));
+            approveProcess.setApproveUserCurrentId(first.get(0).getApproveNodeUserId());
+            approveProcess.setApproveUserCurrentName(first.get(0).getApproveNodeUser());
+        }
+        approveProcessMapper.updateById(approveProcess);
+    }
+
+    private List<Long> firstGroupUserIds(ApproveProcess approveProcess) {
+        List<ApproveNode> first = approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>()
+                .eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId())
+                .eq(ApproveNode::getApproveNodeOrder, 1)
+                .eq(ApproveNode::getDeleteFlag, 0)
+                .orderByAsc(ApproveNode::getId));
+        return first.stream().map(ApproveNode::getApproveNodeUserId).distinct().collect(Collectors.toList());
+    }
+
+    /**
+     * 閫氱煡绗竴鑺傜偣鍏ㄩ儴寰呭浜�
+     */
+    private void notifyApproveUsers(ApproveProcess approveProcess, List<Long> userIds) {
+        if (userIds == null || userIds.isEmpty()) {
+            return;
+        }
+        List<Long> ids = userIds.stream().distinct().collect(Collectors.toList());
+        if (approveProcess.getApproveType() == 8) {
+            sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
+                    approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
+                    ids,
+                    "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
+        } else {
+            sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
+                    approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
+                    ids,
+                    "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
+        }
+    }
 
     //瀹℃壒绫诲瀷鑾峰彇(涓庡墠绔〉闈㈠搴�)
     private String approveProcessType(Integer approveType) {
@@ -422,6 +555,8 @@
                 return "鍙戣揣瀹℃壒";
             case 8:
                 return "鍗遍櫓浣滀笟瀹℃壒";
+            case 9:
+                return "鐢ㄥ嵃瀹℃壒";
         }
         return null;
     }

--
Gitblit v1.9.3