Files
th-hotel-simple/docs/project/frontend-backend/backend-to-frontend-notes.md

346 lines
40 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 后端提醒前端注意事项
## 1. 文档定位
本文记录后端侧提醒前端开发时必须注意的项目规范、业务规则、接口边界和安全要求。当前内容服务于 Reservation 任务详情、订单详情、任务列表、S10/S99 源邮件只读通知卡、旧 S000/S999 兼容展示、历史 Message Notification、系统管理后台等第一版页面。
## 2. 项目开发注意事项
- 前端只调用本项目后端接口,不直接调用 SuperAgent、AgentBus、OPERA、OHIP 或数据库。
- API 调用应统一放在前端 `src/services`,页面组件不要直接拼接后端 URL。
- 业务判断必须使用后端返回的稳定 code不使用中文或英文展示文案做判断。
- 后端返回的时间点字段统一是带 `Z` 的 ISO 8601 UTC 时间,例如 `created_at``updated_at``received_at``last_updated_at`;前端展示时再按用户或酒店时区格式化。
- 入住日期、离店日期、酒店营业日属于酒店本地业务日期,不要按 UTC 时间点自动换算日期。
- 详细时间设计参考 `docs/project/backend-time-design.md`,不要把数据库 UTC 时间直接当酒店当地时间展示。
- 前端不得保存或传递后端 Secret、replay access key、Provider API Key、Oracle 凭证、AgentBus Token。
- 后端数据库 ID 未来应尽量以字符串形式给前端,避免 JavaScript 长整型精度问题;如果当前接口仍返回数字,前端不要自行做数学运算。
- 接口字段发生变化前,需要先更新本目录沟通文档或对应需求文档。
## 3. 字段来源注意事项
- `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/01_Adapter_Frontend/任务卡前端字段变更与路由说明_3.0_to_current.md` 是 0711 P0 前端 / Adapter 路由说明,覆盖 S10/S99、type-known manual review 和 fail-closed 口径;其中 Parent split / 42 路由口径已被 0712 P0.1 覆盖。
- `docs/project/requirements/M002-v3-p0.1-parent-group-routing-update.md` 是当前 Parent Group / Allotment 路由修订说明:前端应按 40 路由口径处理 Parent split。
- `docs/import/20260712/前端字段控件修改说明_给信息系统小伙伴Codex_2026-07-12.md` 是前端字段控件、人工复核编辑和只读证据的外部输入资料;本项目开发以 `docs/project/requirements/M002-task-field-control-contract-v1.md` 的落地口径为准。
- `docs/project/requirements/M002-task-field-control-contract-v1.md` 是后端已扩展 `fields[]` 和前端后续控件渲染的字段控件契约 V1。
- `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/01_Adapter_Frontend/任务卡前端字段变更说明_3.0_to_当前版_2026-07-10.xlsx` 是当前前端展示 / 编辑白名单和三元组路由表。
- `docs/import/20260708/任务卡前端展示字段表 3.0.xlsx` 是历史前端展示 / 编辑白名单,已被 0711 P0 冻结基线承接。
- `docs/import/20260706/任务卡展示编辑矩阵.xlsx` 是后端校验、最终确认写入、OPERA 映射和展示条件的完整规则来源。
- 前端不要直接把整个旧 `ai_task_results[]` 或 V3 `message_events[]` 渲染成表单,只展示白名单允许的字段。
- 如果 3.0 白名单与旧矩阵冲突,应记录为前后端待确认问题,不由前端单方面放宽必填、枚举或校验规则。
## 4. 业务规则注意事项
- 任务详情页里,保存草稿和最终确认是两个独立动作,不能合并。
- 用户可以修改任务字段内容;最终确认后,后端使用 `confirmed_payload_json` 作为 OPERA 模拟输入来源。
- 同一订单下,前置任务未结束时,后续任务只能查看,不能编辑、确认或执行 OPERA 模拟操作。
- 任务状态 `FAILED` 第一版视为结束状态,不阻塞后续任务;但失败的 OPERA 操作不能跳过,必须展示失败原因并允许重试。
- M002 V3 新入口采用结构化 `S10/S99``S10` 表示未匹配当前支持的业务事件,`S99` 表示输入不足或无法形成业务素材包;旧 `S000/S999` 继续按历史数据兼容展示。
- `S10/S99` 后端会创建只读源邮件通知卡,任务列表可见,订单列表不可见;当前代码中的旧 `SOURCE_MESSAGE_ONLY` 任务仍按同一只读语义展示。
- 源邮件只读通知卡不允许编辑、确认、人工转换订单、执行 OPERA 或重试 OPERA不参与订单任务执行队列不阻塞其他任务也不被其他任务阻塞。
- type-known manual review 已支持同卡复核解阻第一版:应展示为原业务任务卡的复核模式,不应统一展示成 Fallback。只有业务类型或 subtype 本身未知时才进入 Fallback。
- 复核场景下允许用户确认订单归属;当前第一版只允许确认当前任务所属订单,不等于开放普通任务任意切换订单。
- 历史 Message Notification 挂临时订单,只读展示,不参与订单任务执行队列,不阻塞其他任务,也不被其他任务阻塞。
- Fallback / manual_review 转为 New / Update / Cancel 时需要展示审计轨迹;登录权限底座已提供,具体业务审计 actor 迁移仍后置。
- 普通任务切换订单接口已确认后置,前端第一版不要把普通任务拖拽或切换订单做成可提交能力。
## 5. 当前前端可用接口注意事项
| 接口 | 用途 | 前端注意 |
| --- | --- | --- |
| `POST /api/auth/login` | 用户名密码登录 | 成功后返回 `access_token`、当前用户、可访问酒店、权限码和可见菜单token 只放 `sessionStorage`,不要放 `localStorage`、URL、日志或错误上报。 |
| `GET /api/auth/me` | 恢复当前登录态 | 前端启动后带 `Authorization: Bearer <access_token>` 调用401 时清理 token 并进入登录页。 |
| `POST /api/auth/logout` | 登出当前 session | 带 `Authorization: Bearer <access_token>`;成功后前端必须清理本地 token 和当前用户上下文。 |
| `GET /api/reservation/orders` | 查询订单列表 | 默认返回全部订单状态;`open_task_count` 排除 `COMPLETED``FAILED`;隐藏技术订单不返回,因此 S10/S99 和旧 S000/S999 不会在订单列表形成订单。 |
| `GET /api/reservation/tasks` | 查询任务列表 / 工作台 | 用 `can_process``readonly_reason_code` 控制入口按钮;列表不返回 AI 原始 payload、邮件正文或附件 URL已返回来源邮件会话摘要字段并支持 `order_status` 按任务所属订单状态筛选;旧 S000/S999 和新 S10/S99 都以 `task_type=SOURCE_MESSAGE_ONLY` 只读任务返回,列表已透出 `result_type``ai_task_type``route_code``system_process_category`。 |
| `GET /api/reservation/orders/{orderId}` | 查询订单详情与任务时间线 | `include_tasks=false` 可只取订单摘要;时间线按后端队列顺序返回,前端不要自行按创建时间重排;`tasks[]` 已返回来源邮件会话摘要字段和 V3 路由字段;隐藏技术订单详情不可作为普通订单页打开。 |
| `GET /api/reservation/tasks/{taskId}` | 查询任务详情 | 以返回的可处理状态和只读原因控制按钮,不只看任务状态;`fields[]` 已包含 P0 字段元数据;源邮件只读通知卡字段列表和 OPERA 操作列表为空;结构化 S10/S99 通过 `source_message_only_result.agent_assessment``notification``manual_review` 展示;普通业务任务可通过 `adapter_contract_errors[]``unhandled_intents[]` 查看同批次未建任务的诊断信息type-known manual review 会返回顶层 `review_status``review_resolution``manual_review`。 |
| `PUT /api/reservation/tasks/{taskId}/draft` | 保存任务草稿 | 只保存草稿,不代表用户最终确认。 |
| `POST /api/reservation/tasks/{taskId}/confirm` | 最终确认任务 | 后端会做第一版字段校验,通过后进入 `READY`。 |
| `POST /api/reservation/tasks/{taskId}/manual-review-conversions` | Fallback 人工转换 | 只用于 manual_review / fallback不用于普通任务切换订单。 |
| `POST /api/reservation/tasks/{taskId}/manual-review-resolutions` | type-known manual review 同卡复核解阻 | 只用于已知业务类型的 `result_type=manual_review` 任务;提交 `field_overrides[]` 和当前订单归属确认,通过后进入 `READY` 并生成两条 OPERA 模拟操作。 |
| `POST /api/reservation/tasks/{taskId}/opera-operations/{operationId}/execute` | 执行 OPERA 模拟操作 | 当前是模拟,不调用真实 OPERA。 |
| `POST /api/reservation/tasks/{taskId}/opera-operations/{operationId}/retry` | 重试失败 OPERA 模拟操作 | 重试会追加 attempt 历史,前端不要覆盖旧失败记录。 |
| `GET /api/reservation/tasks/{taskId}/audits` | 查询任务审计流水 | 用于展示人工确认、转换、模拟操作等轨迹。 |
| `GET /api/source-messages` | 查询来源消息安全摘要 | 列表不返回邮件正文、HTML、附件 URL 或原始 payload。 |
| `GET /api/source-messages/{id}` | 查询来源消息安全详情 | 只用于安全摘要详情。 |
| `GET /api/source-messages/{id}/original` | 读取来源消息原文 | 需要受控访问头,返回 HTML 时前端展示前必须 sanitize。 |
| `GET /api/source-messages/{sourceMessageId}/conversation` | 读取邮件会话详情 | 返回同一外部会话全部邮件的完整 text/html、`html_body_sanitized`、附件外链、内联图片和关联订单 / 任务摘要;前端不传原文读取 key展示 HTML 时优先使用 `html_body_sanitized`。 |
| `POST /api/system/debug/eml-superagent-runs` | Debug 页面上传 `.eml` 并调用 SuperAgent | 仅 dev/test 受控调试使用;会写入 SourceMessage Inbox但不创建订单和任务。 |
| `GET/POST/PUT /api/admin/users...` | 系统管理用户维护 | 需要 Bearer token 和 `SYSTEM_USER_MANAGE`;用户 ID 返回字符串;禁用用户会撤销其 ACTIVE session。 |
| `GET/POST/PUT /api/admin/roles...` | 系统管理角色权限维护 | 需要 `SYSTEM_ROLE_MANAGE`;内置角色只读,自定义角色可新增、编辑和分配权限。 |
| `GET /api/admin/permissions` | 权限码只读列表 | 需要 `SYSTEM_ROLE_MANAGE`;前端只展示和选择已有权限码,不自行造权限码。 |
| `GET/POST/PUT /api/admin/menus...` | 系统管理菜单维护 | 需要 `SYSTEM_MENU_MANAGE`;允许保存未知路由,前端必须有未知路由兜底页。 |
| `GET/POST/PUT /api/admin/hotels...` | 系统管理酒店维护 | 需要 `HOTEL_MANAGE`;新增酒店默认 `DISABLED`,单酒店阶段不能启用第二家 `ACTIVE`。 |
| `GET /api/admin/audits` | 系统管理操作审计 | 需要 `SYSTEM_ADMIN_CONSOLE_ACCESS`用于查看管理后台写操作审计不包含密码、token、secret。 |
### 5.1 本轮新增 / 修改接口说明
本轮后端新增或补齐了以下前端 P0 查询能力。前端后续开发时,应优先以本节作为接入口径。
| 接口 | 本轮变化 | 前端接入注意 |
| --- | --- | --- |
| `GET /api/reservation/orders` | 新增订单列表接口。 | `order_status` 不传时默认查询全部订单状态;`page_num` 从 1 开始;`page_size` 后端有最大值保护;`open_task_count` 排除 `COMPLETED``FAILED``next_processable_task_id` 为空表示当前没有可继续处理的任务。 |
| `GET /api/reservation/tasks` | 补齐来源邮件会话摘要字段,并新增 `order_status` 查询参数。 | `order_status` 按任务所属订单状态过滤,支持 `TEMPORARY``ACTIVE``ENDED``LOGIC_DELETED`列表仍然只返回安全摘要不返回正文、HTML、附件 URL 或 AI 原始 payload点击邮件入口时使用 `source_message_id` 调会话详情。 |
| `GET /api/reservation/orders/{orderId}` | 补齐 `tasks[]` 每条任务的来源邮件会话摘要字段。 | `include_tasks=false` 可只取订单摘要;时间线顺序由后端按订单队列返回,前端不要自行按创建时间重排。`include_source_summary` 第一版不作为前端裁剪字段的强约束,前端暂不要依赖它减少返回字段。 |
| `GET /api/reservation/tasks/{taskId}` | 补齐顶层来源邮件字段,并扩展 `fields[]` 元数据。 | 顶层来源字段用于打开邮件会话;`fields[]` 中的 `result_type``task_type``task_subtype``default_value_source` 用于前端字段分组、调试和白名单对齐。 |
| `GET /api/source-messages/{sourceMessageId}/conversation` | 新增邮件会话详情接口,并补齐 `html_body_sanitized` / `html_render_mode`。 | 当前唯一推荐路径是这个接口;前端渲染邮件 HTML 时优先使用 `html_body_sanitized`;不要调用历史讨论过的 `/api/source-message-conversations/{externalConversationId}`。 |
| `POST /api/system/debug/eml-superagent-runs` | 新增 Debug EML 上传到 SuperAgent 调试接口,并补齐独立 Debug 外部消息 ID、原始 Message-ID 保留、安全 HTML 字段和入口通知识别。 | 只用于调试页面;请求为 multipart/form-data必须传 `X-TH-Hotel-Debug-Upload-Key`,但该 key 不能写进前端源码、构建产物、URL、localStorage 或错误上报SuperAgent 返回旧 S000/S999 或新 S10/S99 入口通知时都不应被前端视为 JSON 解析失败。 |
酒店上下文注意Reservation 列表、订单详情、任务列表和 Debug EML 上传的 `hotel_id` 第一版都是可选参数。前端默认可以不传;后端会按当前登录用户酒店上下文或平台酒店表唯一 `ACTIVE` 酒店解析。如果前端传了当前选中酒店,后端会校验该酒店是否可访问。
### 5.2 登录权限接入注意
后端已提供 M003 登录和权限底座第一版接口:
```text
POST /api/auth/login
GET /api/auth/me
POST /api/auth/logout
```
前端注意:
- 登录成功后只把 `access_token` 保存到 `sessionStorage`;刷新同一浏览器会话可恢复,关闭浏览器后需要重新登录。
- 所有需要登录态的后端请求使用 `Authorization: Bearer <access_token>`
- 当前后端第一版不强制拦截既有 Reservation / SourceMessage 业务接口;但是前端接入登录后应统一带上 Bearer token方便后续审计 actor 和权限收口。
- `/api/auth/me` 返回 `user``default_hotel_id``hotels[]``permissions[]``menus[]`;菜单入口应优先使用 `menus[]`不要继续硬编码订单列表、任务队列、Debug EML。
- `menus[]` 只包含可见菜单;订单详情、任务详情和邮件会话详情是隐藏详情路由,不会作为菜单项返回。
- `DEBUG_EML_SUPERAGENT` 菜单第一版只授予 `SYSTEM_ADMIN`;这只表示页面入口是否可见,不代表后端会把 `X-TH-Hotel-Debug-Upload-Key` 下发给前端。
- `user.id` 是字符串;前端不要把任何后端 ID 转成 JavaScript number。
- 登录失败统一显示用户名或密码错误,不要根据错误文案推断账号是否存在或是否禁用。
- 401 的 `AUTH_TOKEN_REQUIRED` / `AUTH_SESSION_INVALID` 应统一走清理 token、回登录页的逻辑。
### 5.3 来源邮件会话字段说明
任务列表、订单详情任务时间线、任务详情顶层会返回以下来源邮件字段:
| 字段 | 说明 | 前端使用方式 |
| --- | --- | --- |
| `source_message_id` | 本系统内部 SourceMessage Inbox ID。 | 打开邮件会话详情时作为路径参数传入 `/api/source-messages/{sourceMessageId}/conversation`。 |
| `source_subject` | 来源邮件主题安全摘要。 | 用于列表或任务详情标题旁展示,不代表完整邮件主题一定无敏感信息。 |
| `source_sender_summary` | 来源发件人展示值,当前不打码。 | 用于辅助用户判断邮件来源。 |
| `source_received_at` | 邮件来源接收时间UTC优先取 AgentBus payload `received_at`,缺失时使用本系统接收时间。 | 前端展示时按用户或酒店时区格式化。 |
| `external_conversation_id` | 外部邮件会话 ID。 | 仅用于展示或调试,不作为当前会话详情接口路径参数。 |
| `conversation_message_count` | 同一外部会话下的邮件数量。 | 用于提示用户打开的是整段会话,不是单封邮件。 |
### 5.4 邮件会话详情接入注意
- `GET /api/source-messages/{sourceMessageId}/conversation` 只接收路径参数 `sourceMessageId`;第一版不接收 `hotelId``includeBody``includeRelated`
- Reservation 列表、任务列表和订单详情默认不需要前端传 `hotel_id`;如果前端已经接入酒店选择器,可以把当前选中酒店作为可选 `hotel_id` 传给后端。任务详情、任务写操作和邮件会话详情当前仍按对象 ID 定位,不接收该参数。
- 后端会根据 `sourceMessageId` 定位 `external_conversation_id`,并返回同一会话下全部邮件;如果来源消息没有外部会话 ID会降级返回当前单封邮件。
- `messages[]` 按邮件来源接收时间正序返回,前端不要重新按创建时间或任务时间排序。
- 返回内容包含完整 `text_body``html_body``inline_images[]``attachments[]``related_orders[]``related_tasks[]`
- `html_body` 是原始 HTML 兼容字段;`html_body_sanitized` 是后端第一版清洗结果,已移除脚本标签、事件属性和危险协议链接。前端生产展示必须优先使用 `html_body_sanitized`,并可用 `html_render_mode=SANITIZED_HTML` 判断渲染模式。
- 第一版仅处理 HTML 内容安全;`inline_images[]``attachments[]``externalUrl` 来自本系统 OSS 服务暂不做额外拦截但前端仍不得写入普通日志、错误上报、localStorage 或 URL query。
- 会话详情接口由后端内部写原文读取审计,前端不传 `X-TH-Hotel-Source-Original-Read-Key`
- 会话详情外层字段主要是 snake_case但媒体对象沿用原文读取接口字段当前是 `mediaType``fileName``contentType``sizeBytes``externalUrl``externalMediaId` 这种 camelCase前端类型定义需要单独处理。
### 5.5 订单列表接入注意
- `GET /api/reservation/orders` 默认返回全部订单状态,包括 `TEMPORARY``ACTIVE``ENDED``LOGIC_DELETED`
- `keyword` 会匹配订单业务号、临时订单号、展示名、订单状态,也会匹配来源消息安全摘要命中的 SourceMessage ID前端可以用邮件主题、外部消息 ID 或会话 ID 辅助查订单。
- `open_task_count` 只统计未关闭任务,排除 `COMPLETED``FAILED`
- `next_processable_task_id` 是后端按同订单队列实时计算出的下一条可处理任务;前端可以用它做“继续处理”入口。
- `display_order_key` 是前端优先展示的订单业务号或临时订单号;`group_code``confirmation_number` 只有在当前订单业务号类型匹配时返回。
- 订单 ID、任务 ID、SourceMessage ID 在这些前端接口中按字符串返回,前端不要转换成 JavaScript number。
- 源邮件只读通知卡背后有隐藏技术订单用于满足后端任务外键,但订单列表不会返回该订单;任务列表中该类任务的 `display_order_key``temporary_order_no``group_code``confirmation_number` 可能为空,前端不要因此隐藏整条任务。
- 当前前端已按 `SOURCE_MESSAGE_ONLY` 展示旧 S000/S999后端回调已支持结构化 `route_code=S10/S99``result_type=source_message_review_notification` 的新入口通知,并继续只在任务列表和任务详情提供只读查看入口;`INFORMATIONAL_MESSAGE` 仅作为历史 Message Notification 兼容路径保留。
- 任务列表里旧 `task_type=SOURCE_MESSAGE_ONLY``task_subtype=S000/S999` 或新 `task_subtype=S10/S99` 的记录只展示邮件来源和 SuperAgent 入口结果,不展示处理按钮。
- 任务详情里 `source_message_only_result` 仅对 `SOURCE_MESSAGE_ONLY` 返回,包含 `entry_result_code``entry_result_meaning``entry_result_description``entry_result_source_message_id``result_type``route_code``agent_assessment``notification``manual_review``raw_answer`;普通业务任务该字段为空。
- 任务列表、订单任务时间线和任务详情顶层已透出 `result_type``ai_task_type``route_code``system_process_category`。前端展示任务卡标题和标签时优先用这些稳定 code不要只靠旧 `task_type` 判断。
- P0.1 后Parent split 父事件不再是独立 Parent Cancel Booking 卡;前端应展示为 `Parent Group / Cancel Allotment / cancel_allotment_control_block``route_code=R08_CANCEL_ALLOTMENT_CONTROL_BLOCK_NORMAL` 是普通业务卡,`route_code=R08_CANCEL_ALLOTMENT_CONTROL_BLOCK_REVIEW` 是同卡人工复核业务卡,不应展示成 `adapter_contract_error``linked_parent_release_after_child_split` 只作为关系字段或详情信息,不作为任务 subtype 筛选项。
- `manual_review.reason_code=target_object_unclear` 时,前端需要在任务详情展示 `manual_review.visible_reason``missing_fields``blocking_points``conflicting_points``suggested_human_actions``evidence_to_check`,并展示 `context_used.parent_identity_candidates[]` 辅助确认 Parent Group identity。当前前端已兼容顶层 `context_used.parent_identity_candidates[]``manual_review.context_used.parent_identity_candidates[]`;若后端 DTO 不透出 candidates页面会显示候选空态。
- `Cancel Allotment / cancel_allotment_control_block` 第一版复用旧 `Cancel Booking` 字段矩阵。后端在确认和复核解阻时会派生 `extracted_fields.cancel_object_type=allotment_control_block`,并接受 `extracted_fields.cancel_scope=entire_allotment_control_block`;前端不需要为了这两个 P0.1 系统字段额外阻塞人工复核提交。
- P0.1 的“40 条路由”表示当前合法 route definition 数量;`route_code` 保持历史稳定且不连续重编号,因此 `R41_FALLBACK_BUSINESS_EVENT_REVIEW``R42_UNHANDLED_CURRENT_INTENT` 仍是合法展示 code。
- `adapter_contract_errors[]``unhandled_intents[]` 只在任务详情返回,表示同一 SuperAgent 入站批次中没有生成业务任务的诊断块;前端只读展示并提供来源邮件入口,不显示保存、确认、执行或重试按钮。
### 5.5.1 Type-known manual review 同卡复核解阻接入注意
- `result_type=manual_review``system_task_type` 不是 `MANUAL_REVIEW` 时,前端应在原业务任务卡上展示复核模式,不要跳到 Fallback 转换页面。
- 任务详情顶层返回 `review_status``PENDING` 表示等待用户补字段或确认订单归属;`RESOLVED` 表示同卡复核已解阻。
- 任务详情顶层 `manual_review` 返回 SuperAgent 原始复核原因、缺失字段、阻塞点和建议动作,前端只读展示;不要把它当成可编辑表单直接提交。
- 解阻接口使用 `POST /api/reservation/tasks/{taskId}/manual-review-resolutions`。请求体:
```json
{
"confirmed_order_id": "20001",
"reason": "确认 PMS 房型代码后解阻。",
"field_overrides": [
{
"field_pointer": "/extracted_fields/room_items/0/pms_room_type_code",
"value": "RM3"
}
]
}
```
- `field_pointer` 必须是 RFC 6901 JSON Pointer并且只能指向当前任务卡可编辑字段后端会映射到矩阵 `field_path`。非法或只读字段会返回 `TASK_REVIEW_POINTER_INVALID`
- 复核解阻也可以提交 `field_path`,支持 P0 主路径和旧扁平路径;如果同时提交 `field_pointer``field_path`,两者必须指向同一个字段。前端新页面优先用任务详情 `fields[].field_pointer`,无法方便处理 JSON Pointer 时可用 `fields[].field_path`
- Parent / Allotment 场景中SuperAgent 可能在 `manual_review.missing_fields[]` 同时返回 `/case_keys/group_code``/case_keys/block_code`。本系统第一版任务卡只暴露 `case_keys.group_code`,后端复核解阻会把 `/case_keys/block_code` 视为同一业务字段的输入侧别名;前端按 `fields[]` 渲染并提交 `/case_keys/group_code` 即可,不需要额外造 `block_code` 输入框。
- 0711 P0 的房型字段主路径已迁移到 `room_items[0]`。任务详情 `fields[]`房量、房型原文、PMS 房型代码分别返回:
- `field_path=extracted_fields.room_items.0.room_quantity``field_pointer=/extracted_fields/room_items/0/room_quantity`
- `field_path=extracted_fields.room_items.0.room_type_raw``field_pointer=/extracted_fields/room_items/0/room_type_raw`
- `field_path=extracted_fields.room_items.0.pms_room_type_code``field_pointer=/extracted_fields/room_items/0/pms_room_type_code`
- `legacy_field_path` 仅用于前端过渡显示旧扁平字段;新页面保存草稿、最终确认和复核解阻应优先提交 `field_pointer` 或 P0 主 `field_path`
- 后端仍兼容旧提交 key`extracted_fields.room_quantity``extracted_fields.room_type``extracted_fields.pms_room_type_code`;同卡复核也兼容旧 `field_path` / 旧 pointer。响应会归一化到 P0 主 `field_path`;当只提交 `field_path` 时,响应里的 `field_pointer` 使用 P0 主 JSON Pointer。`confirmed_payload.legacy_field_values` / `draft_payload.legacy_field_values` 只供旧前端回显,不作为新逻辑判断依据。
- 当前第一版只支持 `room_items[0]``/extracted_fields/room_items/1/...` 或更大下标不会自动落到 0。
- 同一次请求不能重复提交同一字段;重复 `field_pointer` 或重复映射到同一 `field_path` 会返回 `TASK_REVIEW_POINTER_DUPLICATE`
- `confirmed_order_id` 第一版必须等于当前任务的 `order_id`;如果前端需要选择其他订单,仍属于后续“复核场景订单归属选择”细化,不要复用普通任务切换订单能力。
- 解阻成功后返回 `task_status=READY``review_status=RESOLVED``review_resolution.field_overrides[]``confirmed_payload` 和两条 `opera_operations[]`。前端应刷新任务详情并显示 OPERA 模拟操作入口。
- 解阻过程不改写 `ai_payload_json`;用户修正值保存在 `review_resolution``confirmed_payload.field_values``confirmed_payload.effective_payload` 中。`effective_payload` 是后端第一版嵌套结构,后续真实 OPERA 参数仍会在 OPERA 层重新组装。
- 历史 `field_contract_version=code-v1` 的任务卡如果已经有 `draft_payload_json``confirmed_payload_json`,后端迁移不会强行改成 `20260711-p0`。前端读取历史任务时,如果看到旧版本,应优先使用 `legacy_field_path` / `legacy_field_values` 做过渡回显;新保存或新确认后再以 P0 主路径为准。
- `review_resolution.resolved_at` 是 UTC `Z` 时间点。
- type-known manual review 不允许调用通用 `POST /api/reservation/tasks/{taskId}/confirm`;前端必须使用本节解阻接口,否则后端返回 `TASK_REVIEW_RESOLUTION_REQUIRED`
### 5.6 前端联调演示数据 seed 接口
后端提供一个受控的 dev/test 演示数据入口,方便前端在空库或本地环境快速看到页面效果。
```text
POST /api/system/reservation/demo-data
Header: X-TH-Hotel-Demo-Data-Key: <本地演示数据访问口令>
Content-Type: application/json
{
"run_label": "frontend-smoke"
}
```
启用方式:
- dev profile 默认开启test 默认关闭,需要后端环境显式设置 `reservation.demo-data.enabled=true` 或环境变量 `RESERVATION_TEST_DEMO_DATA_ENABLED=true`
- 必须配置 `reservation.demo-data.access-key`dev 优先使用 `RESERVATION_DEV_DEMO_DATA_ACCESS_KEY`test 优先使用 `RESERVATION_TEST_DEMO_DATA_ACCESS_KEY`,旧通用变量 `RESERVATION_DEMO_DATA_ACCESS_KEY` 仅作为兼容兜底。
- 该接口只用于 dev/test 联调,不允许放进生产普通页面,也不要把访问口令写进前端仓库、浏览器环境变量或构建产物。
返回内容:
- `demo_run_id`:本次 seed 的唯一关键词,可用于任务列表 / 订单列表搜索。
- `source_messages[]`:本次生成的 SourceMessage ID、外部消息 ID 和会话 ID。
- `orders[]`:本次生成的订单 ID、订单状态和展示键。
- `tasks[]`:本次生成的任务 ID、任务类型、任务 subtype 和任务状态。
- `entrypoints`:可直接访问的后端查询入口,包括任务列表、订单列表、队列订单详情、失败任务详情和邮件会话详情。
当前 seed 覆盖的页面效果:
- 同订单前置任务未完成,后续任务只读不可处理。
- 已完成 New Booking 任务和两条 OPERA 模拟成功记录。
- OPERA 模拟失败任务,可在任务详情看到失败 attempt 和重试入口。
- Fallback / manual_review 任务。
- 历史 Message Notification 只读任务;旧 S000/S999 和新 S10/S99 特殊只读任务可通过 SuperAgent 回调补充,前端 fixture 已补 S10 和同卡人工复核最小样例。
- 同一邮件会话下多封邮件、完整 HTML、附件外链和内联图片外链。
### 5.7 任务详情字段元数据接入注意
- M002 V3 CP9 后,`GET /api/reservation/tasks/{taskId}``fields[]` 是后端已经按 `visible``result_type``task_type``task_subtype``display_condition` 过滤后的当前任务生效字段集合。前端必须直接以 `fields[]` 为权威列表渲染、校验和提交,不再按完整字段矩阵自行补齐后端未返回的字段。
- 后端未返回的字段应视为“当前任务不展示 / 不可提交”,不是接口错误。例如 `new_group_block` 不再返回 FIT 专属 `case_keys.confirmation_number`,无附件时也可能不返回 `attachments` 字段;前端不得为了旧矩阵完整性临时合成这些字段。
- 保存草稿、最终确认和同卡人工复核解阻只允许从当前 `fields[]` 中选择字段提交。`manual_review.missing_fields[]` 如果指向的字段没有出现在当前 `fields[]`,前端只展示“当前字段后端未开放编辑”,不要自行构造 `field_pointer``field_path`
- `fields[]` 第一版服务于任务详情动态展示,字段来源与白名单规则后续以 `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/01_Adapter_Frontend/任务卡前端字段变更说明_3.0_to_当前版_2026-07-10.xlsx` 和同目录路由说明为准;当前代码中仍有 20260708 白名单兼容口径。
- `result_type``task_type``task_subtype``default_value_source` 已透出给前端,用于和最新前端白名单对齐。
- 后端校验、最终确认写入、OPERA 映射和展示条件仍以 `docs/import/20260706/任务卡展示编辑矩阵.xlsx` 为完整规则来源。
- 前端保存草稿时不要自行按 `write_path` 重组 OPERA 参数;第一版按任务详情返回的字段和值提交即可,真实 OPERA 参数组装后续由后端 adapter / 转换层处理。
- 任务详情页控制按钮时以 `availability.editable``availability.confirmable``availability.executable``availability.read_only``availability.blocked` 为准;`can_process``readonly_reason_code` 只出现在任务列表 / 订单时间线摘要里。
### 5.7.1 字段控件契约 V1 接入注意
后端已按 `docs/project/requirements/M002-task-field-control-contract-v1.md` 返回字段控件契约 V1。前端接入时注意
- 任务详情 `fields[]` 已新增 `control_type``edit_scope``write_target``options_source``raw_readonly``control_hint`
- 任务详情 `fields[]` 是后端按当前任务生效规则过滤后的字段集合,不是完整字段矩阵;前端不得自行补齐后端未返回的字段,也不要依赖固定 `fields.length`
- 未出现在 `fields[]` 的字段表示当前任务不展示、不校验、不提交。例如 `new_group_block` 不返回 FIT 专属 `case_keys.confirmation_number`,也不返回 Allotment 专属 `extracted_fields.child_room_items[]`;无附件时可以不返回 `attachments`
- 前端应优先按 `control_type` 渲染字段;旧 `input_editable``select_editable``date_picker``number_input``file_display``table_editable` 只作为兼容兜底。
- `raw_readonly=true``edit_scope=never/system_only``write_target=none` 的字段不能展示普通编辑控件。
- `source_message`、邮件正文、附件引用、raw evidence、`event_type``source_event_index`、关系索引、`route_code``result_type``task_type``task_subtype``manual_review.reason_code` 等字段必须只读。
- `extracted_fields.room_items.0.room_type_raw` 是房型原文证据,第一版返回 `control_type=readonly``edit_scope=never``raw_readonly=true`;用户应确认或修改 `pms_room_type_code`,不要覆盖 raw 原文。
- `extracted_fields.room_items.0.room_quantity` 返回 `control_type=number``extracted_fields.room_items.0.pms_room_type_code` 返回 `control_type=select``options_source=active_pms_room_type_catalog`
- type-known manual review 的 `manual_review.missing_fields[]` 应按 JSON Pointer 匹配 `fields[].field_pointer`,并复用对应字段控件提交 `field_overrides[]`;匹配不到的 pointer 不要临时生成任意输入框。
- 缺失字段会返回 `edit_scope=manual_review_only``write_target=review_resolution.field_overrides`;同卡复核中其他可编辑业务字段可能返回 `normal_and_manual_review`,前端第一版仍优先只渲染 `missing_fields[]` 指向的字段。
- `field_overrides[]` 新页面优先提交 `field_pointer`,可同时提交 `fields[]` 中的主 `field_path`;不要提交旧扁平 key 作为新逻辑首选。
- `options_source=active_pms_room_type_catalog``rate_code_catalog``system_case_lookup` 第一版仅代表选项来源,真实目录 / lookup 未接入前,前端不得硬编码 PMS 房型、Rate Code 或系统对象全集。
- 后端可能返回 `control_hint=catalog_backend_pending``lookup_backend_pending``structured_table_editor_pending`用于提示前端目录、lookup 或表格编辑后端能力仍未接入。
- `control_type=structured_table` 第一版如未实现编辑控件,可以只读展示或按后端 `edit_scope/options_source` 给出待接入提示;不要把对象数组压成单行自由文本再提交。
- `control_type=workflow_state` 表示流程状态或动作入口,例如复核解阻状态;不要把它作为普通 `field_values` 保存。
### 5.8 Debug EML 上传接口接入注意
后端已提供 Debug 页面专用的 `.eml` 上传和 SuperAgent 调试入口:
```text
POST /api/system/debug/eml-superagent-runs
Header: X-TH-Hotel-Debug-Upload-Key: <调试访问口令>
Content-Type: multipart/form-data
file: .eml 文件
hotel_id: 可选;缺省使用后端系统酒店,显式传值时必须是当前可访问酒店
run_label: 可选调试标签
```
页面级对接细节请优先阅读 `docs/project/frontend-backend/debug-eml-page-integration-guide.md`
前端注意:
- 该接口只用于 dev/test 调试页面,不是生产普通业务页面接口。
- `hotel_id` 第一版可不传;单酒店阶段后端按平台酒店表唯一 `ACTIVE` 酒店解析。只有在调试人员明确要覆盖当前酒店时,前端才传当前选中酒店。
- 接口会解析 `.eml`,上传原始邮件、内联图片和附件到本系统阿里云 OSS替换 HTML 内 `cid:` 图片,再写入 SourceMessage Inbox。
- SourceMessage 来源 provider 固定为 `DEBUG_EML_UPLOAD`,用于和 AgentBus 入库邮件区分。
- AgentBus 实时收到邮件后自动推 SuperAgent 由 M007 单独建设;这个接口是人工 Debug 上传链路,不代表实时生产链路。
- `external_message_id` 是后端生成的 Debug 独立 ID格式类似 `debug-eml-run-{debugRunId}-{sha256前缀}`;原始邮件 `Message-ID` 保存在 `agentbus_like_payload.source.original_message_id`
- 邮件会话解析支持 `References``In-Reply-To``Thread-Index`,但 Debug EML 的 `external_message_id` 不使用原始 `Message-ID` 做幂等。
- `agentbus_like_payload.schema_version` 固定为 `debug-eml-upload-v1`,前端可用于调试展示和版本判断。
- 第一版只返回 SuperAgent 结果,不创建订单、不创建任务、不调用任务结果通知接口。
- `X-TH-Hotel-Debug-Upload-Key` 只能由调试人员在受控环境手动提供,不能放入 `VITE_*`、源码、构建产物、URL query、localStorage、错误上报或普通日志。
- 返回的 `html_body_sanitized` 复用邮件会话详情的安全策略,前端展示 HTML 时优先使用;`html_body_with_oss_urls` 只作为调试原始处理结果,不建议直接渲染。
- 返回的 `uploaded_media[]``original_eml_oss_url``html_body_with_oss_urls``html_body_sanitized` 可能包含 OSS URL前端不要写入普通日志、埋点、错误上报或 URL query。
- `superagent_parsed_json` 为空时,前端展示 `superagent_raw_answer``warnings[]`,不要假定 SuperAgent 总能返回业务 JSON旧 S000/S999 和新 S10/S99 都属于可解释入口结果,不是普通解析失败。
### 5.9 系统管理后台接口接入注意
系统管理后台 V1 已提供 `/system` 前端入口和 `/api/admin/**` 后端接口。所有管理接口都必须带 `Authorization: Bearer <access_token>`,无 token 返回 401已登录但缺少权限返回 403。
前端路由和按钮注意:
- `/system` 入口需要 `SYSTEM_ADMIN_CONSOLE_ACCESS`;子页面按 `SYSTEM_USER_MANAGE``SYSTEM_ROLE_MANAGE``SYSTEM_MENU_MANAGE``HOTEL_MANAGE` 展示。
- 如果用户只有酒店管理权限,进入 `/system` 时应跳到 `/system/hotels`,不要固定跳 `/system/users`
- 系统管理入口只代表可进入后台,不代表拥有所有子页面操作权限;按钮仍需按具体权限控制。
- 直接访问未知菜单路由时前端必须展示安全兜底页,不要让页面白屏。
接口分页和字段注意:
- 分页统一使用 `page_num``page_size`,响应统一是 `{ items, page: { page_num, page_size, total } }`
- 后端 `BIGINT` ID 返回字符串,前端不要转成 JavaScript number。
- 时间点字段是带 `Z` 的 UTC 时间,展示时按用户或酒店时区格式化。
- 写操作失败时前端应展示后端 `message``error_code`,尤其是启用第二家 `ACTIVE` 酒店、禁用最后一家 `ACTIVE` 酒店、修改内置角色、用户名重复等 409 场景。
用户管理注意:
- 新增用户必须传初始密码,后端只保存哈希。
- 用户启用 / 禁用通过 `PUT /api/admin/users/{userId}``user_status` 完成,没有单独 enable / disable 路径。
- 禁用用户会撤销该用户全部 ACTIVE session前端若正用该用户 token会在下一次 `/api/auth/me` 或业务请求时收到 401。
- 重置密码接口 `POST /api/admin/users/{userId}/password-reset` 只在本次响应返回 `temporary_password`前端不能写入日志、埋点、URL、localStorage 或错误上报。
- 用户授权酒店必须全部是 `ACTIVE` 酒店,默认酒店必须在授权酒店列表内。
角色、菜单、酒店注意:
- 内置角色 `system_builtin=true` 时只读,前端应禁用编辑和权限分配按钮;后端仍会返回 409 兜底。
- 新增自定义角色后,用户需要重新登录或刷新 `/api/auth/me` 才能拿到最新权限上下文。
- 新增菜单允许未知路由;未知路由可以保存,但正式开放可见前要确认前端页面已经存在或兜底页可接受。
- 新增酒店默认 `DISABLED``hotel_id` 新增后不能修改。
- 单酒店阶段只允许一家 `ACTIVE` 酒店,后端会拒绝启用第二家 `ACTIVE`,也会拒绝禁用最后一家 `ACTIVE`
- 系统管理写操作会写入 `platform_admin_audit_log`;审计接口 `GET /api/admin/audits` 可按 `target_type``target_id``action` 查询。
## 6. 不给前端直接调用的接口
- `POST /api/system/reservation/demo-data` 只用于 dev/test 联调造数,不是生产业务页面接口;访问口令不能进入前端代码。
- `POST /api/system/debug/eml-superagent-runs` 只用于 dev/test Debug 页面,不是生产普通业务页面接口;访问口令不能进入前端代码或构建产物。
- `POST /api/integrations/superagent/task-results` 是 SuperAgent 到后端的服务到服务入站接口。
- `POST /api/ai-query/v1/case-context``POST /api/ai-query/v1/object-detail` 是 SuperAgent 查询上下文接口,不是前端页面接口。
- `GET /api/source-message-conversations/{externalConversationId}` 是历史讨论过的候选路径,当前后端不提供,前端不要接入。
- AgentBus probe、fixture、replay、system 类接口不应放到普通业务前端页面。
## 7. 需要持续提醒的后置事项
- 普通任务切换订单接口继续后置。
- M002 V3 的结构化 `S10/S99` 入站、40 条 P0.1 路由枚举 / 稳定配置、`UNHANDLED_CURRENT_INTENT``adapter_contract_error` transition 最小落库、任务列表 / 订单时间线 / 任务详情 V3 路由字段和只读诊断块透出、type-known manual review 同卡解阻第一版、typed infrastructure error、P0 fixtures 回归基线和 Parent Group / Cancel Allotment 路由修订均已完成。
- 系统管理后台 V1 已完成后续若要做用户搜索更多筛选、批量操作、密码策略增强、MFA、登录设备管理应单独开需求。
- 现有 Reservation / SourceMessage 业务接口的强制登录、强制权限和业务审计 actor 全量迁移仍后置。
- 真实 OPERA / OHIP 接入继续后置。