---
schema: "hl-changelog/v2"
ticket: "5368"
title: "非订单页面统一补齐真实团号与团号搜索"
consumer: "admin"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "verified"
frontend_owner: "Pi"
frontend_ref: "hl-admin@4c8bdb97c89fa399e5fbb13240ea082f64fefc59"
target_release: "v2.1"
verified_at: "2026-08-03"
status_note: "PR #5386 已合并（dev-v3@07834e4c5）；order-v2/order-v3/user/fleet 已部署 TEST（tasks 03b0fecb/2b54e87b/258865cf/d290d667）并经网关验证：profile/orders teamNo=groupCode+keyword 搜索、contract teamNo 过滤分页正确、fleet insurance/board teamNo 返回与查询（orderNo 片段不命中）、chat 会话 teamNo、月度对账 teamNo、雪花 ID JSON String。OpenAPI/oasdiff 与 Spring Cloud Contract 仍 not_configured（人工回退证据见 D:/tmp/hl5368-gateway-evidence/）。管理后台已由 Pi 领取并开始逐页核对真实团号消费。"
updated_at: "2026-08-04"
base: "dev-v3"
---

# 管理端：非订单页面统一补齐真实团号与团号搜索

> **服务**: `hl-user-service`、`hl-order-service-v2`、`hl-order-service-v3`、`hl-fleet-service`
> **Issue**: [wx/HL#5368](https://git.1814.love:8443/wx/HL/issues/5368)
> **前端交接 Issue**: `wx/hl-api-changelog#64`
> **日期**: 2026-07-31
> **影响范围**: 管理后台工作台、订单列表、合同、评价、车务、房务、会话等订单关联页面
> **候选基线**: `dev-v3@07834e4c5`（PR #5386 已合并）
> **合并 PR**: [#5386](https://git.1814.love:8443/wx/HL/pulls/5386) head `b65cff23a`，merge commit `07834e4c5`
> **后端/网关状态**: backend=deployed，gateway=verified（2026-08-03）

> **契约裁决（yst 2026-08-03T16:24，承接 #5372）**: `/internal/order/designer-list` 仅扩展 keyword 对真实 `groupCode` 的模糊搜索，保留原响应字段，**不新增 `teamNo`**；对外 `/admin/order/list` 与 `/admin/profile/orders` 返回 `teamNo: String|null`，user-service 在公开边界执行 `teamNo=groupCode`。后端已按此实现并合并。

---

## ⚠️ 关键变化

1. 非订单管理页面统一新增 canonical 字段 `teamNo: string | null`。它只表示真实团号：
   - order-v3 来源为 `order_main.team_no`；
   - order-v2 来源为既有 `groupCode`；
   - 车务司机险来源为派单时真实团号快照；历史无值保持 `null`。
2. **禁止 `teamNo || orderNo` 回退**。`teamNo` 无值时前端统一显示 `-`（或既定空值占位），不得把 `orderNo`、`groupNo` 或其他编号伪装成团号。
3. `orderNo` 不删除：仍用于订单管理、内部关联、兼容展示和原有订单号搜索，但它不是团号。
4. 所有雪花 ID（例如 `orderId`、`contractId`、`schemeId`、`taskId`、`assignmentId`、`driverId`、`requirementId`、`bizId`）按 JSON String 处理。前端不得转为 JavaScript `Number`，路由、行键和动作请求继续使用这些稳定 ID，不得使用 `teamNo` 替代。
5. 本文覆盖并纠正历史 `#5156` changelog 中“团号空值回退订单号”的建议：本次统一口径为**无真实团号即空值，不回退订单号**。

---

## 一、通用字段契约

| 字段 | JSON 类型 | 空值 | 用途 | 兼容规则 |
|------|-----------|------|------|----------|
| `teamNo` | `string \| null` | 未生成、历史无快照或下游降级时为 `null` | 页面团号展示、约定接口的团号搜索 | canonical 新字段；禁止从其他编号推导 |
| `orderNo` | `string \| null` | 依原接口 | 订单号展示、订单管理、内部关联及原有搜索 | 保留，不删除；不得作为团号回退 |
| `groupCode` | `string \| null` | 依原接口 | order-v2 兼容 | 保留；`teamNo` 的真实值取自该字段，但前端新代码读 `teamNo` |
| `groupNo` | `string \| null` | 依原接口 | 司机相关历史兼容 | 保留；司机详情新代码读 `teamNo` |
| 各类雪花 ID | `string` 或 `string \| null` | 依业务字段 | 路由、行键、详情和动作接口参数 | 禁止 `Number(id)`、数学运算或以 `teamNo` 替代 |

前端统一展示示例：

```ts
const visibleTeamNo = teamNo?.trim() || '-'
// 禁止：teamNo?.trim() || orderNo?.trim() || '-'
```

---

## 变更接口

| # | 页面/接口 | 方法与路径 | 请求变化 | 响应变化 |
|---|-----------|------------|----------|----------|
| 1 | 管理后台工作台 | `GET /admin/profile/dashboard` | 无 | 各角色订单项补 `teamNo` |
| 2 | 定制师“我的订单” | `GET /admin/profile/orders` | `keyword` 增加团号模糊匹配 | `data.records[].teamNo` |
| 3 | 订单管理列表 | `GET /admin/order/list` | `keyword` 增加团号模糊匹配 | `data.records[].teamNo`；保留 `groupCode` |
| 4 | 合同列表 | `GET /v3/admin/contract/list` | 新增可选 query `teamNo`，模糊匹配 | `data.records[].teamNo`；合同/订单/方案 ID 为字符串 |
| 5 | 合同详情 | `GET /v3/admin/contract/<id>` | 无 | `data.teamNo`；相关雪花 ID 为字符串 |
| 6 | 评价列表 | `GET /v3/admin/review/list` | `keyword` 的 OR 搜索新增团号 | `data.records[].teamNo` |
| 7 | 评价详情 | `GET /v3/admin/review/<reviewId>` | 无 | `data.teamNo` |
| 8 | 司机险任务 | `GET /admin/fleet/insurance/tasks` | 新增可选 query `teamNo`，仅模糊匹配真实 `team_no` | `data.records[].teamNo`；历史空值为 `null` |
| 9 | 司机详情 | `GET /admin/fleet/drivers/<driverId>` | 无 | `data.relatedOrders[].teamNo`；保留 `groupNo` |
| 10 | 车务派单看板 | `GET /admin/fleet/board/orders` | 既有 `teamNo` 搜索只匹配真实团号，不再匹配订单号 | 既有 `teamNo` 保持；空值不回退 `orderNo` |
| 11 | 车务看板详情 | `GET /admin/fleet/board/orders/<orderId>` | 无 | 既有 `teamNo` 保持；空值不回退 `orderNo` |
| 12 | 车务矩阵 | `GET /admin/fleet/matrix/grid` | 团号搜索/展示遵循真实 `teamNo` | `assignments[].teamNo` 不回退 |
| 13 | 车务矩阵未派单 | `GET /admin/fleet/matrix/unassigned-orders` | 团号搜索/展示遵循真实 `teamNo` | `data[].teamNo` 不回退 |
| 14 | 车务矩阵单日清单 | `GET /admin/fleet/matrix/day-orders` | 团号搜索/展示遵循真实 `teamNo` | `data[].teamNo` 不回退 |
| 15 | 会话列表 | `GET /admin/message/chat/conversations` | 无 | `data.records[].teamNo`；`bizId`、`peerAdminId`、`requirementId` 为字符串 |
| 16 | 打开会话 | `POST /admin/message/chat/open`、`/open-house`、`/open-house-lead`、`/open-fleet` | 无 | `data.order.teamNo`；订单卡需求 ID 为字符串 |
| 17 | 房务选单池 | `GET /v3/admin/order/grab-pool/hotel-requirements` | `keyword` OR 搜索新增真实团号 | `data.records[].teamNo` |
| 18 | 房务我的/全部接单 | `GET /v3/admin/order/grab-pool/my-claims/hotel`、`/all-claims/hotel` | `keyword` OR 搜索新增真实团号 | `data.list[].teamNo` |
| 19 | 房务待办 | `GET /v3/admin/order/todos` | `keyword` 保留 title/reason OR 语义并增加真实团号 | `data.list[].teamNo` |
| 20 | 房务月度对账明细 | `GET /v3/admin/house/reconciliation/monthly/hotel-orders` | 无 | `data[].teamNo` |

内部 Feign 链路同步透传 `teamNo`，供 `/admin/profile/dashboard` 和管理端会话使用；前端不得直接调用 internal API。

> **契约裁决（yst 2026-08-03，承接 #5372）**：`GET /internal/order/designer-list` 仅扩展既有 `keyword` 对真实 `groupCode` 的模糊搜索，**保留原响应字段，不新增 `teamNo`**；对外 `/admin/order/list` 与 `/admin/profile/orders` 返回 `teamNo: String|null`，user-service 在公开边界执行 `teamNo = groupCode`。

---

## 三、接口详情与搜索口径

### 1. 工作台与我的订单

#### `GET /admin/profile/dashboard`

新增响应字段路径：

| 角色/区域 | 字段路径 | 类型 |
|-----------|----------|------|
| 管理员、定制师即将出行 | `data.upcomingTrips[].teamNo` | `string \| null` |
| 房务即将入住 | `data.upcomingTrips[].teamNo` | `string \| null` |
| 房务待办卡片 | `data.todoCards[].teamNo` | `string \| null` |

#### `GET /admin/profile/orders`

- `data.records[].teamNo: string | null`，真实值来自 order-v2 `groupCode`。
- `keyword` 的 OR 搜索范围扩展为：订单号、团号、联系人姓名、产品名。
- 原响应 `groupCode` 保留兼容。

### 2. 订单管理列表 `GET /admin/order/list`

- 新增 `data.records[].teamNo: string | null`，值来自真实 `groupCode`。
- 保留 `data.records[].groupCode`。
- `keyword` 搜索规则：
  - 订单号、团号、联系人姓名、产品名：模糊匹配；
  - 完整手机号：精确匹配；
  - 各条件保持 OR 语义。

示例字段值：

| 字段 | 示例 |
|------|------|
| `orderId` | `"2045390643479412737"` |
| `orderNo` | `"HL20260731123456"` |
| `groupCode` | `"26-0801"` |
| `teamNo` | `"26-0801"` |

### 3. 合同

#### `GET /v3/admin/contract/list`

新增 query：

| 字段 | 类型 | 必填 | 规则 |
|------|------|------|------|
| `teamNo` | `string` | 否 | 模糊匹配 `order_main.team_no`；空白按未传处理 |

新增响应字段 `data.records[].teamNo: string | null`。

#### `GET /v3/admin/contract/<id>`

新增响应字段 `data.teamNo: string | null`。

下列 ID 以 JSON String 返回：`contractId`、`orderId`、`schemeId`；详情中的 `travelers[].travelerId` 及状态日志中的 `logId`、`contractId` 同样按字符串处理。`schemeId`、`travelerId` 等可空字段保持 `null`。

#### ⚠️ v1/v3 切换口径（2026-08-04 决策）

合同页**全量使用 v3 端点**，不再使用 v1：

- 创建合同：`POST /v3/admin/contract/create`、`POST /v3/admin/contract/create-by-scheme`
- 刷新合同状态：`GET /v3/admin/contract/{id}/status`（实测成功）
- 列表、详情、作废、下载、重发短信：均走 `/v3/admin/contract/*`

v1（`/admin/contract/*`）不再用于合同页：

- v1 存量历史合同（约 20 条，SIGNING/VOIDED）自然消亡，**不迁移、不做兼容转换**；
- v1/v3 合同数据隔离不互通：v3 创建的合同 `contractId` 不能调 v1 接口（返回错误码 `510001`）；v1 创建的旧合同不会出现在 v3 列表/详情中。

前端合同页应统一按上述 v3 端点实现，移除 v1 合同调用，不得混用两套接口。

### 4. 评价

#### `GET /v3/admin/review/list`

- 新增 `data.records[].teamNo: string | null`。
- `keyword` 保留原 `content`、`userNickname`、`orderNo`、`targetName` 的 OR 语义，并新增真实 `teamNo` 模糊匹配。

#### `GET /v3/admin/review/<reviewId>`

新增 `data.teamNo: string | null`。评价与订单等雪花 ID 继续按字符串消费。

### 5. 司机险任务 `GET /admin/fleet/insurance/tasks`

新增 query：

| 字段 | 类型 | 必填 | 规则 |
|------|------|------|------|
| `teamNo` | `string` | 否 | 最长 64；trim 后模糊匹配任务真实 `team_no`，**不匹配 `order_no`** |

新增 `data.records[].teamNo: string | null`：

- 新任务保存派单时的真实团号快照；
- 历史任务没有快照时返回 `null`，不伪造、不回填 `orderNo`；
- `taskId`、`driverId`、`assignmentId`、`orderId`、`insuranceOrderId`、`handledBy` 均作为 JSON String（可空字段允许 `null`）。

### 6. 司机详情 `GET /admin/fleet/drivers/<driverId>`

- `data.relatedOrders[].teamNo: string | null` 为 canonical 团号。
- `data.relatedOrders[].groupNo` 保留兼容。
- `teamNo` 无真实来源时返回 `null`，不从 `orderNo` 或 `groupNo` 推导。

### 7. 车务看板与矩阵

已有 `teamNo` 字段继续使用，但统一收紧：

- 看板 `teamNo` 查询仅匹配真实团号，不再把 `orderNo` 当团号命中；
- 页面可见团号只显示 `teamNo`；空值显示 `-`，不得回退 `orderNo`；
- 看板、详情、矩阵的路由、行键、拖拽、派单、改派、取消等动作继续使用 `orderId`、`assignmentId`、`assignmentGroupId` 等字符串 ID；
- `orderNo` 可继续在明确标注“订单号”的区域展示，不得标成团号。

### 8. 管理端会话

- `GET /admin/message/chat/conversations`：`data.records[].teamNo: string | null`。
- 四个打开会话接口：`data.order.teamNo: string | null`。
- order-v3 不可达、订单无团号或历史摘要无值时，`teamNo` 返回 `null`，绝不回退 `orderNo`。
- `bizId`、`peerAdminId`、`requirementId` 等雪花 ID 作为字符串处理。

### 9. 房务选单池、我的订单、待办与对账

- 选单池、我的接单、全部接单的 `keyword` 在原订单号/客人姓名/电话/产品名 OR 搜索基础上增加真实团号模糊匹配。
- 待办 `keyword` 保持 `title`/`reason` OR 搜索，并增加按真实团号预解析订单 ID；筛选在分页前生效。
- 相关列表项和月度对账酒店订单明细新增 `teamNo: string | null`。
- 房务工作台通过 order-v3 → user-service Feign 链路透传同一字段；下游降级时字段保持 `null`。

---

## 四、前端正确调用与展示

1. 页面展示团号只读 `teamNo`，空值显示 `-`；不要使用 `orderNo`、`groupCode` 或 `groupNo` 做运行时回退。
2. 订单管理已有代码可继续使用 `groupCode`，但新改页面统一迁移到 canonical `teamNo`。
3. 明确标注“订单号”的区域可以继续显示 `orderNo`；“团号”区域不得混入订单号。
4. 搜索框按各接口契约传参：
   - 合同、司机险使用独立 query `teamNo`；
   - profile orders、订单列表、评价、房务列表使用原 `keyword`；
   - 车务看板使用既有 `teamNo` 参数，但其语义已收紧为只查真实团号。
5. 所有雪花 ID 从响应到 store、路由参数、表格 row key 和动作 payload 全程保持字符串。禁止 `parseInt`、一元 `+`、`Number()` 或数值排序。
6. `frontend_status` 必须保持 `pending`；只有前端按自身流程完成、验证并回填合法引用后才能迁移状态，后端不得代填。

---

## 五、边界行为

- 真实团号未生成：`teamNo: null`，页面显示 `-`。
- 历史司机险任务没有团号快照：`teamNo: null`，不做订单号回退。
- order-v3/Feign 降级：工作台或会话中 `teamNo` 可为 `null`，页面不得报错。
- 独立 `teamNo` 参数为空白：按未传处理。
- 团号关键词搜索在数据库分页前生效；不得仅过滤当前页。
- 原有 `orderNo`、`groupCode`、`groupNo` 及其他响应字段保持兼容。
- 本次为只读字段扩展和查询语义扩展，不改变订单状态机、合同状态机、评价审核、房务接单、车务派单和聊天权限。

---

## 六、展示与分页守恒

- 同一字符串 `orderId` 在工作台、合同、评价、车务、房务与聊天响应中的非空 `teamNo` 必须一致。
- 新字段与搜索扩展不增删业务状态，不改变状态标签、颜色、权限、排序主键或动作参数。
- 合同、评价、司机险、房务等分页列表必须在数据库分页前应用团号条件；`total` 与切页结果守恒，禁止仅过滤当前页。
- 房务 `todoCards` 与 `upcomingTrips` 中同一订单的 `teamNo` 必须一致；OPEN 聚合与历史分页均遵循相同真实团号来源。

---

## 七、不影响范围

- 不删除 `orderNo`、`groupCode`、`groupNo`。
- 不改变任何写接口的稳定 ID 入参。
- 不授权前端直连 order-v3 internal API。
- 不代表后端已合并、网关已放行、测试服已部署或前端已适配。
- `D:/work2/hl-ui` 未修改；前端变更由前端 owner 独立完成。

---

## 验证证据（已完成项与剩余门禁）

- [x] PR #5386 已合并至 `dev-v3@07834e4c5`；合并前独立只读复审 P0/P1=0、唯一 P2（profile/orders 镜像缺 displayStatus/displayStatusLabel/updateTime 透传）已修复并回归。
- [x] 全量验证通过：order-v2 3496 tests、order-v3 7272 tests、user 3512 tests、fleet 2887 tests，全 0 failures；fleet spotless:check 通过；`FleetInsuranceTaskTeamNoMysqlTest` 以外部 MySQL 8 实跑 3/3。证据：`D:/tmp/hl5368-fleet-verify-final2.log`、`D:/tmp/hl5368-user-test4.log`。
- [x] 4 服务已部署 TEST：order-v2 task `03b0fecb`、order-v3 `2b54e87b`、user `258865cf`、fleet `d290d667`（均 success）。
- [x] 网关实测（`api.test.1814.love:9443`）：profile/orders 返回 `teamNo=groupCode` 且 keyword 团号搜索 total 正确；`/admin/order/list` 同；contract list 团号过滤分页前生效（精确 total=1/模糊 total=2）且 detail 返回 teamNo；fleet insurance tasks 返回并可按 teamNo 查询（命中 4/不存在 0）；fleet board teamNo 搜索仅匹配真实团号（orderNo 片段不命中）；chat 订单会话返回 teamNo、非订单会话 null；house 月度对账返回 teamNo；所有雪花 ID 均 JSON String；同一订单 2079576729147338754 在 contract 与月度对账均返回 `26-4165`。证据：`D:/tmp/hl5368-gateway-evidence/gateway-evidence.md`。
- [ ] OpenAPI/oasdiff 与 Spring Cloud Contract 仍未配置（`not_configured`）；已用上述生产者/消费者 JUnit 与真实网关 HTTP 作为人工回退证据。
- [ ] 测试环境 review 列表与 grab-pool 无业务数据（total=0），团号 OR 搜索由 Mapper 单测覆盖，未做真数据命中验证。
- [ ] 前端完成展示、搜索、路由与动作回归后，由前端 owner 更新 `frontend_status`；当前保持 `pending`。

---

## 八、相关文档

- 后端 Issue: [wx/HL#5368](https://git.1814.love:8443/wx/HL/issues/5368)
- 后端 Draft PR: [wx/HL#5386](https://git.1814.love:8443/wx/HL/pulls/5386)
- 前端交接 Issue: `wx/hl-api-changelog#64`
- 历史车务契约: `changelogs-v2/2026-07/85_5156_车务看板与矩阵主标识显示团号-前端待处理-管理后台.md`（其中团号空值回退订单号的建议被本次口径取代）
