---
schema: "hl-changelog/v2"
ticket: "5750"
title: "派单操作时间线接口：订单卡片「查看日志」数据源"
consumer: "admin"
author: "wx"
change_type: "新增接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "implemented"
frontend_owner: "mmg"
frontend_ref: "a9a48643"
target_release: ""
verified_at: ""
status_note: "已实现。board.js 新增 getFleetOrderOperationLog；resolveBoardRowActions 全状态分支加「查看日志」（卡片图标按钮+悬浮提示、表格入「更多」）；新建 OperationLogModal 时间线弹窗（分页/keyword/时间区间/升降序，opTypeLabel/summary 直渲）。frontend_ref=a9a48643（BoardCardView 卡片入口由并发提交 7ec70cc0 承载）。"
updated_at: "2026-08-10"
base: "dev-v3"
generated: "2026-08-09T18:10:00+08:00"
---

## 新增接口

`GET /admin/fleet/orders/{orderId}/operation-log`

查询该订单全部派单操作时间线（数据源 `fleet_assignment_operation_log`），按 create_time 倒序分页（默认 pageSize=50，上限 200）。

### 请求参数（query）

| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| page | int | 否 | 页码，默认 1 |
| pageSize | int | 否 | 每页条数，默认 50，上限 200 |
| sortBy | string | 否 | `time,desc`（默认）/ `time,asc` 升序看完整时间线 |
| keyword | string | 否 | 模糊搜索（summary/操作人），≤32 字 |
| startDate / endDate | string | 否 | 时间区间过滤（ISO 8601，如 `2026-08-01T00:00:00`） |

### 返回体

```json
{
  "code": 0,
  "data": {
    "records": [
      {
        "id": "2086386125831561218",
        "time": "2026-08-09 17:36:30",
        "opType": "change_completed",
        "opTypeLabel": "修改派单完成",
        "summary": "王骁 修改派单完成：蒙A-E2E99宝音德力格尔 → 蒙A-K1999其木格，生效日 2026-08-23",
        "operatorName": "王骁",
        "effectiveDate": "2026-08-23",
        "detailJson": "{\"previousVehicleId\":\"...\",\"newVehicleId\":\"...\"}"
      }
    ],
    "total": 25,
    "page": 1,
    "pageSize": 50
  }
}
```

### 字段说明

- `id` / `time`：日志 ID / 操作时间
- `opType`：操作类型英文枚举（cancel_requested / cancel_completed / cancel_restored / cancel_failed / cancel_evidence_recorded / driver_notification_recorded / insurance_refund_pending / insurance_refund_succeeded / insurance_refund_failed / change_requested / change_completed / change_failed / slot_added / slot_removed / hold_notification / assignment_created / confirmed / driver_confirmed）
- `opTypeLabel`：中文标签（直接渲染）
- `summary`：**后端拼好的可读摘要**（操作人 + 动作 + 前后资源对比，如改派「旧车牌旧司机 → 新车牌新司机，生效日 x」、失败带原因、保险退保带明细统计），前端直接展示
- `operatorName`：操作人——**企业微信名优先，无企微名显示用户名**；系统/自动动作（如保险退保定时任务）为「系统」
- `effectiveDate`：生效日（按天改派/取消等），无则 null
- `detailJson`：明细 JSON 字符串（前后值/原因等），前端按需展示或忽略

### 权限

网关 `/admin/fleet/**` 统一鉴权，车务/管理员可见。

## 验证证据

- hl-fleet-service verify 3319/0F/0E + FleetRedLineArchTest 12/12 + spotless 通过；定向测试 7/7
- TEST 网关实证（订单 26-6436，探针 `tools/probe_5750_operation_log.py` 11/11 PASS）：字段齐全、opTypeLabel 中文、summary 含前后资源对比、系统动作显示「系统」、分页/升序/翻页正常、total 与 DB 一致

---

## 后端修复补充 (#5770，2026-08-10，PR #5775)

首版只给 `assignment_created / hold_notification / confirmed / driver_confirmed` 四类补了枚举中文标签，但**没有写入点**——时间线永远缺「新建派单/HOLD 通知/司机确认/确认执行」这四类里程碑行。本次读侧合成补齐，前端**无需改动**，同一接口现返回更完整的时间线。

### 行为变化（同接口，返回项更全）
1. **新增 4 类里程碑合成行**：读接口时从 `fleet_assignment` 的 `create_time / hold_sent_at / driver_confirmed_at / confirmed_at` 合成 `assignment_created`(新建派单)/`hold_notification`(HOLD 通知)/`driver_confirmed`(司机确认)/`confirmed`(确认执行) 行，与落表行按时间合并、去重后返回。
   - 合成行 `id=null`（无 `fleet_assignment_operation_log` 主键，前端可据此区分合成 vs 真实行，与房务 #4246 同约定）。
   - 司机确认行 `operatorName` = 司机姓名（非管理员）；其余里程碑走操作人解析。
2. **keyword 现按前端所见字段过滤**：此前只搜库里恒为「车务/系统」的原始 actor_name 与写侧动作词，按操作人真名/车牌/司机名搜必空；现改为对**渲染后**的 operatorName/summary/opTypeLabel/detailJson 过滤，可搜到展示的操作人真名、车牌、司机名。
3. **`effectiveDate`「生效日」修复**：改派 summary 的生效日此前因写侧 Hutool 把 LocalDate 序列化成 epoch 毫秒、读侧解析失败而**永不渲染**；现写侧改 ISO 明文、读侧兼容 epoch 毫秒/ISO 两形态，存量数据也能正确显示。

### TEST 实证（2026-08-10）
`GET /admin/fleet/orders/2086341233369616386/operation-log` 返回 4 条合成行：新建派单(系统) / 司机确认(巴雅尔) / HOLD 通知(米明光) / 新建派单(系统)，中文标签、操作人三路解析、时间倒序正确。
