|
@@ -3,6 +3,7 @@ package com.qqflow.engine.domain.flow.controller;
|
|
|
import com.qqflow.engine.common.Result;
|
|
import com.qqflow.engine.common.Result;
|
|
|
import com.qqflow.engine.common.service.ExcelParseService;
|
|
import com.qqflow.engine.common.service.ExcelParseService;
|
|
|
import com.qqflow.engine.common.util.SecurityUtils;
|
|
import com.qqflow.engine.common.util.SecurityUtils;
|
|
|
|
|
+import com.qqflow.engine.domain.flow.service.impl.WeComNotificationService;
|
|
|
import com.qqflow.engine.config.security.LoginUser;
|
|
import com.qqflow.engine.config.security.LoginUser;
|
|
|
import com.qqflow.engine.domain.flow.dto.StartProcessDTO;
|
|
import com.qqflow.engine.domain.flow.dto.StartProcessDTO;
|
|
|
import com.qqflow.engine.domain.flow.mapper.ProcessDefinitionMapper;
|
|
import com.qqflow.engine.domain.flow.mapper.ProcessDefinitionMapper;
|
|
@@ -14,6 +15,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.http.MediaType;
|
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
@@ -29,6 +31,7 @@ import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
import java.util.Objects;
|
|
|
|
|
|
|
|
|
|
+@Slf4j
|
|
|
@Tag(name = "流程导入")
|
|
@Tag(name = "流程导入")
|
|
|
@RestController
|
|
@RestController
|
|
|
@RequestMapping("/flow/import")
|
|
@RequestMapping("/flow/import")
|
|
@@ -96,6 +99,7 @@ public class FlowImportController {
|
|
|
String titlePrefix = definition.getProcessName() + "-"
|
|
String titlePrefix = definition.getProcessName() + "-"
|
|
|
+ java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("MMddHHmm"));
|
|
+ java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("MMddHHmm"));
|
|
|
|
|
|
|
|
|
|
+ WeComNotificationService.suppress();
|
|
|
List<Long> instanceIds = new ArrayList<>();
|
|
List<Long> instanceIds = new ArrayList<>();
|
|
|
List<String> failReasons = new ArrayList<>();
|
|
List<String> failReasons = new ArrayList<>();
|
|
|
int successCount = 0;
|
|
int successCount = 0;
|
|
@@ -113,6 +117,8 @@ public class FlowImportController {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
String bizValue = (String) row.get("bizValue");
|
|
String bizValue = (String) row.get("bizValue");
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
|
+ Map<String, String> nodeApproveTimes = (Map<String, String>) row.get("nodeApproveTimes");
|
|
|
|
|
|
|
|
Long effectiveOwnerId = null;
|
|
Long effectiveOwnerId = null;
|
|
|
if (isAdmin) {
|
|
if (isAdmin) {
|
|
@@ -126,15 +132,15 @@ public class FlowImportController {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- if (bizValue != null && !bizValue.isBlank()) {
|
|
|
|
|
|
|
+ if (bizValue != null && !bizValue.isBlank()
|
|
|
|
|
+ && this.processInstanceMapper.existsByInstanceNo(bizValue)) {
|
|
|
ProcessInstance existing = this.processInstanceMapper.selectByInstanceNo(bizValue);
|
|
ProcessInstance existing = this.processInstanceMapper.selectByInstanceNo(bizValue);
|
|
|
- if (existing != null) {
|
|
|
|
|
- this.processInstanceService.updateFormData(
|
|
|
|
|
- existing.getId(), mapper.writeValueAsString(formData), nodeName);
|
|
|
|
|
- instanceIds.add(existing.getId());
|
|
|
|
|
- updateCount++;
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ this.processInstanceService.updateFormData(
|
|
|
|
|
+ existing.getId(), mapper.writeValueAsString(formData), nodeName);
|
|
|
|
|
+ applyNodeApproveTimes(existing.getId(), nodeApproveTimes);
|
|
|
|
|
+ instanceIds.add(existing.getId());
|
|
|
|
|
+ updateCount++;
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
StartProcessDTO dto = new StartProcessDTO();
|
|
StartProcessDTO dto = new StartProcessDTO();
|
|
@@ -152,10 +158,26 @@ public class FlowImportController {
|
|
|
} else {
|
|
} else {
|
|
|
instanceId = this.processInstanceService.startProcess(dto);
|
|
instanceId = this.processInstanceService.startProcess(dto);
|
|
|
}
|
|
}
|
|
|
|
|
+ applyNodeApproveTimes(instanceId, nodeApproveTimes);
|
|
|
instanceIds.add(instanceId);
|
|
instanceIds.add(instanceId);
|
|
|
successCount++;
|
|
successCount++;
|
|
|
|
|
+ } catch (org.springframework.dao.DuplicateKeyException e) {
|
|
|
|
|
+ // 并发/隔离级别导致预检未命中,降级为更新
|
|
|
|
|
+ if (bizValue != null && !bizValue.isBlank()) {
|
|
|
|
|
+ ProcessInstance existing = this.processInstanceMapper.selectByInstanceNo(bizValue);
|
|
|
|
|
+ if (existing != null) {
|
|
|
|
|
+ this.processInstanceService.updateFormData(
|
|
|
|
|
+ existing.getId(), mapper.writeValueAsString(formData), nodeName);
|
|
|
|
|
+ applyNodeApproveTimes(existing.getId(), nodeApproveTimes);
|
|
|
|
|
+ instanceIds.add(existing.getId());
|
|
|
|
|
+ updateCount++;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ failReasons.add("第" + rowNo + "行:实例编号重复");
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
String msg = e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName();
|
|
String msg = e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName();
|
|
|
|
|
+ log.error("[导入] 第{}行失败: {}", rowNo, msg);
|
|
|
failReasons.add("第" + rowNo + "行:" + msg);
|
|
failReasons.add("第" + rowNo + "行:" + msg);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -172,6 +194,15 @@ public class FlowImportController {
|
|
|
return Result.error("字段映射格式错误");
|
|
return Result.error("字段映射格式错误");
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
return Result.error("导入失败: " + e.getMessage());
|
|
return Result.error("导入失败: " + e.getMessage());
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ WeComNotificationService.unsuppress();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void applyNodeApproveTimes(Long instanceId, Map<String, String> nodeApproveTimes) {
|
|
|
|
|
+ if (nodeApproveTimes == null || nodeApproveTimes.isEmpty()) return;
|
|
|
|
|
+ for (Map.Entry<String, String> entry : nodeApproveTimes.entrySet()) {
|
|
|
|
|
+ this.processInstanceService.recordApprovalTime(instanceId, entry.getKey(), entry.getValue());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|