diff --git a/web-app/src/main/java/com/zcloud/eightwork/command/TaskLogAddExe.java b/web-app/src/main/java/com/zcloud/eightwork/command/TaskLogAddExe.java index 326c582..bc60597 100644 --- a/web-app/src/main/java/com/zcloud/eightwork/command/TaskLogAddExe.java +++ b/web-app/src/main/java/com/zcloud/eightwork/command/TaskLogAddExe.java @@ -5,6 +5,7 @@ import com.jjb.saas.framework.auth.utils.AuthContext; import com.zcloud.eightwork.domain.gateway.TaskFlowGateway; import com.zcloud.eightwork.domain.gateway.TaskLogGateway; 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.TaskLogAddCmd; import com.zcloud.eightwork.dto.TaskSignStepInfoCmd; @@ -15,88 +16,198 @@ import com.zcloud.eightwork.persistence.repository.TaskLogRepository; import com.zcloud.gbscommon.utils.DateUtil; import com.zcloud.gbscommon.utils.Tools; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; 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.List; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** - * web-app + * 任务日志新增执行器 + * 负责创建新的作业流程 * * @Author fangjiakai * @Date 2025-11-05 09:53:53 */ +@Slf4j @Component @AllArgsConstructor public class TaskLogAddExe { + /** 第一步(申请步骤)的步骤ID */ + private static final Long FIRST_STEP_ID = 1L; + /** 可跳过标识 */ + private static final Integer CAN_SKIP_FLAG = 1; + /** 持续步骤标识 */ + private static final Integer ONGOING_FLAG = 1; + /** 票号 Redis Key 前缀 */ + private static final String TICKET_NO_KEY_PREFIX = "eightwork:ticket:no:"; + /** Redis Key 过期时间(48小时,确保跨天仍可用) */ + private static final long KEY_EXPIRE_HOURS = 48; + private final TaskLogGateway taskLogGateway; private final TaskLogRepository taskLogRepository; private final TaskFlowGateway taskFlowGateway; private final EightworkInfoRepository eightworkInfoRepository; + private final StringRedisTemplate stringRedisTemplate; @Transactional(rollbackFor = Exception.class) - public synchronized List execute(TaskLogAddCmd cmd) { + public List execute(TaskLogAddCmd cmd) { + log.info("开始创建作业流程: workType={}, workLevel={}", cmd.getWorkType(), cmd.getWorkLevel()); + try { + // 1. 创建作业信息 String workId = saveWork(cmd); + log.info("作业信息已创建: workId={}", workId); + + // 2. 获取流程配置 List flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel()); - List taskLogs = flows.stream().map(flow -> { - TaskLogDO taskLogDO = new TaskLogDO(Tools.get32UUID()); - BeanUtils.copyProperties(flow, taskLogDO, "id"); - taskLogDO.setWorkId(workId); - taskLogDO.setStatus(-99); - if (flow.getStepId() == 1) { - taskLogDO.setSign(flow.getActorField(), - AuthContext.getOrgId(), - AuthContext.getCurrentUser().getOrgName(), - AuthContext.getUserId(), - AuthContext.getName()); - } - TaskSignStepInfoCmd taskSignStepInfoCmd = cmd.getSignLogs().stream().filter(info -> info.getStepId().equals(flow.getStepId())).findFirst().orElse(null); - if (taskSignStepInfoCmd != null) { - if (flow.getCanSkip() == 1 && taskSignStepInfoCmd.getActUser() == null) { - taskLogDO.setStatus(-1); // 设置跳过 - } else { - taskLogDO.setSign(taskSignStepInfoCmd.getActorField(), - taskSignStepInfoCmd.getActUserDepartment(), - taskSignStepInfoCmd.getActUserDepartmentName(), - taskSignStepInfoCmd.getActUser(), - taskSignStepInfoCmd.getActUserName()); - taskLogDO.setWorkType(cmd.getWorkType()); - } - } - return taskLogDO; - }).collect(Collectors.toList()); + log.info("获取到 {} 个流程步骤", flows.size()); + + // 3. 生成任务日志 + List taskLogs = flows.stream().map(flow -> createTaskLog(flow, workId, cmd)).collect(Collectors.toList()); + + // 4. 批量保存 taskLogRepository.saveBatch(taskLogs); + + log.info("作业流程创建成功: workId={}, stepCount={}", workId, taskLogs.size()); return taskLogs; } catch (Exception e) { - e.printStackTrace(); - throw new BizException("保存失败"); + log.error("创建作业流程失败: workType={}", cmd.getWorkType(), e); + throw new BizException("保存失败: " + e.getMessage()); } } + /** + * 创建任务日志记录 + */ + private TaskLogDO createTaskLog(TaskFlowE flow, String workId, TaskLogAddCmd cmd) { + TaskLogDO taskLogDO = new TaskLogDO(Tools.get32UUID()); + BeanUtils.copyProperties(flow, taskLogDO, "id"); + taskLogDO.setWorkId(workId); + + // 持续步骤(如气体检测):申请后就开始,且状态始终为进行中 + if (flow.getOngoingFlag() != null && flow.getOngoingFlag() == 1) { + taskLogDO.setStatus(TaskLogStatus.IN_PROGRESS.getCode()); + taskLogDO.setCurrentFillTimes(0); + log.info("持续步骤已初始化: stepName={}", flow.getStepName()); + } else { + // 默认状态为未开始 + taskLogDO.setStatus(TaskLogStatus.NOT_STARTED.getCode()); + } + + // 第一步自动设置为当前申请人 + if (FIRST_STEP_ID.equals(flow.getStepId())) { + taskLogDO.setSign( + flow.getActorField(), + AuthContext.getOrgId(), + AuthContext.getCurrentUser().getOrgName(), + AuthContext.getUserId(), + AuthContext.getName() + ); + log.info("第一步已设置申请人: stepName={}", flow.getStepName()); + } + + // 处理用户预设的签字人 + TaskSignStepInfoCmd signInfo = findSignInfo(cmd, flow.getStepId()); + if (signInfo != null) { + handlePredefinedSigner(taskLogDO, flow, signInfo, cmd); + } + + return taskLogDO; + } + + /** + * 查找用户预设的签字人信息 + */ + private TaskSignStepInfoCmd findSignInfo(TaskLogAddCmd cmd, Long stepId) { + if (cmd.getSignLogs() == null) { + return null; + } + return cmd.getSignLogs().stream() + .filter(info -> info.getStepId().equals(stepId)) + .findFirst() + .orElse(null); + } + + /** + * 处理用户预设的签字人 + */ + private void handlePredefinedSigner(TaskLogDO taskLogDO, TaskFlowE flow, TaskSignStepInfoCmd signInfo, TaskLogAddCmd cmd) { + // 可跳过步骤且未设置签字人,则设置为跳过状态 + if (CAN_SKIP_FLAG.equals(flow.getCanSkip()) && signInfo.getActUser() == null) { + taskLogDO.setStatus(TaskLogStatus.SKIPPED.getCode()); + log.info("步骤设置为跳过: stepName={}", flow.getStepName()); + } else { + // 设置预设签字人 + taskLogDO.setSign( + signInfo.getActorField(), + signInfo.getActUserDepartment(), + signInfo.getActUserDepartmentName(), + signInfo.getActUser(), + signInfo.getActUserName() + ); + taskLogDO.setWorkType(cmd.getWorkType()); + log.info("已设置预设签字人: stepName={}, userName={}", flow.getStepName(), signInfo.getActUserName()); + } + } + + /** + * 创建作业信息 + * 使用 Redis 原子递增生成票号,确保并发安全 + */ private String saveWork(TaskLogAddCmd cmd) { - Long workCountBytype = eightworkInfoRepository.countByWorkType(cmd.getWorkType()); - String nosb = "QG" + - WorkCodeEnum.getCodeByWorkType(cmd.getWorkType()) + - DateUtil.getDays() + - workCountBytype; - EightworkInfoDO eightworkInfo = new EightworkInfoDO(Tools.get32UUID() - , cmd.getWorkType() - , cmd.getWorkLevel() - , cmd.getCorpinfoId() - , cmd.getXgfFlag() - , cmd.getInternalOperationFlag() - , cmd.getProjectId() - , cmd.getXgfId() - , nosb - , 1 - , cmd.getInfo() - , cmd.getDepartmentId()); + String workType = cmd.getWorkType(); + String workTypeCode = WorkCodeEnum.getCodeByWorkType(workType); + String date = DateUtil.getDays(); + + // 构建 Redis Key: eightwork:ticket:no:DH:20250312 + String redisKey = buildTicketNoKey(workTypeCode, date); + + // Redis 原子递增获取序号(从1开始) + Long seq = stringRedisTemplate.opsForValue().increment(redisKey); + + if (seq == 1) { + stringRedisTemplate.expire(redisKey, KEY_EXPIRE_HOURS, TimeUnit.HOURS); + } + + log.info("生成票号: workType={}, date={}, seq={}", workType, date, seq); + + // 生成票号: QG + 作业类型代码 + 日期 + 4位序号 + String checkNo = "QG" + workTypeCode + date + String.format("%04d", seq); + + EightworkInfoDO eightworkInfo = new EightworkInfoDO( + Tools.get32UUID(), + cmd.getWorkType(), + cmd.getWorkLevel(), + cmd.getCorpinfoId(), + cmd.getXgfFlag(), + cmd.getInternalOperationFlag(), + cmd.getProjectId(), + cmd.getXgfId(), + checkNo, + TaskLogStatus.IN_PROGRESS.getCode(), // 初始状态为进行中 + cmd.getInfo(), + cmd.getDepartmentId() + ); + eightworkInfoRepository.save(eightworkInfo); return eightworkInfo.getWorkId(); } -} + /** + * 构建票号 Redis Key + * 格式: eightwork:ticket:no:{作业类型代码}:{日期} + * + * @param workTypeCode 作业类型代码,如 DH、MBCD 等 + * @param date 日期,格式 yyyyMMdd + * @return Redis Key + */ + private String buildTicketNoKey(String workTypeCode, String date) { + return TICKET_NO_KEY_PREFIX + workTypeCode + ":" + date; + } +} diff --git a/web-app/src/main/java/com/zcloud/eightwork/command/TaskLogUpdateExe.java b/web-app/src/main/java/com/zcloud/eightwork/command/TaskLogUpdateExe.java index 9e679cc..ba5fcb3 100644 --- a/web-app/src/main/java/com/zcloud/eightwork/command/TaskLogUpdateExe.java +++ b/web-app/src/main/java/com/zcloud/eightwork/command/TaskLogUpdateExe.java @@ -6,10 +6,15 @@ 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.zcloud.eightwork.command.convertor.TaskLogConvertUtil; import com.zcloud.eightwork.domain.gateway.TaskLogGateway; +import com.zcloud.eightwork.domain.gateway.EightworkSupplementaryInfoGateway; import com.zcloud.eightwork.domain.model.MeasuresLogsE; +import com.zcloud.eightwork.domain.model.EightworkSupplementaryInfoE; import com.zcloud.eightwork.domain.model.TaskLogE; -import com.zcloud.eightwork.domain.model.enums.MenuEnum; +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.domain.model.enums.WorkCodeEnum; import com.zcloud.eightwork.dto.TaskLogNextCmd; import com.zcloud.eightwork.dto.TaskLogUpdateCmd; @@ -24,6 +29,7 @@ import com.zcloud.gbscommon.todolistmq.TodoListEventPusherUtil; import com.zcloud.gbscommon.todolistmq.event.TodoListAddEvent; import com.zcloud.gbscommon.todolistmq.event.TodoListCompleteEvent; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Component; @@ -35,19 +41,37 @@ import java.util.stream.Collectors; /** - * web-app + * 任务日志更新执行器 + * 负责处理任务日志的更新和流转逻辑 * * @Author fangjiakai * @Date 2025-11-05 09:53:54 */ +@Slf4j @Component @AllArgsConstructor public class TaskLogUpdateExe { + /** 签字步骤标识 */ + private static final Integer SIGN_STEP_FLAG = 1; + /** 多人签字标识 */ + private static final Integer MULTIPLE_FLAG = 1; + /** 主要措施类型 */ + private static final Integer MAIN_MEASURE_TYPE = 1; + /** 可添加其他安全措施标识 */ + private static final Integer MEASURES_STEP_FLAG = 1; + /** 可跳过标识 */ + private static final Integer CAN_SKIP_FLAG = 1; + /** PC端待办标识 */ + private static final Integer PC_FLAG = 1; + /** APP端待办标识 */ + private static final Integer APP_FLAG = 1; + private final TaskLogGateway taskLogGateway; private final TaskLogRepository taskLogRepository; private final MeasuresLogsRepository measuresLogsRepository; private final EightworkInfoRepository eightworkInfoRepository; - private final TodoListEventPusherUtil todoListEventPusherUtil; + private final TodoListEventPusherUtil todoListEventPusherUtil; + private final EightworkSupplementaryInfoGateway eightworkSupplementaryInfoGateway; @Transactional(rollbackFor = Exception.class) public void execute(TaskLogUpdateCmd taskLogUpdateCmd) { @@ -59,178 +83,547 @@ public class TaskLogUpdateExe { } } + /** + * 处理步骤流转 + * 这是核心的流转逻辑,负责: + * 1. 完成当前步骤 + * 2. 判断是否可以流转到下一步 + * 3. 处理特殊步骤逻辑 + * 4. 激活下一步 + * 5. 处理分支流程 + * 6. 设置后续签字人 + * + * @param cmd 步骤流转命令 + */ @Transactional(rollbackFor = Exception.class) public void nextStep(TaskLogNextCmd cmd) { + log.info("开始处理步骤流转: workId={}, stepId={}, status={}", + cmd.getWorkId(), cmd.getStepId(), cmd.getStatus()); + List logs = taskLogGateway.listAllByWorkId(cmd.getWorkId()); - // 待操作logs List actionLogs = new ArrayList<>(); - logs.forEach(log -> { - // 修改当前步骤状态 - if (log.getId().equals(cmd.getId())) { - log.setStatus(cmd.getStatus()); - if (log.getSignStepFlag() == 1) { - log.setSignPath(cmd.getSignPath()); - } - TodoListCompleteEvent todoCompletedTaskEvent = new TodoListCompleteEvent(); - todoCompletedTaskEvent.setForeignSubsidiaryKey(log.getId()); - todoListEventPusherUtil.sendMessageCompleteEvent(todoCompletedTaskEvent); + // 查找当前处理的步骤日志 + TaskLogE currentLog = findCurrentLog(logs, cmd.getId()); - TaskLogDO logDO = new TaskLogDO(); - BeanUtils.copyProperties(log, logDO); - actionLogs.add(logDO); - // 同意时 - if (cmd.getStatus() == 1) { - // 多人签字步骤时 - boolean canNext = true; - if (log.getMultipleFlag() == 1) { - // 获取多人签字步骤未签字的其他人人数 - long multipleSigns = logs.stream().filter(info -> info.getStepId().equals(log.getStepId()) && log.getStatus() != 1 && !log.getId().equals(cmd.getId())).collect(Collectors.toList()).size(); - canNext = multipleSigns == 0; - } - // 特殊步骤 - if (StringUtils.isNotBlank(log.getSpecialStepCode())) { - canNext = handleSpecialStep(log, cmd, actionLogs); - } - // 其他安全措施步骤 - if (log.getMeasuresStepFlag() != null && 1 == log.getMeasuresStepFlag()) { - MeasuresLogsDO measuresLogsDO = new MeasuresLogsDO( - cmd.getOthers().getString("otherMeasures"), - log.getWorkId(), - log.getWorkType() - ); - measuresLogsRepository.save(measuresLogsDO); - } - if (canNext) { - // 递归 直到找到不跳过的下一步 - handleNextStep(log, actionLogs, logs); - } + if (currentLog == null) { + throw new BizException("未找到对应的步骤记录"); + } - // 如果当前步骤为分支开始步骤 - if (log.getStepType() == 1 && log.getBranchFlag() == 1) { - TaskLogE branchStep = logs.stream().filter(info -> info.getStepId().equals(log.getBranchStep())).findFirst().orElse(null); - if (branchStep != null) { - branchStep.setStatus(0); - TaskLogDO branchLogDO = new TaskLogDO(); - BeanUtils.copyProperties(branchStep, branchLogDO); - actionLogs.add(branchLogDO); - } - } - // 判断是否有当前步骤设置的签字人 - if (cmd.getSignLogs() != null && cmd.getSignLogs().size() > 0) { - cmd.getSignLogs().stream().forEach(info -> { - TaskLogE signStepLog = logs.stream().filter(tempLog -> tempLog.getStepId().equals(info.getStepId())).findFirst().orElse(null); - if (signStepLog != null) { - if (log.getCanSkip() == 1 && signStepLog.getActUser() == null) { - log.setStatus(-1); // 设置跳过 - TaskLogDO skipLogDO = new TaskLogDO(); - BeanUtils.copyProperties(log, skipLogDO); - actionLogs.add(skipLogDO); - } else { - signStepLog.setSign(info.getActorField(), - info.getActUserDepartment(), - info.getActUserDepartmentName(), - info.getActUser(), - info.getActUserName()); - TaskLogDO signLogDO = new TaskLogDO(); - BeanUtils.copyProperties(signStepLog, signLogDO); - actionLogs.add(signLogDO); - } - } - }); - } + // 1. 完成当前步骤 + completeCurrentStep(currentLog, cmd, actionLogs); + + // 2. 判断是否通过,通过才流转 + if (TaskLogStatus.APPROVED.equalsCode(cmd.getStatus())) { + // 3. 判断是否可以流转到下一步 + if (canProceedToNext(currentLog, logs, cmd)) { + // 4. 处理特殊步骤逻辑 + boolean shouldProceed = handleSpecialStepIfNeeded(currentLog, cmd, actionLogs); + + // 5. 处理其他安全措施 + handleOtherMeasuresIfNeeded(currentLog, cmd); + + // 6. 流转到下一步 + if (shouldProceed) { + proceedToNextStep(currentLog, actionLogs, logs); } } - }); + + // 7. 处理分支流程 + handleBranchIfNeeded(currentLog, actionLogs, logs); + + // 8. 设置后续签字人 + handleSignStepsIfNeeded(currentLog, cmd, actionLogs, logs); + } + + // 批量更新 taskLogRepository.updateBatchById(actionLogs); + + log.info("步骤流转完成: workId={}, currentStep={}", cmd.getWorkId(), currentLog.getStepName()); } /** - * 下一步 递归 - * - * @param log 当前步骤 - * @param actionLogs 待修改记录 - * @param logs 所有步骤 - * @return + * 查找当前处理的步骤日志 */ - private void handleNextStep(TaskLogE log, List actionLogs, List logs) { - List nextStep = logs.stream().filter(info -> info.getStepId().equals(log.getNextStep())).collect(Collectors.toList()); - if (!CollectionUtil.isEmpty(nextStep)) { - // 下一步跳过时, 多人签字不存在跳过情况 - TaskLogE nextStepTemp = nextStep.get(0); - if (nextStepTemp.getStatus() == -1) { // 步骤可跳过 并且未设置签字人 则判断为跳过步骤 - handleNextStep(nextStepTemp, actionLogs, logs); - } else { // 非跳过时 - Long workId = eightworkInfoRepository.getOne(new LambdaQueryWrapper().select(EightworkInfoDO::getId).eq(EightworkInfoDO::getWorkId, log.getWorkId())).getId(); - // 可能涉及多人签字 - nextStep.forEach(next -> { - next.setStatus(0); - TaskLogDO nextLogDO = new TaskLogDO(); - BeanUtils.copyProperties(next, nextLogDO); - actionLogs.add(nextLogDO); - - // 添加待办 - TodoListAddEvent event = new TodoListAddEvent(); - event.setTitle("您有一条"+ WorkCodeEnum.getNameByWorkType(log.getWorkType()) +"流程待处理"); - event.setContent(next.getNextStepName()); - event.setForeignKey(workId); // 业务表ID - event.setForeignSubsidiaryKey(next.getId()); // 业务附表ID 没有附表时为foreignKey的值 - event.setReceiveUser(next.getActUser());// user表ID - event.setPcFlag(1); // 是否PC端待办 1是 0否 - event.setAppFlag(1); // 是否APP端待办 1是 0否 - event.setOtherParams(new JSONObject()); - todoListEventPusherUtil.sendMessageAddEvent(event); - }); - eightworkInfoRepository.updateWorkStatus(log.getWorkId(),nextStep.get(0).getStepName() , null); - } - }else{ - // 没有下一步 则设置作业状态为999 验收 - eightworkInfoRepository.updateWorkStatus(log.getWorkId(), "已归档", 999); - } + private TaskLogE findCurrentLog(List logs, Long id) { + return logs.stream() + .filter(log -> log.getId().equals(id)) + .findFirst() + .orElse(null); } /** - * 特殊步骤 - * - * @param log 当前步骤 - * @param cmd 特殊步骤参数 - * @param actionLogs 待修改记录 - * @return + * 完成当前步骤 + * - 更新状态 + * - 保存签字图片 + * - 发送待办完成事件 */ - private boolean handleSpecialStep(TaskLogE log, TaskLogNextCmd cmd, List actionLogs) { - if ("delay".equals(cmd.getSpecialStepCode())) { // 延时监火转交时, 完成时SpecialStepCode为null走正常下一步 - // 保存下一步转交人记录 - TaskLogE newDelayStep = new TaskLogE(log); - TaskLogDO nextLogDO = new TaskLogDO(); - BeanUtils.copyProperties(newDelayStep, nextLogDO); - nextLogDO.setActUserDepartment(cmd.getOthers().getLong("actUserDepartment")); - nextLogDO.setActUserDepartmentName(cmd.getOthers().getString("actUserDepartmentName")); - taskLogRepository.save(nextLogDO); + private void completeCurrentStep(TaskLogE currentLog, TaskLogNextCmd cmd, List actionLogs) { + log.info("完成当前步骤: stepName={}, status={}", currentLog.getStepName(), cmd.getStatus()); - // 修改当前步骤状态为已完成 - log.setStatus(1); - TaskLogDO currentLog = new TaskLogDO(); - BeanUtils.copyProperties(log, currentLog); - actionLogs.add(currentLog); - return false; - }else if("measures".equals(cmd.getSpecialStepCode())){ - List list = new ArrayList<>(); - JSONArray array = cmd.getOthers().getJSONArray("measures"); - if (array != null) { - for (int i = 0; i < array.size(); i++) { - MeasuresLogsE cmdItem = JSONUtil.toBean(array.getJSONObject(i).toJSONString(), MeasuresLogsE.class); - list.add(cmdItem); - } - } - measuresLogsRepository.saveBatch(list.stream().map(item -> { - MeasuresLogsDO d = new MeasuresLogsDO(); - BeanUtils.copyProperties(item, d, "id"); - d.setType(1); - return d; - }).collect(Collectors.toList())); - return true; + currentLog.setStatus(cmd.getStatus()); + + // 签字步骤,保存签字图片 + if (SIGN_STEP_FLAG.equals(currentLog.getSignStepFlag())) { + currentLog.setSignPath(cmd.getSignPath()); } + + // 发送待办完成事件 + sendTodoCompleteEvent(currentLog.getId()); + + actionLogs.add(TaskLogConvertUtil.toDO(currentLog)); + } + + /** + * 判断是否可以流转到下一步 + * - 检查多人签字是否都已完成 + * - 检查特殊步骤是否允许流转 + */ + private boolean canProceedToNext(TaskLogE currentLog, List logs, TaskLogNextCmd cmd) { + // 1. 多人签字步骤:需要所有人都签字 + if (MULTIPLE_FLAG.equals(currentLog.getMultipleFlag())) { + long pendingSigns = logs.stream() + .filter(log -> log.getStepId().equals(currentLog.getStepId()) + && !TaskLogStatus.APPROVED.equalsCode(log.getStatus()) + && !log.getId().equals(currentLog.getId())) + .count(); + + if (pendingSigns > 0) { + log.info("多人签字步骤,还有 {} 人未签字,暂不流转", pendingSigns); + return false; + } + } + + // 2. 检查是否为特殊步骤 + if (StringUtils.isNotBlank(currentLog.getSpecialStepCode())) { + // 特殊步骤的流转判断在 handleSpecialStepIfNeeded 中处理 + } + return true; } -} + /** + * 处理特殊步骤逻辑 + * - delay: 延时监火转交 + * - measures: 安全措施确认 + * - gas: 气体检测记录 + * + * @return 是否允许继续流转到下一步 + */ + private boolean handleSpecialStepIfNeeded(TaskLogE currentLog, TaskLogNextCmd cmd, List actionLogs) { + String specialStepCode = cmd.getSpecialStepCode(); + + if (StringUtils.isBlank(specialStepCode)) { + return true; + } + + log.info("处理特殊步骤: stepCode={}", specialStepCode); + + switch (specialStepCode) { + case "delay": + return handleDelayStep(currentLog, cmd, actionLogs); + case "measures": + return handleMeasuresStep(currentLog, cmd, actionLogs); + case "gas": + return handleGasDetectionStep(currentLog, cmd, actionLogs); + default: + log.warn("未知的特殊步骤类型: {}", specialStepCode); + return true; + } + } + + /** + * 处理延时监火转交步骤 + * 创建一个新的转交记录,当前步骤标记为已完成 + */ + private boolean handleDelayStep(TaskLogE currentLog, TaskLogNextCmd cmd, List actionLogs) { + log.info("处理延时监火转交"); + + // 保存延时监火信息到 eightwork_supplementary_info 表 + EightworkSupplementaryInfoE supplementaryInfo = new EightworkSupplementaryInfoE(); + supplementaryInfo.setTaskLogId(currentLog.getTaskLogId()); + supplementaryInfo.setWorkId(currentLog.getWorkId()); + supplementaryInfo.setType("delay"); + supplementaryInfo.setDetails(cmd.getOthers()); + eightworkSupplementaryInfoGateway.add(supplementaryInfo); + + // 保存下一步转交人记录 + TaskLogE newDelayStep = new TaskLogE(currentLog); + TaskLogDO nextLogDO = new TaskLogDO(); + BeanUtils.copyProperties(newDelayStep, nextLogDO); + nextLogDO.setActUserDepartment(cmd.getOthers().getLong("actUserDepartment")); + nextLogDO.setActUserDepartmentName(cmd.getOthers().getString("actUserDepartmentName")); + taskLogRepository.save(nextLogDO); + + // 修改当前步骤状态为已完成 + currentLog.setStatus(TaskLogStatus.APPROVED.getCode()); + actionLogs.add(TaskLogConvertUtil.toDO(currentLog)); + + // 延时转交步骤不自动流转下一步 + return false; + } + + /** + * 处理安全措施确认步骤 + * 保存安全措施记录 + */ + private boolean handleMeasuresStep(TaskLogE currentLog, TaskLogNextCmd cmd, List actionLogs) { + log.info("处理安全措施确认"); + + List measuresList = new ArrayList<>(); + JSONArray array = cmd.getOthers().getJSONArray("measures"); + if (array != null) { + for (int i = 0; i < array.size(); i++) { + MeasuresLogsE item = JSONUtil.toBean(array.getJSONObject(i).toJSONString(), MeasuresLogsE.class); + measuresList.add(item); + } + } + + measuresLogsRepository.saveBatch(measuresList.stream().map(item -> { + MeasuresLogsDO d = new MeasuresLogsDO(); + BeanUtils.copyProperties(item, d, "id"); + d.setType(MAIN_MEASURE_TYPE); + return d; + }).collect(Collectors.toList())); + + return true; + } + + /** + * 处理气体检测记录步骤 + * 保存气体检测记录,更新填写次数 + */ + private boolean handleGasDetectionStep(TaskLogE currentLog, TaskLogNextCmd cmd, List actionLogs) { + log.info("处理气体检测记录"); + + // 保存气体检测信息到 eightwork_supplementary_info 表 + EightworkSupplementaryInfoE supplementaryInfo = new EightworkSupplementaryInfoE(); + supplementaryInfo.setTaskLogId(currentLog.getTaskLogId()); + supplementaryInfo.setWorkId(currentLog.getWorkId()); + supplementaryInfo.setType("gas"); + supplementaryInfo.setDetails(cmd.getOthers()); + eightworkSupplementaryInfoGateway.add(supplementaryInfo); + + // 更新持续步骤的填写次数 + Integer currentTimes = currentLog.getCurrentFillTimes(); + if (currentTimes == null) { + currentTimes = 0; + } + currentLog.setCurrentFillTimes(currentTimes + 1); + actionLogs.add(TaskLogConvertUtil.toDO(currentLog)); + + log.info("气体检测记录已保存,当前填写次数: {}", currentTimes + 1); + + // 气体检测步骤不流转,保持活跃状态 + return false; + } + + /** + * 处理其他安全措施步骤 + * 当 steps.measuresStepFlag == 1 时,允许添加其他安全措施 + */ + private void handleOtherMeasuresIfNeeded(TaskLogE currentLog, TaskLogNextCmd cmd) { + if (MEASURES_STEP_FLAG.equals(currentLog.getMeasuresStepFlag())) { + String otherMeasures = cmd.getOthers() != null ? cmd.getOthers().getString("otherMeasures") : null; + if (StringUtils.isNotBlank(otherMeasures)) { + MeasuresLogsDO measuresLogsDO = new MeasuresLogsDO( + otherMeasures, + currentLog.getWorkId(), + currentLog.getWorkType() + ); + measuresLogsRepository.save(measuresLogsDO); + log.info("已添加其他安全措施"); + } + } + } + + /** + * 流转到下一步 + * 递归处理,直到找到不需要跳过的步骤或流程结束 + */ + private void proceedToNextStep(TaskLogE currentLog, List actionLogs, List allLogs) { + List nextSteps = findNextSteps(currentLog, allLogs); + + if (CollectionUtil.isEmpty(nextSteps)) { + // 没有下一步,流程结束 + completeWorkflow(currentLog); + return; + } + + TaskLogE nextStep = nextSteps.get(0); + + // 判断下一步是否为跳过状态 + if (TaskLogStatus.SKIPPED.equalsCode(nextStep.getStatus())) { + log.info("下一步为跳过步骤,继续递归: {}", nextStep.getStepName()); + proceedToNextStep(nextStep, actionLogs, allLogs); + return; + } + + // 判断下一步是否为合并节点(需要等待所有前置步骤都完成) + if (isMergeNode(nextStep)) { + if (!areAllBranchesCompleted(nextStep, allLogs)) { + List pendingSteps = getPendingBranches(nextStep, allLogs); + log.info("合并节点等待其他前置步骤完成: mergeNode={}, waitingSteps={}", + nextStep.getStepName(), + pendingSteps.stream() + .map(TaskLogE::getStepName) + .collect(java.util.stream.Collectors.joining(", "))); + // 不激活合并节点,等待其他前置步骤完成 + return; + } + log.info("所有前置步骤已完成,激活合并节点: {}", nextStep.getStepName()); + } + + // 判断下一步是否被持续步骤阻塞(如气体检测必须填写指定次数) + if (isBlockedByOngoingStep(nextStep, allLogs)) { + TaskLogE blockingStep = findBlockingStep(nextStep, allLogs); + log.info("步骤被持续步骤阻塞: step={}, blockingStep={}, currentTimes={}, requiredTimes={}", + nextStep.getStepName(), + blockingStep != null ? blockingStep.getStepName() : "未知", + blockingStep != null ? blockingStep.getCurrentFillTimes() : 0, + blockingStep != null ? blockingStep.getMinFillTimes() : 0); + // 不激活步骤,等待持续步骤填写足够次数 + return; + } + + // 激活下一步 + activateNextSteps(nextSteps, actionLogs, currentLog); + } + + /** + * 判断是否为合并节点 + */ + private boolean isMergeNode(TaskLogE step) { + BranchFlag branchFlag = BranchFlag.getByCode(step.getBranchFlag()); + return branchFlag.isBranchEnd(); + } + + /** + * 检查所有指向合并节点的前置步骤是否都已完成(并行模式) + * 包括主流程和分支步骤,必须都完成才能激活合并节点 + * + * @param mergeNode 合并节点 + * @param allLogs 所有步骤日志 + * @return true-所有前置步骤都已完成,false-还有步骤未完成 + */ + private boolean areAllBranchesCompleted(TaskLogE mergeNode, List allLogs) { + List pendingSteps = getPendingBranches(mergeNode, allLogs); + return pendingSteps.isEmpty(); + } + + /** + * 获取所有未完成的前置步骤 + * 对于并行模式,需要检查所有指向合并节点的步骤(包括主流程和分支) + * + * @param mergeNode 合并节点 + * @param allLogs 所有步骤日志 + * @return 未完成的步骤列表 + */ + private List getPendingBranches(TaskLogE mergeNode, List allLogs) { + List pendingSteps = new ArrayList<>(); + + for (TaskLogE log : allLogs) { + // 找出所有指向该合并节点的步骤(通过 nextStep 判断) + // 这样可以同时检查主流程和分支步骤 + if (mergeNode.getStepId().equals(log.getNextStep())) { + // 检查是否已完成 + if (!TaskLogStatus.APPROVED.equalsCode(log.getStatus())) { + pendingSteps.add(log); + } + } + } + + return pendingSteps; + } + + /** + * 判断步骤是否被持续步骤阻塞 + * 持续步骤(如气体检测)必须填写指定次数后,阻塞的步骤才能激活 + */ + private boolean isBlockedByOngoingStep(TaskLogE step, List allLogs) { + // 找出阻塞当前步骤的持续步骤 + TaskLogE blockingStep = findBlockingStep(step, allLogs); + if (blockingStep == null) { + return false; + } + + // 检查填写次数是否满足要求 + Integer currentTimes = blockingStep.getCurrentFillTimes(); + Integer requiredTimes = blockingStep.getMinFillTimes(); + + return currentTimes == null || currentTimes < requiredTimes; + } + + /** + * 查找阻塞指定步骤的持续步骤 + */ + private TaskLogE findBlockingStep(TaskLogE step, List allLogs) { + for (TaskLogE log : allLogs) { + // 找出持续步骤,且其阻塞的步骤ID等于当前步骤ID + if (Integer.valueOf(1).equals(log.getOngoingFlag()) + && step.getStepId().equals(log.getBlockingStepId())) { + return log; + } + } + return null; + } + + /** + * 查找下一步骤 + */ + private List findNextSteps(TaskLogE currentLog, List allLogs) { + return allLogs.stream() + .filter(log -> log.getStepId().equals(currentLog.getNextStep())) + .collect(Collectors.toList()); + } + + /** + * 激活下一步骤 + * - 设置状态为进行中 + * - 发送待办通知 + * - 更新作业当前步骤 + */ + private void activateNextSteps(List nextSteps, List actionLogs, TaskLogE currentLog) { + Long workId = getWorkId(currentLog.getWorkId()); + + for (TaskLogE next : nextSteps) { + next.setStatus(TaskLogStatus.IN_PROGRESS.getCode()); + actionLogs.add(TaskLogConvertUtil.toDO(next)); + + // 发送待办通知 + sendTodoAddEvent(workId, next, currentLog.getWorkType()); + + log.info("已激活下一步: {}", next.getStepName()); + } + + // 更新作业当前步骤 + eightworkInfoRepository.updateWorkStatus( + currentLog.getWorkId(), + nextSteps.get(0).getStepName(), + null + ); + } + + /** + * 完成工作流 + * 设置作业状态为已归档 + */ + private void completeWorkflow(TaskLogE currentLog) { + log.info("工作流已完成,开始归档: workId={}", currentLog.getWorkId()); + eightworkInfoRepository.updateWorkStatus( + currentLog.getWorkId(), + "已归档", + TaskLogStatus.ARCHIVED.getCode() + ); + } + + /** + * 处理分支流程 + * 职责:当主流程步骤为分支开始节点时,激活对应的分支步骤 + */ + private void handleBranchIfNeeded(TaskLogE currentLog, List actionLogs, List allLogs) { + StepType stepType = StepType.getByCode(currentLog.getStepType()); + BranchFlag branchFlag = BranchFlag.getByCode(currentLog.getBranchFlag()); + + // 只处理:主流程步骤完成,且为分支开始节点 → 激活分支步骤 + if (stepType != null && stepType.isNormalStep() && branchFlag.isBranchStart()) { + TaskLogE branchStep = allLogs.stream() + .filter(log -> log.getStepId().equals(currentLog.getBranchStep())) + .findFirst() + .orElse(null); + + if (branchStep != null) { + branchStep.setStatus(TaskLogStatus.IN_PROGRESS.getCode()); + actionLogs.add(TaskLogConvertUtil.toDO(branchStep)); + sendTodoAddEvent(getWorkId(currentLog.getWorkId()), branchStep, currentLog.getWorkType()); + log.info("已激活分支步骤: stepName={}, mergeTo={}", branchStep.getStepName(), branchStep.getBranchMergeStep()); + } + } + } + + /** + * 设置后续签字人 + * 处理当前步骤设置的签字人信息 + */ + private void handleSignStepsIfNeeded(TaskLogE currentLog, TaskLogNextCmd cmd, + List actionLogs, List allLogs) { + List signLogs = cmd.getSignLogs(); + if (CollectionUtil.isEmpty(signLogs)) { + return; + } + + for (TaskSignStepInfoCmd signInfo : signLogs) { + TaskLogE signStepLog = allLogs.stream() + .filter(log -> log.getStepId().equals(signInfo.getStepId())) + .findFirst() + .orElse(null); + + if (signStepLog == null) { + continue; + } + + // 检查是否需要跳过 + if (CAN_SKIP_FLAG.equals(currentLog.getCanSkip()) && signInfo.getActUser() == null) { + // 设置为跳过状态 + signStepLog.setStatus(TaskLogStatus.SKIPPED.getCode()); + actionLogs.add(TaskLogConvertUtil.toDO(signStepLog)); + log.info("步骤设置为跳过: {}", signStepLog.getStepName()); + } else { + // 设置签字人 + signStepLog.setSign( + signInfo.getActorField(), + signInfo.getActUserDepartment(), + signInfo.getActUserDepartmentName(), + signInfo.getActUser(), + signInfo.getActUserName() + ); + actionLogs.add(TaskLogConvertUtil.toDO(signStepLog)); + log.info("已设置签字人: step={}, user={}", signStepLog.getStepName(), signInfo.getActUserName()); + } + } + } + + /** + * 发送待办完成事件 + */ + private void sendTodoCompleteEvent(Long taskLogId) { + try { + TodoListCompleteEvent event = new TodoListCompleteEvent(); + event.setForeignSubsidiaryKey(taskLogId); + todoListEventPusherUtil.sendMessageCompleteEvent(event); + } catch (Exception e) { + log.error("发送待办完成事件失败: taskLogId={}", taskLogId, e); + } + } + + /** + * 发送待办新增事件 + */ + private void sendTodoAddEvent(Long workId, TaskLogE nextStep, String workType) { + try { + TodoListAddEvent event = new TodoListAddEvent(); + event.setTitle("您有一条" + WorkCodeEnum.getNameByWorkType(workType) + "流程待处理"); + event.setContent(nextStep.getNextStepName()); + event.setForeignKey(workId); + event.setForeignSubsidiaryKey(nextStep.getId()); + event.setReceiveUser(nextStep.getActUser()); + event.setPcFlag(PC_FLAG); + event.setAppFlag(APP_FLAG); + event.setOtherParams(new JSONObject()); + todoListEventPusherUtil.sendMessageAddEvent(event); + } catch (Exception e) { + log.error("发送待办新增事件失败: stepId={}", nextStep.getId(), e); + } + } + + /** + * 获取作业ID + */ + private Long getWorkId(String workId) { + return eightworkInfoRepository.getOne( + new LambdaQueryWrapper() + .select(EightworkInfoDO::getId) + .eq(EightworkInfoDO::getWorkId, workId) + ).getId(); + } +} diff --git a/web-app/src/main/java/com/zcloud/eightwork/command/convertor/TaskLogConvertUtil.java b/web-app/src/main/java/com/zcloud/eightwork/command/convertor/TaskLogConvertUtil.java new file mode 100644 index 0000000..0b58eb5 --- /dev/null +++ b/web-app/src/main/java/com/zcloud/eightwork/command/convertor/TaskLogConvertUtil.java @@ -0,0 +1,38 @@ +package com.zcloud.eightwork.command.convertor; + +import com.zcloud.eightwork.domain.model.TaskLogE; +import com.zcloud.eightwork.persistence.dataobject.TaskLogDO; +import org.springframework.beans.BeanUtils; + +/** + * TaskLog 转换工具类 + * + * @author fangjiakai + * @date 2026-03-12 + */ +public class TaskLogConvertUtil { + + /** + * 将 TaskLogE 转换为 TaskLogDO + */ + public static TaskLogDO toDO(TaskLogE log) { + if (log == null) { + return null; + } + TaskLogDO logDO = new TaskLogDO(); + BeanUtils.copyProperties(log, logDO); + return logDO; + } + + /** + * 将多个 TaskLogE 转换为 TaskLogDO + */ + public static java.util.List toDOList(java.util.List logs) { + if (logs == null) { + return new java.util.ArrayList<>(); + } + return logs.stream() + .map(TaskLogConvertUtil::toDO) + .collect(java.util.stream.Collectors.toList()); + } +} diff --git a/web-app/src/main/java/com/zcloud/eightwork/command/query/TaskFlowQueryExe.java b/web-app/src/main/java/com/zcloud/eightwork/command/query/TaskFlowQueryExe.java index 396ead9..674713d 100644 --- a/web-app/src/main/java/com/zcloud/eightwork/command/query/TaskFlowQueryExe.java +++ b/web-app/src/main/java/com/zcloud/eightwork/command/query/TaskFlowQueryExe.java @@ -34,6 +34,11 @@ import java.util.stream.Collectors; @Component @AllArgsConstructor public class TaskFlowQueryExe { + /** 第一步(申请步骤)的步骤ID */ + private static final Long FIRST_STEP_ID = 1L; + /** 需要选择签字人的步骤标识 */ + private static final Integer NEED_SELECT_SIGN = 1; + private final TaskFlowRepository taskFlowRepository; private final TaskFlowCoConvertor taskFlowCoConvertor; private final EightworkTaskRepository eightworkTaskRepository; @@ -69,7 +74,7 @@ public class TaskFlowQueryExe { TaskFlowInitCO taskFlowInitCO = new TaskFlowInitCO(); taskFlowInitCO.setSettingSignSteps(taskFlowCoConvertor.converDOsToCOs( flows.stream() - .filter(flow -> flow.getSelectSignStep() != null && 1 == flow.getSelectSignStep()) + .filter(flow -> flow.getSelectSignStep() != null && NEED_SELECT_SIGN.equals(flow.getSelectSignStep())) .collect(Collectors.toList()) )); @@ -81,10 +86,10 @@ public class TaskFlowQueryExe { List taskIds = taskDOs.stream().map(EightworkTaskDO::getId).collect(Collectors.toList()); List flows = taskFlowRepository.list(new QueryWrapper() - .select("DISTINCT step_id") + .select("DISTINCT step_id as step_id") .select("step_name") .in("task_id", taskIds) - .ne("step_id", 1) + .ne("step_id", FIRST_STEP_ID) .orderByAsc("step_order")); return taskFlowCoConvertor.converDOsToCOs(flows); diff --git a/web-app/src/main/java/com/zcloud/eightwork/service/TaskLogServiceImpl.java b/web-app/src/main/java/com/zcloud/eightwork/service/TaskLogServiceImpl.java index c859a71..010bb60 100644 --- a/web-app/src/main/java/com/zcloud/eightwork/service/TaskLogServiceImpl.java +++ b/web-app/src/main/java/com/zcloud/eightwork/service/TaskLogServiceImpl.java @@ -5,6 +5,7 @@ import com.zcloud.eightwork.command.TaskLogAddExe; import com.zcloud.eightwork.command.TaskLogRemoveExe; import com.zcloud.eightwork.command.TaskLogUpdateExe; import com.zcloud.eightwork.command.query.TaskLogQueryExe; +import com.zcloud.eightwork.domain.model.enums.TaskLogStatus; import com.zcloud.eightwork.dto.TaskLogAddCmd; import com.zcloud.eightwork.dto.TaskLogNextCmd; import com.zcloud.eightwork.dto.TaskLogPageQry; @@ -54,7 +55,7 @@ public class TaskLogServiceImpl implements TaskLogServiceI { TaskLogNextCmd taskLogNextCmd = new TaskLogNextCmd(commitTaskLogDO.getId(), commitTaskLogDO.getWorkId(), commitTaskLogDO.getStepId(), - 1,null,null,null,null); + TaskLogStatus.APPROVED.getCode(),null,null,null,null); taskLogUpdateExe.nextStep(taskLogNextCmd); return SingleResponse.buildSuccess(); diff --git a/web-client/src/main/java/com/zcloud/eightwork/dto/clientobject/TaskFlowCO.java b/web-client/src/main/java/com/zcloud/eightwork/dto/clientobject/TaskFlowCO.java index 927bf75..cc4f84a 100644 --- a/web-client/src/main/java/com/zcloud/eightwork/dto/clientobject/TaskFlowCO.java +++ b/web-client/src/main/java/com/zcloud/eightwork/dto/clientobject/TaskFlowCO.java @@ -74,4 +74,13 @@ public class TaskFlowCO extends ClientObject { //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; } diff --git a/web-client/src/main/java/com/zcloud/eightwork/dto/clientobject/TaskLogCO.java b/web-client/src/main/java/com/zcloud/eightwork/dto/clientobject/TaskLogCO.java index e703219..810d845 100644 --- a/web-client/src/main/java/com/zcloud/eightwork/dto/clientobject/TaskLogCO.java +++ b/web-client/src/main/java/com/zcloud/eightwork/dto/clientobject/TaskLogCO.java @@ -118,6 +118,18 @@ public class TaskLogCO extends ClientObject { //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 = "当前步骤需设置的签字人") List settingSignSteps; diff --git a/web-domain/src/main/java/com/zcloud/eightwork/domain/model/TaskFlowE.java b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/TaskFlowE.java index e23e51f..de9335a 100644 --- a/web-domain/src/main/java/com/zcloud/eightwork/domain/model/TaskFlowE.java +++ b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/TaskFlowE.java @@ -46,15 +46,21 @@ public class TaskFlowE extends BaseE { private Integer measuresStepFlag; //0无分支1有分支开始2有分支结束 private Integer branchFlag; - //branch_flag == 1 分支节点 - private Integer branchStep; - //step_type == 2 分支节点合并节点 - private Integer branchMergeStep; + //branch_flag == 1 分支节点ID + private Long branchStep; + //step_type == 2 分支节点合并节点ID + private Long branchMergeStep; //分支排序 示例10-1-5 private Integer stepOrder; //是否可跳过1是 private Integer canSkip; //can_skip == 1 跳过条件 示例 age == 20 private String skipCondition; + //是否持续步骤1是(如气体检测,在整个流程期间都活跃) + private Integer ongoingFlag; + //持续步骤最少填写次数 + private Integer minFillTimes; + //持续步骤阻塞的步骤ID(必须填写足够次数后才能激活的步骤) + private Long blockingStepId; } diff --git a/web-domain/src/main/java/com/zcloud/eightwork/domain/model/TaskLogE.java b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/TaskLogE.java index d085ccf..0714f98 100644 --- a/web-domain/src/main/java/com/zcloud/eightwork/domain/model/TaskLogE.java +++ b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/TaskLogE.java @@ -71,16 +71,24 @@ public class TaskLogE extends BaseE { private Integer measuresStepFlag; //0无分支1有分支开始2有分支结束 private Integer branchFlag; - //branch_flag == 1 分支节点 - private Integer branchStep; - //step_type == 2 分支节点合并节点 - private Integer branchMergeStep; + //branch_flag == 1 分支节点ID + private Long branchStep; + //step_type == 2 分支节点合并节点ID + private Long branchMergeStep; //分支排序 示例10-1-5 private Integer stepOrder; //是否可跳过1是 private Integer canSkip; //can_skip == 1 跳过条件 示例 age == 20 private String skipCondition; + //是否持续步骤1是(如气体检测,在整个流程期间都活跃) + private Integer ongoingFlag; + //持续步骤最少填写次数 + private Integer minFillTimes; + //持续步骤阻塞的步骤ID(必须填写足够次数后才能激活的步骤) + private Long blockingStepId; + //持续步骤当前填写次数 + private Integer currentFillTimes; public TaskLogE(TaskLogE log) { this.taskLogId = log.getTaskLogId(); @@ -110,6 +118,10 @@ public class TaskLogE extends BaseE { this.stepOrder = log.getStepOrder(); this.canSkip = log.getCanSkip(); this.skipCondition = log.getSkipCondition(); + this.ongoingFlag = log.getOngoingFlag(); + this.minFillTimes = log.getMinFillTimes(); + this.blockingStepId = log.getBlockingStepId(); + this.currentFillTimes = log.getCurrentFillTimes(); } diff --git a/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/BranchFlag.java b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/BranchFlag.java new file mode 100644 index 0000000..9d463af --- /dev/null +++ b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/BranchFlag.java @@ -0,0 +1,64 @@ +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; + +/** + * 分支标识枚举 + * + * @author fangjiakai + * @date 2026-03-12 + */ +@Getter +public enum BranchFlag { + NONE(0, "无分支"), + BRANCH_START(1, "有分支开始"), + BRANCH_END(2, "有分支结束"); + + private final Integer code; + private final String desc; + + private static final Map CODE_MAP = + Arrays.stream(values()) + .collect(Collectors.toMap(BranchFlag::getCode, Function.identity())); + + BranchFlag(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + /** + * 根据标识码获取枚举 + */ + public static BranchFlag getByCode(Integer code) { + if (code == null) { + return NONE; + } + return CODE_MAP.getOrDefault(code, NONE); + } + + /** + * 判断是否为分支开始 + */ + public boolean isBranchStart() { + return this == BRANCH_START; + } + + /** + * 判断是否为分支结束 + */ + public boolean isBranchEnd() { + return this == BRANCH_END; + } + + /** + * 判断是否有分支 + */ + public boolean hasBranch() { + return this == BRANCH_START || this == BRANCH_END; + } +} diff --git a/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/StepType.java b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/StepType.java new file mode 100644 index 0000000..30422a8 --- /dev/null +++ b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/StepType.java @@ -0,0 +1,56 @@ +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; + +/** + * 步骤类型枚举 + * + * @author fangjiakai + * @date 2026-03-12 + */ +@Getter +public enum StepType { + NORMAL(1, "正常步骤"), + BRANCH(2, "分支步骤"); + + private final Integer code; + private final String desc; + + private static final Map CODE_MAP = + Arrays.stream(values()) + .collect(Collectors.toMap(StepType::getCode, Function.identity())); + + StepType(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + /** + * 根据类型码获取枚举 + */ + public static StepType getByCode(Integer code) { + if (code == null) { + return null; + } + return CODE_MAP.get(code); + } + + /** + * 判断是否为分支步骤 + */ + public boolean isBranchStep() { + return this == BRANCH; + } + + /** + * 判断是否为正常步骤 + */ + public boolean isNormalStep() { + return this == NORMAL; + } +} diff --git a/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/TaskLogStatus.java b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/TaskLogStatus.java new file mode 100644 index 0000000..f8b3e6f --- /dev/null +++ b/web-domain/src/main/java/com/zcloud/eightwork/domain/model/enums/TaskLogStatus.java @@ -0,0 +1,67 @@ +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; + +/** + * 任务日志状态枚举 + * + * @author fangjiakai + * @date 2026-03-12 + */ +@Getter +public enum TaskLogStatus { + NOT_STARTED(-99, "未开始"), + IN_PROGRESS(0, "进行中"), + APPROVED(1, "通过"), + REJECTED(2, "打回"), + SKIPPED(-1, "已跳过"), + ARCHIVED(999, "已归档"); + + private final Integer code; + private final String desc; + + private static final Map CODE_MAP = + Arrays.stream(values()) + .collect(Collectors.toMap(TaskLogStatus::getCode, Function.identity())); + + TaskLogStatus(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + /** + * 根据状态码获取枚举 + */ + public static TaskLogStatus getByCode(Integer code) { + if (code == null) { + return null; + } + return CODE_MAP.get(code); + } + + /** + * 判断状态是否为指定状态 + */ + public boolean equalsCode(Integer code) { + return this.code != null && this.code.equals(code); + } + + /** + * 判断是否为已完成状态(通过或打回) + */ + public boolean isFinished() { + return this == APPROVED || this == REJECTED; + } + + /** + * 判断是否可以流转到下一步 + */ + public boolean canProceed() { + return this == APPROVED; + } +} diff --git a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/dataobject/TaskFlowDO.java b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/dataobject/TaskFlowDO.java index 129ee65..b2c9887 100644 --- a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/dataobject/TaskFlowDO.java +++ b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/dataobject/TaskFlowDO.java @@ -62,12 +62,12 @@ public class TaskFlowDO extends BaseDO { //0无分支1有分支开始2有分支结束 @ApiModelProperty(value = "0无分支1有分支开始2有分支结束") private Integer branchFlag; - //branch_flag == 1 分支节点 - @ApiModelProperty(value = "branch_flag == 1 分支节点") - private Integer branchStep; - //step_type == 2 分支节点合并节点 - @ApiModelProperty(value = "step_type == 2 分支节点合并节点") - private Integer branchMergeStep; + //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; @@ -77,6 +77,15 @@ public class TaskFlowDO extends BaseDO { //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; } diff --git a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/dataobject/TaskLogDO.java b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/dataobject/TaskLogDO.java index a5f3fa0..74fcfe3 100644 --- a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/dataobject/TaskLogDO.java +++ b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/dataobject/TaskLogDO.java @@ -101,12 +101,12 @@ public class TaskLogDO extends BaseDO { //0无分支1有分支开始2有分支结束 @ApiModelProperty(value = "0无分支1有分支开始2有分支结束") private Integer branchFlag; - //branch_flag == 1 分支节点 - @ApiModelProperty(value = "branch_flag == 1 分支节点") - private Integer branchStep; - //step_type == 2 分支节点合并节点 - @ApiModelProperty(value = "step_type == 2 分支节点合并节点") - private Integer branchMergeStep; + //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; @@ -116,6 +116,18 @@ public class TaskLogDO extends BaseDO { //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; public TaskLogDO(String taskLogId) { this.taskLogId = taskLogId; diff --git a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/mapper/TaskLogMapper.java b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/mapper/TaskLogMapper.java index 383d840..dbc7721 100644 --- a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/mapper/TaskLogMapper.java +++ b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/mapper/TaskLogMapper.java @@ -20,5 +20,7 @@ public interface TaskLogMapper extends BaseMapper { List getTodoCount(@Param("orgId") Long orgId,@Param("userId") Long userId); List getTodoCountForWork(@Param("orgId") Long orgId,@Param("userId") Long userId,@Param("workType") String workType); + + TaskLogDO getByWorkIdAndStepId(@Param("workId") String workId, @Param("stepId") Long stepId); } diff --git a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/repository/TaskLogRepository.java b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/repository/TaskLogRepository.java index ffbacf6..41b6bd3 100644 --- a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/repository/TaskLogRepository.java +++ b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/repository/TaskLogRepository.java @@ -24,5 +24,7 @@ public interface TaskLogRepository extends BaseRepository { List getTodoCount(Long orgId, Long userId); List getTodoCountForWork(Long orgId, Long userId, String workType); + + TaskLogDO getByWorkIdAndStepId(String workId, Long stepId); } diff --git a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/repository/impl/TaskLogRepositoryImpl.java b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/repository/impl/TaskLogRepositoryImpl.java index 54e77e8..845d2a8 100644 --- a/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/repository/impl/TaskLogRepositoryImpl.java +++ b/web-infrastructure/src/main/java/com/zcloud/eightwork/persistence/repository/impl/TaskLogRepositoryImpl.java @@ -59,5 +59,10 @@ public class TaskLogRepositoryImpl extends BaseRepositoryImpl getTodoCountForWork(Long orgId, Long userId, String workType){ return taskLogMapper.getTodoCountForWork(orgId, userId, workType); } + + @Override + public TaskLogDO getByWorkIdAndStepId(String workId, Long stepId) { + return taskLogMapper.getByWorkIdAndStepId(workId, stepId); + } } diff --git a/web-infrastructure/src/main/resources/mapper/TaskLogMapper.xml b/web-infrastructure/src/main/resources/mapper/TaskLogMapper.xml index d7799f0..8ea8cc9 100644 --- a/web-infrastructure/src/main/resources/mapper/TaskLogMapper.xml +++ b/web-infrastructure/src/main/resources/mapper/TaskLogMapper.xml @@ -25,5 +25,13 @@ or (act_user_department = #{orgId} and act_user is null)) group by step_id + +