feat(workflow): 完善作业流程管理功能

master
zhaokai 2026-04-27 08:34:31 +08:00
parent 486cc0d0dc
commit 6e726ac4b3
7 changed files with 138 additions and 19 deletions

View File

@ -49,12 +49,12 @@ public class TaskFlowController {
@ApiOperation("作业初始化") @ApiOperation("作业初始化")
@PostMapping("/getWorkInit") @PostMapping("/getWorkInit")
public SingleResponse<TaskWorkInitCO> getWorkInit(@RequestBody TaskWorkQryCmd qry) { public SingleResponse<TaskWorkInitCO> getWorkInit(@Validated @RequestBody TaskWorkQryCmd qry) {
return SingleResponse.of(taskFlowService.getWorkInit(qry)); return SingleResponse.of(taskFlowService.getWorkInit(qry));
} }
@ApiOperation("作业初始化流程") @ApiOperation("作业初始化流程")
@PostMapping("/getFlowInit") @PostMapping("/getFlowInit")
public SingleResponse<TaskFlowInitCO> getFlowInit(@RequestBody TaskFlowQryCmd qry) { public SingleResponse<TaskFlowInitCO> getFlowInit(@Validated @RequestBody TaskFlowQryCmd qry) {
return SingleResponse.of(taskFlowService.getFlowInit(qry)); return SingleResponse.of(taskFlowService.getFlowInit(qry));
} }

View File

@ -181,6 +181,9 @@ public class EightworkInfoSaveDraftExe {
*/ */
private TaskLogDO createApplyTaskLog(String workId, EightworkInfoSaveDraftCmd cmd) { private TaskLogDO createApplyTaskLog(String workId, EightworkInfoSaveDraftCmd cmd) {
// 获取流程配置 // 获取流程配置
if(StringUtils.isNotEmpty(cmd.getWorkLevel())){
}
List<TaskFlowE> flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel()); List<TaskFlowE> flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel());
TaskFlowE applyFlow = flows.stream() TaskFlowE applyFlow = flows.stream()
.filter(f -> FIRST_STEP_ID.equals(f.getStepId())) .filter(f -> FIRST_STEP_ID.equals(f.getStepId()))

View File

@ -23,10 +23,7 @@ import com.zcloud.eightwork.domain.model.EightworkSupplementaryInfoE;
import com.zcloud.eightwork.domain.model.MeasuresLogsE; import com.zcloud.eightwork.domain.model.MeasuresLogsE;
import com.zcloud.eightwork.domain.model.TaskFlowE; import com.zcloud.eightwork.domain.model.TaskFlowE;
import com.zcloud.eightwork.domain.model.TaskLogE; import com.zcloud.eightwork.domain.model.TaskLogE;
import com.zcloud.eightwork.domain.model.enums.BranchFlag; import com.zcloud.eightwork.domain.model.enums.*;
import com.zcloud.eightwork.domain.model.enums.StepType;
import com.zcloud.eightwork.domain.model.enums.TaskLogStatus;
import com.zcloud.eightwork.domain.model.enums.WorkCodeEnum;
import com.zcloud.eightwork.dto.TaskLogNextCmd; import com.zcloud.eightwork.dto.TaskLogNextCmd;
import com.zcloud.eightwork.dto.TaskLogUpdateCmd; import com.zcloud.eightwork.dto.TaskLogUpdateCmd;
import com.zcloud.eightwork.dto.TaskSignStepInfoCmd; import com.zcloud.eightwork.dto.TaskSignStepInfoCmd;
@ -283,7 +280,7 @@ public class TaskLogUpdateExe {
// 签字步骤,保存签字图片 // 签字步骤,保存签字图片
if (SIGN_STEP_FLAG.equals(currentLog.getSignStepFlag())) { if (SIGN_STEP_FLAG.equals(currentLog.getSignStepFlag())) {
currentLog.setSignPath(cmd.getSignPath()); currentLog.setSignPath(cmd.getSignPath());
currentLog.setSignTime(LocalDateTime.now()); currentLog.setSignTime(cmd.getSignTime());
} }
// 定位步骤,保存经纬度 // 定位步骤,保存经纬度
@ -427,7 +424,7 @@ public class TaskLogUpdateExe {
return d; return d;
}).collect(Collectors.toList())); }).collect(Collectors.toList()));
} else { } else {
measuresLogsRepository.deleteByWorkId(currentLog.getWorkId()); measuresLogsRepository.deleteByWorkId(currentLog.getWorkId(), MeasuresLogType.PRIMARY.getCode());
measuresLogsRepository.saveBatch(measuresList.stream().map(item -> { measuresLogsRepository.saveBatch(measuresList.stream().map(item -> {
MeasuresLogsDO d = new MeasuresLogsDO(); MeasuresLogsDO d = new MeasuresLogsDO();
BeanUtils.copyProperties(item, d, "id"); BeanUtils.copyProperties(item, d, "id");
@ -1000,6 +997,8 @@ public class TaskLogUpdateExe {
} }
private void handleRejectStep(TaskLogNextCmd cmd) { private void handleRejectStep(TaskLogNextCmd cmd) {
log.info("请求参数:{}",JSONUtil.toJsonStr( cmd));
log.info("开始处理打回到某一步: workId={}, stepId={}", cmd.getWorkId(), cmd.getStepId()); log.info("开始处理打回到某一步: workId={}, stepId={}", cmd.getWorkId(), cmd.getStepId());
@ -1010,8 +1009,6 @@ public class TaskLogUpdateExe {
} }
Integer rejectStepId = currentLog.getRejectStepId(); Integer rejectStepId = currentLog.getRejectStepId();
if(rejectStepId==null){ if(rejectStepId==null){
log.warn("未找到对应的步骤记录.workId={}, stepId={}", cmd.getWorkId(), cmd.getStepId()); log.warn("未找到对应的步骤记录.workId={}, stepId={}", cmd.getWorkId(), cmd.getStepId());
@ -1025,6 +1022,8 @@ public class TaskLogUpdateExe {
log.warn("未找到作业信息: workId={}", cmd.getWorkId()); log.warn("未找到作业信息: workId={}", cmd.getWorkId());
return; return;
} }
// 从 others.otherParams.hotTime 中提取并更新作业结束时间
updateWorkEndTimeFromOtherParams(infoDO, cmd, cmd.getWorkId(),currentLog);
// 1. 归档当前的 task_log 记录(除了申请步骤) // 1. 归档当前的 task_log 记录(除了申请步骤)
archiveTaskLogs(allLogs); archiveTaskLogs(allLogs);
@ -1046,7 +1045,7 @@ public class TaskLogUpdateExe {
// 3. 设置所有步骤的id // 3. 设置所有步骤的id
for (TaskLogDO taskLog : taskLogs) { for (TaskLogDO taskLog : taskLogs) {
taskLog.setId(null); taskLog.setId(null);
taskLog.setTaskLogId(Tools.get32UUID()); // taskLog.setTaskLogId(Tools.get32UUID());
taskLog.setUpdateTime(LocalDateTime.now()); taskLog.setUpdateTime(LocalDateTime.now());
taskLog.setUpdateId(null); taskLog.setUpdateId(null);
taskLog.setUpdateName( null); taskLog.setUpdateName( null);
@ -1058,13 +1057,13 @@ public class TaskLogUpdateExe {
taskLogRepository.saveBatch(taskLogs); taskLogRepository.saveBatch(taskLogs);
// 批量更新 eightworkInfo.info只更新本次变化的步骤 // 批量更新 eightworkInfo.info只更新本次变化的步骤
updateEightworkInfo(cmd.getWorkId(), taskLogs); // updateEightworkInfo(cmd.getWorkId(), taskLogs);
// 6. 发送待办完成事件 // 6. 发送待办完成事件
sendTodoCompleteEvent(currentLog.getId()); sendTodoCompleteEvent(currentLog.getId());
TaskLogE branchStep = new TaskLogE(); TaskLogE branchStep = new TaskLogE();
branchStep.setActUser(currentLog.getActUser()); branchStep.setActUser(currentLog.getActUser());
branchStep.setStatus(TaskLogStatus.REJECTED.getCode()); branchStep.setStatus(TaskLogStatus.IN_PROGRESS.getCode());
branchStep.setStepName(currentLog.getStepName()); branchStep.setStepName(currentLog.getStepName());
messageNotice(branchStep, currentLog); messageNotice(branchStep, currentLog);
log.info("工作流已打回到指定步骤: workId={},step={}", cmd.getWorkId(),rejectStepId); log.info("工作流已打回到指定步骤: workId={},step={}", cmd.getWorkId(),rejectStepId);
@ -1090,7 +1089,68 @@ public class TaskLogUpdateExe {
log.info("工作流已打回到指定步骤: workId={}, step={}", cmd.getWorkId(), rejectStepId); log.info("工作流已打回到指定步骤: workId={}, step={}", cmd.getWorkId(), rejectStepId);
} }
/**
* otherParams hotTime infoDO workEndTime
*
* @param infoDO
* @param cmd
* @param workId ID
*/
private void updateWorkEndTimeFromOtherParams(EightworkInfoDO infoDO, TaskLogNextCmd cmd, String workId,TaskLogE currentLog) {
JSONObject others = cmd.getOthers();
if (others == null || !others.containsKey("otherParams")) {
return;
}
String otherParamsStr = others.getString("otherParams");
if (StringUtils.isBlank(otherParamsStr)) {
return;
}
try {
// 解析 otherParams JSON 字符串
JSONObject otherParamsJson = JSONObject.parseObject(otherParamsStr);
String hotTime = otherParamsJson.getString("hotTime");
if (StringUtils.isBlank(hotTime)) {
return;
}
// 解析现有的 info JSON
JSONObject infoJson;
if (StringUtils.isNotBlank(infoDO.getInfo())) {
try {
infoJson = JSONObject.parseObject(infoDO.getInfo());
} catch (Exception e) {
log.warn("解析 info 失败,使用空对象: workId={}", workId, e);
infoJson = new JSONObject();
}
} else {
infoJson = new JSONObject();
}
//更新当前步骤的签字时间个日期
Object o = infoJson.get("step_" + currentLog.getStepId());
log.info("更新签名和路径的step={}",currentLog.getStepId());
if (o instanceof JSONObject) {
JSONObject stepInfo = (JSONObject) o;
LocalDateTime signTime = cmd.getSignTime() != null ? cmd.getSignTime() : LocalDateTime.now();
String formattedSignTime = DateUtil.format(DateUtil.date(signTime), DatePattern.NORM_DATETIME_PATTERN);
stepInfo.put("signTime", formattedSignTime);
stepInfo.put("signPath", cmd.getSignPath());
infoJson.put("step_" + currentLog.getStepId(), stepInfo);
}
// 设置 workEndTime 字段
infoJson.put("workEndTime", hotTime);
infoDO.setInfo(infoJson.toJSONString());
eightworkInfoRepository.updateById(infoDO);
log.info("更新作业结束时间: workId={}, hotTime={}", workId, hotTime);
} catch (Exception e) {
log.error("解析 otherParams 失败: workId={}, otherParams={}", workId, otherParamsStr, e);
}
}
/** /**
* ID * ID
@ -1844,7 +1904,7 @@ public class TaskLogUpdateExe {
// 签字路径:只覆盖空值 // 签字路径:只覆盖空值
if (source.getSignPath() != null) { if (source.getSignPath() != null) {
target.setSignPath(source.getSignPath()); target.setSignPath(source.getSignPath());
target.setSignTime(LocalDateTime.now()); target.setSignTime(source.getSignTime());
} }
// 填写次数:只覆盖空值 // 填写次数:只覆盖空值
if (source.getCurrentFillTimes() != null) { if (source.getCurrentFillTimes() != null) {
@ -1979,6 +2039,7 @@ public class TaskLogUpdateExe {
}*/ }*/
private void updateEightworkInfo(String workId, List<TaskLogDO> actionLogs) { private void updateEightworkInfo(String workId, List<TaskLogDO> actionLogs) {
if (actionLogs == null || actionLogs.isEmpty()) { if (actionLogs == null || actionLogs.isEmpty()) {
log.warn("未找到作业信息: workId={}", workId);
return; return;
} }
@ -2004,7 +2065,7 @@ public class TaskLogUpdateExe {
} else { } else {
infoJson = new JSONObject(); infoJson = new JSONObject();
} }
log.info("已解析 wordId={},info: {}",workId, infoJson);
// 循环更新本次变化的步骤 // 循环更新本次变化的步骤
for (TaskLogDO logDO : actionLogs) { for (TaskLogDO logDO : actionLogs) {
String baseKey = "step_" + logDO.getStepId(); String baseKey = "step_" + logDO.getStepId();
@ -2012,22 +2073,25 @@ public class TaskLogUpdateExe {
// 判断是否为多人签字步骤 // 判断是否为多人签字步骤
if (logDO.getMultipleFlag() != null && logDO.getMultipleFlag() == 1) { if (logDO.getMultipleFlag() != null && logDO.getMultipleFlag() == 1) {
// 多人签字步骤:根据 actUser 查找并更新,或追加新记录 // 多人签字步骤:根据 actUser 查找并更新,或追加新记录
log.info("更新多人签字步骤wordId={}: {}", workId,baseKey);
updateOrAppendMultipleSignStepByUser(infoJson, baseKey, logDO); updateOrAppendMultipleSignStepByUser(infoJson, baseKey, logDO);
} else { } else {
// 普通步骤:直接替换 // 普通步骤:直接替换
JSONObject stepInfo = buildStepInfo(logDO); JSONObject stepInfo = buildStepInfo(logDO);
infoJson.put(baseKey, stepInfo); infoJson.put(baseKey, stepInfo);
log.info("更新普通步骤: {}", baseKey); log.info("更新普通步骤wordId={}: {}", workId,baseKey);
} }
} }
// 更新到数据库 // 更新到数据库
infoDO.setInfo(infoJson.toJSONString()); infoDO.setInfo(infoJson.toJSONString());
log.info("已更新 info: workId={},info={}", workId,infoJson.toJSONString());
eightworkInfoRepository.updateById(infoDO); eightworkInfoRepository.updateById(infoDO);
log.info("已批量更新步骤 info: workId={}, count={}", workId, actionLogs.size()); log.info("已批量更新步骤 info: workId={}, count={}", workId, actionLogs.size());
} }
/** /**
* actUser * actUser
* *
@ -2116,7 +2180,12 @@ public class TaskLogUpdateExe {
stepInfo.put("actUser", logDO.getActUser()); stepInfo.put("actUser", logDO.getActUser());
stepInfo.put("actUserName", logDO.getActUserName()); stepInfo.put("actUserName", logDO.getActUserName());
stepInfo.put("signPath", logDO.getSignPath()); stepInfo.put("signPath", logDO.getSignPath());
stepInfo.put("signTime", DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN)); if(logDO.getSignTime() != null){
LocalDateTime signTime = logDO.getSignTime();
String formattedSignTime = DateUtil.format(DateUtil.date(signTime), DatePattern.NORM_DATETIME_PATTERN);
stepInfo.put("signTime", formattedSignTime);
}
stepInfo.put("status", logDO.getStatus()); stepInfo.put("status", logDO.getStatus());
// 定位步骤,添加经纬度信息 // 定位步骤,添加经纬度信息

View File

@ -2,6 +2,7 @@ package com.zcloud.eightwork.dto;
import com.alibaba.cola.dto.Command; import com.alibaba.cola.dto.Command;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@ -9,6 +10,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import javax.validation.constraints.*; import javax.validation.constraints.*;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
/** /**
@ -55,6 +57,8 @@ public class TaskLogNextCmd extends Command {
private String filePath; private String filePath;
@ApiModelProperty(value = "备注") @ApiModelProperty(value = "备注")
private String remarks; private String remarks;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime signTime = LocalDateTime.now();
public TaskLogNextCmd(Long id, String workId, Long stepId, Integer status, JSONObject others) { public TaskLogNextCmd(Long id, String workId, Long stepId, Integer status, JSONObject others) {
this.id = id; this.id = id;

View File

@ -0,0 +1,42 @@
package com.zcloud.eightwork.domain.model.enums;
import lombok.Getter;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
*
* 12
*/
@Getter
public enum MeasuresLogType {
PRIMARY(1, "主要"),
OTHER(2, "其他");
private final Integer code;
private final String desc;
private static final Map<Integer, MeasuresLogType> CODE_MAP =
Arrays.stream(values())
.collect(Collectors.toMap(MeasuresLogType::getCode, Function.identity()));
MeasuresLogType(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
/**
*
*/
public static MeasuresLogType getByCode(Integer code) {
if (code == null) {
return null;
}
return CODE_MAP.get(code);
}
}

View File

@ -25,6 +25,6 @@ public interface MeasuresLogsRepository extends BaseRepository<MeasuresLogsDO> {
*/ */
int physicalDeleteByWorkId(String workId); int physicalDeleteByWorkId(String workId);
void deleteByWorkId(String workId); void deleteByWorkId(String workId, Integer code);
} }

View File

@ -56,7 +56,7 @@ public class MeasuresLogsRepositoryImpl extends BaseRepositoryImpl<MeasuresLogsM
} }
@Override @Override
public void deleteByWorkId(String workId) { public void deleteByWorkId(String workId, Integer type) {
if (workId == null || workId.isEmpty()) { if (workId == null || workId.isEmpty()) {
log.warn("workId 为空,跳过删除操作"); log.warn("workId 为空,跳过删除操作");
return; return;
@ -64,6 +64,7 @@ public class MeasuresLogsRepositoryImpl extends BaseRepositoryImpl<MeasuresLogsM
LambdaQueryWrapper<MeasuresLogsDO> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<MeasuresLogsDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MeasuresLogsDO::getWorkId, workId); queryWrapper.eq(MeasuresLogsDO::getWorkId, workId);
queryWrapper.eq(MeasuresLogsDO::getType, type);
int deletedCount = measuresLogsMapper.delete(queryWrapper); int deletedCount = measuresLogsMapper.delete(queryWrapper);
log.info("逻辑删除安全措施记录: workId={}, 删除数量={}", workId, deletedCount); log.info("逻辑删除安全措施记录: workId={}, 删除数量={}", workId, deletedCount);