--- 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/` | 无 | `data.teamNo`;相关雪花 ID 为字符串 | | 6 | 评价列表 | `GET /v3/admin/review/list` | `keyword` 的 OR 搜索新增团号 | `data.records[].teamNo` | | 7 | 评价详情 | `GET /v3/admin/review/` | 无 | `data.teamNo` | | 8 | 司机险任务 | `GET /admin/fleet/insurance/tasks` | 新增可选 query `teamNo`,仅模糊匹配真实 `team_no` | `data.records[].teamNo`;历史空值为 `null` | | 9 | 司机详情 | `GET /admin/fleet/drivers/` | 无 | `data.relatedOrders[].teamNo`;保留 `groupNo` | | 10 | 车务派单看板 | `GET /admin/fleet/board/orders` | 既有 `teamNo` 搜索只匹配真实团号,不再匹配订单号 | 既有 `teamNo` 保持;空值不回退 `orderNo` | | 11 | 车务看板详情 | `GET /admin/fleet/board/orders/` | 无 | 既有 `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/` 新增响应字段 `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/` 新增 `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/` - `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`(其中团号空值回退订单号的建议被本次口径取代)