坐席端审批线降级跳转 + 回调最终一致回写 (Phase 0 T01+T02) #3

Merged
simon merged 1 commits from feat/agent-approval-degrade-jump into main 2026-08-09 08:28:37 +08:00
Owner

摘要

实现 Phase 0 审批线(T01 + T02),将审批动作降级为"前端跳转企微审批深链 + 后端 sys_approval_change 回调回写",达成服务台与企微最终一致

依据:

  • PRD:docs/01-产品文档/04-坐席工作台/PRD-REQ-坐席-011-统一工作队列重构-v0.1.md
  • 技术验证:docs/02-技术文档/技术架构/技术验证-U-1-审批与工单操作闭环可行性-v1.0.md
  • 核心结论:企微审批不可服务端闭环(官方无代审批接口;PC Web 无 JS-SDK 原生表单能力),故审批动作必须降级跳转。

改动清单(8 files)

前端(T01)

后端(T02)

  • src/backend/app/api/approval.py — 新增 writeback_approval_todo_status 主入口(缓存就地改写 45s 窗口 + 7 天快照 todo:approval:status:{sp_no} + WS 推送,全程 try/except 不阻塞 ACK);/approval/callback(line 1243)解析 sys_approval_change 后 asyncio.create_task 接线
  • src/backend/app/api/approval_webhook.py — 新增 _writeback_agent_todo 复用回调 → WS 推送通道

测试(新增)

  • src/backend/tests/test_approval_todo_writeback.py — 51 例(状态映射 16 / 缓存 Key 6 / 回写主入口 13 / 回调端点 3 / webhook 字符串映射 11 / 接线 2)

文档

  • docs/01-产品文档/04-坐席工作台/PRD-REQ-坐席-011-统一工作队列重构-v0.1.md
  • docs/02-技术文档/技术架构/技术验证-U-1-审批与工单操作闭环可行性-v1.0.md

关联键

本地待办 id = "approval:{sp_no}",description.sp_no 同值;企微回调必带 sp_no(webhook 中即 approval_id),无需中间映射表。

部署契约须知(重要)

PRD/设计写回调地址 /api/approval/callback,后端实际注册 /approval/callback(无 /api)。原因:app/main.py:918 注释表明 nginx location /api/ 已 strip 前缀,后端故意不加。

企微侧回填回调 URL 必须带 /api(如 https:///api/approval/callback,由 nginx strip 后到达后端 /approval/callback)。全站审批端点(jump/submit 等)均无 /api 前缀,一致。

已知设计行为(非缺陷)

  • 不落库:回写作用于 Redis 缓存(45s 窗口)+ 7 天快照。缓存过期后由聚合层重拉企微权威数据自然趋同 → 属"最终一致"模型。
  • 降级跳转:坐席点击审批动作后会在新标签页打开企微审批,企微侧处理完成经 sys_approval_change / approval_webhook 回调回写服务台,前端经 WS todo_status_changed 实时刷新。

QA 回归

严过关独立回归(FakeRedis,无需真实 Redis/企微):51 passed / 0 failed。首轮 12 处失败全为测试代码自身 Bug(已自修:pydantic frozen Settings 替身;新版 Starlette 路由 path 枚举);修复后全绿。前端改动文件 vue-tsc --noEmit 干净(全仓 105 处存量 type-check 错误 0 处落在本次改动文件)。无源码缺陷。

工单线(T03+)未启动

U-1.2(ITSM 读链路断裂——ITSMService.get_todo_list() 无条件 return [],坐席待办工单数恒为 0)+ U-1.1(写接口缺失——itsm_service.py 全文件仅只读)双重外部阻塞。需向 ITSM 平台方索取 列表 API + 操作类 API + app_id/secret 写权限 + 测试账号。该项另行立项,不在本次 PR 范围。

风险

ID 风险 等级 缓解
R-1 缓存过期窗口期(>45s 无请求)的回写延后 聚合层下次拉取企微权威数据自然一致;如需更强保证另立落库任务
R-2 企微侧未配置 /api/ 前缀回调 URL 致链路断 部署前由运维对照"部署契约须知"段确认;运维侧 checklist 已加

提交

9292f41763d9f8d6d4efe00435af41a28c623549 — feat(agent/backend): 坐席端审批线降级跳转 + 回调最终一致回写

## 摘要 实现 Phase 0 审批线(T01 + T02),将审批动作降级为"前端跳转企微审批深链 + 后端 sys_approval_change 回调回写",达成服务台与企微**最终一致**。 依据: - PRD:docs/01-产品文档/04-坐席工作台/PRD-REQ-坐席-011-统一工作队列重构-v0.1.md - 技术验证:docs/02-技术文档/技术架构/技术验证-U-1-审批与工单操作闭环可行性-v1.0.md - 核心结论:企微审批不可服务端闭环(官方无代审批接口;PC Web 无 JS-SDK 原生表单能力),故审批动作必须降级跳转。 ## 改动清单(8 files) **前端(T01)** - src/frontend-agent/src/components/chat/TaskDetailView.vue — handleAction 移除 mock ElMessage.success,审批类仅 console.info,其他类 ElMessage.info("该操作需在原系统中完成") - src/frontend-agent/src/components/chat/task/ApprovalDetail.vue — 通过/拒绝/转交 + 打开按钮接线为 <a target="_blank" :href="wecomApprovalUrl"> 真实跳转 - src/frontend-agent/src/composables/useWebSocket.ts — 新增 case "todo_status_changed" 实时刷新分支 **后端(T02)** - src/backend/app/api/approval.py — 新增 writeback_approval_todo_status 主入口(缓存就地改写 45s 窗口 + 7 天快照 todo:approval:status:{sp_no} + WS 推送,全程 try/except 不阻塞 ACK);/approval/callback(line 1243)解析 sys_approval_change 后 asyncio.create_task 接线 - src/backend/app/api/approval_webhook.py — 新增 _writeback_agent_todo 复用回调 → WS 推送通道 **测试(新增)** - src/backend/tests/test_approval_todo_writeback.py — 51 例(状态映射 16 / 缓存 Key 6 / 回写主入口 13 / 回调端点 3 / webhook 字符串映射 11 / 接线 2) **文档** - docs/01-产品文档/04-坐席工作台/PRD-REQ-坐席-011-统一工作队列重构-v0.1.md - docs/02-技术文档/技术架构/技术验证-U-1-审批与工单操作闭环可行性-v1.0.md ## 关联键 本地待办 id = "approval:{sp_no}",description.sp_no 同值;企微回调必带 sp_no(webhook 中即 approval_id),无需中间映射表。 ## 部署契约须知(重要) PRD/设计写回调地址 /api/approval/callback,后端**实际注册** /approval/callback(无 /api)。原因:app/main.py:918 注释表明 nginx location /api/ 已 strip 前缀,后端故意不加。 → **企微侧回填回调 URL 必须带 /api**(如 https://<domain>/api/approval/callback,由 nginx strip 后到达后端 /approval/callback)。全站审批端点(jump/submit 等)均无 /api 前缀,一致。 ## 已知设计行为(非缺陷) - **不落库**:回写作用于 Redis 缓存(45s 窗口)+ 7 天快照。缓存过期后由聚合层重拉企微权威数据自然趋同 → 属"最终一致"模型。 - **降级跳转**:坐席点击审批动作后会在新标签页打开企微审批,企微侧处理完成经 sys_approval_change / approval_webhook 回调回写服务台,前端经 WS todo_status_changed 实时刷新。 ## QA 回归 严过关独立回归(FakeRedis,无需真实 Redis/企微):**51 passed / 0 failed**。首轮 12 处失败全为测试代码自身 Bug(已自修:pydantic frozen Settings 替身;新版 Starlette 路由 path 枚举);修复后全绿。前端改动文件 vue-tsc --noEmit 干净(全仓 105 处存量 type-check 错误 0 处落在本次改动文件)。无源码缺陷。 ## 工单线(T03+)未启动 受 **U-1.2**(ITSM 读链路断裂——ITSMService.get_todo_list() 无条件 return [],坐席待办工单数恒为 0)+ **U-1.1**(写接口缺失——itsm_service.py 全文件仅只读)双重外部阻塞。需向 ITSM 平台方索取 `列表 API + 操作类 API + app_id/secret 写权限 + 测试账号`。该项另行立项,不在本次 PR 范围。 ## 风险 | ID | 风险 | 等级 | 缓解 | |---|---|---|---| | R-1 | 缓存过期窗口期(>45s 无请求)的回写延后 | 低 | 聚合层下次拉取企微权威数据自然一致;如需更强保证另立落库任务 | | R-2 | 企微侧未配置 /api/ 前缀回调 URL 致链路断 | 中 | 部署前由运维对照"部署契约须知"段确认;运维侧 checklist 已加 | ## 提交 9292f41763d9f8d6d4efe00435af41a28c623549 — feat(agent/backend): 坐席端审批线降级跳转 + 回调最终一致回写
workbuddy-claude added 1 commit 2026-08-09 01:04:54 +08:00
实现 Phase 0 审批线 T01+T02(依据 PRD-REQ-坐席-011 + U-1 技术验证结论)。

前端(T01):
- TaskDetailView.handleAction 移除 mock toast,审批类仅 console.info
- ApprovalDetail 通过/拒绝/转交 + 打开按钮接线为企微审批深链真实跳转(<a target="_blank">)
- useWebSocket 新增 todo_status_changed 实时刷新分支

后端(T02):
- approval.py 新增 writeback_approval_todo_status 主入口 + /approval/callback 接线
- approval_webhook.py 新增 _writeback_agent_todo 复用回调→WS 推送通道
- 以 approval:{sp_no} 为关联键,缓存就地改写 + 7天快照 + WS 推送,最终一致

测试:src/backend/tests/test_approval_todo_writeback.py(51 例全绿)
文档:PRD-REQ-坐席-011 v0.1、技术验证-U-1 v1.0
simon merged commit 9294cf12c1 into main 2026-08-09 08:28:37 +08:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: simon/wecom_it_smart_desk#3