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 |  490 ++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 328 insertions(+), 162 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 14fe835..2ac1bae 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -6,15 +6,18 @@
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo;
+import com.ruoyi.approve.bean.vo.ApproveProcessConfigNodeVo;
+import com.ruoyi.approve.bean.vo.ApproveProcessVO;
 import com.ruoyi.approve.mapper.ApproveNodeMapper;
 import com.ruoyi.approve.mapper.ApproveProcessMapper;
 import com.ruoyi.approve.pojo.ApproveNode;
 import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.approve.service.ApproveProcessConfigNodeService;
 import com.ruoyi.approve.service.IApproveNodeService;
 import com.ruoyi.approve.service.IApproveProcessService;
-import com.ruoyi.approve.utils.DailyRedisCounter;
-import com.ruoyi.approve.vo.ApproveGetAndUpdateVo;
-import com.ruoyi.approve.vo.ApproveProcessVO;
+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;
@@ -25,83 +28,78 @@
 import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.project.system.service.ISysNoticeService;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
 import com.ruoyi.sales.pojo.CommonFile;
+import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
-import lombok.AllArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
 import java.io.IOException;
-import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
-//@RequiredArgsConstructor
+@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();
 
-    @Autowired
-    private  StringRedisTemplate redisTemplate;
-    @Autowired
-    private  DailyRedisCounter dailyRedisCounter;
-    @Autowired
-    private  SysDeptMapper sysDeptMapper;
-    @Autowired
-    private  IApproveNodeService approveNodeService;
-    @Autowired
-    private  SysUserMapper sysUserMapper;
-    @Autowired
-    private  ApproveProcessMapper approveProcessMapper;
-    @Autowired
-    private  TempFileServiceImpl tempFileService;
-    @Autowired
-    private  CommonFileMapper commonFileMapper;
-    @Autowired
-    private  CommonFileServiceImpl commonFileService;
-    @Autowired
-    private  ISysNoticeService sysNoticeService;
+    private final SysDeptMapper sysDeptMapper;
+    private final IApproveNodeService approveNodeService;
+    private final SysUserMapper sysUserMapper;
+    private final ApproveProcessMapper approveProcessMapper;
+    private final TempFileServiceImpl tempFileService;
+    private final CommonFileMapper commonFileMapper;
+    private final CommonFileServiceImpl commonFileService;
+    private final ISysNoticeService sysNoticeService;
+    private final PurchaseLedgerMapper purchaseLedgerMapper;
+    private final ShippingInfoMapper shippingInfoMapper;
+    private final ApproveNodeMapper approveNodeMapper;
+    private final ApproveProcessConfigNodeService approveProcessConfigNodeService;
 
     @Override
-    public void addApprove(ApproveProcessVO approveProcessVO) throws Exception {
-        SysUser sysUser = sysUserMapper.selectUserById(approveProcessVO.getApproveUser());
-        SysDept sysDept = sysDeptMapper.selectDeptById(approveProcessVO.getApproveDeptId());
-        String[] split = approveProcessVO.getApproveUserIds().split(",");
-        List<Long> longList = Arrays.stream(split)
-                .map(Long::valueOf)  // 灏嗘瘡涓� String 杞崲涓� Long
+    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<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());
-        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(longList);
+        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("閮ㄩ棬涓嶅瓨鍦�");
         if (sysUser == null) throw new RuntimeException("鐢宠浜轰笉瀛樺湪");
-        String today = LocalDate.now().format(DATE_FORMAT);
-        Long approveId = dailyRedisCounter.incrementAndGetByDb();
-        String formattedCount = String.format("%03d", approveId);
-        //娴佺▼ ID
-        String approveID = today + formattedCount;
+//        String today = LocalDate.now().format(DATE_FORMAT);
+//        Long approveId = dailyRedisCounter.incrementAndGetByDb();
+//        String formattedCount = String.format("%03d", approveId);
+//        //娴佺▼ ID
+//        String approveID = today + formattedCount;
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         ApproveProcess approveProcess = new ApproveProcess();
-        approveProcess.setApproveId(approveID);
-        approveProcess.setApproveUser(approveProcessVO.getApproveUser());
+        String no = OrderUtils.countAfterServiceTodayByCreateTime(approveProcessMapper, "CGSP");
+        approveProcess.setApproveId(no);
+        approveProcess.setApproveUser(sysUser.getUserId());
         approveProcess.setApproveUserName(sysUser.getNickName());
-        approveProcess.setApproveDeptId(approveProcessVO.getApproveDeptId());
+        approveProcess.setApproveDeptId(sysDept.getDeptId());
+        approveProcess.setApproveUserIds(nodeIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
         approveProcess.setApproveDeptName(sysDept.getDeptName());
         approveProcess.setApproveUserNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(",")));
-        approveProcess.setApproveTime(StringUtils.isEmpty(approveProcessVO.getApproveTime()) ? null : dateFormat.parse(approveProcessVO.getApproveTime()));
+        approveProcess.setApproveTime(StringUtils.isEmpty(approveProcessVO.getApproveTime()) ? new Date(): dateFormat.parse(approveProcessVO.getApproveTime()));
         approveProcess.setApproveReason(approveProcessVO.getApproveReason());
         approveProcess.setDeviceRepairId(approveProcessVO.getDeviceRepairId());
         approveProcess.setMaintenancePrice(approveProcessVO.getMaintenancePrice());
@@ -113,38 +111,23 @@
         approveProcess.setApproveType(approveProcessVO.getApproveType());
         approveProcess.setCreateTime(LocalDateTime.now());
         approveProcess.setTenantId(approveProcessVO.getApproveDeptId());
-        approveProcess.setApproveUserIds(approveProcessVO.getApproveUserIds());
-        approveProcess.setApproveUserCurrentId(longList.get(0));
-        approveProcess.setApproveUserCurrentName(sysUsers
-                .stream()
-                .filter(SysUser -> SysUser.getUserId().equals(longList.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);
-        //鍒濆鍖栧鎵硅妭鐐�
-        approveNodeService.initApproveNodes(approveProcessVO.getApproveUserIds(), approveID, approveProcessVO.getApproveDeptId());
+        //鍒濆鍖栧鎵硅妭鐐癸紙鎸夐厤缃妭鐐瑰垎缁勶紝鏀寔鍚岃妭鐐瑰瀹℃壒浜�/鎴栫浼氱锛�
+        approveNodeService.initApproveNodes(list, no, approveProcessVO.getApproveDeptId());
         // 闄勪欢缁戝畾
         tempFileService.migrateTempFilesToFormal(approveProcess.getId(), approveProcessVO.getTempFileIds(), FileNameType.ApproveProcess.getValue());
-        /*娑堟伅閫氱煡*/
-        String id = approveProcessVO.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());
-        }
+        /*娑堟伅閫氱煡锛堥�氱煡绗竴鑺傜偣鍏ㄩ儴瀹℃壒浜猴級*/
+        notifyApproveUsers(approveProcess, firstGroupUserIds(approveProcess));
+        return approveProcess.getId();
     }
 
     @Override
@@ -157,15 +140,56 @@
         return sysDeptList;
     }
 
+
     @Override
     public IPage<ApproveProcess> listAll(Page page, ApproveProcess approveProcess) {
         IPage<ApproveProcess> approveProcessIPage = approveProcessMapper.listPage(page, approveProcess);
         List<ApproveProcess> records = approveProcessIPage.getRecords();
+
         for (ApproveProcess record : records) {
-            List<CommonFile> commonFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
-                    .eq(CommonFile::getCommonId, record.getId())
-                    .eq(CommonFile::getType, FileNameType.ApproveProcess.getValue()));
-            record.setCommonFileList(commonFiles);
+            List<CommonFile> allFiles = new ArrayList<>();
+
+            //  閲囪喘瀹℃壒鏌ヨ
+            if (record.getApproveType() == 5) {
+                String contractNo = record.getApproveReason();
+                PurchaseLedger ledger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>()
+                        .eq(PurchaseLedger::getPurchaseContractNumber, contractNo)
+                        .last("limit 1"));
+
+                if (ledger != null) {
+                    allFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
+                            .eq(CommonFile::getCommonId, ledger.getId())
+                            .eq(CommonFile::getType, FileNameType.PURCHASE.getValue()));
+                }
+            }
+
+            //  鍙戣揣瀹℃壒鏌ヨ
+            else if (record.getApproveType() == 7) {
+                String reason = record.getApproveReason(); // 鏍煎紡涓� "xx:...-..."
+                if (StringUtils.hasText(reason) && reason.contains(":")) {
+                    // 鎻愬彇鍐掑彿鍚庨潰鐨勫彂璐у崟鍙�
+                    String shippingNo = reason.split(":")[1];
+                    // 鏍规嵁鍙戣揣鍗曞彿鏌ヨ鍙戣揣鍙拌处璁板綍
+                    ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
+                            .eq(ShippingInfo::getShippingNo, shippingNo)
+                            .last("limit 1"));
+                    if (shippingInfo != null) {
+                        // 浣跨敤鍙戣揣鍙拌处鐨� 閿�鍞彴璐D 鍘绘煡闄勪欢
+                        allFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
+                                .eq(CommonFile::getCommonId, shippingInfo.getSalesLedgerId())
+                                .eq(CommonFile::getType, FileNameType.SALE.getValue()));
+                    }
+                }
+            }
+
+            //  鏌ヨ瀹℃壒鍗曡嚜韬殑闄勪欢
+            else {
+                allFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
+                        .eq(CommonFile::getCommonId, record.getId())
+                        .eq(CommonFile::getType, FileNameType.ApproveProcess.getValue()));
+            }
+
+            record.setCommonFileList(allFiles);
         }
         return approveProcessIPage;
     }
@@ -207,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)
@@ -221,7 +245,7 @@
             // 鍒犻櫎瀵瑰簲鐨勯檮浠�
             commonFileService.deleteByBusinessId(approveProcess.getId(), FileNameType.ApproveProcess.getValue());
             //  鍒犻櫎瀹℃壒鑺傜偣
-            approveNodeService.delApproveNodeByApproveId(approveId.toString());
+            approveNodeService.delApproveNodeByApproveId(approveId);
 
             //  鍙煡鏈�鏂颁竴鏉″鎵规祦绋�
             ApproveProcess latestProcess = approveProcessMapper.selectOne(
@@ -254,8 +278,6 @@
         return one;
     }
 
-    @Autowired
-    private ApproveNodeMapper approveNodeMapper;
 
     // 鎶ヤ环瀹℃壒缂栬緫瀹℃牳浜�
     public void updateApproveUser(ApproveGetAndUpdateVo approveGetAndUpdateVo) {
@@ -265,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) {
@@ -391,6 +555,8 @@
                 return "鍙戣揣瀹℃壒";
             case 8:
                 return "鍗遍櫓浣滀笟瀹℃壒";
+            case 9:
+                return "鐢ㄥ嵃瀹℃壒";
         }
         return null;
     }

--
Gitblit v1.9.3