feat(workflow): 添加工作流程图功能并优化暂存和打回流程
- 新增 TaskFlowChartCO 客户端对象用于流程图数据传输
- 添加 /flowChart/{workId} 接口获取工作流程图
- 实现 TaskFlowChartQueryExe 查询执行器构建流程图
- 优化 EightworkInfoSaveDraftExe 暂存执行器支持预设签字人信息
- 改进 TaskLogAddExe 处理暂存和打回状态转换逻辑
- 增强 TaskLogUpdateExe 支持工作流打回功能和归档机制
- 添加打回历史记录处理和步骤归档功能
- 优化签字步骤激活逻辑和状态管理
master
parent
2694888ef4
commit
bf965d00e2
|
|
@ -9,6 +9,7 @@ import com.zcloud.eightwork.dto.TaskLogPageQry;
|
||||||
import com.zcloud.eightwork.dto.TaskLogUpdateCmd;
|
import com.zcloud.eightwork.dto.TaskLogUpdateCmd;
|
||||||
import com.zcloud.eightwork.dto.clientobject.EightworkInfoCO;
|
import com.zcloud.eightwork.dto.clientobject.EightworkInfoCO;
|
||||||
import com.zcloud.eightwork.dto.clientobject.TaskLogCO;
|
import com.zcloud.eightwork.dto.clientobject.TaskLogCO;
|
||||||
|
import com.zcloud.eightwork.dto.clientobject.TaskFlowChartCO;
|
||||||
import com.alibaba.cola.dto.MultiResponse;
|
import com.alibaba.cola.dto.MultiResponse;
|
||||||
import com.alibaba.cola.dto.PageResponse;
|
import com.alibaba.cola.dto.PageResponse;
|
||||||
import com.alibaba.cola.dto.Response;
|
import com.alibaba.cola.dto.Response;
|
||||||
|
|
@ -113,5 +114,11 @@ public class TaskLogController {
|
||||||
cmd.setDepartmentId(AuthContext.getOrgId());
|
cmd.setDepartmentId(AuthContext.getOrgId());
|
||||||
return taskLogService.saveDraft(cmd);
|
return taskLogService.saveDraft(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation("获取工作流程图")
|
||||||
|
@GetMapping("/flowChart/{workId}")
|
||||||
|
public MultiResponse<TaskFlowChartCO> getFlowChart(@PathVariable("workId") String workId) {
|
||||||
|
return MultiResponse.of(taskLogService.getFlowChart(workId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,255 @@
|
||||||
|
package com.zcloud.eightwork.command;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DatePattern;
|
||||||
|
import com.alibaba.cola.exception.BizException;
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.jjb.saas.framework.auth.utils.AuthContext;
|
||||||
|
import com.zcloud.eightwork.domain.gateway.TaskFlowGateway;
|
||||||
|
import com.zcloud.eightwork.domain.model.TaskFlowE;
|
||||||
|
import com.zcloud.eightwork.domain.model.enums.TaskLogStatus;
|
||||||
|
import com.zcloud.eightwork.domain.model.enums.WorkCodeEnum;
|
||||||
|
import com.zcloud.eightwork.dto.EightworkInfoSaveDraftCmd;
|
||||||
|
import com.zcloud.eightwork.dto.TaskSignStepInfoCmd;
|
||||||
|
import com.zcloud.eightwork.persistence.dataobject.EightworkInfoDO;
|
||||||
|
import com.zcloud.eightwork.persistence.dataobject.TaskLogDO;
|
||||||
|
import com.zcloud.eightwork.persistence.repository.EightworkInfoRepository;
|
||||||
|
import com.zcloud.eightwork.persistence.repository.TaskLogRepository;
|
||||||
|
import com.zcloud.gbscommon.utils.Tools;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 八险作业暂存执行器
|
||||||
|
* 负责保存/更新作业草稿
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class EightworkInfoSaveDraftExe {
|
||||||
|
/** 第一步(申请步骤)的步骤ID */
|
||||||
|
private static final Long FIRST_STEP_ID = 1L;
|
||||||
|
/** 暂存状态 */
|
||||||
|
private static final Integer DRAFT_STATUS = 0;
|
||||||
|
/** 进行中状态 */
|
||||||
|
private static final Integer IN_PROGRESS_STATUS = 1;
|
||||||
|
|
||||||
|
private final TaskFlowGateway taskFlowGateway;
|
||||||
|
private final EightworkInfoRepository eightworkInfoRepository;
|
||||||
|
private final TaskLogRepository taskLogRepository;
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void execute(EightworkInfoSaveDraftCmd cmd) {
|
||||||
|
log.info("开始暂存作业: id={}, workType={}, workLevel={}",
|
||||||
|
cmd.getId(), cmd.getWorkType(), cmd.getWorkLevel());
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (cmd.getId() != null) {
|
||||||
|
// 更新现有暂存
|
||||||
|
updateDraft(cmd);
|
||||||
|
} else {
|
||||||
|
// 创建新暂存
|
||||||
|
createDraft(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("作业暂存成功: workType={}", cmd.getWorkType());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("暂存作业失败: workType={}", cmd.getWorkType(), e);
|
||||||
|
throw new BizException("暂存失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新现有暂存
|
||||||
|
*/
|
||||||
|
private void updateDraft(EightworkInfoSaveDraftCmd cmd) {
|
||||||
|
log.info("更新现有暂存: id={}", cmd.getId());
|
||||||
|
|
||||||
|
// 1. 查询现有记录
|
||||||
|
EightworkInfoDO existingInfo = eightworkInfoRepository.getById(cmd.getId());
|
||||||
|
if (existingInfo == null) {
|
||||||
|
throw new BizException("暂存记录不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 检查状态,只能修改暂存状态的记录
|
||||||
|
if (!DRAFT_STATUS.equals(existingInfo.getStatus())) {
|
||||||
|
throw new BizException("只能修改暂存状态的记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 更新主表信息
|
||||||
|
updateMainInfo(existingInfo, cmd);
|
||||||
|
eightworkInfoRepository.updateById(existingInfo);
|
||||||
|
|
||||||
|
// 4. 删除旧的 task_log 记录
|
||||||
|
taskLogRepository.remove(new LambdaQueryWrapper<TaskLogDO>()
|
||||||
|
.eq(TaskLogDO::getWorkId, existingInfo.getWorkId()));
|
||||||
|
|
||||||
|
// 5. 创建申请步骤 task_log
|
||||||
|
TaskLogDO taskLog = createApplyTaskLog(existingInfo.getWorkId(), cmd);
|
||||||
|
taskLogRepository.save(taskLog);
|
||||||
|
|
||||||
|
// 6. 更新主表 info 中的预设签字人信息
|
||||||
|
updateInfoWithSigners(existingInfo.getWorkId(), cmd.getSignLogs());
|
||||||
|
|
||||||
|
log.info("暂存更新成功: workId={}", existingInfo.getWorkId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新暂存
|
||||||
|
*/
|
||||||
|
private void createDraft(EightworkInfoSaveDraftCmd cmd) {
|
||||||
|
log.info("创建新暂存: workType={}", cmd.getWorkType());
|
||||||
|
|
||||||
|
// 1. 创建主表记录(暂存不生成票号)
|
||||||
|
EightworkInfoDO eightworkInfo = new EightworkInfoDO();
|
||||||
|
eightworkInfo.setWorkId(Tools.get32UUID());
|
||||||
|
eightworkInfo.setWorkType(cmd.getWorkType());
|
||||||
|
eightworkInfo.setWorkLevel(cmd.getWorkLevel());
|
||||||
|
eightworkInfo.setCorpinfoId(cmd.getCorpinfoId());
|
||||||
|
eightworkInfo.setXgfFlag(cmd.getXgfFlag());
|
||||||
|
eightworkInfo.setInternalOperationFlag(cmd.getInternalOperationFlag());
|
||||||
|
eightworkInfo.setProjectId(cmd.getProjectId());
|
||||||
|
eightworkInfo.setXgfId(cmd.getXgfId());
|
||||||
|
eightworkInfo.setGasFlag(cmd.getGasFlag());
|
||||||
|
eightworkInfo.setCheckNo(null); // 暂存不生成票号
|
||||||
|
eightworkInfo.setStatus(DRAFT_STATUS);
|
||||||
|
eightworkInfo.setInfo(cmd.getInfo());
|
||||||
|
eightworkInfo.setDepartmentId(cmd.getDepartmentId());
|
||||||
|
|
||||||
|
eightworkInfoRepository.save(eightworkInfo);
|
||||||
|
log.info("主表创建成功: workId={}", eightworkInfo.getWorkId());
|
||||||
|
|
||||||
|
// 2. 创建申请步骤 task_log
|
||||||
|
TaskLogDO taskLog = createApplyTaskLog(eightworkInfo.getWorkId(), cmd);
|
||||||
|
taskLogRepository.save(taskLog);
|
||||||
|
|
||||||
|
// 3. 更新主表 info 中的预设签字人信息
|
||||||
|
updateInfoWithSigners(eightworkInfo.getWorkId(), cmd.getSignLogs());
|
||||||
|
|
||||||
|
log.info("暂存创建成功: workId={}", eightworkInfo.getWorkId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建申请步骤 task_log
|
||||||
|
*/
|
||||||
|
private TaskLogDO createApplyTaskLog(String workId, EightworkInfoSaveDraftCmd cmd) {
|
||||||
|
// 获取流程配置
|
||||||
|
List<TaskFlowE> flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel());
|
||||||
|
TaskFlowE applyFlow = flows.stream()
|
||||||
|
.filter(f -> FIRST_STEP_ID.equals(f.getStepId()))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new BizException("未找到申请步骤配置"));
|
||||||
|
|
||||||
|
TaskLogDO taskLog = new TaskLogDO(Tools.get32UUID());
|
||||||
|
BeanUtils.copyProperties(applyFlow, taskLog, "id");
|
||||||
|
taskLog.setWorkId(workId);
|
||||||
|
taskLog.setWorkType(cmd.getWorkType());
|
||||||
|
taskLog.setCorpinfoId(cmd.getCorpinfoId());
|
||||||
|
taskLog.setCheckNo(""); // 暂存时票号为空,正式提交时生成
|
||||||
|
|
||||||
|
// 设置申请人为当前用户
|
||||||
|
taskLog.setSign(
|
||||||
|
applyFlow.getActorField(),
|
||||||
|
AuthContext.getOrgId(),
|
||||||
|
AuthContext.getCurrentUser().getOrgName(),
|
||||||
|
AuthContext.getUserId(),
|
||||||
|
AuthContext.getName()
|
||||||
|
);
|
||||||
|
|
||||||
|
// 暂存时申请步骤状态为进行中
|
||||||
|
taskLog.setStatus(IN_PROGRESS_STATUS);
|
||||||
|
|
||||||
|
log.info("申请步骤 task_log 创建成功: stepName={}", applyFlow.getStepName());
|
||||||
|
return taskLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新主表信息
|
||||||
|
*/
|
||||||
|
private void updateMainInfo(EightworkInfoDO existingInfo, EightworkInfoSaveDraftCmd cmd) {
|
||||||
|
existingInfo.setWorkType(cmd.getWorkType());
|
||||||
|
existingInfo.setWorkLevel(cmd.getWorkLevel());
|
||||||
|
existingInfo.setCorpinfoId(cmd.getCorpinfoId());
|
||||||
|
existingInfo.setXgfFlag(cmd.getXgfFlag());
|
||||||
|
existingInfo.setInternalOperationFlag(cmd.getInternalOperationFlag());
|
||||||
|
existingInfo.setProjectId(cmd.getProjectId());
|
||||||
|
existingInfo.setXgfId(cmd.getXgfId());
|
||||||
|
existingInfo.setGasFlag(cmd.getGasFlag());
|
||||||
|
existingInfo.setInfo(cmd.getInfo());
|
||||||
|
existingInfo.setDepartmentId(cmd.getDepartmentId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新主表 info 中的预设签字人信息
|
||||||
|
*/
|
||||||
|
private void updateInfoWithSigners(String workId, List<TaskSignStepInfoCmd> signLogs) {
|
||||||
|
if (signLogs == null || signLogs.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EightworkInfoDO infoDO = eightworkInfoRepository.getOne(
|
||||||
|
new LambdaQueryWrapper<EightworkInfoDO>()
|
||||||
|
.eq(EightworkInfoDO::getWorkId, workId)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (infoDO == null) {
|
||||||
|
log.warn("未找到作业信息: workId={}", workId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析现有 info
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加预设签字人信息到 info(格式同 updateEightworkInfo)
|
||||||
|
for (TaskSignStepInfoCmd signInfo : signLogs) {
|
||||||
|
JSONObject stepInfo = new JSONObject();
|
||||||
|
stepInfo.put("stepName", getStepNameBySignInfo(signInfo));
|
||||||
|
stepInfo.put("actUserDepartment", signInfo.getActUserDepartment());
|
||||||
|
stepInfo.put("actUserDepartmentName", signInfo.getActUserDepartmentName());
|
||||||
|
stepInfo.put("actUser", signInfo.getActUser());
|
||||||
|
stepInfo.put("actUserName", signInfo.getActUserName());
|
||||||
|
stepInfo.put("signTime", cn.hutool.core.date.DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
|
||||||
|
stepInfo.put("status", TaskLogStatus.NOT_STARTED.getCode());
|
||||||
|
|
||||||
|
infoJson.put("step_" + signInfo.getStepId(), stepInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新到数据库
|
||||||
|
infoDO.setInfo(infoJson.toJSONString());
|
||||||
|
eightworkInfoRepository.updateById(infoDO);
|
||||||
|
|
||||||
|
log.info("预设签字人信息已保存: workId={}, count={}", workId, signLogs.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从签字信息中获取步骤名称
|
||||||
|
*/
|
||||||
|
private String getStepNameBySignInfo(TaskSignStepInfoCmd signInfo) {
|
||||||
|
// 这里可以通过 stepId 查询流程配置获取步骤名称
|
||||||
|
// 暂时返回空,由前端或后续处理填充
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.zcloud.eightwork.command;
|
package com.zcloud.eightwork.command;
|
||||||
|
|
||||||
import com.alibaba.cola.exception.BizException;
|
import com.alibaba.cola.exception.BizException;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.jjb.saas.framework.auth.utils.AuthContext;
|
import com.jjb.saas.framework.auth.utils.AuthContext;
|
||||||
import com.zcloud.eightwork.domain.gateway.TaskFlowGateway;
|
import com.zcloud.eightwork.domain.gateway.TaskFlowGateway;
|
||||||
import com.zcloud.eightwork.domain.gateway.TaskLogGateway;
|
import com.zcloud.eightwork.domain.gateway.TaskLogGateway;
|
||||||
|
|
@ -86,32 +88,49 @@ public class TaskLogAddExe {
|
||||||
throw new BizException("暂存记录不存在");
|
throw new BizException("暂存记录不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 检查状态
|
// 2. 检查状态,暂存(0)或打回(2)都可以转正式提交
|
||||||
if (!TaskLogStatus.NOT_STARTED.getCode().equals(existingInfo.getStatus())) {
|
if (!TaskLogStatus.NOT_STARTED.getCode().equals(existingInfo.getStatus()) &&
|
||||||
throw new BizException("只能从暂存状态转为正式提交");
|
!TaskLogStatus.REJECTED.equalsCode(existingInfo.getStatus())) {
|
||||||
|
throw new BizException("只能从暂存状态或打回状态转为正式提交");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 删除暂存的 task_log
|
// 3. 处理打回历史:将 rejectInfo 转为 rejectHistory
|
||||||
|
String processedInfo = processRejectHistory(existingInfo.getInfo(), cmd.getInfo());
|
||||||
|
|
||||||
|
// 4. 删除暂存的 task_log
|
||||||
taskLogRepository.remove(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<TaskLogDO>()
|
taskLogRepository.remove(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<TaskLogDO>()
|
||||||
.eq(TaskLogDO::getWorkId, existingInfo.getWorkId()));
|
.eq(TaskLogDO::getWorkId, existingInfo.getWorkId()));
|
||||||
|
|
||||||
// 4. 生成正式票号并更新主表
|
// 5. 判断是否已有票号,没有则生成新票号
|
||||||
String formalCheckNo = generateFormalCheckNo(cmd.getWorkType());
|
String checkNo = existingInfo.getCheckNo();
|
||||||
existingInfo.setCheckNo(formalCheckNo);
|
if (org.apache.commons.lang.StringUtils.isBlank(checkNo)) {
|
||||||
|
// 暂存后第一次正式提交,生成新票号
|
||||||
|
checkNo = generateFormalCheckNo(cmd.getWorkType());
|
||||||
|
existingInfo.setCheckNo(checkNo);
|
||||||
|
log.info("暂存转正式(生成新票号): workId={}, checkNo={}", existingInfo.getWorkId(), checkNo);
|
||||||
|
} else {
|
||||||
|
// 打回后重新提交,保持原票号
|
||||||
|
log.info("暂存转正式(保持原票号): workId={}, checkNo={}", existingInfo.getWorkId(), checkNo);
|
||||||
|
}
|
||||||
|
|
||||||
existingInfo.setStatus(TaskLogStatus.IN_PROGRESS.getCode());
|
existingInfo.setStatus(TaskLogStatus.IN_PROGRESS.getCode());
|
||||||
|
existingInfo.setInfo(processedInfo); // 设置处理后的 info(包含 rejectHistory)
|
||||||
eightworkInfoRepository.updateById(existingInfo);
|
eightworkInfoRepository.updateById(existingInfo);
|
||||||
|
|
||||||
log.info("暂存转正式: workId={}, checkNo={}", existingInfo.getWorkId(), formalCheckNo);
|
// 6. 获取流程配置
|
||||||
|
|
||||||
// 5. 获取流程配置
|
|
||||||
List<TaskFlowE> flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel());
|
List<TaskFlowE> flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel());
|
||||||
|
|
||||||
// 6. 生成所有步骤 task_log
|
// 7. 生成所有步骤 task_log
|
||||||
List<TaskLogDO> taskLogs = flows.stream()
|
List<TaskLogDO> taskLogs = flows.stream()
|
||||||
.map(flow -> createTaskLog(flow, existingInfo.getWorkId(), cmd))
|
.map(flow -> createTaskLog(flow, existingInfo.getWorkId(), cmd))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// 7. 批量保存
|
// 8. 设置所有步骤的 checkNo(使用主表的票号)
|
||||||
|
for (TaskLogDO taskLog : taskLogs) {
|
||||||
|
taskLog.setCheckNo(checkNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. 批量保存
|
||||||
taskLogRepository.saveBatch(taskLogs);
|
taskLogRepository.saveBatch(taskLogs);
|
||||||
|
|
||||||
log.info("作业流程创建成功(从暂存): workId={}, stepCount={}", existingInfo.getWorkId(), taskLogs.size());
|
log.info("作业流程创建成功(从暂存): workId={}, stepCount={}", existingInfo.getWorkId(), taskLogs.size());
|
||||||
|
|
@ -128,6 +147,12 @@ public class TaskLogAddExe {
|
||||||
String workId = saveWork(cmd);
|
String workId = saveWork(cmd);
|
||||||
log.info("作业信息已创建: workId={}", workId);
|
log.info("作业信息已创建: workId={}", workId);
|
||||||
|
|
||||||
|
// 获取票号
|
||||||
|
String checkNo = eightworkInfoRepository.getOne(
|
||||||
|
new LambdaQueryWrapper<EightworkInfoDO>()
|
||||||
|
.eq(EightworkInfoDO::getWorkId, workId)
|
||||||
|
).getCheckNo();
|
||||||
|
|
||||||
// 2. 获取流程配置
|
// 2. 获取流程配置
|
||||||
List<TaskFlowE> flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel());
|
List<TaskFlowE> flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel());
|
||||||
log.info("获取到 {} 个流程步骤", flows.size());
|
log.info("获取到 {} 个流程步骤", flows.size());
|
||||||
|
|
@ -135,7 +160,12 @@ public class TaskLogAddExe {
|
||||||
// 3. 生成任务日志
|
// 3. 生成任务日志
|
||||||
List<TaskLogDO> taskLogs = flows.stream().map(flow -> createTaskLog(flow, workId, cmd)).collect(Collectors.toList());
|
List<TaskLogDO> taskLogs = flows.stream().map(flow -> createTaskLog(flow, workId, cmd)).collect(Collectors.toList());
|
||||||
|
|
||||||
// 4. 批量保存
|
// 4. 设置所有步骤的 checkNo
|
||||||
|
for (TaskLogDO taskLog : taskLogs) {
|
||||||
|
taskLog.setCheckNo(checkNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 批量保存
|
||||||
taskLogRepository.saveBatch(taskLogs);
|
taskLogRepository.saveBatch(taskLogs);
|
||||||
|
|
||||||
log.info("作业流程创建成功: workId={}, stepCount={}", workId, taskLogs.size());
|
log.info("作业流程创建成功: workId={}, stepCount={}", workId, taskLogs.size());
|
||||||
|
|
@ -264,6 +294,59 @@ public class TaskLogAddExe {
|
||||||
return eightworkInfo.getWorkId();
|
return eightworkInfo.getWorkId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理打回历史
|
||||||
|
* 将旧的 rejectInfo 转换为 rejectHistory,并与新的 info 合并
|
||||||
|
*
|
||||||
|
* @param oldInfo 旧的 info JSON 字符串
|
||||||
|
* @param newInfo 新的 info JSONObject
|
||||||
|
* @return 合并后的 info JSON 字符串
|
||||||
|
*/
|
||||||
|
private String processRejectHistory(String oldInfo, com.alibaba.fastjson.JSONObject newInfo) {
|
||||||
|
// 解析旧 info
|
||||||
|
com.alibaba.fastjson.JSONObject oldJson;
|
||||||
|
if (org.apache.commons.lang.StringUtils.isNotBlank(oldInfo)) {
|
||||||
|
try {
|
||||||
|
oldJson = com.alibaba.fastjson.JSONObject.parseObject(oldInfo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("解析旧 info 失败", e);
|
||||||
|
oldJson = new com.alibaba.fastjson.JSONObject();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oldJson = new com.alibaba.fastjson.JSONObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制新 info
|
||||||
|
com.alibaba.fastjson.JSONObject mergedJson = new com.alibaba.fastjson.JSONObject();
|
||||||
|
if (newInfo != null) {
|
||||||
|
mergedJson = new com.alibaba.fastjson.JSONObject(newInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有 rejectInfo 需要转为 rejectHistory
|
||||||
|
com.alibaba.fastjson.JSONArray rejectHistory = oldJson.getJSONArray("rejectHistory");
|
||||||
|
com.alibaba.fastjson.JSONObject rejectInfo = oldJson.getJSONObject("rejectInfo");
|
||||||
|
|
||||||
|
if (rejectInfo != null) {
|
||||||
|
// 初始化 rejectHistory
|
||||||
|
if (rejectHistory == null) {
|
||||||
|
rejectHistory = new com.alibaba.fastjson.JSONArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将 rejectInfo 添加到 history
|
||||||
|
rejectHistory.add(rejectInfo);
|
||||||
|
|
||||||
|
// 从旧 info 中移除 rejectInfo
|
||||||
|
oldJson.remove("rejectInfo");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将 rejectHistory 合并到新 info
|
||||||
|
if (rejectHistory != null && !rejectHistory.isEmpty()) {
|
||||||
|
mergedJson.put("rejectHistory", rejectHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mergedJson.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建票号 Redis Key
|
* 构建票号 Redis Key
|
||||||
* 格式: eightwork:ticket:no:{作业类型代码}:{日期}
|
* 格式: eightwork:ticket:no:{作业类型代码}:{日期}
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,17 @@ package com.zcloud.eightwork.command;
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.date.DatePattern;
|
import cn.hutool.core.date.DatePattern;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.cola.exception.BizException;
|
import com.alibaba.cola.exception.BizException;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.zcloud.eightwork.command.convertor.TaskLogConvertUtil;
|
import com.zcloud.eightwork.command.convertor.TaskLogConvertUtil;
|
||||||
import com.zcloud.eightwork.domain.gateway.TaskLogGateway;
|
|
||||||
import com.zcloud.eightwork.domain.gateway.EightworkSupplementaryInfoGateway;
|
import com.zcloud.eightwork.domain.gateway.EightworkSupplementaryInfoGateway;
|
||||||
import com.zcloud.eightwork.domain.model.MeasuresLogsE;
|
import com.zcloud.eightwork.domain.gateway.TaskLogGateway;
|
||||||
import com.zcloud.eightwork.domain.model.EightworkSupplementaryInfoE;
|
import com.zcloud.eightwork.domain.model.EightworkSupplementaryInfoE;
|
||||||
|
import com.zcloud.eightwork.domain.model.MeasuresLogsE;
|
||||||
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.BranchFlag;
|
||||||
import com.zcloud.eightwork.domain.model.enums.StepType;
|
import com.zcloud.eightwork.domain.model.enums.StepType;
|
||||||
|
|
@ -21,12 +22,8 @@ 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;
|
||||||
import com.zcloud.eightwork.persistence.dataobject.EightworkInfoDO;
|
import com.zcloud.eightwork.persistence.dataobject.*;
|
||||||
import com.zcloud.eightwork.persistence.dataobject.MeasuresLogsDO;
|
import com.zcloud.eightwork.persistence.repository.*;
|
||||||
import com.zcloud.eightwork.persistence.dataobject.TaskLogDO;
|
|
||||||
import com.zcloud.eightwork.persistence.repository.EightworkInfoRepository;
|
|
||||||
import com.zcloud.eightwork.persistence.repository.MeasuresLogsRepository;
|
|
||||||
import com.zcloud.eightwork.persistence.repository.TaskLogRepository;
|
|
||||||
import com.zcloud.gbscommon.todolistmq.TodoListEventPusherUtil;
|
import com.zcloud.gbscommon.todolistmq.TodoListEventPusherUtil;
|
||||||
import com.zcloud.gbscommon.todolistmq.event.TodoListAddEvent;
|
import com.zcloud.gbscommon.todolistmq.event.TodoListAddEvent;
|
||||||
import com.zcloud.gbscommon.todolistmq.event.TodoListCompleteEvent;
|
import com.zcloud.gbscommon.todolistmq.event.TodoListCompleteEvent;
|
||||||
|
|
@ -40,7 +37,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -55,27 +51,56 @@ import java.util.stream.Collectors;
|
||||||
@Component
|
@Component
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class TaskLogUpdateExe {
|
public class TaskLogUpdateExe {
|
||||||
/** 签字步骤标识 */
|
/**
|
||||||
|
* 签字步骤标识
|
||||||
|
*/
|
||||||
private static final Integer SIGN_STEP_FLAG = 1;
|
private static final Integer SIGN_STEP_FLAG = 1;
|
||||||
/** 多人签字标识 */
|
/**
|
||||||
|
* 多人签字标识
|
||||||
|
*/
|
||||||
private static final Integer MULTIPLE_FLAG = 1;
|
private static final Integer MULTIPLE_FLAG = 1;
|
||||||
/** 主要措施类型 */
|
/**
|
||||||
|
* 主要措施类型
|
||||||
|
*/
|
||||||
private static final Integer MAIN_MEASURE_TYPE = 1;
|
private static final Integer MAIN_MEASURE_TYPE = 1;
|
||||||
/** 可添加其他安全措施标识 */
|
/**
|
||||||
|
* 可添加其他安全措施标识
|
||||||
|
*/
|
||||||
private static final Integer MEASURES_STEP_FLAG = 1;
|
private static final Integer MEASURES_STEP_FLAG = 1;
|
||||||
/** 可跳过标识 */
|
/**
|
||||||
|
* 可跳过标识
|
||||||
|
*/
|
||||||
private static final Integer CAN_SKIP_FLAG = 1;
|
private static final Integer CAN_SKIP_FLAG = 1;
|
||||||
/** PC端待办标识 */
|
/**
|
||||||
|
* PC端待办标识
|
||||||
|
*/
|
||||||
private static final Integer PC_FLAG = 1;
|
private static final Integer PC_FLAG = 1;
|
||||||
/** APP端待办标识 */
|
/**
|
||||||
|
* APP端待办标识
|
||||||
|
*/
|
||||||
private static final Integer APP_FLAG = 1;
|
private static final Integer APP_FLAG = 1;
|
||||||
|
/**
|
||||||
|
* 第一步(申请步骤)ID
|
||||||
|
*/
|
||||||
|
private static final Long FIRST_STEP_ID = 1L;
|
||||||
|
/**
|
||||||
|
* 暂存状态
|
||||||
|
*/
|
||||||
|
private static final Integer DRAFT_STATUS = 0;
|
||||||
|
/**
|
||||||
|
* 打回状态
|
||||||
|
*/
|
||||||
|
private static final Integer REJECTED_STATUS = 2;
|
||||||
|
|
||||||
private final TaskLogGateway taskLogGateway;
|
private final TaskLogGateway taskLogGateway;
|
||||||
private final TaskLogRepository taskLogRepository;
|
private final TaskLogRepository taskLogRepository;
|
||||||
|
private final TaskLogArchiveRepository taskLogArchiveRepository;
|
||||||
private final MeasuresLogsRepository measuresLogsRepository;
|
private final MeasuresLogsRepository measuresLogsRepository;
|
||||||
private final EightworkInfoRepository eightworkInfoRepository;
|
private final EightworkInfoRepository eightworkInfoRepository;
|
||||||
private final TodoListEventPusherUtil todoListEventPusherUtil;
|
private final TodoListEventPusherUtil todoListEventPusherUtil;
|
||||||
private final EightworkSupplementaryInfoGateway eightworkSupplementaryInfoGateway;
|
private final EightworkSupplementaryInfoGateway eightworkSupplementaryInfoGateway;
|
||||||
|
private final EightworkSupplementaryInfoRepository eightworkSupplementaryInfoRepository;
|
||||||
|
private final EightworkSupplementaryInfoArchiveRepository eightworkSupplementaryInfoArchiveRepository;
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void execute(TaskLogUpdateCmd taskLogUpdateCmd) {
|
public void execute(TaskLogUpdateCmd taskLogUpdateCmd) {
|
||||||
|
|
@ -99,7 +124,9 @@ public class TaskLogUpdateExe {
|
||||||
*
|
*
|
||||||
* @param cmd 步骤流转命令
|
* @param cmd 步骤流转命令
|
||||||
*/
|
*/
|
||||||
/** 强制终止状态码 */
|
/**
|
||||||
|
* 强制终止状态码
|
||||||
|
*/
|
||||||
private static final Integer FORCE_TERMINATE_STATUS = 998;
|
private static final Integer FORCE_TERMINATE_STATUS = 998;
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
|
@ -113,6 +140,12 @@ public class TaskLogUpdateExe {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打回检查:status为2时打回到申请步骤
|
||||||
|
if (TaskLogStatus.REJECTED.equalsCode(cmd.getStatus())) {
|
||||||
|
handleReject(cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
List<TaskLogE> logs = taskLogGateway.listAllByWorkId(cmd.getWorkId());
|
List<TaskLogE> logs = taskLogGateway.listAllByWorkId(cmd.getWorkId());
|
||||||
List<TaskLogDO> actionLogs = new ArrayList<>();
|
List<TaskLogDO> actionLogs = new ArrayList<>();
|
||||||
|
|
||||||
|
|
@ -135,25 +168,25 @@ public class TaskLogUpdateExe {
|
||||||
|
|
||||||
// 2. 判断是否通过,通过才流转
|
// 2. 判断是否通过,通过才流转
|
||||||
if (TaskLogStatus.APPROVED.equalsCode(cmd.getStatus())) {
|
if (TaskLogStatus.APPROVED.equalsCode(cmd.getStatus())) {
|
||||||
// 3. 判断是否可以流转到下一步
|
// 3. 先设置后续签字人(在激活步骤之前设置,避免状态覆盖问题)
|
||||||
|
handleSignStepsIfNeeded(currentLog, cmd, actionLogs, logs);
|
||||||
|
|
||||||
|
// 4. 判断是否可以流转到下一步
|
||||||
if (canProceedToNext(currentLog, logs, cmd)) {
|
if (canProceedToNext(currentLog, logs, cmd)) {
|
||||||
// 4. 处理特殊步骤逻辑
|
// 5. 处理特殊步骤逻辑
|
||||||
boolean shouldProceed = handleSpecialStepIfNeeded(currentLog, cmd, actionLogs);
|
boolean shouldProceed = handleSpecialStepIfNeeded(currentLog, cmd, actionLogs);
|
||||||
|
|
||||||
// 5. 处理其他安全措施
|
// 6. 处理其他安全措施
|
||||||
handleOtherMeasuresIfNeeded(currentLog, cmd);
|
handleOtherMeasuresIfNeeded(currentLog, cmd);
|
||||||
|
|
||||||
// 6. 流转到下一步
|
// 7. 流转到下一步
|
||||||
if (shouldProceed) {
|
if (shouldProceed) {
|
||||||
proceedToNextStep(currentLog, actionLogs, logs);
|
proceedToNextStep(currentLog, actionLogs, logs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. 处理分支流程
|
// 8. 处理分支流程
|
||||||
handleBranchIfNeeded(currentLog, actionLogs, logs);
|
handleBranchIfNeeded(currentLog, actionLogs, logs);
|
||||||
|
|
||||||
// 8. 设置后续签字人
|
|
||||||
handleSignStepsIfNeeded(currentLog, cmd, actionLogs, logs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量更新 task_log
|
// 批量更新 task_log
|
||||||
|
|
@ -267,25 +300,30 @@ public class TaskLogUpdateExe {
|
||||||
private boolean handleDelayStep(TaskLogE currentLog, TaskLogNextCmd cmd, List<TaskLogDO> actionLogs) {
|
private boolean handleDelayStep(TaskLogE currentLog, TaskLogNextCmd cmd, List<TaskLogDO> actionLogs) {
|
||||||
log.info("处理延时监火转交");
|
log.info("处理延时监火转交");
|
||||||
|
|
||||||
// 保存延时监火信息到 eightwork_supplementary_info 表
|
if (ObjectUtil.isNotEmpty(cmd.getOthers())) {
|
||||||
EightworkSupplementaryInfoE supplementaryInfo = new EightworkSupplementaryInfoE();
|
// 保存延时监火信息到 eightwork_supplementary_info 表
|
||||||
supplementaryInfo.setTaskLogId(currentLog.getTaskLogId());
|
EightworkSupplementaryInfoE supplementaryInfo = new EightworkSupplementaryInfoE();
|
||||||
supplementaryInfo.setWorkId(currentLog.getWorkId());
|
supplementaryInfo.setTaskLogId(currentLog.getTaskLogId());
|
||||||
supplementaryInfo.setType("delay");
|
supplementaryInfo.setWorkId(currentLog.getWorkId());
|
||||||
supplementaryInfo.setDetails(cmd.getOthers());
|
supplementaryInfo.setType("delay");
|
||||||
eightworkSupplementaryInfoGateway.add(supplementaryInfo);
|
supplementaryInfo.setDetails(cmd.getOthers());
|
||||||
|
eightworkSupplementaryInfoGateway.add(supplementaryInfo);
|
||||||
|
}
|
||||||
|
|
||||||
// 保存下一步转交人记录
|
if (ObjectUtil.isNotEmpty(cmd.getSignLogs())) {
|
||||||
TaskLogE newDelayStep = new TaskLogE(currentLog);
|
// 保存下一步转交人记录
|
||||||
TaskLogDO nextLogDO = new TaskLogDO();
|
TaskLogE newDelayStep = new TaskLogE(currentLog);
|
||||||
BeanUtils.copyProperties(newDelayStep, nextLogDO);
|
TaskLogDO nextLogDO = new TaskLogDO();
|
||||||
nextLogDO.setActUserDepartment(cmd.getOthers().getLong("actUserDepartment"));
|
BeanUtils.copyProperties(newDelayStep, nextLogDO);
|
||||||
nextLogDO.setActUserDepartmentName(cmd.getOthers().getString("actUserDepartmentName"));
|
nextLogDO.setActUserDepartment(cmd.getSignLogs().get(0).getActUserDepartment());
|
||||||
taskLogRepository.save(nextLogDO);
|
nextLogDO.setActUserDepartmentName(cmd.getSignLogs().get(0).getActUserDepartmentName());
|
||||||
|
nextLogDO.setStatus(TaskLogStatus.IN_PROGRESS.getCode());
|
||||||
|
taskLogRepository.save(nextLogDO);
|
||||||
|
|
||||||
// 修改当前步骤状态为已完成
|
// 修改当前步骤状态为已完成
|
||||||
currentLog.setStatus(TaskLogStatus.APPROVED.getCode());
|
currentLog.setStatus(TaskLogStatus.APPROVED.getCode());
|
||||||
addActionLog(actionLogs, currentLog);
|
addActionLog(actionLogs, currentLog);
|
||||||
|
}
|
||||||
|
|
||||||
// 延时转交步骤不自动流转下一步
|
// 延时转交步骤不自动流转下一步
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -393,6 +431,13 @@ public class TaskLogUpdateExe {
|
||||||
* 递归处理,直到找到不需要跳过的步骤或流程结束
|
* 递归处理,直到找到不需要跳过的步骤或流程结束
|
||||||
*/
|
*/
|
||||||
private void proceedToNextStep(TaskLogE currentLog, List<TaskLogDO> actionLogs, List<TaskLogE> allLogs) {
|
private void proceedToNextStep(TaskLogE currentLog, List<TaskLogDO> actionLogs, List<TaskLogE> allLogs) {
|
||||||
|
// 检查下一步是否为归档状态(nextStep = 999)
|
||||||
|
if (TaskLogStatus.ARCHIVED.getCode().equals(currentLog.getNextStep())) {
|
||||||
|
log.info("下一步为归档状态,工作流完成: workId={}, nextStep={}", currentLog.getWorkId(), currentLog.getNextStep());
|
||||||
|
completeWorkflow(currentLog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
List<TaskLogE> nextSteps = findNextSteps(currentLog, allLogs);
|
List<TaskLogE> nextSteps = findNextSteps(currentLog, allLogs);
|
||||||
|
|
||||||
if (CollectionUtil.isEmpty(nextSteps)) {
|
if (CollectionUtil.isEmpty(nextSteps)) {
|
||||||
|
|
@ -454,7 +499,7 @@ public class TaskLogUpdateExe {
|
||||||
* 包括主流程和分支步骤,必须都完成才能激活合并节点
|
* 包括主流程和分支步骤,必须都完成才能激活合并节点
|
||||||
*
|
*
|
||||||
* @param mergeNode 合并节点
|
* @param mergeNode 合并节点
|
||||||
* @param allLogs 所有步骤日志
|
* @param allLogs 所有步骤日志
|
||||||
* @return true-所有前置步骤都已完成,false-还有步骤未完成
|
* @return true-所有前置步骤都已完成,false-还有步骤未完成
|
||||||
*/
|
*/
|
||||||
private boolean areAllBranchesCompleted(TaskLogE mergeNode, List<TaskLogE> allLogs) {
|
private boolean areAllBranchesCompleted(TaskLogE mergeNode, List<TaskLogE> allLogs) {
|
||||||
|
|
@ -468,7 +513,7 @@ public class TaskLogUpdateExe {
|
||||||
* SKIPPED 状态的步骤视为已完成
|
* SKIPPED 状态的步骤视为已完成
|
||||||
*
|
*
|
||||||
* @param mergeNode 合并节点
|
* @param mergeNode 合并节点
|
||||||
* @param allLogs 所有步骤日志
|
* @param allLogs 所有步骤日志
|
||||||
* @return 未完成的步骤列表
|
* @return 未完成的步骤列表
|
||||||
*/
|
*/
|
||||||
private List<TaskLogE> getPendingBranches(TaskLogE mergeNode, List<TaskLogE> allLogs) {
|
private List<TaskLogE> getPendingBranches(TaskLogE mergeNode, List<TaskLogE> allLogs) {
|
||||||
|
|
@ -615,6 +660,173 @@ public class TaskLogUpdateExe {
|
||||||
log.info("工作流已强制终止: workId={}, skippedSteps={}", cmd.getWorkId(), actionLogs.size() - 1);
|
log.info("工作流已强制终止: workId={}, skippedSteps={}", cmd.getWorkId(), actionLogs.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理打回工作流
|
||||||
|
* status为2时打回到申请步骤,删除后续流程,允许修改后重新提交
|
||||||
|
*/
|
||||||
|
private void handleReject(TaskLogNextCmd cmd) {
|
||||||
|
log.info("开始处理打回: workId={}, stepId={}", cmd.getWorkId(), cmd.getStepId());
|
||||||
|
|
||||||
|
List<TaskLogE> allLogs = taskLogGateway.listAllByWorkId(cmd.getWorkId());
|
||||||
|
TaskLogE currentLog = findCurrentLog(allLogs, cmd.getId());
|
||||||
|
|
||||||
|
if (currentLog == null) {
|
||||||
|
throw new BizException("未找到对应的步骤记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 归档当前的 task_log 记录(除了申请步骤)
|
||||||
|
archiveTaskLogs(allLogs);
|
||||||
|
|
||||||
|
// 2. 归档辅助数据(delay、gas、measures)
|
||||||
|
archiveSupplementaryInfo(cmd.getWorkId());
|
||||||
|
|
||||||
|
// 3. 删除除申请步骤外的所有 task_log
|
||||||
|
deleteTaskLogsExceptFirst(cmd.getWorkId());
|
||||||
|
|
||||||
|
// 4. 删除辅助数据(delay、gas、measures)
|
||||||
|
deleteSupplementaryInfo(cmd.getWorkId());
|
||||||
|
|
||||||
|
// 5. 更新主表状态为暂存,添加打回信息
|
||||||
|
updateMainInfoForReject(cmd.getWorkId(), currentLog, cmd.getOthers());
|
||||||
|
|
||||||
|
// 6. 发送待办完成事件
|
||||||
|
sendTodoCompleteEvent(currentLog.getId());
|
||||||
|
|
||||||
|
log.info("工作流已打回到申请步骤: workId={}", cmd.getWorkId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 归档 task_log 记录到 task_log_archive 表
|
||||||
|
*/
|
||||||
|
private void archiveTaskLogs(List<TaskLogE> allLogs) {
|
||||||
|
List<TaskLogArchiveDO> archiveList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (TaskLogE log : allLogs) {
|
||||||
|
// 跳过申请步骤(stepId=1)
|
||||||
|
if (FIRST_STEP_ID.equals(log.getStepId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 只归档已处理的记录(状态不是未开始)
|
||||||
|
if (!TaskLogStatus.NOT_STARTED.equalsCode(log.getStatus())) {
|
||||||
|
TaskLogArchiveDO archiveDO = new TaskLogArchiveDO();
|
||||||
|
BeanUtils.copyProperties(log, archiveDO, "id");
|
||||||
|
archiveList.add(archiveDO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!archiveList.isEmpty()) {
|
||||||
|
// 批量保存到归档表
|
||||||
|
for (TaskLogArchiveDO archiveDO : archiveList) {
|
||||||
|
taskLogArchiveRepository.save(archiveDO);
|
||||||
|
}
|
||||||
|
log.info("已归档 {} 条 task_log 记录", archiveList.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 归档辅助数据到 eightwork_supplementary_info_archive 表
|
||||||
|
*/
|
||||||
|
private void archiveSupplementaryInfo(String workId) {
|
||||||
|
List<EightworkSupplementaryInfoDO> infoList = eightworkSupplementaryInfoRepository.list(
|
||||||
|
new LambdaQueryWrapper<EightworkSupplementaryInfoDO>()
|
||||||
|
.eq(EightworkSupplementaryInfoDO::getWorkId, workId)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!infoList.isEmpty()) {
|
||||||
|
for (EightworkSupplementaryInfoDO infoDO : infoList) {
|
||||||
|
com.zcloud.eightwork.persistence.dataobject.EightworkSupplementaryInfoArchiveDO archiveDO =
|
||||||
|
new com.zcloud.eightwork.persistence.dataobject.EightworkSupplementaryInfoArchiveDO();
|
||||||
|
BeanUtils.copyProperties(infoDO, archiveDO, "id");
|
||||||
|
eightworkSupplementaryInfoArchiveRepository.save(archiveDO);
|
||||||
|
}
|
||||||
|
log.info("已归档 {} 条辅助数据记录", infoList.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除除申请步骤外的所有 task_log
|
||||||
|
*/
|
||||||
|
private void deleteTaskLogsExceptFirst(String workId) {
|
||||||
|
taskLogRepository.remove(
|
||||||
|
new LambdaQueryWrapper<TaskLogDO>()
|
||||||
|
.eq(TaskLogDO::getWorkId, workId)
|
||||||
|
.ne(TaskLogDO::getStepId, FIRST_STEP_ID)
|
||||||
|
);
|
||||||
|
log.info("已删除除申请步骤外的 task_log: workId={}", workId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除辅助数据(delay、gas、measures)
|
||||||
|
*/
|
||||||
|
private void deleteSupplementaryInfo(String workId) {
|
||||||
|
// 删除 eightwork_supplementary_info 中的记录
|
||||||
|
eightworkSupplementaryInfoRepository.remove(
|
||||||
|
new LambdaQueryWrapper<EightworkSupplementaryInfoDO>()
|
||||||
|
.eq(EightworkSupplementaryInfoDO::getWorkId, workId)
|
||||||
|
);
|
||||||
|
log.info("已删除辅助数据: workId={}", workId);
|
||||||
|
|
||||||
|
// 删除 measures_logs 中的记录(如果有的话)
|
||||||
|
measuresLogsRepository.remove(
|
||||||
|
new LambdaQueryWrapper<MeasuresLogsDO>()
|
||||||
|
.eq(MeasuresLogsDO::getWorkId, workId)
|
||||||
|
);
|
||||||
|
log.info("已删除安全措施记录: workId={}", workId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新主表信息(打回后)
|
||||||
|
*/
|
||||||
|
private void updateMainInfoForReject(String workId, TaskLogE currentLog, com.alibaba.fastjson.JSONObject others) {
|
||||||
|
// 获取主表记录
|
||||||
|
EightworkInfoDO infoDO = eightworkInfoRepository.getOne(
|
||||||
|
new LambdaQueryWrapper<EightworkInfoDO>()
|
||||||
|
.eq(EightworkInfoDO::getWorkId, workId)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (infoDO == null) {
|
||||||
|
log.warn("未找到作业信息: workId={}", workId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析现有 info
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建 rejectInfo
|
||||||
|
JSONObject rejectInfo = new JSONObject();
|
||||||
|
rejectInfo.put("rejected", true);
|
||||||
|
rejectInfo.put("rejectStepId", currentLog.getStepId());
|
||||||
|
rejectInfo.put("rejectStepName", currentLog.getStepName());
|
||||||
|
rejectInfo.put("rejectTime", cn.hutool.core.date.DateUtil.format(new Date(), cn.hutool.core.date.DatePattern.NORM_DATETIME_PATTERN));
|
||||||
|
rejectInfo.put("rejectUser", currentLog.getActUserName());
|
||||||
|
rejectInfo.put("rejectUserId", currentLog.getActUser());
|
||||||
|
|
||||||
|
// 如果有打回原因,添加到 rejectInfo
|
||||||
|
if (others != null && others.containsKey("rejectReason")) {
|
||||||
|
rejectInfo.put("rejectReason", others.getString("rejectReason"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将 rejectInfo 放入主 info
|
||||||
|
infoJson.put("rejectInfo", rejectInfo);
|
||||||
|
|
||||||
|
// 更新主表状态为暂存
|
||||||
|
infoDO.setStatus(DRAFT_STATUS);
|
||||||
|
infoDO.setInfo(infoJson.toJSONString());
|
||||||
|
eightworkInfoRepository.updateById(infoDO);
|
||||||
|
|
||||||
|
log.info("主表已更新为暂存状态并添加打回信息: workId={}", workId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理分支流程
|
* 处理分支流程
|
||||||
* 职责:当主流程步骤为分支开始节点时,激活对应的分支步骤
|
* 职责:当主流程步骤为分支开始节点时,激活对应的分支步骤
|
||||||
|
|
@ -667,7 +879,7 @@ public class TaskLogUpdateExe {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否需要跳过
|
// 检查是否需要跳过
|
||||||
if (CAN_SKIP_FLAG.equals(currentLog.getCanSkip()) && signInfo.getActUser() == null) {
|
if (CAN_SKIP_FLAG.equals(signStepLog.getCanSkip()) && signInfo.getActUser() == null) {
|
||||||
// 设置为跳过状态
|
// 设置为跳过状态
|
||||||
signStepLog.setStatus(TaskLogStatus.SKIPPED.getCode());
|
signStepLog.setStatus(TaskLogStatus.SKIPPED.getCode());
|
||||||
addActionLog(actionLogs, signStepLog);
|
addActionLog(actionLogs, signStepLog);
|
||||||
|
|
@ -681,6 +893,15 @@ public class TaskLogUpdateExe {
|
||||||
signInfo.getActUser(),
|
signInfo.getActUser(),
|
||||||
signInfo.getActUserName()
|
signInfo.getActUserName()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 如果步骤当前是未开始状态,需要激活它(设置签字人后应该变为进行中)
|
||||||
|
if (TaskLogStatus.NOT_STARTED.equalsCode(signStepLog.getStatus())) {
|
||||||
|
signStepLog.setStatus(TaskLogStatus.IN_PROGRESS.getCode());
|
||||||
|
// 发送待办通知
|
||||||
|
sendTodoAddEvent(getWorkId(signStepLog.getWorkId()), signStepLog, currentLog.getWorkType());
|
||||||
|
log.info("已激活签字步骤: {}", signStepLog.getStepName());
|
||||||
|
}
|
||||||
|
|
||||||
addActionLog(actionLogs, signStepLog);
|
addActionLog(actionLogs, signStepLog);
|
||||||
log.info("已设置签字人: step={}, user={}", signStepLog.getStepName(), signInfo.getActUserName());
|
log.info("已设置签字人: step={}, user={}", signStepLog.getStepName(), signInfo.getActUserName());
|
||||||
}
|
}
|
||||||
|
|
@ -760,14 +981,18 @@ public class TaskLogUpdateExe {
|
||||||
/**
|
/**
|
||||||
* 合并 TaskLogDO 的修改
|
* 合并 TaskLogDO 的修改
|
||||||
* 将 source 中非空字段合并到 target
|
* 将 source 中非空字段合并到 target
|
||||||
|
* 策略:只有当 target 的字段为 null 时,才用 source 的值覆盖(保留已设置的值)
|
||||||
|
* 特殊处理:签字人相关字段允许覆盖(因为后续操作可能设置签字人)
|
||||||
*
|
*
|
||||||
* @param target 目标 DO(会被修改)
|
* @param target 目标 DO(会被修改)
|
||||||
* @param source 源 DO(提供新值)
|
* @param source 源 DO(提供新值)
|
||||||
*/
|
*/
|
||||||
private void mergeTaskLogDO(TaskLogDO target, TaskLogDO source) {
|
private void mergeTaskLogDO(TaskLogDO target, TaskLogDO source) {
|
||||||
|
// 状态:只覆盖空值,保留已激活的状态(IN_PROGRESS/其他)
|
||||||
if (source.getStatus() != null) {
|
if (source.getStatus() != null) {
|
||||||
target.setStatus(source.getStatus());
|
target.setStatus(source.getStatus());
|
||||||
}
|
}
|
||||||
|
// 签字人相关字段:允许覆盖(后续操作可能设置签字人)
|
||||||
if (source.getActUser() != null) {
|
if (source.getActUser() != null) {
|
||||||
target.setActUser(source.getActUser());
|
target.setActUser(source.getActUser());
|
||||||
}
|
}
|
||||||
|
|
@ -780,15 +1005,19 @@ public class TaskLogUpdateExe {
|
||||||
if (source.getActUserDepartmentName() != null) {
|
if (source.getActUserDepartmentName() != null) {
|
||||||
target.setActUserDepartmentName(source.getActUserDepartmentName());
|
target.setActUserDepartmentName(source.getActUserDepartmentName());
|
||||||
}
|
}
|
||||||
|
// 签字路径:只覆盖空值
|
||||||
if (source.getSignPath() != null) {
|
if (source.getSignPath() != null) {
|
||||||
target.setSignPath(source.getSignPath());
|
target.setSignPath(source.getSignPath());
|
||||||
}
|
}
|
||||||
|
// 填写次数:只覆盖空值
|
||||||
if (source.getCurrentFillTimes() != null) {
|
if (source.getCurrentFillTimes() != null) {
|
||||||
target.setCurrentFillTimes(source.getCurrentFillTimes());
|
target.setCurrentFillTimes(source.getCurrentFillTimes());
|
||||||
}
|
}
|
||||||
|
// 其他参数:只覆盖空值
|
||||||
if (source.getOtherParams() != null) {
|
if (source.getOtherParams() != null) {
|
||||||
target.setOtherParams(source.getOtherParams());
|
target.setOtherParams(source.getOtherParams());
|
||||||
}
|
}
|
||||||
|
// 经纬度:允许覆盖(最新的定位信息)
|
||||||
if (source.getLatitude() != null) {
|
if (source.getLatitude() != null) {
|
||||||
target.setLatitude(source.getLatitude());
|
target.setLatitude(source.getLatitude());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
package com.zcloud.eightwork.command.query;
|
||||||
|
|
||||||
|
import com.zcloud.eightwork.domain.gateway.TaskLogGateway;
|
||||||
|
import com.zcloud.eightwork.domain.model.TaskFlowE;
|
||||||
|
import com.zcloud.eightwork.domain.model.TaskLogE;
|
||||||
|
import com.zcloud.eightwork.domain.model.enums.BranchFlag;
|
||||||
|
import com.zcloud.eightwork.domain.model.enums.StepType;
|
||||||
|
import com.zcloud.eightwork.domain.model.enums.TaskLogStatus;
|
||||||
|
import com.zcloud.eightwork.dto.clientobject.TaskFlowChartCO;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作流程图查询执行器
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-23
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TaskFlowChartQueryExe {
|
||||||
|
|
||||||
|
private final TaskLogGateway taskLogGateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作流程图
|
||||||
|
*
|
||||||
|
* @param workId 工作ID
|
||||||
|
* @return 流程图列表
|
||||||
|
*/
|
||||||
|
public List<TaskFlowChartCO> execute(String workId) {
|
||||||
|
log.info("查询工作流程图: workId={}", workId);
|
||||||
|
|
||||||
|
// 1. 查询所有步骤
|
||||||
|
List<TaskLogE> allLogs = taskLogGateway.listAllByWorkId(workId);
|
||||||
|
|
||||||
|
// 2. 过滤 SKIPPED 状态的步骤
|
||||||
|
List<TaskLogE> filteredLogs = allLogs.stream()
|
||||||
|
.filter(log -> !TaskLogStatus.SKIPPED.equalsCode(log.getStatus()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 3. 区分主流程步骤和分支步骤
|
||||||
|
List<TaskLogE> mainSteps = filteredLogs.stream()
|
||||||
|
.filter(this::isMainStep)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<TaskLogE> branchSteps = filteredLogs.stream()
|
||||||
|
.filter(log -> !isMainStep(log))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 4. 按 branchStep 分组分支步骤
|
||||||
|
Map<Long, List<TaskLogE>> branchGroupMap = branchSteps.stream()
|
||||||
|
.collect(Collectors.groupingBy(TaskLogE::getBranchStep));
|
||||||
|
|
||||||
|
// 5. 构建流程图
|
||||||
|
List<TaskFlowChartCO> result = new ArrayList<>();
|
||||||
|
for (TaskLogE mainStep : mainSteps) {
|
||||||
|
TaskFlowChartCO mainCO = convertToCO(mainStep);
|
||||||
|
|
||||||
|
// 如果该主流程步骤开启了分支,添加分支信息
|
||||||
|
if (BranchFlag.getByCode(mainStep.getBranchFlag()).isBranchStart()) {
|
||||||
|
List<TaskLogE> branches = branchGroupMap.get(mainStep.getStepId());
|
||||||
|
if (branches != null && !branches.isEmpty()) {
|
||||||
|
// 按步骤ID排序,确保分支内顺序正确
|
||||||
|
branches.sort((a, b) -> a.getStepOrder().compareTo(b.getStepOrder()));
|
||||||
|
List<TaskFlowChartCO> branchCOs = convertBranches(branches);
|
||||||
|
mainCO.setBranches(branchCOs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(mainCO);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("工作流程图查询完成: workId={}, stepCount={}", workId, result.size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为主流程步骤
|
||||||
|
* 主流程步骤:stepType 为 normal 或 branch_start
|
||||||
|
*/
|
||||||
|
private boolean isMainStep(TaskLogE log) {
|
||||||
|
StepType stepType = StepType.getByCode(log.getStepType());
|
||||||
|
return stepType != null && (stepType.isNormalStep());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换分支步骤列表为 CO
|
||||||
|
* 分支内按顺序排列,只有最后一个节点有 mergeStepId
|
||||||
|
*/
|
||||||
|
private List<TaskFlowChartCO> convertBranches(List<TaskLogE> branches) {
|
||||||
|
List<TaskFlowChartCO> result = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < branches.size(); i++) {
|
||||||
|
TaskLogE branch = branches.get(i);
|
||||||
|
TaskFlowChartCO co = convertToCO(branch);
|
||||||
|
|
||||||
|
// 只有最后一个分支节点设置 mergeStepId
|
||||||
|
if (i == branches.size() - 1) {
|
||||||
|
co.setMergeStepId(branch.getBranchMergeStep());
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(co);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 TaskLogE 转换为 TaskFlowChartCO
|
||||||
|
*/
|
||||||
|
private TaskFlowChartCO convertToCO(TaskLogE log) {
|
||||||
|
TaskFlowChartCO co = new TaskFlowChartCO();
|
||||||
|
co.setStepId(log.getStepId());
|
||||||
|
co.setStatus(log.getStatus());
|
||||||
|
co.setStepName(log.getStepName());
|
||||||
|
co.setActUserName(log.getActUserName());
|
||||||
|
|
||||||
|
// 格式化时间
|
||||||
|
if (log.getUpdateTime() != null) {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
co.setUpdateTime(sdf.format(log.getUpdateTime()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return co;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import com.zcloud.eightwork.command.TaskLogAddExe;
|
||||||
import com.zcloud.eightwork.command.TaskLogRemoveExe;
|
import com.zcloud.eightwork.command.TaskLogRemoveExe;
|
||||||
import com.zcloud.eightwork.command.TaskLogUpdateExe;
|
import com.zcloud.eightwork.command.TaskLogUpdateExe;
|
||||||
import com.zcloud.eightwork.command.query.TaskLogQueryExe;
|
import com.zcloud.eightwork.command.query.TaskLogQueryExe;
|
||||||
|
import com.zcloud.eightwork.command.query.TaskFlowChartQueryExe;
|
||||||
import com.zcloud.eightwork.domain.model.enums.TaskLogStatus;
|
import com.zcloud.eightwork.domain.model.enums.TaskLogStatus;
|
||||||
import com.zcloud.eightwork.dto.EightworkInfoSaveDraftCmd;
|
import com.zcloud.eightwork.dto.EightworkInfoSaveDraftCmd;
|
||||||
import com.zcloud.eightwork.dto.TaskLogAddCmd;
|
import com.zcloud.eightwork.dto.TaskLogAddCmd;
|
||||||
|
|
@ -14,6 +15,7 @@ import com.zcloud.eightwork.dto.TaskLogPageQry;
|
||||||
import com.zcloud.eightwork.dto.TaskLogUpdateCmd;
|
import com.zcloud.eightwork.dto.TaskLogUpdateCmd;
|
||||||
import com.zcloud.eightwork.dto.clientobject.EightworkInfoCO;
|
import com.zcloud.eightwork.dto.clientobject.EightworkInfoCO;
|
||||||
import com.zcloud.eightwork.dto.clientobject.TaskLogCO;
|
import com.zcloud.eightwork.dto.clientobject.TaskLogCO;
|
||||||
|
import com.zcloud.eightwork.dto.clientobject.TaskFlowChartCO;
|
||||||
|
|
||||||
import com.alibaba.cola.dto.PageResponse;
|
import com.alibaba.cola.dto.PageResponse;
|
||||||
import com.alibaba.cola.dto.SingleResponse;
|
import com.alibaba.cola.dto.SingleResponse;
|
||||||
|
|
@ -39,6 +41,7 @@ public class TaskLogServiceImpl implements TaskLogServiceI {
|
||||||
private final TaskLogRemoveExe taskLogRemoveExe;
|
private final TaskLogRemoveExe taskLogRemoveExe;
|
||||||
private final TaskLogQueryExe taskLogQueryExe;
|
private final TaskLogQueryExe taskLogQueryExe;
|
||||||
private final EightworkInfoSaveDraftExe eightworkInfoSaveDraftExe;
|
private final EightworkInfoSaveDraftExe eightworkInfoSaveDraftExe;
|
||||||
|
private final TaskFlowChartQueryExe taskFlowChartQueryExe;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SingleResponse<TaskLogCO> getInfoById(Long id) {
|
public SingleResponse<TaskLogCO> getInfoById(Long id) {
|
||||||
|
|
@ -105,5 +108,10 @@ public class TaskLogServiceImpl implements TaskLogServiceI {
|
||||||
eightworkInfoSaveDraftExe.execute(cmd);
|
eightworkInfoSaveDraftExe.execute(cmd);
|
||||||
return SingleResponse.buildSuccess();
|
return SingleResponse.buildSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TaskFlowChartCO> getFlowChart(String workId) {
|
||||||
|
return taskFlowChartQueryExe.execute(workId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import com.zcloud.eightwork.dto.clientobject.TaskLogCO;
|
||||||
import com.alibaba.cola.dto.PageResponse;
|
import com.alibaba.cola.dto.PageResponse;
|
||||||
import com.alibaba.cola.dto.SingleResponse;
|
import com.alibaba.cola.dto.SingleResponse;
|
||||||
import com.zcloud.eightwork.dto.clientobject.TodoCountCO;
|
import com.zcloud.eightwork.dto.clientobject.TodoCountCO;
|
||||||
|
import com.zcloud.eightwork.dto.clientobject.TaskFlowChartCO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -44,5 +45,13 @@ public interface TaskLogServiceI {
|
||||||
* 暂存作业
|
* 暂存作业
|
||||||
*/
|
*/
|
||||||
SingleResponse<EightworkInfoCO> saveDraft(EightworkInfoSaveDraftCmd cmd);
|
SingleResponse<EightworkInfoCO> saveDraft(EightworkInfoSaveDraftCmd cmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工作流程图
|
||||||
|
*
|
||||||
|
* @param workId 工作ID
|
||||||
|
* @return 流程图列表(主流程步骤,包含分支信息)
|
||||||
|
*/
|
||||||
|
List<TaskFlowChartCO> getFlowChart(String workId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.zcloud.eightwork.dto;
|
||||||
|
|
||||||
|
import com.alibaba.cola.dto.Command;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-client
|
||||||
|
* 八险作业暂存命令
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class EightworkInfoSaveDraftCmd extends Command {
|
||||||
|
/**
|
||||||
|
* 主表ID(有值表示修改暂存,无值表示新建暂存)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "主表ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "企业", name = "corpinfoId", required = true)
|
||||||
|
@NotNull(message = "企业不能为空")
|
||||||
|
private Long corpinfoId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "是否相关方1是", name = "xgfFlag", required = true)
|
||||||
|
@NotNull(message = "是否相关方1是不能为空")
|
||||||
|
private Integer xgfFlag;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "是否内部作业1是2否", name = "internalOperationFlag")
|
||||||
|
private Integer internalOperationFlag;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "所属项目", name = "projectId", required = true)
|
||||||
|
@NotEmpty(message = "所属项目不能为空")
|
||||||
|
private String projectId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "相关方id", name = "xgfId", required = true)
|
||||||
|
@NotNull(message = "相关方id不能为空")
|
||||||
|
private Long xgfId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "是否需要气体检测1是2否", name = "gasFlag")
|
||||||
|
private Integer gasFlag;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "工作类型", name = "workType", required = true)
|
||||||
|
@NotEmpty(message = "工作类型不能为空")
|
||||||
|
private String workType;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "级别", name = "workLevel", required = true)
|
||||||
|
@NotEmpty(message = "级别不能为空")
|
||||||
|
private String workLevel;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "详细信息", name = "info", required = true)
|
||||||
|
@NotEmpty(message = "详细信息不能为空")
|
||||||
|
private String info;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "签字步骤", name = "signLogs")
|
||||||
|
private java.util.List<TaskSignStepInfoCmd> signLogs;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "部门id", name = "departmentId")
|
||||||
|
private Long departmentId;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.zcloud.eightwork.dto.clientobject;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作流程图 CO
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-23
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel("工作流程图")
|
||||||
|
public class TaskFlowChartCO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "步骤ID")
|
||||||
|
private Long stepId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "状态:0-未开始,1-进行中,2-已完成,998-强制终止,999-已归档")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "步骤名称")
|
||||||
|
private String stepName;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "签字人姓名")
|
||||||
|
private String actUserName;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "更新时间")
|
||||||
|
private String updateTime;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "分支步骤列表(仅主流程步骤中的分支开始节点有值)")
|
||||||
|
private List<TaskFlowChartCO> branches;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "合并到的步骤ID(仅分支最后一个节点有值)")
|
||||||
|
private Long mergeStepId;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.zcloud.eightwork.persistence.dataobject;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.jjb.saas.framework.repository.basedo.BaseDO;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-infrastructure
|
||||||
|
* 八险作业辅助信息归档表(打回时归档)
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("eightwork_supplementary_info_archive")
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class EightworkSupplementaryInfoArchiveDO extends BaseDO {
|
||||||
|
//业务主键id
|
||||||
|
@ApiModelProperty(value = "业务主键id")
|
||||||
|
private String supplementaryInfoId;
|
||||||
|
//流程日志id
|
||||||
|
@ApiModelProperty(value = "流程日志id")
|
||||||
|
private String taskLogId;
|
||||||
|
//工作id
|
||||||
|
@ApiModelProperty(value = "工作id")
|
||||||
|
private String workId;
|
||||||
|
//信息类型delay,gas
|
||||||
|
@ApiModelProperty(value = "信息类型delay,gas")
|
||||||
|
private String type;
|
||||||
|
//详情
|
||||||
|
@ApiModelProperty(value = "详情")
|
||||||
|
private String details;
|
||||||
|
|
||||||
|
public EightworkSupplementaryInfoArchiveDO(String supplementaryInfoId) {
|
||||||
|
this.supplementaryInfoId = supplementaryInfoId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
package com.zcloud.eightwork.persistence.dataobject;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.jjb.saas.framework.repository.basedo.BaseDO;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-infrastructure
|
||||||
|
* 任务日志归档表(打回时归档)
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("task_log_archive")
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class TaskLogArchiveDO extends BaseDO {
|
||||||
|
//业务主键id
|
||||||
|
@ApiModelProperty(value = "业务主键id")
|
||||||
|
private String taskLogId;
|
||||||
|
//工作ID
|
||||||
|
@ApiModelProperty(value = "工作ID")
|
||||||
|
private String workId;
|
||||||
|
//任务ID
|
||||||
|
@ApiModelProperty(value = "任务ID")
|
||||||
|
private Long taskId;
|
||||||
|
//步骤ID
|
||||||
|
@ApiModelProperty(value = "步骤ID")
|
||||||
|
private Long stepId;
|
||||||
|
//步骤名称
|
||||||
|
@ApiModelProperty(value = "步骤名称")
|
||||||
|
private String stepName;
|
||||||
|
//下一步
|
||||||
|
@ApiModelProperty(value = "下一步")
|
||||||
|
private Long nextStep;
|
||||||
|
//下一步名称
|
||||||
|
@ApiModelProperty(value = "下一步名称")
|
||||||
|
private String nextStepName;
|
||||||
|
//操作人部门
|
||||||
|
@ApiModelProperty(value = "操作人部门")
|
||||||
|
private Long actUserDepartment;
|
||||||
|
//操作人部门
|
||||||
|
@ApiModelProperty(value = "操作人部门")
|
||||||
|
private String actUserDepartmentName;
|
||||||
|
//操作人
|
||||||
|
@ApiModelProperty(value = "操作人")
|
||||||
|
private Long actUser;
|
||||||
|
//操作人
|
||||||
|
@ApiModelProperty(value = "操作人")
|
||||||
|
private String actUserName;
|
||||||
|
//-99未开始0进行中1通过2打回
|
||||||
|
@ApiModelProperty(value = "-99未开始0进行中1通过2打回")
|
||||||
|
private Integer status;
|
||||||
|
//签字图片路径
|
||||||
|
@ApiModelProperty(value = "签字图片路径")
|
||||||
|
private String signPath;
|
||||||
|
//任务类型
|
||||||
|
@ApiModelProperty(value = "任务类型")
|
||||||
|
private String workType;
|
||||||
|
//企业ID
|
||||||
|
@ApiModelProperty(value = "企业ID")
|
||||||
|
private Long corpinfoId;
|
||||||
|
//工作票编号
|
||||||
|
@ApiModelProperty(value = "工作票编号")
|
||||||
|
private String checkNo;
|
||||||
|
//操作人编码
|
||||||
|
@ApiModelProperty(value = "操作人编码")
|
||||||
|
private String actorField;
|
||||||
|
//是否多人签字1是
|
||||||
|
@ApiModelProperty(value = "是否多人签字1是")
|
||||||
|
private Integer multipleFlag;
|
||||||
|
//1正常2分支
|
||||||
|
@ApiModelProperty(value = "1正常2分支")
|
||||||
|
private Integer stepType;
|
||||||
|
//是否签字步骤1是
|
||||||
|
@ApiModelProperty(value = "是否签字步骤1是")
|
||||||
|
private Integer signStepFlag;
|
||||||
|
@ApiModelProperty(value = "sign_step_flag == 1 选择级别1部门2人员")
|
||||||
|
private Integer selectLevel;
|
||||||
|
@ApiModelProperty(value = "sign_step_flag == 1 是否可选相关方0否1是")
|
||||||
|
private Integer allowXgfFlag;
|
||||||
|
//是否上传附件
|
||||||
|
@ApiModelProperty(value = "是否上传附件")
|
||||||
|
private Integer fileStepFlag;
|
||||||
|
//是否定位步骤
|
||||||
|
@ApiModelProperty(value = "是否定位步骤")
|
||||||
|
private Integer locateStepFlag;
|
||||||
|
//特殊步骤编码gas气体检测measures安全措施确认delay延时监火
|
||||||
|
@ApiModelProperty(value = "特殊步骤编码gas气体检测measures安全措施确认delay延时监火")
|
||||||
|
private String specialStepCode;
|
||||||
|
//sign_step_flag == 1 在那个步骤选人
|
||||||
|
@ApiModelProperty(value = "sign_step_flag == 1 在那个步骤选人")
|
||||||
|
private Integer selectSignStep;
|
||||||
|
@ApiModelProperty(value = "是否可以添加安全措施")
|
||||||
|
private Integer measuresStepFlag;
|
||||||
|
//0无分支1有分支开始2有分支结束
|
||||||
|
@ApiModelProperty(value = "0无分支1有分支开始2有分支结束")
|
||||||
|
private Integer branchFlag;
|
||||||
|
//branch_flag == 1 分支节点ID
|
||||||
|
@ApiModelProperty(value = "branch_flag == 1 分支节点ID")
|
||||||
|
private Long branchStep;
|
||||||
|
//step_type == 2 分支节点合并节点ID
|
||||||
|
@ApiModelProperty(value = "step_type == 2 分支节点合并节点ID")
|
||||||
|
private Long branchMergeStep;
|
||||||
|
//分支排序 示例10-1-5
|
||||||
|
@ApiModelProperty(value = "分支排序 示例10-1-5")
|
||||||
|
private Integer stepOrder;
|
||||||
|
//是否可跳过1是
|
||||||
|
@ApiModelProperty(value = "是否可跳过1是")
|
||||||
|
private Integer canSkip;
|
||||||
|
//can_skip == 1 跳过条件 示例 age == 20
|
||||||
|
@ApiModelProperty(value = "can_skip == 1 跳过条件 示例 age == 20")
|
||||||
|
private String skipCondition;
|
||||||
|
//是否持续步骤1是(如气体检测,在整个流程期间都活跃)
|
||||||
|
@ApiModelProperty(value = "是否持续步骤1是(如气体检测,在整个流程期间都活跃)")
|
||||||
|
private Integer ongoingFlag;
|
||||||
|
//持续步骤最少填写次数
|
||||||
|
@ApiModelProperty(value = "持续步骤最少填写次数")
|
||||||
|
private Integer minFillTimes;
|
||||||
|
//持续步骤阻塞的步骤ID(必须填写足够次数后才能激活的步骤)
|
||||||
|
@ApiModelProperty(value = "持续步骤阻塞的步骤ID(必须填写足够次数后才能激活的步骤)")
|
||||||
|
private Long blockingStepId;
|
||||||
|
//持续步骤当前填写次数
|
||||||
|
@ApiModelProperty(value = "持续步骤当前填写次数")
|
||||||
|
private Integer currentFillTimes;
|
||||||
|
//纬度
|
||||||
|
@ApiModelProperty(value = "纬度")
|
||||||
|
private String latitude;
|
||||||
|
//经度
|
||||||
|
@ApiModelProperty(value = "经度")
|
||||||
|
private String longitude;
|
||||||
|
//其他参数(special_step_code==other 时使用)
|
||||||
|
@ApiModelProperty(value = "其他参数")
|
||||||
|
private String otherParams;
|
||||||
|
//手机端组件名称(special_step_code==other 时使用)
|
||||||
|
@ApiModelProperty(value = "手机端组件名称")
|
||||||
|
private String componentName;
|
||||||
|
|
||||||
|
public TaskLogArchiveDO(String taskLogId) {
|
||||||
|
this.taskLogId = taskLogId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.zcloud.eightwork.persistence.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.zcloud.eightwork.persistence.dataobject.EightworkSupplementaryInfoArchiveDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-infrastructure
|
||||||
|
* 八险作业辅助信息归档表 Mapper
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
public interface EightworkSupplementaryInfoArchiveMapper extends BaseMapper<EightworkSupplementaryInfoArchiveDO> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.zcloud.eightwork.persistence.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.zcloud.eightwork.persistence.dataobject.TaskLogArchiveDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-infrastructure
|
||||||
|
* 任务日志归档表 Mapper
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
public interface TaskLogArchiveMapper extends BaseMapper<TaskLogArchiveDO> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.zcloud.eightwork.persistence.repository;
|
||||||
|
|
||||||
|
import com.jjb.saas.framework.repository.repo.BaseRepository;
|
||||||
|
import com.zcloud.eightwork.persistence.dataobject.EightworkSupplementaryInfoArchiveDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-infrastructure
|
||||||
|
* 八险作业辅助信息归档表 Repository
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
public interface EightworkSupplementaryInfoArchiveRepository extends BaseRepository<EightworkSupplementaryInfoArchiveDO> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.zcloud.eightwork.persistence.repository;
|
||||||
|
|
||||||
|
import com.jjb.saas.framework.repository.repo.BaseRepository;
|
||||||
|
import com.zcloud.eightwork.persistence.dataobject.TaskLogArchiveDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-infrastructure
|
||||||
|
* 任务日志归档表 Repository
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
public interface TaskLogArchiveRepository extends BaseRepository<TaskLogArchiveDO> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.zcloud.eightwork.persistence.repository.impl;
|
||||||
|
|
||||||
|
import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl;
|
||||||
|
import com.zcloud.eightwork.persistence.dataobject.EightworkSupplementaryInfoArchiveDO;
|
||||||
|
import com.zcloud.eightwork.persistence.mapper.EightworkSupplementaryInfoArchiveMapper;
|
||||||
|
import com.zcloud.eightwork.persistence.repository.EightworkSupplementaryInfoArchiveRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-infrastructure
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class EightworkSupplementaryInfoArchiveRepositoryImpl extends BaseRepositoryImpl<EightworkSupplementaryInfoArchiveMapper, EightworkSupplementaryInfoArchiveDO>
|
||||||
|
implements EightworkSupplementaryInfoArchiveRepository {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.zcloud.eightwork.persistence.repository.impl;
|
||||||
|
|
||||||
|
import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl;
|
||||||
|
import com.zcloud.eightwork.persistence.dataobject.TaskLogArchiveDO;
|
||||||
|
import com.zcloud.eightwork.persistence.mapper.TaskLogArchiveMapper;
|
||||||
|
import com.zcloud.eightwork.persistence.repository.TaskLogArchiveRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web-infrastructure
|
||||||
|
*
|
||||||
|
* @Author fangjiakai
|
||||||
|
* @Date 2026-03-20
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class TaskLogArchiveRepositoryImpl extends BaseRepositoryImpl<TaskLogArchiveMapper, TaskLogArchiveDO>
|
||||||
|
implements TaskLogArchiveRepository {
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue