hl-api-changelog/changelogs-v2/2026-07/57_4882_车务派单看板当前订单字段统计行程与保险事务收口-管理后台.md
2026-07-12 17:29:01 +08:00

20 KiB

【前端对接·管理后台】车务派单看板当前订单字段、统计、行程与保险事务收口

Issue: wx/HL#4882 PR: wx/HL#4897 / wx/HL#4898 / wx/HL#4920 服务: hl-fleet-service / hl-order-service-v3 / hl-user-service 日期: 2026-07-12 影响范围: 车务派单看板、派单弹窗详情、状态统计、筛选、逐日行程、司机险自动投退保可靠性

1. 对接结论

  • 派单看板继续使用分页接口,默认 page=1&pageSize=20pageSize 最大 100;不要一次性全量拉取。
  • 看板卡片、筛选和详情以 order-v3 的当前订单当前 active 用车需求为权威数据源,不再使用旧派单快照覆盖当前团号、联系人、定制师、日期或诉求。
  • 汇总和列表使用同一套“当前需求 + 派车组状态”投影。summary.statusOptions[].count 必须和对应状态列表的 total 一致。
  • 日期筛选、紧急态、排序、详情起止日期和逐日行程均使用当前订单档期;改期后不得展示旧日期。
  • itinerary.days 来自 order_itinerary_day,一天一条;无有效逐日行程时返回空数组,不生成伪数据。
  • 定制师显示优先使用 consultantDisplayName;后端已按企业微信昵称优先、用户名兜底处理。
  • 前端不要自己映射车务状态中文,也不要自行计算能否派车/驳回;直接使用后端返回的 statusOptionsassignmentStatusLabelcanAssigncanRejectRequirement
  • 司机险可靠性本轮没有新增管理后台请求字段。派单 ASSIGNED/RESTORED/CANCELED/COMPLETED 与保险动作改为事务 Outbox,并由 user 微服务既有 Quartz 框架重放兜底。

2. 接口清单

# 接口 方法 路径 本轮契约
1 派单看板汇总 GET /admin/fleet/board/summary 六项概览、全状态计数和状态文案统一由后端返回
2 派单看板列表 GET /admin/fleet/board/orders 当前订单字段、组合筛选、确定性排序、分页总数收口
3 派单看板详情 GET /admin/fleet/board/orders/{orderId} 当前订单、当前需求、逐日行程、大交通、动态步骤和操作记录一次返回
4 派单时间线 GET /admin/fleet/board/orders/{orderId}/timeline 派车域已发生事件,按时间升序返回
5 Outbox 重放 POST /internal/fleet/jobs/assignment-insurance-outbox/replay 仅 user Quartz 经内部 Feign 调用,不对前端开放

3. 派单看板汇总

3.1 请求

GET /admin/fleet/board/summary
Authorization: Bearer <fleet-manager-token>

无请求参数。

3.2 响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "pendingCount": 26,
    "pendingUrgentCount": 4,
    "todayDepartCount": 2,
    "idleVehicleCount": 9,
    "idleDriverCount": 5,
    "holdingTimeoutCount": 1,
    "statusCounts": {
      "unassigned": 26,
      "holding": 2,
      "assigned": 8,
      "changeRequested": 0,
      "completed": 32,
      "canceled": 43,
      "unassignedUrgent": 4,
      "holdingUrgent": 1
    },
    "statusOptions": [
      {
        "value": "unassigned",
        "label": "待派车",
        "description": "已提出有效用车需求,车务尚未派车",
        "count": 26,
        "urgentCount": 4
      },
      {
        "value": "holding",
        "label": "排车中",
        "description": "车务已派车,司机未回复确认",
        "count": 2,
        "urgentCount": 1
      },
      {
        "value": "assigned",
        "label": "已派车",
        "description": "司机已确认,派车已生效",
        "count": 8,
        "urgentCount": 0
      },
      {
        "value": "change_requested",
        "label": "换车请求",
        "description": "客户或车务提出换车待处理",
        "count": 0,
        "urgentCount": 0
      },
      {
        "value": "completed",
        "label": "已完结",
        "description": "用车行程已完结",
        "count": 32,
        "urgentCount": 0
      },
      {
        "value": "canceled",
        "label": "已取消",
        "description": "派车需求已取消",
        "count": 43,
        "urgentCount": 0
      }
    ]
  }
}

上述数字仅用于说明响应结构,不是固定业务值。页面每次读取接口实时结果。

3.3 一致性规则

statusOptions[value=unassigned].count
  == 未附加其他筛选时 GET /admin/fleet/board/orders?statuses=unassigned 返回的 data.total
  • 统计维度是派车组,不是数据库逐日切片行数。
  • 同订单旧需求、已失效需求和孤儿派单不计入当前看板。
  • pendingCountstatusCounts.unassigned 是同一业务口径;前端可二选一展示,不要相加。
  • 状态筛选值、中文名和急单数直接读取 statusOptions,前端不得维护独立枚举文案。

4. 派单看板列表

4.1 请求示例

GET /admin/fleet/board/orders?page=1&pageSize=20&statuses=unassigned,holding&startDate=2026-07-01&endDate=2026-07-31&typeKeys=suv&keyword=7218&consultantId=2021059720172838914
Authorization: Bearer <fleet-manager-token>

4.2 查询参数

参数 类型 必填 规则
page int 默认 1。
pageSize int 默认 20,最大 100。
statuses string[] 多状态任一命中;支持重复 query 参数或逗号分隔。
status string 兼容单状态/逗号分隔写法,与 statuses 合并。
startDayFrom / startDate date 日期起,两个参数是别名;与当前行程区间做重叠匹配。
startDayTo / endDate date 日期止,两个参数是别名;与当前行程区间做重叠匹配。
vehicleTypeKeys / typeKeys string[] 车型大类多选。未派按当前需求车型,已派按实际车辆大类。
driverName string 司机姓名模糊匹配。
keyword string 统一包含匹配:司机、联系人/客户、团号、订单号。
contactName / contactKeyword string 联系人/客户名模糊匹配。
teamNo string 团号包含匹配,例如 7218 可命中 26-7218
consultantId string 当前负责定制师 ID 精确匹配,值来自定制师下拉。
plannerName / consultantName string 旧前端兼容的定制师文本筛选;新页面使用 consultantId
variant string list(默认)或 grid;其他值返回参数错误。

状态值:

unassigned / unassigned_urgent / holding / holding_urgent /
assigned / change_requested / canceled / completed

其中:

  • holding 的业务含义是“排车中”,即车务已派司机、司机尚未确认。
  • unassigned_urgentholding_urgent 是后端实时派生态,不是独立落库状态。
  • change_requested 当前无独立换车请求表时可能恒为空;前端仍按 statusOptions 渲染。

4.3 响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "page": 1,
    "pageSize": 20,
    "total": 1,
    "records": [
      {
        "id": "HL20260708144557879",
        "orderNo": "HL20260708144557879",
        "orderId": "2074746808742928386",
        "teamNo": "26-7218",
        "unreadMessageCount": 0,
        "assignmentId": "2075001000000000001",
        "assignmentGroupId": "2075001000000000001",
        "fleetItemIndex": 0,
        "customerName": "何子墨",
        "contactName": "何子墨",
        "productName": "测试核心产品-单档-固定订金",
        "headcount": 2,
        "adultCount": 2,
        "childCount": 0,
        "youngChildCount": 0,
        "babyCount": 0,
        "startDate": "2026-07-20",
        "endDate": "2026-07-22",
        "days": 3,
        "pickupAt": "海拉尔东山机场",
        "dropoffAt": "海拉尔站",
        "isHailarPickup": true,
        "isHailarDropoff": true,
        "consultantId": "2021059720172838914",
        "plannerName": "王骁",
        "consultantName": "王骁",
        "consultantDisplayName": "王骁",
        "customerNote": "需要接送机",
        "vehicleAdvice": null,
        "specialTags": ["大行李空间", "有 WiFi"],
        "requirementRemark": "接机后直接前往酒店",
        "requiredVehicles": [
          {
            "vehicleType": "suv",
            "categoryLabel": "SUV系列",
            "seats": 5,
            "count": 1
          }
        ],
        "assignmentStatus": "unassigned_urgent",
        "assignmentStatusLabel": "待派车",
        "currentVehiclePlate": null,
        "currentVehicleModel": null,
        "currentVehicleSeats": null,
        "currentVehicleFleet": null,
        "currentDriverName": null,
        "currentDriverPhone": null,
        "urgentBadge": "T-2",
        "canAssign": true,
        "canRejectRequirement": true
      }
    ]
  }
}

4.4 字段来源与前端用法

响应字段 权威来源 前端规则
orderNo/orderId 当前 order_main 雪花 ID 按字符串处理。
teamNo 当前 order_main.team_no 没有团号时为 null,不要显示旧快照团号。
customerName/contactName 当前订单联系人 两字段同口径,卡片优先读 contactName
headcount 与四类人数 当前订单出行人统计 不从派单数量反推。
startDate/endDate/days 当前订单档期 days=endDate-startDate+1,含首尾。
consultantId 当前 order_main.consultant_id 定制师下拉筛选值。
consultantDisplayName 当前定制师,企微昵称优先 卡片无条件独立展示,不得受客户留言/车辆建议是否存在影响。
specialTags/requirementRemark 当前 active 用车需求 不读取旧需求或派单快照。
requiredVehicles 当前需求车型项 车型筛选和卡片 chip 使用。
assignmentStatusLabel 后端状态投影 前端直接展示。
canAssign 后端能力判断 true 才显示派车入口。
canRejectRequirement 后端能力判断 true 才显示驳回需求;已产生有效派单后为 false

排序固定为:紧急待处理组置顶,普通进行中次之,终态沉底,同优先级使用稳定 ID 兜底。前端不要二次改序,否则分页间会出现跳行或重复。

5. 派单看板详情

5.1 请求

GET /admin/fleet/board/orders/2074746808742928386
Authorization: Bearer <fleet-manager-token>

orderId 是数字订单 ID,不是订单号。

打开详情后,后端会尝试把当前 active 用车需求从待处理推进为 PROCESSING。车务没有抢单池,任何车务管理员都能处理全部车务订单。

5.2 响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "id": "HL20260708144557879",
    "orderNo": "HL20260708144557879",
    "teamNo": "26-7218",
    "customerName": "何子墨",
    "headcount": 2,
    "adultCount": 2,
    "childCount": 0,
    "youngChildCount": 0,
    "babyCount": 0,
    "startDate": "2026-07-20",
    "endDate": "2026-07-22",
    "pickupAt": "海拉尔东山机场",
    "dropoffAt": "海拉尔站",
    "productName": "测试核心产品-单档-固定订金",
    "plannerName": "王骁",
    "consultantId": "2021059720172838914",
    "consultantName": "王骁",
    "consultantDisplayName": "王骁",
    "plannerNote": null,
    "customerNote": "需要接送机",
    "requirements": "接机后直接前往酒店",
    "vehicleAdvice": null,
    "specialTags": ["大行李空间", "有 WiFi"],
    "requirementRemark": "接机后直接前往酒店",
    "itinerary": {
      "theme": "草原深度 3 日",
      "route": "海拉尔 → 额尔古纳 → 满洲里",
      "days": [
        {
          "dayNumber": 1,
          "date": "2026-07-20",
          "title": "海拉尔集合",
          "detail": "接机后入住酒店"
        },
        {
          "dayNumber": 2,
          "date": "2026-07-21",
          "title": "草原行程",
          "detail": "前往额尔古纳"
        },
        {
          "dayNumber": 3,
          "date": "2026-07-22",
          "title": "返程送站",
          "detail": "送往海拉尔站"
        }
      ]
    },
    "transport": {
      "transferTimeHint": null,
      "arrive": null,
      "depart": null,
      "batches": [
        {
          "travelerNames": "何子墨, 李静",
          "transportNo": "CA1234",
          "time": "2026-07-20 10:45:00",
          "station": "海拉尔东山机场"
        },
        {
          "travelerNames": "何子墨, 李静",
          "transportNo": "K1234",
          "time": "2026-07-22 16:30:00",
          "station": "海拉尔站"
        }
      ],
      "pickupRequired": true
    },
    "progressSteps": [
      {
        "step": 1,
        "code": "ORDER_DETAIL",
        "label": "订单详情",
        "status": "DONE",
        "statusLabel": "已完成",
        "active": false,
        "time": "2026-07-12 16:22:14"
      },
      {
        "step": 2,
        "code": "DISPATCH",
        "label": "排车",
        "status": "PROCESSING",
        "statusLabel": "进行中",
        "active": true,
        "time": "2026-07-12 16:22:14"
      }
    ],
    "operationLog": {
      "records": [],
      "total": 0,
      "summary": { "totalCount": 0 }
    },
    "currentAssignment": null,
    "relatedDetailReady": true
  }
}

5.3 逐日行程规则

  • itinerary.days[].date 必须落在当前 [startDate,endDate] 内。
  • 改期后用当前 startDate + dayNumber - 1 对齐日期,历史旧档期行不能继续展示。
  • order_itinerary_day 中越界、非法 dayNumber 或重复旧版本数据会被过滤。
  • 结束日当天是有效行程日,不能误删。
  • 没有有效逐日行程时:
{
  "itinerary": {
    "theme": null,
    "route": null,
    "days": []
  }
}

前端显示“暂无每日行程”,不得按总天数生成假行程。

5.4 大交通空值规则

有到达、返程或分批接送数据时,读取 arrive/depart/batches。完全没有时间数据时:

{
  "transport": {
    "transferTimeHint": "暂无接送机时间",
    "arrive": null,
    "depart": null,
    "batches": [],
    "pickupRequired": false
  }
}

5.5 降级规则

  • order-v3 正常:relatedDetailReady=true,返回当前订单、当前需求、逐日行程和大交通。
  • order-v3 整体不可达fleet 才回退本地派单快照,relatedDetailReady=false;前端显示“订单详情暂不可用”,不要把空字段当成真实无数据。
  • currentAssignment=null 表示当前没有有效派单,不表示接口失败。

6. 派单时间线

6.1 请求

GET /admin/fleet/board/orders/2074746808742928386/timeline
Authorization: Bearer <fleet-manager-token>

6.2 响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": [
    {
      "time": "2026-07-12 15:30:00",
      "type": "requirement_received",
      "actor": "系统",
      "desc": "收到用车需求SUV系列,5座,1辆"
    },
    {
      "time": "2026-07-12 15:35:00",
      "type": "hold_sent",
      "actor": "车务",
      "desc": "微信通知司机,等待确认"
    }
  ]
}
  • 只返回已经发生的车务事件,不补空步骤。
  • 同一派车组的组级动作去重,逐日完成事件按实际日期保留。
  • 无事件返回 data=[]

7. 保险事务可靠性

本节用于说明后端行为,不需要管理后台新增调用。

7.1 触发关系

派单动作 Outbox 事件 保险结果
司机确认派单 ASSIGNED 按当前司机保险类型逐服务日检查/购买
恢复已取消派单 RESTORED 恢复保障,且同司机同日不重复购买
取消派单 CANCELED 当天没有其他有效派单时退保;仍有有效派单时保留
提前完结 COMPLETED 只退完结截止日之后不再服务的保单

7.2 一致性保证

  • 派单状态变更与 Outbox 事件同事务落库,避免派单成功但保险事件丢失。
  • 同一派单按事件 ID 顺序处理;后继事件不会越过未完成前驱。
  • 失败按退避时间重试,超时 PROCESSING 可重新领取。
  • 单轮最多扫描 100 条,避免任务无界执行;这是后端技术保护,不是前端分页规则。
  • 定时重放复用 hl-user-servicesys_job/QuartzassignmentInsuranceOutboxJob.execute(),每分钟执行一次。
  • 内部重放接口受 X-Internal-Token 保护,不配置网关路由,前端/admin token 不应直接调用。

8. 前端必须处理

  1. 看板保持分页,按 data.total/page/pageSize 驱动分页器。
  2. 状态筛选读取 summary.statusOptions,不要维护独立状态映射或独立计数。
  3. 卡片始终独立展示 consultantDisplayName,不要放进 vehicleAdvice/customerNote 的条件块。
  4. 卡片展示当前 teamNocontactNameheadcountstartDate/endDatespecialTagsrequirementRemark
  5. 定制师筛选使用 /admin/user/customizers 下拉的 adminId,传 consultantId
  6. 文本搜索框可统一传 keyword;联系人、团号和定制师下拉仍可作为高级精确筛选。
  7. 派车/驳回按钮只看 canAssign/canRejectRequirement;急单样式不能隐藏操作按钮。
  8. 派单详情逐日行程直接渲染 itinerary.days;空数组显示空态,不造假。
  9. 大交通完全为空时展示 transport.transferTimeHint
  10. 所有雪花 ID 按字符串处理,禁止转 JavaScript Number

9. 不影响范围

  • 不修改前端仓库,本文件仅做后端契约告知。
  • 不新增“不分页全量看板”接口。
  • 不改变车型大类、座位数、司机占一座等既有业务规则。
  • 不把司机险成本计入客户退款;司机险仍只计车队成本。
  • 团期配车本轮不做。

10. 测试环境验收证据

环境:https://api.test.1814.love:9443,真实角色账号 fleet_mgr_4760 / VEHICLE_MANAGERdesigner_4760 / CUSTOMIZER

代码验证
- hl-fleet-service verify: 1537/1537
- hl-user-service verify: 3168/3168
- 独立复审: P0/P1=0

部署
- hl-fleet-service: task 77d19165,8087/8187 双实例健康
- hl-user-service: task 0c32a732,8081/8181 双实例健康
- hl-order-service-v3: task 06023fb6,8086/8186 双实例健康

部署后真实网关流程
- 126/126 通过,失败 0
- 覆盖新建订单、补全两名出行人、补全大交通、提交用车需求、车务查看、派单预检、
  排车、司机确认、取消(已/未通知司机)、恢复、换司机、提前完结、司机拒接、未派驳回、
  已派禁止驳回、矩阵、车辆/司机、价格日历、对账、保险任务与车管模板

数据库地面真相
- 本轮 3 个真实派单产生 8 条保险 Outbox 事件
- ASSIGNED/CANCELED/RESTORED/COMPLETED 全部 SUCCESS,retryCount=0
- sys_job 1037 为 ACTIVE,Quartz trigger 为 WAITING,最近 10 次执行全部 SUCCESS

11. 与既有文档关系

  • 本文补充并纠正 53_4871_车务提需求派单看板闭环契约-管理后台.md 的当前订单/当前需求、统计一致性和逐日行程口径。
  • 定制师下拉仍以 54_4876_派单看板团号与定制师下拉筛选-管理后台.md 为准。
  • 司机险业务规则仍以 26_4760_车务司机险自动投退保闭环与保险菜单契约-管理后台.md 为准;本文只补充事务可靠性实现和验收证据。