7.3 KiB
7.3 KiB
搬运任务操作重构 + PC 端操作功能设计
- 日期:2026-07-15
- 分支:feature/20260713/task-module
- 状态:已评审通过(方案 A:单类路由表)
1. 背景与目标
任务状态操作目前存在两个入口:
- ACS 入口:
AcsFeedbackController→TransportTaskFeedbackServiceImpl.receiveAcsFeedback(),用字符串 if-else 按status分发到handleExecuting/handlePicked/handleFinished/handleCancelled,代码凌乱。 - PC 入口:尚不存在。前端
views/task/transporttask/index.vue已有"完成任务/取消任务/强制完成任务"三个按钮,但都错绑在handleEdit上,未传操作类型。
目标:
- 消灭 if-else 分发,改为表驱动策略(路由表)。
- 操作业务代码统一集中到
TransportTaskServiceImpl;handleExecuting/handlePicked/handleFinished/handleCancelled/publishEvent方法体原样迁移,不改业务逻辑。 - 新增 PC 端统一操作接口
POST /task/transport-task/operate(taskId + operationType),支持 FINISHED / CANCELLED / FORCE-FINISH。 APPLY-AGAIN(二次请求)、FORCE-FINISH(强制完成)业务未开发,路由表中注册 todo 占位(仅打日志)。- 前端按钮补齐操作类型标识与调用逻辑。
2. 操作类型与入口矩阵
| 操作类型 | code | ACS 触发 | PC 触发 | 业务 |
|---|---|---|---|---|
| EXECUTING | EXECUTING | ✅ | ❌ | handleExecuting(已有) |
| PICKED | PICKED | ✅ | ❌ | handlePicked(已有) |
| FINISHED | FINISHED | ✅ | ✅ | handleFinished(已有) |
| CANCELLED | CANCELLED | ✅ | ✅ | handleCancelled(已有) |
| APPLY_AGAIN | APPLY-AGAIN | ✅ | ❌ | todo,未开发 |
| FORCE_FINISH | FORCE-FINISH | ❌ | ✅ | todo,未开发 |
3. 后端设计
3.1 枚举增强 TaskOperationTypeEnum(task-api 模块)
- 增加两个布尔属性:
acsAllowed(允许 ACS 触发)、pcAllowed(允许 PC 触发),取值见上表。 - 增加静态解析方法
getByCode(String code):忽略大小写匹配code,找不到返回null。
3.2 TransportTaskServiceImpl:路由表 + PC 入口
- 从
TransportTaskFeedbackServiceImpl原样迁入:handleExecuting、handlePicked、handleFinished、handleCancelled、publishEvent、buildCallbackReq(当前无调用方,随迁保留);依赖TaskEventProducer、TaskCommonApiFactory、OBJECT_MAPPER相关部分随迁。 - 路由表:
EnumMap<TaskOperationTypeEnum, BiConsumer<TransportTaskDO, AcsFeedbackReqDTO>>,在@PostConstruct中注册六种类型;APPLY_AGAIN、FORCE_FINISH注册为 todo 占位(打 log.info,不做业务)。 - 新增接口方法
dispatchOperation(TransportTaskDO task, TaskOperationTypeEnum type, AcsFeedbackReqDTO reqDTO):查路由表分发,查不到打 warn 日志。 - 新增 PC 入口
operateTransportTask(TransportTaskOperateReqVO reqVO),@Transactional(rollbackFor = Exception.class):- 查任务,不存在 → 抛
TRANSPORT_TASK_NOT_EXISTS。 getByCode解析 operationType,为null或pcAllowed=false→ 抛新错误码TRANSPORT_TASK_OPERATION_NOT_SUPPORTED。- 任务已终态(79 完成 / 89 取消)→ 抛新错误码
TRANSPORT_TASK_ALREADY_FINAL(PC 端需给用户明确反馈,区别于 ACS 入口的静默幂等返回)。 - PC 与 ACS 的差异点——记录完成类型/来源:
FINISHED→task.setFinishedType("MANUAL")(人工完成);FORCE_FINISH→task.setFinishedType("FORCE")(强制完成);CANCELLED不设置。注意:FORCE_FINISH的业务 handler 当前为 todo 占位、不执行updateById,因此该 finishedType 设置在业务开发完成前不会实际落库,属预期行为。 - 构造仅含
taskId、status的AcsFeedbackReqDTO,调用dispatchOperation走同一路由表(保持 handler 签名不变)。
- 查任务,不存在 → 抛
- 新错误码追加到
ErrorCodeConstants,编号顺延现有 task 模块段。
3.3 TransportTaskFeedbackServiceImpl 瘦身
只保留 ACS 前置处理,注入 TransportTaskService 后委托分发:
- 查任务(不存在打 warn 返回,保持现状)。
- 终态幂等判断(保持现状)。
- 保存
resultParam(保持现状)。 - 分发段替换为:
TaskOperationTypeEnum type = TaskOperationTypeEnum.getByCode(reqDTO.getStatus());
if (type == null || !type.isAcsAllowed()) {
log.warn("未知或不允许的 ACS 反馈状态, taskId={}, status={}", reqDTO.getTaskId(), reqDTO.getStatus());
return;
}
transportTaskService.dispatchOperation(task, type, reqDTO);
handle*、publishEvent、buildCallbackReq 从此类删除。依赖方向为 Feedback → TransportTaskService 单向,无循环依赖;receiveAcsFeedback 的 @Transactional 保持,跨 Bean 调用按 REQUIRED 传播沿用同一事务。
3.4 Controller / VO
TransportTaskController新增:
@PostMapping("/operate")
@Operation(summary = "PC 端操作搬运任务(完成/取消/强制完成)")
@PreAuthorize("@ss.hasPermission('task:transport-task:operate')")
public CommonResult<Boolean> operateTransportTask(@Valid @RequestBody TransportTaskOperateReqVO reqVO)
- 新 VO
TransportTaskOperateReqVO(controller vo 包):@NotNull Long taskId;@NotEmpty String operationType(取值 FINISHED/CANCELLED/FORCE-FINISH)。
4. 前端设计(web-antdv-next)
4.1 API(api/task/transporttask/index.ts)
/** PC 端操作搬运任务(完成/取消/强制完成) */
export function operateTransportTask(data: {
operationType: string;
taskId: number;
}) {
return requestClient.post('/task/transport-task/operate', data);
}
4.2 页面(views/task/transporttask/index.vue)
- 新增操作函数:
async function handleOperate(
row: TaskTransportTaskApi.TransportTask,
operationType: string,
label: string,
) {
await confirm(`确认要${label}【${row.taskCode}】吗?`);
await operateTransportTask({ taskId: row.taskId!, operationType });
message.success(`${label}成功`);
handleRefresh();
}
- 三个按钮
onClick替换错绑的handleEdit:- 完成任务 →
handleOperate(row, 'FINISHED', '完成任务') - 取消任务 →
handleOperate(row, 'CANCELLED', '取消任务') - 强制完成任务 →
handleOperate(row, 'FORCE-FINISH', '强制完成任务')
- 完成任务 →
- 备注:强制完成按钮当前
auth复用task:transport-task:cancel、icon 用CANCEL,本次不调整权限(需菜单配套),仅修正绑定。
5. 错误处理
- PC 入口:任务不存在 / 操作类型不支持 / 任务已终态,均抛 ServiceException,由全局异常处理返回给前端提示。
- ACS 入口:保持现状(不存在/终态/未知状态均打日志静默返回成功,避免 ACS 重试)。
- MQ 发布失败:沿用
publishEvent现有逻辑(callbackStatus=FAILED + 记录错误信息)。
6. 测试与验证
- 按项目约定本次不编写测试(CLAUDE.md:除非用户允许测试)。
- 验证方式:后端
mvn compile(task 模块)通过;前端 lint/类型检查通过。
7. 范围外(明确不做)
- APPLY-AGAIN、FORCE-FINISH 的具体业务实现(todo 占位)。
- 强制完成按钮的独立权限与菜单配置。
- PC 操作联动 ACS(如向 ACS 下发取消指令)。
finishedType的字典配置与前端字典展示。