|
|
@@ -46,6 +46,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import java.io.File;
|
|
|
+import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.ArrayList;
|
|
|
@@ -685,4 +686,89 @@ public class ProcessInstanceServiceImpl implements ProcessInstanceService {
|
|
|
.eq(SysUserRole::getUserId, userId)
|
|
|
.eq(SysUserRole::getRoleId, roleId));
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW)
|
|
|
+ public void recordApprovalTime(Long instanceId, String nodeName, String approveTimeStr) {
|
|
|
+ if (approveTimeStr == null || approveTimeStr.isBlank()) return;
|
|
|
+ ProcessInstance instance = this.processInstanceMapper.selectById(instanceId);
|
|
|
+ if (instance == null) return;
|
|
|
+ ProcessDefinition definition = this.processDefinitionMapper.selectById(instance.getProcessDefinitionId());
|
|
|
+ if (definition == null) return;
|
|
|
+ FlowModel model = this.flowEngineService.parseModel(definition.getModelJson());
|
|
|
+ FlowNode targetNode = model.getNodes().stream()
|
|
|
+ .filter(n -> nodeName.equals(n.getName()))
|
|
|
+ .findFirst().orElse(null);
|
|
|
+ if (targetNode == null) return;
|
|
|
+
|
|
|
+ LocalDateTime approveTime = parseTime(approveTimeStr);
|
|
|
+ if (approveTime == null) return;
|
|
|
+
|
|
|
+ // 优先取当前节点的任务负责人作为操作人
|
|
|
+ List<ApprovalTask> tasks = this.approvalTaskMapper.selectByInstanceId(instanceId).stream()
|
|
|
+ .filter(t -> t.getNodeId().equals(targetNode.getId()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ Long operatorId = tasks.isEmpty() ? instance.getApplicantId() : tasks.get(0).getAssigneeId();
|
|
|
+ String operatorName = null;
|
|
|
+ if (operatorId != null) {
|
|
|
+ SysUser operator = this.sysUserMapper.selectById(operatorId);
|
|
|
+ if (operator != null) operatorName = operator.getRealName();
|
|
|
+ }
|
|
|
+
|
|
|
+ List<ApprovalRecord> existingRecords = this.approvalRecordMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ApprovalRecord>()
|
|
|
+ .eq(ApprovalRecord::getInstanceId, instanceId)
|
|
|
+ .eq(ApprovalRecord::getNodeId, targetNode.getId()));
|
|
|
+ if (!existingRecords.isEmpty()) {
|
|
|
+ for (ApprovalRecord r : existingRecords) {
|
|
|
+ r.setCreateTime(approveTime);
|
|
|
+ this.approvalRecordMapper.updateById(r);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Long taskId = tasks.isEmpty() ? null : tasks.get(0).getId();
|
|
|
+
|
|
|
+ ApprovalRecord record = new ApprovalRecord();
|
|
|
+ record.setTaskId(taskId);
|
|
|
+ record.setInstanceId(instanceId);
|
|
|
+ record.setNodeId(targetNode.getId());
|
|
|
+ record.setNodeName(targetNode.getName());
|
|
|
+ record.setOperatorId(operatorId);
|
|
|
+ record.setOperatorName(operatorName);
|
|
|
+ record.setActionType(com.qqflow.engine.domain.flow.enums.ApprovalAction.APPROVE.getCode());
|
|
|
+ record.setActionResult(com.qqflow.engine.domain.flow.enums.ApprovalResult.PASS.getCode());
|
|
|
+ record.setCreateTime(approveTime);
|
|
|
+ this.approvalRecordMapper.insert(record);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final java.time.format.DateTimeFormatter[] TIME_FORMATS = {
|
|
|
+ // java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
|
|
|
+ // java.time.format.DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"),
|
|
|
+ // java.time.format.DateTimeFormatter.ofPattern("yyyy-M-d HH:mm:ss"),
|
|
|
+ // java.time.format.DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss"),
|
|
|
+ java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"),
|
|
|
+ java.time.format.DateTimeFormatter.ofPattern("yyyy/MM/dd"),
|
|
|
+ java.time.format.DateTimeFormatter.ofPattern("yyyy/M/d"),
|
|
|
+ java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME,
|
|
|
+ };
|
|
|
+
|
|
|
+ private LocalDateTime parseTime(String s) {
|
|
|
+ if (s == null || s.isBlank()) return null;
|
|
|
+ // 尝试 Excel 数值日期(如 46207.0)
|
|
|
+ try {
|
|
|
+ double days = Double.parseDouble(s);
|
|
|
+ if (days > 1 && days < 100000) {
|
|
|
+ return LocalDateTime.of(1899, 12, 30, 0, 0, 0).plusDays((long) days);
|
|
|
+ }
|
|
|
+ } catch (NumberFormatException ignored) {}
|
|
|
+ for (var fmt : TIME_FORMATS) {
|
|
|
+ try {
|
|
|
+ if (fmt.toString().contains("HH")) {
|
|
|
+ return LocalDateTime.parse(s, fmt);
|
|
|
+ }
|
|
|
+ return LocalDate.parse(s, fmt).atStartOfDay();
|
|
|
+ } catch (Exception ignored) {}
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
}
|