feat(task): 添加作业暂存功能

- 在 TaskLogController 中新增 saveDraft 接口用于暂存作业
- 修改 TaskLogAddExe 将作业创建逻辑拆分为首次提交和暂存转正式两种场景
- 实现从暂存记录转为正式提交的功能,包括状态检查和票号重新生成
- 重构作业信息保存逻辑,提取正式票号生成功能到独立方法
- 更新 TaskLogServiceI 接口定义,添加 saveDraft 方法声明
- 在 TaskLogAddCmd 中新增 id 字段标识暂存转正式操作
- 新增 gasFlag 字段支持其他分析标识功能
master
fangjiakai 2026-03-20 15:37:20 +08:00
parent 83c6e2bf43
commit 2694888ef4
5 changed files with 133 additions and 35 deletions

View File

@ -2,10 +2,12 @@ package com.zcloud.eightwork.web;
import com.zcloud.eightwork.api.TaskLogServiceI; import com.zcloud.eightwork.api.TaskLogServiceI;
import com.zcloud.eightwork.dto.EightworkInfoSaveDraftCmd;
import com.zcloud.eightwork.dto.TaskLogAddCmd; import com.zcloud.eightwork.dto.TaskLogAddCmd;
import com.zcloud.eightwork.dto.TaskLogNextCmd; import com.zcloud.eightwork.dto.TaskLogNextCmd;
import com.zcloud.eightwork.dto.TaskLogPageQry; 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.TaskLogCO; import com.zcloud.eightwork.dto.clientobject.TaskLogCO;
import com.alibaba.cola.dto.MultiResponse; import com.alibaba.cola.dto.MultiResponse;
import com.alibaba.cola.dto.PageResponse; import com.alibaba.cola.dto.PageResponse;
@ -104,5 +106,12 @@ public class TaskLogController {
public MultiResponse<TodoCountCO> getTodoCountForWork(@PathVariable("workType") String workType) { public MultiResponse<TodoCountCO> getTodoCountForWork(@PathVariable("workType") String workType) {
return MultiResponse.of(taskLogService.getTodoCountForWork(AuthContext.getOrgId(),AuthContext.getUserId(),workType)); return MultiResponse.of(taskLogService.getTodoCountForWork(AuthContext.getOrgId(),AuthContext.getUserId(),workType));
} }
@ApiOperation("暂存作业")
@PostMapping("/saveDraft")
public SingleResponse<EightworkInfoCO> saveDraft(@Validated @RequestBody EightworkInfoSaveDraftCmd cmd) {
cmd.setDepartmentId(AuthContext.getOrgId());
return taskLogService.saveDraft(cmd);
}
} }

View File

@ -57,9 +57,73 @@ public class TaskLogAddExe {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public List<TaskLogDO> execute(TaskLogAddCmd cmd) { public List<TaskLogDO> execute(TaskLogAddCmd cmd) {
log.info("开始创建作业流程: workType={}, workLevel={}", cmd.getWorkType(), cmd.getWorkLevel()); log.info("开始创建作业流程: workType={}, workLevel={}, id={}",
cmd.getWorkType(), cmd.getWorkLevel(), cmd.getId());
try { try {
if (cmd.getId() != null) {
// 从暂存转正式提交
return submitFromDraft(cmd);
} else {
// 首次正式提交
return submitNew(cmd);
}
} catch (Exception e) {
log.error("创建作业流程失败: workType={}", cmd.getWorkType(), e);
throw new BizException("保存失败: " + e.getMessage());
}
}
/**
*
*/
private List<TaskLogDO> submitFromDraft(TaskLogAddCmd cmd) {
log.info("从暂存转正式提交: id={}", cmd.getId());
// 1. 查询暂存记录
EightworkInfoDO existingInfo = eightworkInfoRepository.getById(cmd.getId());
if (existingInfo == null) {
throw new BizException("暂存记录不存在");
}
// 2. 检查状态
if (!TaskLogStatus.NOT_STARTED.getCode().equals(existingInfo.getStatus())) {
throw new BizException("只能从暂存状态转为正式提交");
}
// 3. 删除暂存的 task_log
taskLogRepository.remove(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<TaskLogDO>()
.eq(TaskLogDO::getWorkId, existingInfo.getWorkId()));
// 4. 生成正式票号并更新主表
String formalCheckNo = generateFormalCheckNo(cmd.getWorkType());
existingInfo.setCheckNo(formalCheckNo);
existingInfo.setStatus(TaskLogStatus.IN_PROGRESS.getCode());
eightworkInfoRepository.updateById(existingInfo);
log.info("暂存转正式: workId={}, checkNo={}", existingInfo.getWorkId(), formalCheckNo);
// 5. 获取流程配置
List<TaskFlowE> flows = taskFlowGateway.listAllByWorkType(cmd.getWorkType(), cmd.getWorkLevel());
// 6. 生成所有步骤 task_log
List<TaskLogDO> taskLogs = flows.stream()
.map(flow -> createTaskLog(flow, existingInfo.getWorkId(), cmd))
.collect(Collectors.toList());
// 7. 批量保存
taskLogRepository.saveBatch(taskLogs);
log.info("作业流程创建成功(从暂存): workId={}, stepCount={}", existingInfo.getWorkId(), taskLogs.size());
return taskLogs;
}
/**
*
*/
private List<TaskLogDO> submitNew(TaskLogAddCmd cmd) {
log.info("首次正式提交: workType={}, workLevel={}", cmd.getWorkType(), cmd.getWorkLevel());
// 1. 创建作业信息 // 1. 创建作业信息
String workId = saveWork(cmd); String workId = saveWork(cmd);
log.info("作业信息已创建: workId={}", workId); log.info("作业信息已创建: workId={}", workId);
@ -76,10 +140,29 @@ public class TaskLogAddExe {
log.info("作业流程创建成功: workId={}, stepCount={}", workId, taskLogs.size()); log.info("作业流程创建成功: workId={}, stepCount={}", workId, taskLogs.size());
return taskLogs; return taskLogs;
} catch (Exception e) {
log.error("创建作业流程失败: workType={}", cmd.getWorkType(), e);
throw new BizException("保存失败: " + e.getMessage());
} }
/**
*
*/
private String generateFormalCheckNo(String workType) {
String workTypeCode = WorkCodeEnum.getCodeByWorkType(workType);
String date = DateUtil.getDays();
// 构建 Redis Key
String redisKey = buildTicketNoKey(workTypeCode, date);
// Redis 原子递增获取序号
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位序号
return "QG" + workTypeCode + date + String.format("%04d", seq);
} }
/** /**
@ -159,24 +242,8 @@ public class TaskLogAddExe {
* 使 Redis * 使 Redis
*/ */
private String saveWork(TaskLogAddCmd cmd) { private String saveWork(TaskLogAddCmd cmd) {
String workType = cmd.getWorkType(); // 生成正式票号
String workTypeCode = WorkCodeEnum.getCodeByWorkType(workType); String checkNo = generateFormalCheckNo(cmd.getWorkType());
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( EightworkInfoDO eightworkInfo = new EightworkInfoDO(
Tools.get32UUID(), Tools.get32UUID(),

View File

@ -1,15 +1,18 @@
package com.zcloud.eightwork.service; package com.zcloud.eightwork.service;
import com.zcloud.eightwork.api.TaskLogServiceI; import com.zcloud.eightwork.api.TaskLogServiceI;
import com.zcloud.eightwork.command.EightworkInfoSaveDraftExe;
import com.zcloud.eightwork.command.TaskLogAddExe; 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.domain.model.enums.TaskLogStatus; import com.zcloud.eightwork.domain.model.enums.TaskLogStatus;
import com.zcloud.eightwork.dto.EightworkInfoSaveDraftCmd;
import com.zcloud.eightwork.dto.TaskLogAddCmd; import com.zcloud.eightwork.dto.TaskLogAddCmd;
import com.zcloud.eightwork.dto.TaskLogNextCmd; import com.zcloud.eightwork.dto.TaskLogNextCmd;
import com.zcloud.eightwork.dto.TaskLogPageQry; 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.TaskLogCO; import com.zcloud.eightwork.dto.clientobject.TaskLogCO;
import com.alibaba.cola.dto.PageResponse; import com.alibaba.cola.dto.PageResponse;
@ -35,6 +38,7 @@ public class TaskLogServiceImpl implements TaskLogServiceI {
private final TaskLogUpdateExe taskLogUpdateExe; private final TaskLogUpdateExe taskLogUpdateExe;
private final TaskLogRemoveExe taskLogRemoveExe; private final TaskLogRemoveExe taskLogRemoveExe;
private final TaskLogQueryExe taskLogQueryExe; private final TaskLogQueryExe taskLogQueryExe;
private final EightworkInfoSaveDraftExe eightworkInfoSaveDraftExe;
@Override @Override
public SingleResponse<TaskLogCO> getInfoById(Long id) { public SingleResponse<TaskLogCO> getInfoById(Long id) {
@ -95,5 +99,11 @@ public class TaskLogServiceImpl implements TaskLogServiceI {
public List<TodoCountCO> getTodoCountForWork(Long orgId, Long userId, String workType){ public List<TodoCountCO> getTodoCountForWork(Long orgId, Long userId, String workType){
return taskLogQueryExe.getTodoCountForWork(orgId, userId, workType); return taskLogQueryExe.getTodoCountForWork(orgId, userId, workType);
} }
@Override
public SingleResponse<EightworkInfoCO> saveDraft(EightworkInfoSaveDraftCmd cmd) {
eightworkInfoSaveDraftExe.execute(cmd);
return SingleResponse.buildSuccess();
}
} }

View File

@ -1,9 +1,11 @@
package com.zcloud.eightwork.api; package com.zcloud.eightwork.api;
import com.zcloud.eightwork.dto.EightworkInfoSaveDraftCmd;
import com.zcloud.eightwork.dto.TaskLogAddCmd; import com.zcloud.eightwork.dto.TaskLogAddCmd;
import com.zcloud.eightwork.dto.TaskLogNextCmd; import com.zcloud.eightwork.dto.TaskLogNextCmd;
import com.zcloud.eightwork.dto.TaskLogPageQry; 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.TaskLogCO; import com.zcloud.eightwork.dto.clientobject.TaskLogCO;
import com.alibaba.cola.dto.PageResponse; import com.alibaba.cola.dto.PageResponse;
@ -37,5 +39,10 @@ public interface TaskLogServiceI {
List<TodoCountCO> getTodoCount(Long orgId, Long userId); List<TodoCountCO> getTodoCount(Long orgId, Long userId);
List<TodoCountCO> getTodoCountForWork(Long orgId, Long userId, String workType); List<TodoCountCO> getTodoCountForWork(Long orgId, Long userId, String workType);
/**
*
*/
SingleResponse<EightworkInfoCO> saveDraft(EightworkInfoSaveDraftCmd cmd);
} }

View File

@ -22,6 +22,9 @@ import java.util.List;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class TaskLogAddCmd extends Command { public class TaskLogAddCmd extends Command {
@ApiModelProperty(value = "主表ID有值表示从暂存转正式无值表示首次正式提交")
private Long id;
@ApiModelProperty(value = "任务类型", name = "workType",required = true) @ApiModelProperty(value = "任务类型", name = "workType",required = true)
@NotBlank @NotBlank
private String workType; private String workType;
@ -33,6 +36,8 @@ public class TaskLogAddCmd extends Command {
@ApiModelProperty(value = "是否相关方1是", name = "xgfFlag", required = true) @ApiModelProperty(value = "是否相关方1是", name = "xgfFlag", required = true)
private Integer xgfFlag; private Integer xgfFlag;
@ApiModelProperty(value = "是否其他分析1是", name = "gasFlag", required = true)
private Integer gasFlag;
@ApiModelProperty(value = "是否内部作业1是2否", name = "internalOperationFlag") @ApiModelProperty(value = "是否内部作业1是2否", name = "internalOperationFlag")
private Integer internalOperationFlag; private Integer internalOperationFlag;