hl-api-changelog/changelogs/2026-03/2026-03-19_order_todo.md
API Changelog Bot b632390c8b feat: 订单待办事项(Todo)完整对接方案
7个接口详细定义 + 字典 + 页面布局 + 权限控制 + 调用示例

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 16:59:32 +08:00

18 KiB

订单待办事项Todo完整对接方案

日期: 2026-03-19 | 服务: hl-order-service


一、功能说明

订单支付成功后,系统自动生成一组「待办事项」,按顺序推进内部流程。每个待办有对应的负责角色,完成后自动推进到下一步。

待办流程6步

确认订单 → 配置保险 → 签订合同 → 安排住宿 → 安排车辆 → 确认清单
(定制师)   (定制师)   (定制师)   (房管)     (车管)     (定制师)

关联字典

order_todo_type(订单待办类型)

dict_value dict_label 序号 负责角色
CONFIRM_ORDER 确认订单 1 CUSTOMIZER定制师
INSURANCE 配置保险 2 CUSTOMIZER定制师
CONTRACT 签订合同 3 CUSTOMIZER定制师
ARRANGE_ROOM 安排住宿 4 ROOM_MANAGER房管
ARRANGE_VEHICLE 安排车辆 5 VEHICLE_MANAGER车管
CONFIRM_CHECKLIST 确认清单 6 CUSTOMIZER定制师
PROCESS_REFUND 处理退款 7 CUSTOMIZER定制师

待办状态

含义
PENDING 待处理
COMPLETED 已完成
CANCELLED 已取消(订单取消/退款时自动取消)

二、接口清单

# 方法 路径 说明 使用场景
1 GET /admin/order/{orderId}/todos 获取订单待办列表 订单详情页 → 待办面板
2 PUT /admin/order/todo/{todoId}/complete 完成待办 点击「完成」/「去投保」按钮
3 GET /admin/order/todo/my-list 我的待办列表 首页/工作台 → 待办列表
4 GET /admin/order/todo/my-count 我的待办数量 首页/菜单 → 红点角标
5 GET /admin/order/todo/customizer-list 定制师列表 更换定制师弹窗 → 下拉选择
6 PUT /admin/order/{orderId}/customizer 更换定制师 更换定制师弹窗 → 确认
7 GET /admin/order/todo/contract-eligible 可签合同订单列表 合同管理页 → 待签合同

三、接口详细定义

1. 获取订单待办列表

接口GET /admin/order/{orderId}/todos

使用场景:订单详情页右侧「待办事项」面板,展示该订单所有待办项的时间线

路径参数

参数 类型 必填 说明
orderId Long(String) 订单ID

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "todoId": "1902000000000000001",
      "orderId": "1901000000000000001",
      "orderNo": "HL202603191600255172",
      "todoType": "CONFIRM_ORDER",
      "todoLabel": "确认订单",
      "sequence": 1,
      "status": "COMPLETED",
      "assigneeRoleKey": "CUSTOMIZER",
      "assigneeAdminId": "1800000000000000010",
      "completedBy": "1800000000000000010",
      "completedAt": "2026-03-19 10:30:00",
      "createTime": "2026-03-19 10:00:00"
    },
    {
      "todoId": "1902000000000000002",
      "orderId": "1901000000000000001",
      "orderNo": "HL202603191600255172",
      "todoType": "INSURANCE",
      "todoLabel": "配置保险",
      "sequence": 2,
      "status": "PENDING",
      "assigneeRoleKey": "CUSTOMIZER",
      "assigneeAdminId": "1800000000000000010",
      "completedBy": null,
      "completedAt": null,
      "createTime": "2026-03-19 10:00:00"
    },
    {
      "todoId": "1902000000000000003",
      "orderId": "1901000000000000001",
      "orderNo": "HL202603191600255172",
      "todoType": "CONTRACT",
      "todoLabel": "签订合同",
      "sequence": 3,
      "status": "PENDING",
      "assigneeRoleKey": "CUSTOMIZER",
      "assigneeAdminId": "1800000000000000010",
      "completedBy": null,
      "completedAt": null,
      "createTime": "2026-03-19 10:00:00"
    },
    {
      "todoId": "1902000000000000004",
      "orderId": "1901000000000000001",
      "orderNo": "HL202603191600255172",
      "todoType": "ARRANGE_ROOM",
      "todoLabel": "安排住宿",
      "sequence": 4,
      "status": "PENDING",
      "assigneeRoleKey": "ROOM_MANAGER",
      "assigneeAdminId": null,
      "completedBy": null,
      "completedAt": null,
      "createTime": "2026-03-19 10:00:00"
    },
    {
      "todoId": "1902000000000000005",
      "orderId": "1901000000000000001",
      "orderNo": "HL202603191600255172",
      "todoType": "ARRANGE_VEHICLE",
      "todoLabel": "安排车辆",
      "sequence": 5,
      "status": "PENDING",
      "assigneeRoleKey": "VEHICLE_MANAGER",
      "assigneeAdminId": null,
      "completedBy": null,
      "completedAt": null,
      "createTime": "2026-03-19 10:00:00"
    },
    {
      "todoId": "1902000000000000006",
      "orderId": "1901000000000000001",
      "orderNo": "HL202603191600255172",
      "todoType": "CONFIRM_CHECKLIST",
      "todoLabel": "确认清单",
      "sequence": 6,
      "status": "PENDING",
      "assigneeRoleKey": "CUSTOMIZER",
      "assigneeAdminId": "1800000000000000010",
      "completedBy": null,
      "completedAt": null,
      "createTime": "2026-03-19 10:00:00"
    }
  ]
}

返回字段说明

字段 类型 说明
todoId String 待办ID
orderId String 订单ID
orderNo String 订单号
todoType String 待办类型(字典:order_todo_type
todoLabel String 待办名称(中文)
sequence Integer 排序序号1-6,决定显示顺序
status String 状态:PENDING=待处理 / COMPLETED=已完成 / CANCELLED=已取消
assigneeRoleKey String 负责角色标识:CUSTOMIZER / ROOM_MANAGER / VEHICLE_MANAGER
assigneeAdminId String 负责管理员ID可能为null,表示尚未分配具体人
completedBy String 完成人ID未完成时为null
completedAt String 完成时间未完成时为null,格式 yyyy-MM-dd HH:mm:ss
createTime String 创建时间,格式 yyyy-MM-dd HH:mm:ss

2. 完成待办

接口PUT /admin/order/todo/{todoId}/complete

使用场景:点击待办项的「完成」或「去投保」按钮

路径参数

参数 类型 必填 说明
todoId Long(String) 待办ID

请求体:无

响应示例

{
  "code": 200,
  "message": "成功",
  "data": null
}

权限说明

  • 需要对应角色权限,例如 ARRANGE_ROOM 待办需要 ROOM_MANAGER 角色
  • SUPER_ADMIN 可以完成所有类型的待办
  • 权限不足时返回 403

业务逻辑

  • 完成待办后,系统自动检查是否满足推进条件
  • 所有6个待办全部完成后,内部流程状态自动推进到 READY(就绪)

3. 我的待办列表

接口GET /admin/order/todo/my-list

使用场景:首页/工作台的「我的待办」列表,展示当前登录管理员需要处理的所有未完成待办

请求参数:无(根据登录用户的 adminId 和 roleKey 自动筛选)

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "todoId": "1902000000000000002",
      "orderId": "1901000000000000001",
      "orderNo": "HL202603191600255172",
      "todoType": "INSURANCE",
      "todoLabel": "配置保险",
      "sequence": 2,
      "status": "PENDING",
      "assigneeRoleKey": "CUSTOMIZER",
      "assigneeAdminId": "1800000000000000010",
      "completedBy": null,
      "completedAt": null,
      "createTime": "2026-03-19 10:00:00",
      "productName": "嗨·冰雪3.0南线7日游",
      "contactName": "张三",
      "departureDate": "2026-04-01",
      "orderStatus": "PAID",
      "blocked": false,
      "blockedReason": null
    }
  ]
}

返回字段说明(在基础字段上增加关联信息):

字段 类型 说明
productName String 产品名称(关联查询)
contactName String 联系人姓名(关联查询)
departureDate String 出发日期(关联查询),格式 yyyy-MM-dd
orderStatus String 订单状态(字典:order_status
blocked Boolean 是否被阻塞前序待办未完成时为true
blockedReason String 阻塞原因(如 "等待「配置保险」完成"

角色筛选逻辑

  • SUPER_ADMIN:看到所有未完成待办
  • CUSTOMIZER:只看到 CONFIRM_ORDER / INSURANCE / CONTRACT / CONFIRM_CHECKLIST 类型的待办
  • ROOM_MANAGER:只看到 ARRANGE_ROOM 类型的待办
  • VEHICLE_MANAGER:只看到 ARRANGE_VEHICLE 类型的待办

4. 我的待办数量

接口GET /admin/order/todo/my-count

使用场景:菜单栏/首页角标红点提醒

请求参数:无

响应示例

{
  "code": 200,
  "message": "成功",
  "data": 5
}

5. 定制师列表

接口GET /admin/order/todo/customizer-list

使用场景:更换定制师弹窗中的下拉选择框

请求参数:无

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "adminId": "1800000000000000010",
      "realName": "王骁",
      "avatar": "https://oss.example.com/avatar/wx.jpg"
    },
    {
      "adminId": "1800000000000000011",
      "realName": "李明",
      "avatar": "https://oss.example.com/avatar/lm.jpg"
    }
  ]
}

返回字段说明

字段 类型 说明
adminId String 管理员ID
realName String 姓名
avatar String 头像URL

6. 更换定制师

接口PUT /admin/order/{orderId}/customizer

使用场景:更换定制师弹窗 → 确认按钮

路径参数

参数 类型 必填 说明
orderId Long(String) 订单ID

请求体

{
  "customizerId": "1800000000000000011"
}
字段 类型 必填 说明
customizerId Long(String) 目标定制师的管理员ID,从定制师列表接口获取

响应示例

{
  "code": 200,
  "message": "成功",
  "data": null
}

业务逻辑

  • 更换后,该订单中所有 CUSTOMIZER 角色的待办自动转移给新定制师
  • 订单时间线会记录「更换定制师」操作

7. 可签合同订单列表

接口GET /admin/order/todo/contract-eligible

使用场景:合同管理页面,展示保险已完成、可以进入签合同环节的订单列表

请求参数:无

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "todoId": "1902000000000000003",
      "orderId": "1901000000000000001",
      "orderNo": "HL202603191600255172",
      "todoType": "CONTRACT",
      "todoLabel": "签订合同",
      "sequence": 3,
      "status": "PENDING",
      "assigneeRoleKey": "CUSTOMIZER",
      "assigneeAdminId": "1800000000000000010",
      "completedBy": null,
      "completedAt": null,
      "createTime": "2026-03-19 10:00:00",
      "productName": "嗨·冰雪3.0南线7日游",
      "contactName": "张三",
      "departureDate": "2026-04-01",
      "orderStatus": "PAID",
      "blocked": false,
      "blockedReason": null
    }
  ]
}

返回字段与「我的待办列表」相同(OrderTodoVO


四、前端页面布局

1. 订单详情页 → 待办事项面板

在订单详情页右侧(或底部),使用时间线组件展示待办进度:

┌──────────────────────────────────────────────┐
│ 待办事项                                       │
│                                              │
│ ✅ 确认订单          已完成 2026-03-19 10:30    │
│                                              │
│ ⏳ 配置保险          [ 去投保 ]                │
│                                              │
│ ○ 签订合同           (等待上一步完成)           │
│                                              │
│ ○ 安排住宿           (等待上一步完成)           │
│                                              │
│ ○ 安排车辆           (等待上一步完成)           │
│                                              │
│ ○ 确认清单           (等待上一步完成)           │
│                                              │
│ [更换定制师]                                   │
└──────────────────────────────────────────────┘

2. 待办项状态展示规则

状态 图标 按钮 说明文字
COMPLETED 绿色勾 显示 completedAt 完成时间
PENDING + 非阻塞 黄色 显示操作按钮 当前可操作项
PENDING + 阻塞 ○ 灰色 显示 blockedReason(如"等待上一步完成"
CANCELLED 红色 显示"已取消"

3. 操作按钮规则

待办类型 按钮文案 按钮类型 点击行为
CONFIRM_ORDER 完成 primary 调用完成待办接口
INSURANCE 去投保 warning 跳转到保险配置页面(或弹窗配置后调用完成接口)
CONTRACT 去签合同 primary 跳转到合同签署页面(或弹窗操作后调用完成接口)
ARRANGE_ROOM 完成 primary 调用完成待办接口仅ROOM_MANAGER角色可见
ARRANGE_VEHICLE 完成 primary 调用完成待办接口仅VEHICLE_MANAGER角色可见
CONFIRM_CHECKLIST 完成 primary 调用完成待办接口

4. 权限控制

  • 当前登录用户的 roleKey 不匹配待办的 assigneeRoleKey 时,不显示操作按钮
  • SUPER_ADMIN 可以看到并操作所有待办的按钮
  • 具体映射:
    • CUSTOMIZER → 可操作 CONFIRM_ORDER / INSURANCE / CONTRACT / CONFIRM_CHECKLIST
    • ROOM_MANAGER → 可操作 ARRANGE_ROOM
    • VEHICLE_MANAGER → 可操作 ARRANGE_VEHICLE

五、首页待办角标

实现要点

  1. 页面加载时调用 GET /admin/order/todo/my-count 获取待办数量
  2. 如果 data > 0,在菜单项(如「订单管理」)右侧显示红点或数字角标
  3. 点击菜单进入「我的待办」列表页

我的待办列表页

调用 GET /admin/order/todo/my-list,展示为卡片或表格:

┌──────────────────────────────────────────────────────────────┐
│ 我的待办 (5)                                                   │
├──────────────────────────────────────────────────────────────┤
│ 📋 配置保险 | HL202603191600255172 | 嗨·冰雪3.0南线7日游       │
│    联系人: 张三 | 出发: 2026-04-01 | [ 去投保 ] [ 查看订单 ]    │
├──────────────────────────────────────────────────────────────┤
│ 📋 签订合同 | HL202603191800123456 | 海岛亲子5日游              │
│    联系人: 李四 | 出发: 2026-04-15 | ⚠️ 等待「配置保险」完成     │
├──────────────────────────────────────────────────────────────┤
│ ...                                                          │
└──────────────────────────────────────────────────────────────┘

六、更换定制师

实现要点

  1. 订单详情页待办面板底部放「更换定制师」按钮
  2. 点击弹出弹窗,调用 GET /admin/order/todo/customizer-list 加载定制师列表
  3. 下拉选择目标定制师(显示 realName,值 adminId
  4. 确认后调用 PUT /admin/order/{orderId}/customizer
  5. 成功后刷新待办列表

七、调用示例

import { http } from '@/utils/request'

// 1. 获取订单待办列表(订单详情页加载时)
const todos = await http.get(`/order/${orderId}/todos`)
// todos = [{ todoId, todoType, todoLabel, status, completedAt, ... }]

// 2. 完成待办(点击「完成」按钮)
await http.put(`/order/todo/${todoId}/complete`)

// 3. 获取我的待办列表(首页/工作台)
const myTodos = await http.get('/order/todo/my-list')
// myTodos = [{ todoId, orderNo, todoLabel, productName, contactName, departureDate, blocked, ... }]

// 4. 获取待办数量(菜单角标)
const countRes = await http.get('/order/todo/my-count')
const todoCount = countRes  // Number

// 5. 获取定制师列表(更换定制师弹窗)
const customizers = await http.get('/order/todo/customizer-list')
// customizers = [{ adminId, realName, avatar }]

// 6. 更换定制师
await http.put(`/order/${orderId}/customizer`, { customizerId: targetAdminId })

// 7. 获取可签合同订单(合同管理页)
const eligibleOrders = await http.get('/order/todo/contract-eligible')

八、待办生命周期

订单支付成功
  ↓
系统自动创建6个待办status=PENDING
  ↓
定制师逐步完成待办PENDING → COMPLETED
  ↓
所有待办完成 → 内部流程推进到 READY就绪
  ↓
如果订单取消/退款 → 所有未完成待办自动取消status=CANCELLED

注意事项

  • 待办按 sequence 排序显示1→6
  • 虽然显示顺序固定,但 ARRANGE_ROOM(4) 和 ARRANGE_VEHICLE(5) 可以并行完成(不互相阻塞)
  • 只有 INSURANCE 完成后,CONTRACT 才能操作(有依赖关系)
  • 前端拿到 blocked: true 的待办不显示操作按钮,显示 blockedReason 文字即可