Procházet zdrojové kódy

fix(leave): 修复请假流程 waiting 与业务 draft 不同步导致无审批按钮

申请人提交后业务表可能仍停在 draft,办理页不显示审批按钮;在请假模块内补齐任务创建时状态对齐,禁止 waiting 被回写为 draft,并仅在暂存时写 draft。

Co-authored-by: Cursor <cursoragent@cursor.com>
“wuzhen” před 1 měsícem
rodič
revize
a6a5b88f47

+ 42 - 13
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgStudentLeaveServiceImpl.java

@@ -414,6 +414,16 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
     public Boolean updateByBo(XgStudentLeaveBo bo) {
         XgStudentLeave update = MapstructUtils.convert(bo, XgStudentLeave.class);
         validEntityBeforeSave(update);
+        // 流程已在待审核时,禁止被前端再次保存成 draft(否则办理页审批按钮会消失)
+        if (update.getId() != null && StringUtils.isNotBlank(update.getApprovalStatus())) {
+            XgStudentLeave existing = baseMapper.selectById(update.getId());
+            if (ObjectUtil.isNotNull(existing)
+                && BusinessStatusEnum.WAITING.getStatus().equals(existing.getApprovalStatus())
+                && BusinessStatusEnum.DRAFT.getStatus().equals(update.getApprovalStatus())) {
+                log.warn("忽略将请假审批状态从 waiting 回写为 draft, leaveId={}", update.getId());
+                update.setApprovalStatus(null);
+            }
+        }
         return baseMapper.updateById(update) > 0;
     }
 
@@ -441,16 +451,25 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
 
     /**
      * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
-     * 正常使用只需#processEvent.flowCode=='leave1'
-     * 示例为了方便则使用startsWith匹配了全部示例key
+     * 仅处理请假流程 hzdyjs-qj*
      *
      * @param processEvent 参数
      */
+    @Transactional(rollbackFor = Exception.class)
     @EventListener(condition = "#processEvent.flowCode.startsWith('hzdyjs-qj')")
     public void processHandler(ProcessEvent processEvent) {
         log.info("当前任务执行了{}", processEvent.toString());
         XgStudentLeave xgStudentLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessId()));
-        xgStudentLeave.setApprovalStatus(processEvent.getStatus());
+        if (ObjectUtil.isNull(xgStudentLeave)) {
+            log.error("请假流程事件未找到业务数据, businessId={}", processEvent.getBusinessId());
+            return;
+        }
+        // 申请人提交:强制对齐为 waiting;其它事件按流程状态同步(空 status 不覆盖)
+        if (processEvent.getSubmit()) {
+            xgStudentLeave.setApprovalStatus(BusinessStatusEnum.WAITING.getStatus());
+        } else if (StringUtils.isNotBlank(processEvent.getStatus())) {
+            xgStudentLeave.setApprovalStatus(processEvent.getStatus());
+        }
         // 用于例如审批附件 审批意见等 存储到业务表内 自行根据业务实现存储流程
         Map<String, Object> params = processEvent.getParams();
         if (MapUtil.isNotEmpty(params)) {
@@ -461,9 +480,6 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
             // 办理意见
             String message = Convert.toStr(params.get("message"));
         }
-        if (processEvent.getSubmit()) {
-            xgStudentLeave.setApprovalStatus(BusinessStatusEnum.WAITING.getStatus());
-        }
         baseMapper.updateById(xgStudentLeave);
     }
 
@@ -505,19 +521,32 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
     }
 
     /**
-     * 执行任务创建监听
-     * 示例:也可通过 @EventListener(condition =
-     * "#processTaskEvent.flowCode=='leave1'")进行判断
-     * 在方法中判断流程节点key
-     * if ("xxx".equals(processTaskEvent.getNodeCode())) {
-     * //执行业务逻辑
-     * }
+     * 执行任务创建监听(仅 hzdyjs-qj*)
+     * <p>
+     * 补齐缺口:申请人办理后流程已是 waiting,但业务表仍停在 draft 时(submit 标记丢失等),
+     * 在审批任务创建时把 approval_status 对齐为 waiting,避免办理页无「审批」按钮。
      *
      * @param processTaskEvent 参数
      */
+    @Transactional(rollbackFor = Exception.class)
     @EventListener(condition = "#processTaskEvent.flowCode.startsWith('hzdyjs-qj')")
     public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
         log.info("当前任务创建了{}", processTaskEvent.toString());
+        if (StringUtils.isBlank(processTaskEvent.getBusinessId())) {
+            return;
+        }
+        XgStudentLeave leave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessId()));
+        if (ObjectUtil.isNull(leave)) {
+            log.error("请假任务创建事件未找到业务数据, businessId={}", processTaskEvent.getBusinessId());
+            return;
+        }
+        if (BusinessStatusEnum.DRAFT.getStatus().equals(leave.getApprovalStatus())
+            && BusinessStatusEnum.WAITING.getStatus().equals(processTaskEvent.getStatus())) {
+            leave.setApprovalStatus(BusinessStatusEnum.WAITING.getStatus());
+            baseMapper.updateById(leave);
+            log.info("请假业务状态已从 draft 对齐为 waiting, businessId={}, taskId={}, nodeName={}",
+                processTaskEvent.getBusinessId(), processTaskEvent.getTaskId(), processTaskEvent.getNodeName());
+        }
     }
 
     /**

+ 4 - 2
mobile/src/pages/xg/xsjcxx/xsqj/leaveEdit/index.vue

@@ -2999,10 +2999,12 @@ export default {
                 this.form.attachmentOssIds = attachmentOssIds;
                 console.log('提交的附件ossIds:', attachmentOssIds);
 
-                // 保存数据
+                // 保存数据:仅暂存时写入草稿;提交时不强制 draft,避免覆盖流程已同步的 waiting
                 const saveData = { ...this.form };
                 saveData.status = status;
-                saveData.approvalStatus = 'draft';
+                if (status === 'draft') {
+                    saveData.approvalStatus = 'draft';
+                }
 
                 let response;
                 if (saveData.id) {

+ 4 - 2
web/src/views/xg/xsjcxx/xsqj/dialog.vue

@@ -1046,8 +1046,10 @@ const submitForm = (status: string) => {
       // 将附件ID添加到表单数据中,处理成逗号分隔的字符串
       form.attachmentOssIds = attachmentOssIds.join(',');
 
-      // 设置审批状态为草稿
-      form.approvalStatus = 'draft';
+      // 仅暂存时写入草稿;提交时不强制 draft,避免覆盖流程已同步的 waiting
+      if (status === 'draft') {
+        form.approvalStatus = 'draft';
+      }
 
       // 保存业务数据
       try {