Files
wecom_it_smart_desk/docs/02-技术文档/技术架构/技术方案-REQ-坐席-007-分诊排查系统-v1.0.md
T
Simon facc04aa65 chore: docs 结构整改 + compose 双目录对齐(合并重建提交)
本提交为 .git 对象库损坏后的重建提交,内容等价于原先三个本地提交
(5e2fd4c2 / 57a53c98 / 5d7e1873)的累积结果,未做任何额外改动。

一、docs 结构整改(整改 #14)
根因:重构时新结构为 untracked 文件,执行 git stash(未带 -u)未纳入,
随后 git reset 拉回 HEAD 旧 tracked 树,导致旧树复活、新旧两棵目录
树并存于 docs/,共 791 文件、双分类体系冲突。

修复动作:
- b2 同名异主题文件改名迁移保全 9 个
- C 类 39 个孤立文件按主题正确归类
- A/B1 类 222 个重复文件删除(新结构已有内容副本)
- 9 个旧独有空目录删除
- 270 处内部引用按 verified 映射改写
- 整改记录 #14 登记于 04-运维文档/部署运维

结果:docs 791 → 569 文件,顶层仅规范 8 类 + 治理文件,单树恢复。
残留:约 20 处指向从未存在文件的陈旧死链,归入独立文档卫生任务。

二、compose 双目录对齐(消除踩坑 A)
- docker-compose.yml:nginx 前端挂载全部由根目录 frontend-*/dist
  改为 src/frontend-*/dist(h5 / agent / admin / terminal)
- docker-compose.dev.yml:dev 服务 build context 与卷同步改 src/
- 效果:本地 docker compose up 不再把根目录 stale dist 挂回,
  与线上一致,分叉隐患消除(已 docker compose config 校验通过)

防复发铁律:
- 重构须提交;仓库修复须 git stash -u 或先 commit
- 新结构须 git add 并提交,避免再次 untracked 复活
- H5 改动只动 src/frontend-h5/,禁改根目录遗留 frontend-*/
2026-08-07 22:31:32 +08:00

596 lines
26 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.
# 技术方案 - 分诊排查系统(一体两面:Troubleshooting + Triage
> **REQ编号**: REQ-坐席-007
> **版本**: v1.1
> **日期**: 2026-07-28
> **状态**: [待评审]
> **作者**: 宋献
> **关联文档**:
> - PRD: `../../01-产品文档/04-坐席工作台/PRD-REQ-坐席-007-分诊排查系统-v1.0.md`v1.3
> - 原型: `../../01-产品文档/04-坐席工作台/原型-REQ-坐席-007-分诊排查系统-v1.0.html`v1.3
> - 功能测试: `../../03-测试文档/03-功能测试用例/TC-坐席-007-分诊排查系统.md`v1.0,54 条用例,已补齐)
---
## 一、方案概述
### 1.1 建设目标
将现有“排查流程图管理”从进程内 Mock 数据和客户端本地状态,改造为具备**模板持久化、草稿发布、版本隔离、会话级执行、跨端同步、权限审计和可观测性**的生产闭环。
### 1.2 当前实现基线
| 层级 | 已有实现 | 主要问题 |
|---|---|---|
| 管理端 | `Flowcharts.vue`、JSON 编辑/预览、CRUD 客户端 | 列表契约错位;无发布、版本、审计;导入只做基础字段校验 |
| 后端 API | 5 个 REST 接口和 8 套 Mock 模板 | CRUD 只修改 `MOCK_TEMPLATES`,重启丢失;无管理员 RBAC |
| 数据模型 | `troubleshooting_templates` SQLAlchemy 模型 | API 未使用;字段不足以支持草稿、版本、负责人和员工可见范围 |
| 坐席端 | `TroubleshootBar.vue` 可选择模板和手动推进 | 状态在组件内,不绑定会话,不持久化,不同步 H5 |
| 员工 H5 | 自助列表、详情、流程和进度组件 | 页面未正式接入路由;执行事件和转人工上下文未闭环 |
| 数据契约 | `flowchart``path_steps`、种子数据 `root_node` | 多套结构并存,导入导出不兼容 |
| 测试 | 未发现独立功能用例和 E2E 验收 | 无上线质量闸门 |
### 1.3 技术原则
1. **服务端唯一状态源**:模板版本和执行进度均以数据库为准,客户端仅展示与发起命令。
2. **版本不可变**:发布后不允许原地修改;执行实例固定绑定版本快照。
3. **命令与事件分离**:客户端发送“完成节点/选择分支”等命令,后端校验后产生状态事件。
4. **契约统一**:管理端、坐席端、H5、种子文件和导入导出使用同一 JSON Schema。
5. **增量兼容**:保留现有 5 个基础路径的兼容层,但生产接口逐步切到 `/admin``/executions` 分域。
6. **最小权限与全审计**:维护、发布、执行、查看日志权限分离。
---
## 二、总体架构
```mermaid
flowchart LR
A[管理后台] -->|草稿维护/发布| B[Template API]
C[坐席工作台] -->|启动/推进/结束| D[Execution API]
E[员工 H5] -->|自助执行/转人工| D
B --> F[(PostgreSQL)]
D --> F
D --> G[WebSocket Manager\n单 worker]
G --> C
G --> E
H[AI/Dify 路由] -. 推荐模板 .-> D
I[审计与指标] <-->|事件/查询| F
```
### 2.1 模块边界
| 模块 | 职责 |
|---|---|
| Template Service | 模板元数据、草稿、版本、结构校验、发布、停用、回滚 |
| Execution Service | 创建实例、合法节点推进、暂停恢复、结束、转人工摘要 |
| Sync Service | 将执行事件推送给坐席连接池和员工连接池,支持断线恢复 |
| Audit Service | 记录模板管理操作和关键执行操作 |
| Metrics Service | 聚合采用率、完成率、解决率、退出节点和异常率 |
---
## 三、统一模板契约
### 3.1 JSON Schema v1
```json
{
"schema_version": "1.0",
"purpose": "troubleshooting",
"code": "vpn-remote-connection",
"name": "VPN 远程办公连接失败",
"category": "vpn",
"description": "远程办公 VPN 故障标准排查",
"estimated_minutes": 8,
"difficulty": 2,
"tags": ["VPN", "远程办公"],
"visibility": {
"agent": true,
"employee": true,
"departments": []
},
"root_node_id": "start-1",
"nodes": [
{
"id": "start-1",
"type": "step",
"title": "确认故障现象",
"employee_text": "请确认报错内容和发生时间",
"agent_text": "记录报错码、网络环境和客户端版本",
"next_node_id": "decision-1"
},
{
"id": "decision-1",
"type": "decision",
"title": "是否能打开互联网网站",
"options": [
{"key": "yes", "label": "可以", "next_node_id": "check-version"},
{"key": "no", "label": "不可以", "next_node_id": "end-network"}
]
},
{
"id": "end-network",
"type": "end",
"title": "转入网络排查",
"result": "redirect",
"linked_template_code": "network-connectivity"
}
]
}
```
> `purpose` 字段为 v1.1 新增,必填,值域 `troubleshooting` / `triage`。`code` 为业务稳定编码,便于跨版本引用、跨模板跳转和路由兜底。
#### 3.1.1 问诊模板(Triage)示例
```json
{
"schema_version": "1.0",
"purpose": "triage",
"code": "triage_intake",
"name": "问诊对话",
"category": "intake",
"description": "路由无匹配时的兜底问诊模板",
"estimated_minutes": 2,
"difficulty": 1,
"tags": ["triage", "intake"],
"visibility": {"agent": true, "employee": true, "departments": []},
"root_node_id": "triage-1",
"nodes": [
{
"id": "triage-1",
"type": "step",
"title": "请选择最贴近的故障现象",
"employee_text": "请选择最贴近的故障现象",
"agent_text": "等待员工自选",
"next_node_id": "triage-end"
},
{"id": "triage-end", "type": "end", "title": "回到标准模板选择", "result": "redirect"}
]
}
```
> Triage 模板走相同 Schema、相同版本、相同执行 API;由 §3.3 的 per-purpose 校验规则保证其节点数与结构可控。
### 3.2 节点类型
| 类型 | 必填字段 | 说明 |
|---|---|---|
| `step` | `id,type,title,next_node_id` | 操作或信息确认步骤 |
| `decision` | `id,type,title,options[]` | 至少 2 个选项,每个选项指向下一节点 |
| `end` | `id,type,title,result` | `resolved/unresolved/redirect/cancelled` |
### 3.3 校验规则
校验入口按 `purpose` 加载对应规则集。
**通用规则**(所有 purpose):
1. `schema_version` 必须为支持版本。
2. `purpose` 必填且值域为 `troubleshooting` / `triage`
3. `root_node_id` 必须存在,节点 `id` 全局唯一。
4. 除结束节点外均必须存在合法后继。
5. 决策节点至少 2 个选项,选项 key 不重复。
6. 从根节点出发所有生产节点均可达,至少存在一个结束节点。
7. 首版禁止循环。
8. 员工可见模板的路径必须具备 `employee_text`,且不得包含内部凭据或管理员命令。
9. 导入旧格式时执行显式迁移,不能静默丢字段;迁移报告随草稿保存。
**`purpose=troubleshooting` 专属规则**
- 节点数上限 100;最大深度 20。
- 结束节点 `result` 允许 `resolved` / `unresolved` / `redirect` / `cancelled`
**`purpose=triage` 专属规则**
- 节点数上限 10;最大深度 4。
- 必须存在结束节点,且结束节点 `result=redirect`(回到标准模板选择)。
- `tags` 必须包含 `triage``intake`
- 不允许 `linked_template_code` 指向其他排查,避免问诊模板变排查。
**`purpose` 字段保护规则**
- 模板创建成功后 `purpose` 字段不可修改。
- 如需另一种用途,必须显式调用 “基于此模板复制为另一种用途” 接口,新模板继承旧模板节点结构但重置 `purpose` 并触发完整校验。
- 导入 JSON 时若未声明 `purpose`,默认 `troubleshooting` 并写入导入报告。
### 3.4 旧数据映射
| 旧字段 | 新字段/处理 |
|---|---|
| `flowchart` 递归树 | 展开为 `nodes[]` + `root_node_id` |
| `root_node` | 作为旧格式根节点输入并转换 |
| `path_steps` | 仅作为只读展示缓存,不再作为事实源;由已选择路径动态计算 |
| `estimated_time` | `estimated_minutes` |
| `is_active` | 模板主记录 `status=active/disabled` |
---
## 四、数据库设计
### 4.1 `troubleshooting_templates` 模板主表
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | UUID PK | 模板 ID |
| `code` | varchar(64) unique | 稳定业务编码 |
| `purpose` | varchar(16) not null | 模板用途:`troubleshooting`(默认)/ `triage`;创建后不可修改,需通过“克隆为另一用途”产生新模板 |
| `name` | varchar(256) | 名称 |
| `category` | varchar(32) | 分类 |
| `description` | text | 描述 |
| `status` | varchar(16) | `active/disabled/archived` |
| `current_published_version_id` | UUID nullable | 当前发布版本 |
| `owner_id` | varchar | 内容负责人 |
| `review_due_at` | timestamptz nullable | 复审日期 |
| `created_by/updated_by` | varchar | 操作者 |
| `created_at/updated_at` | timestamptz | 时间戳 |
### 4.2 `troubleshooting_template_versions` 版本表
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | UUID PK | 版本 ID |
| `template_id` | UUID FK | 模板主记录 |
| `version_no` | integer | 单调递增版本号 |
| `version_label` | varchar(32) | v1.0、v1.1 等展示值 |
| `state` | varchar(16) | `draft/published/superseded` |
| `schema_version` | varchar(16) | JSON Schema 版本 |
| `definition` | JSONB | 完整模板定义 |
| `checksum` | varchar(64) | 内容哈希,检测重复发布 |
| `change_summary` | text | 版本说明 |
| `lock_version` | integer | 乐观锁 |
| `created_by/published_by` | varchar nullable | 操作者 |
| `created_at/published_at` | timestamptz nullable | 时间戳 |
约束:`unique(template_id, version_no)``published` 记录不可更新或删除。
### 4.3 `troubleshooting_executions` 执行实例表
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | UUID PK | 执行实例 |
| `conversation_id` | UUID nullable | 关联会话;员工纯自助阶段可为空 |
| `employee_id` | varchar | 员工 |
| `agent_id` | varchar nullable | 坐席 |
| `template_id/version_id` | UUID FK | 固定模板版本 |
| `source` | varchar(16) | `agent` / `employee` / `ai_recommend` / `triage_fallback``triage_fallback` 为路由无匹配时的兜底问诊实例,不计入排查完成率与解决率指标 |
| `status` | varchar(16) | `running/paused/completed/transferred/cancelled` |
| `current_node_id` | varchar(64) | 当前节点 |
| `path` | JSONB | 已执行节点与分支选择摘要 |
| `result` | varchar(24) nullable | 结果 |
| `started_at/finished_at` | timestamptz | 时间 |
| `last_event_seq` | bigint | 事件顺序号 |
### 4.4 `troubleshooting_execution_events` 事件表
保存 `started/node_completed/decision_selected/paused/resumed/transferred/completed` 等事件;以 `(execution_id, client_event_id)` 唯一约束保证幂等。
### 4.5 `troubleshooting_audit_logs` 审计表
记录模板 ID、版本 ID、动作、操作者、来源 IP、变更摘要、前后校验和、时间和结果。定义中可能包含敏感文本,审计差异需脱敏或仅存校验和与摘要。
---
## 五、API 设计
### 5.1 响应规范
继续使用项目统一结构:
```json
{"code": 0, "message": "success", "data": {}}
```
列表统一返回:
```json
{"items": [], "total": 0, "page": 1, "page_size": 20}
```
管理端客户端必须读取 `data.items`,不得将列表对象当数组调用 `map()`
### 5.2 模板管理 API
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | `/admin/troubleshooting-templates` | admin/auditor | 分页查询模板,支持 `purpose``category``status``keyword` 过滤 |
| POST | `/admin/troubleshooting-templates` | admin | 创建模板与初始草稿 |
| GET | `/admin/troubleshooting-templates/{id}` | admin/auditor | 模板详情与当前版本 |
| PATCH | `/admin/troubleshooting-templates/{id}` | admin | 更新主信息,使用 `If-Match``lock_version` |
| POST | `/admin/troubleshooting-templates/{id}/drafts` | admin | 从指定版本创建草稿 |
| POST | `/admin/troubleshooting-templates/{id}/clone-as-purpose` | admin | 复制为另一 `purpose` 的新草稿(继承节点结构、重置 `purpose` 并触发完整校验) |
| PUT | `/admin/troubleshooting-template-versions/{version_id}` | admin | 保存草稿定义 |
| POST | `/admin/troubleshooting-template-versions/{version_id}/validate` | admin | 完整校验 |
| POST | `/admin/troubleshooting-template-versions/{version_id}/publish` | admin | 发布新版本 |
| POST | `/admin/troubleshooting-templates/{id}/disable` | admin | 停用模板 |
| GET | `/admin/troubleshooting-templates/{id}/versions` | admin/auditor | 版本历史 |
| POST | `/admin/troubleshooting-template-versions/{version_id}/rollback` | admin | 复制为新草稿 |
| POST | `/admin/troubleshooting-templates/import` | admin | 导入并返回迁移/校验报告 |
| GET | `/admin/troubleshooting-templates/export` | admin | 导出选定版本 |
| GET | `/admin/troubleshooting-audit-logs` | admin/auditor | 查询审计日志 |
### 5.3 执行 API
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | `/troubleshooting-templates` | employee/agent | 只返回已发布、启用且有权可见的模板摘要 |
| GET | `/troubleshooting-templates/{id}` | employee/agent | 返回当前已发布版本的角色裁剪视图 |
| POST | `/troubleshooting-executions` | employee/agent | 启动执行实例 |
| GET | `/troubleshooting-executions/{id}` | participant/admin | 获取当前状态和路径 |
| POST | `/troubleshooting-executions/{id}/commands` | participant | 提交完成步骤、选择分支等命令 |
| POST | `/troubleshooting-executions/{id}/pause` | agent | 暂停 |
| POST | `/troubleshooting-executions/{id}/resume` | participant | 恢复 |
| POST | `/troubleshooting-executions/{id}/transfer` | employee/agent | 转人工并产生摘要 |
| POST | `/troubleshooting-executions/{id}/complete` | participant | 结束并记录结果 |
命令示例:
```json
{
"client_event_id": "f4d8...",
"expected_seq": 7,
"command": "select_option",
"node_id": "decision-1",
"option_key": "yes"
}
```
服务端校验:参与者身份、实例状态、当前节点、选项合法性、`expected_seq`、幂等键。冲突返回 `409` 并携带最新状态。
---
## 六、发布与执行状态机
### 6.1 模板版本状态
```mermaid
stateDiagram-v2
[*] --> Draft
Draft --> Draft: 保存/校验
Draft --> Published: 校验通过并发布
Published --> Superseded: 新版本发布
Published --> Draft: 复制或回滚为新草稿
Superseded --> Draft: 回滚为新草稿
```
### 6.2 执行实例状态
```mermaid
stateDiagram-v2
[*] --> Running
Running --> Paused: 暂停
Paused --> Running: 恢复
Running --> Transferred: 转人工
Transferred --> Running: 坐席继续
Running --> Completed: 已解决/未解决
Running --> Cancelled: 主动取消
```
状态转换必须由后端服务执行,客户端不得直接写状态。
**`source` 枚举与 triage 实例语义**
- 执行实例 `source` 取值:`agent`(坐席手动启动)、`employee`(员工自助启动)、`ai_recommend`(路由自动启动)、`triage_fallback`(路由无匹配兜底问诊)。
- `triage_fallback` 实例复用完全相同的状态机;其结束(`end` 节点 `result=redirect`**不记录** `resolved` / `unresolved`,由服务端在结束命令中复位会话的路由状态,自动回到“路由推荐 + 手动覆盖”双轨,允许路由层后续再次推荐标准排查。
- 同一 `conversation_id` 同一时刻**仅允许一个 `running` 实例**:创建实例时后端校验该会话不存在未结束实例,否则返回 `409 Conflict` 并携带当前实例信息;手动切换模板须先 `complete` / `cancel` 旧实例再创建新实例(对应 PRD §5.4.5)。
---
## 七、WebSocket 同步方案
### 7.1 消息类型
统一事件消息:
```json
{
"message_type": "troubleshooting_execution_event",
"message_id": "evt-uuid",
"conversation_id": "conv-uuid",
"execution_id": "exec-uuid",
"event_seq": 8,
"event_type": "node_changed",
"data": {
"current_node_id": "check-version",
"progress": {"completed": 5, "visited": 6}
},
"created_at": "2026-07-28T12:00:00+08:00"
}
```
### 7.2 推送规则
1. 事件落库成功后再推送,避免客户端看到未持久化状态。
2. 同时推送坐席会话连接池和员工连接池;项目后端保持 `--workers 1`,符合现有 WebSocket 单例约束。
3. `message_id``event_seq` 用于前端去重与顺序判断。
4. 断线重连后先 `GET execution` 恢复快照,再消费新事件。
5. 客户端收到间断序号时主动拉取快照,不自行猜测中间状态。
### 7.3 转人工摘要
转人工事件至少包含模板名称、版本、启动时间、已访问节点、分支选择、员工备注、当前节点和建议下一步。内部节点说明仅对坐席展示。
---
## 八、权限与安全
### 8.1 后端强制权限
- 管理 API 强制管理员或指定模板管理员角色;不能只依赖前端路由 `requiresAuth`
- 执行 API 校验当前用户是员工本人、会话坐席或管理员。
- 审计员只读,不得发布或推进实例。
- IP 白名单中间件继续作为管理端附加控制,但不能代替 RBAC。
- **按 `purpose` 的显式隔离**`triage` 模板对员工**始终可见**,不受 `visibility.departments` / 角色过滤约束,且不得在可见范围写入敏感过滤条件(避免兜底模板被过滤);对坐席**仅只读**(可查看,不可创建/发布/编辑/停用)。`troubleshooting` 模板仍按权限矩阵与可见范围过滤。
### 8.2 内容安全
1. 发布前执行敏感字段扫描,禁止密码、Token、Secret、生产私钥和个人敏感信息进入模板。
2. 员工视图由后端按角色裁剪,不通过前端隐藏字段实现保密。
3. 模板导入限制文件大小、节点数和嵌套深度,防止资源消耗攻击。
4. JSON 作为数据渲染,禁止执行 HTML、JavaScript 和任意表达式。
5. 高风险操作节点只能链接已审批自动化能力,不能内嵌任意命令。
---
## 九、前端改造
### 9.1 管理端
- `Flowcharts.vue` 更名语义为“分诊排查管理”,保留兼容路由 `/flowcharts`
- 列表适配 `{items,total}`,增加状态、负责人、发布版本、筛选和分页;**按 `purpose` 分 TabTroubleshooting / Triage**,便于运营区分两类模板。
- 编辑器顶部增加 **“模板用途”选项**,新建时强制选择 `purpose`,创建后不可修改;切换用途只能通过“复制为另一种用途”产生新草稿。
- 编辑器由“整个模板 JSON”调整为“结构化编辑 + JSON 高级模式”,两者共用 schema 校验。
- 增加版本历史、发布确认、停用、回滚、并发冲突和审计入口。
- 预览同时显示坐席视图和员工视图,及时发现角色文案缺失或敏感信息暴露。
### 9.2 坐席端
- `TroubleshootBar.vue` 不再维护权威本地步骤状态,改为消费执行实例快照。
- 模板选择后调用启动 API;节点操作发送 command,成功后根据服务端状态更新。
- 支持暂停、恢复、转模板、结束和查看完整路径。
- 页面刷新或切换会话后按 `conversation_id` 恢复进行中的实例。
### 9.3 员工 H5
- 正式注册自助列表、详情和执行路由。
- 员工端只接收角色裁剪后的节点字段。
- “需要人工帮助”调用 transfer API,并跳转或创建服务会话。
- 聊天内嵌排查组件与独立自助页面复用同一 execution store,避免双套状态。
---
## 十、迁移与兼容
### 10.1 数据迁移步骤
1. 新增版本、执行、事件和审计表;扩展模板主表。
2. 将现有 `MOCK_TEMPLATES``data/seed-templates/*.json` 通过离线迁移器转换为 Schema v1 草稿。
3. 对每份迁移结果执行结构校验,生成“成功/警告/失败”报告,人工确认后发布。
4. 管理端先切换新管理 API;旧 GET 列表保留一个版本周期的适配层。
5. 坐席端切换执行实例 API,验证稳定后接入 H5。
6. 删除运行时对 `MOCK_TEMPLATES` 的读写,Mock 仅保留为测试 fixture。
### 10.2 回滚策略
- 数据库迁移具备 Alembic downgrade;涉及版本表的数据迁移必须先备份。
- 新执行 API 使用功能开关 `TROUBLESHOOTING_EXECUTION_ENABLED`,关闭后隐藏执行入口,不回写 Mock。
- 发布失败不改变 `current_published_version_id`;新版本切换使用单事务完成。
- 已创建执行实例永远引用版本快照,回滚当前发布版本不影响历史和进行中实例。
---
## 十一、可观测性
### 11.1 指标
- `troubleshooting_template_start_total{template_id,version,source}`
- `troubleshooting_execution_complete_total{result}`
- `troubleshooting_execution_duration_seconds`
- `troubleshooting_node_exit_total{node_id,reason}`
- `troubleshooting_command_conflict_total`
- `troubleshooting_ws_sync_latency_seconds`
- `troubleshooting_validation_failure_total{rule}`
- `troubleshooting_template_complete_total{result}`:排查完成实例计数(与 `troubleshooting_execution_complete_total` 同源,按 `result` 区分)。
- `troubleshooting_template_resolved_total`:标记为“已解决”的完成实例计数。
**指标隔离规则(对应 PRD §5.4.8、§6.3 #10**
- 指标服务层硬编码 `source=triage_fallback` 的实例**不计入** `troubleshooting_template_complete_total``troubleshooting_template_resolved_total`
- 问诊实例仅计入启动指标:`troubleshooting_template_start_total{...,source=triage_conversion}`,用于观测问诊→标准模板的转化率。
- 此隔离需在 Metrics Service 采集层强制,避免运营指标被兜底问诊流量污染。
### 11.2 日志与告警
| 场景 | 级别 | 告警建议 |
|---|---|---|
| 发布事务失败 | ERROR | 5 分钟 ≥3 次告警 |
| 执行状态推进异常 | ERROR | 错误率 >2% 告警 |
| WebSocket 同步 P95 >2 秒 | WARN | 连续 10 分钟告警 |
| 死路/非法后继 | ERROR | 任意生产实例立即告警 |
| 模板复审到期 | INFO/WARN | 到期前 14 天通知负责人 |
日志禁止输出模板内可能含敏感信息的完整 JSON,仅记录模板/版本/节点 ID、错误码和追踪 ID。
---
## 十二、测试策略
### 12.1 单元测试
- Schema 校验:根节点、重复 ID、不可达、缺失分支、循环、深度和节点上限。
- 状态机:所有合法/非法状态转换。
- 节点推进:步骤、判断、结束和跨模板跳转。
- 幂等:重复 `client_event_id` 不重复推进。
- 角色裁剪:员工响应不包含 `agent_text` 和内部字段。
### 12.2 集成测试
- 草稿创建、校验、发布、停用、回滚完整链路。
- 乐观锁冲突返回 409。
- 发布事务失败时当前版本不改变。
- 执行实例固定绑定版本,新版本发布不影响进行中实例。
- 坐席与员工 WebSocket 双端同步和断线恢复。
### 12.3 E2E 验证
1. 管理员登录 → 创建 VPN 模板 → 校验 → 发布。
2. 坐席登录 → 打开会话 → 启动模板 → 推进判断分支。
3. 员工 H5 登录 → 查看同步进度 → 选择分支或请求人工。
4. 坐席收到转人工摘要 → 继续执行 → 标记解决。
5. 查询数据库、审计日志和指标,确认路径、版本、结果一致。
遵循项目验证铁律:未完成真实端到端验证,不得宣布生产可用。
---
## 十三、实施顺序与完成标准
### 13.1 建议迭代
| 阶段 | 范围 | 完成标准 |
|---|---|---|
| 1 | 统一 Schema、DB、管理 API、发布版本、RBAC、审计 | 管理闭环和 API 测试通过 |
| 2 | 管理端改造、导入迁移、双端预览 | 原型验收和浏览器 E2E 通过 |
| 3 | 执行实例、坐席接入、事件日志 | 会话级暂停恢复和版本隔离通过 |
| 4 | H5 接入、双端同步、转人工 | 端到端三端闭环通过 |
| 5 | 指标、告警、首批模板治理 | 上线与回滚演练通过 |
### 13.2 Definition of Done
- [ ] PRD、原型、技术方案和测试用例完成评审并相互关联。
- [ ] 不再使用进程内 Mock 作为生产数据源。
- [ ] 统一 Schema 覆盖管理端、坐席端、H5、种子和导入导出。
- [ ] 发布版本不可变,执行实例固定绑定版本。
- [ ] 后端 RBAC、IP 附加控制和审计日志有效。
- [ ] 坐席与员工断线恢复、消息去重和顺序一致。
- [ ] 单元、集成、E2E、回归和安全测试通过。
- [ ] 部署、迁移、回滚、监控和告警方案完成验证。
---
## 十四、技术决策与待评审项
### 14.1 建议锁定
1. 产品和技术统一使用“排查”,管理菜单显示“分诊排查管理”。
2. 使用扁平 `nodes[]` 作为唯一存储结构,便于校验、差异比较和节点引用。
3. `path_steps` 不再独立维护,执行时由事件路径计算,避免双数据源不一致。
4. 发布版本不可变,回滚等价于复制历史版本为新草稿并重新发布。
5. WebSocket 仅承担实时通知,最终一致性依赖数据库快照和事件序号。
### 14.2 待评审
- 是否保留兼容的 `/troubleshooting-templates` 管理写接口,或一次性切换到 `/admin`
- 模板版本号由系统自动生成还是允许管理员输入展示标签。
- 跨模板跳转首版是否纳入 P0;如纳入,需要循环依赖校验。
- 执行事件采用直接数据库写入还是引入 outbox;首版建议同事务写事件并同步推送,规模增长后再引入 outbox。
---
## 十五、变更记录
| 日期 | 版本 | 变更内容 | 变更人 | 变更原因 |
|---|---|---|---|---|
| 2026-07-28 | v1.0 | 新建完整技术方案,覆盖统一契约、版本发布、执行状态、双端同步、权限审计、迁移和测试 | Duckula | 补齐 REQ-坐席-007 技术文档缺口 |
| 2026-07-28 | v1.1 | 落实“一体两面”模型:§4.1 模板主表新增 `purpose` 字段、§4.3 执行实例 `source``triage_fallback`;§5.2 列表支持 `purpose` 过滤并新增 `clone-as-purpose` 接口;§6.2 补 triage 实例语义与同会话单实例约束;§8.1 补按 purpose 的权限隔离;§9.1 管理端按 purpose 分 Tab + “模板用途”选项;§11.1 新增 `triage_conversion` 指标隔离规则;头部测试状态同步为已补齐 | Duckula | 对齐 PRD v1.3 的 `purpose` 统一管理与问诊模板闭环 |