facc04aa65
本提交为 .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-*/
14 KiB
14 KiB
PRD: 代办事项系统集成真实数据源
实现状态(2026-07-11 更新):
- ✅ P0 REQ-001 企微审批待处理列表 — 已实现并验证(
getapprovalinfoAPI +TokenManager)- ✅ P0 REQ-003 统一代办列表 API — 已实现(
todo_aggregator_service.py,Redis 缓存 45s)- ✅ P0 REQ-004 前端移除 mock fallback — 已实现
- ✅ P0 REQ-005 移除 device 类型 — 已实现
- ✅ P1 REQ-006 按类型筛选 — 已实现
- ✅ P1 REQ-008 手动刷新 — 已实现(
_force=1跳过缓存)- ⏳ P0 REQ-002 ITSM 代办工单列表 — 待 ITSM API 抓包 + app_id/app_secret 申请
- ⏳ P1 REQ-007 点击代办条目展示详情 — 待 ITSM 部分完成
- ⏳ P2 REQ-009/010 自动刷新/跳转 — 待后续迭代
项目信息
- Language: 中文
- Programming Language: 后端 FastAPI + SQLAlchemy + PostgreSQL + Redis | 前端 Vue3 + Element Plus + Pinia
- Project Name:
todo_integration_real_data - 原始需求复述: 将坐席端"代办事项"面板从 mock 数据切换为真实数据源。数据来源包括企微审批待处理审批单(
getapprovalinfoAPI)和 ITSM 运维平台"我的代办"工单(ITSM API + 企微 SSO 免登录)。移除所有 mock 数据和 device 类型,不保留 mock fallback。 - API 变更说明: 原始需求引用的
getapprovaldata(/cgi-bin/oa/getapprovaldata)已于 2019 年废弃返回 404,实际使用新接口getapprovalinfo(/cgi-bin/oa/getapprovalinfo),分页参数从cursor(int) 变为new_cursor(string),返回从data数组变为sp_no_list字符串数组。 - Token 变更说明: 原始设计使用
ApprovalTokenManager(审批应用 Secret),但服务器出口 IP218.75.34.87未在审批应用可信 IP 白名单中(errcode=60020)。实际改用TokenManager(IT 支持应用 Secret,IP 已在白名单)。
1. 产品目标
- 数据真实性:将坐席端代办面板从 20 条硬编码 mock 数据切换为两个真实数据源(企微审批 + ITSM 工单),确保坐席看到的是真实待处理工作。
- 统一聚合:后端聚合企微审批和 ITSM 工单两个异构数据源为统一代办列表 API,保持前端交互体验不变。
- 彻底去 mock:移除所有 mock 数据(后端
MOCK_TODO_ITEMS、前端mockTodoListData)和 device 类型相关代码,确保系统数据真实性,不留 fallback。
2. 用户故事
- 作为坐席,我希望在代办面板看到我真实的待处理企微审批单和 ITSM 工单,而不是 mock 数据,以便我了解真实的工作待办。
- 作为坐席,我希望点击代办条目能查看对应的审批单/工单详情,以便快速了解任务内容并决定处理优先级。
- 作为坐席,我希望代办列表能按类型(全部/审批/工单)筛选,以便高效分类处理不同来源的待办。
- 作为坐席,我希望代办列表能反映最新的待处理状态(支持手动刷新),以便不遗漏新分配的审批和工单。
- 作为坐席,我希望代办条目中能清晰区分审批单和工单的类型标签和优先级,以便快速识别紧急事项。
3. 需求池
P0 — Must Have
| ID | 需求描述 | 验收标准 |
|---|---|---|
| REQ-001 ✅ | 后端实现企微审批待处理列表查询:集成企微 getapprovalinfo API(POST https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo),查询当前登录坐席的待处理审批单列表。使用 TokenManager(IT 支持应用 Secret)获取 access_token,通过 filters 参数按审批状态(sp_status=1 审批中)过滤,返回 sp_no_list 后调用 getapprovaldetail 补充详情,在代码层按 18 个模板 ID 过滤,再通过 _extract_current_approver 按当前审批人过滤。 |
① 调用 getapprovalinfo 成功返回审批单号列表;② 仅返回 sp_status=1(审批中)的审批单;③ 支持分页(new_cursor + new_next_cursor);④ token 获取复用 Redis 缓存机制(wecom:access_token);⑤ 异常时记日志并返回空列表(不阻塞另一个数据源) |
| REQ-002 ⏳ | 后端实现 ITSM 代办工单列表查询:集成 ITSM 平台 API(https://devops.dc.servyou-it.com/ITSM/workflow/allTickets/umiAllticketsTodo),通过企微 SSO 免登录认证查询当前坐席的代办工单列表。待办:需抓包获取 API 接口规范 + 申请 app_id/app_secret。 |
① 成功调用 ITSM API 返回代办工单列表;② SSO 认证无需坐席手动登录;③ 返回工单包含标题、优先级、状态、创建时间等关键字段;④ 网络异常时记日志并返回空列表(不阻塞另一个数据源) |
| REQ-003 ✅ | 后端聚合两个数据源为统一代办列表 API:重写 GET /api/todo-items 端点,并行查询企微审批和 ITSM 工单两个数据源,将结果映射为统一的 TodoItemResponse 格式返回。移除 MOCK_TODO_ITEMS 硬编码数据。 |
① API 返回的 items 仅包含 type=approval 和 type=ticket 两种类型;② 两个数据源并行查询(asyncio.gather),任一失败不影响另一个返回;③ 返回数据按优先级排序(urgent→high→normal);④ 响应时间 < 3 秒(两个外部 API 并行);⑤ 不再返回任何 mock 数据 |
| REQ-004 ✅ | 前端移除 mock fallback 逻辑:修改 stores/todo.ts,移除 import { mockTodoListData } from '@/mock/data' 和 catch 块中的 mock fallback 逻辑。API 调用失败时显示空列表 + 错误提示,不回退 mock。 |
① 代码中不再 import mockTodoListData;② API 失败时 todoList 为空数组;③ 控制台输出错误日志;④ 开发环境和生产环境行为一致(无 DEV 特殊分支) |
| REQ-005 ✅ | 移除 device 类型相关代码:后端从 VALID_TODO_TYPES 移除 "device"(schema/model);前端从 typeLabel、typeLabelMap、TaskDetailView 的 DeviceDetail 分支、TodoPanel 的 type-device 样式中移除 device 相关代码。DeviceDetail.vue 组件可保留文件但不再被引用。 |
① 后端 VALID_TODO_TYPES 不再包含 "device";② 前端 typeLabel 不再包含 device 映射;③ TaskDetailView.vue 不再渲染 DeviceDetail 分支;④ TodoPanel 中无 type-device 样式或该样式不生效;⑤ API 返回数据中无 type=device 的条目 |
P1 — Should Have
| ID | 需求描述 | 验收标准 |
|---|---|---|
| REQ-006 ✅ | 代办列表支持按类型筛选:在 TodoPanel.vue 标题行增加"全部 / 审批 / 工单"三个筛选 Tab,点击后过滤展示对应类型的代办条目。后端 API 增加 type 查询参数支持服务端过滤。 |
① 默认显示"全部";② 点击"审批"仅显示 type=approval 的条目;③ 点击"工单"仅显示 type=ticket 的条目;④ 筛选状态有视觉高亮 |
| REQ-007 ⏳ | 点击代办条目展示对应详情:复用现有 TaskDetailView → TicketDetail / ApprovalDetail 子视图。点击审批条目展示审批详情,点击工单条目展示工单详情。详情数据来自后端 GET /api/todo-items/{id} 端点(需支持按 ID 查询单条代办详情,可能需要缓存或重新查询外部 API)。 |
① 点击审批条目 → 中间栏切换为 task 视图,展示 ApprovalDetail;② 点击工单条目 → 展示 TicketDetail;③ 详情数据正确展示标题、优先级、描述等字段;④ 返回按钮正常回到会话视图 |
| REQ-008 ✅ | 代办列表支持手动刷新:在 TodoPanel 标题行增加刷新按钮,点击后重新调用 fetchTodoList() 获取最新数据。 |
① 刷新按钮可见且有刷新图标;② 点击后触发 API 重新查询;③ 刷新过程中按钮显示 loading 状态;④ 刷新完成后列表更新 |
P2 — Nice to Have
| ID | 需求描述 | 验收标准 |
|---|---|---|
| REQ-009 ⏳ | 代办列表自动定时刷新:TodoPanel 挂载后每 60 秒自动刷新一次代办列表,组件卸载时清除定时器。 | ① 每 60 秒自动调用 fetchTodoList;② 组件卸载时 clearInterval;③ 不与手动刷新冲突 |
| REQ-010 ⏳ | 代办条目支持跳转到原系统操作:在详情页底部增加"在企微审批中打开" / "在 ITSM 中打开"按钮,点击后在新窗口打开对应的审批单/工单原始页面。 | ① 审批详情页有"在企微审批中打开"按钮,跳转到企微审批 URL;② 工单详情页有"在 ITSM 中打开"按钮,跳转到 ITSM 工单 URL |
4. UI 设计稿描述
4.1 TodoPanel(左栏待办面板)变化
标题行变化:
- 现有:
📋 待办事项+ 紧急数量徽章 - 变更后:
📋 待办事项+ 紧急数量徽章 + 类型筛选 Tab(全部/审批/工单)+ 刷新按钮(🔄 图标) - 布局:标题文字左对齐,筛选 Tab 紧跟其后,刷新按钮最右侧
待办条目变化:
- 每条代办仍保持现有布局:优先级圆点 + 标题文本 + 类型标签 + 时间 + 上报人头像
- 类型标签仅保留两种:
工单(蓝色,type=ticket)、审批(紫色,type=approval) - 移除
设备(橙色,type=device)标签 - 数据来源从 mock 变为真实 API 返回
空状态变化:
- 现有:
暂无待办 - 变更后:API 加载中显示 loading 动画;加载完成无数据时显示
暂无待办;API 失败时显示加载失败,点击重试
底部坐席统计:
- 保持不变(仍使用
getAgentStats()mock 数据,不在本次改造范围内)
4.2 TaskDetailView(中间栏任务详情)变化
顶部标题栏:
- 类型标签映射移除 device:
📋 运维工单/📝 审批单(移除🖥 设备异常) - 优先级标签保持不变
内容区:
- type=ticket → 渲染
TicketDetail子视图(保持不变,但数据来自 ITSM 真实工单) - type=approval → 渲染
ApprovalDetail子视图(保持不变,但数据来自企微真实审批单) - 移除 type=device →
DeviceDetail分支 - 未知类型 fallback 保持不变
4.3 ApprovalDetail / TicketDetail 子视图
- 整体布局保持不变(卡片式信息展示 + 操作按钮区)
- 数据字段需适配真实 API 返回结构:
- 审批详情:
description字段需映射企微审批返回的申请人、审批类型、表单内容等 - 工单详情:
description字段需映射 ITSM 返回的工单标题、类型、上报人、描述等
- 审批详情:
- 操作按钮(审批通过/拒绝、接单/结单等)的具体行为取决于待确认问题 #4 的决策
5. 待确认问题
5.1 ITSM API 相关(阻塞 REQ-002)— ⏳ 待申请授权
| # | 问题 | 说明 | 状态 |
|---|---|---|---|
| Q1 | ITSM API 的完整接口规范 | 需抓包获取请求方法/参数/返回格式 | ⏳ 待 agent-browser 抓包 |
| Q2 | ITSM SSO 认证的具体方式 | 后端调用 ITSM API 的认证链路待确认 | ⏳ 待抓包确认 |
| Q2.1 | ITSM app_id/app_secret 申请 | openapi 签名认证需要 app_id 和 app_secret(签名:params 按 key 升序 → 拼接 value → quote_plus → SHA1 → 大写 hex) | ⏳ 待向 ITSM 平台申请 |
5.2 企微审批相关(影响 REQ-001)— ✅ 已确认
| # | 问题 | 确认结果 |
|---|---|---|
| Q3 | 过滤条件与时间范围 | ✅ API 层只传 sp_status=1(每个 filter key 只能一次),代码层按 18 个模板 ID 过滤。时间范围 7 天(企微 API 最大 31 天,建议改为 30 天) |
| Q4 | "待处理"定义 | ✅ sp_status=1=审批中,需二次过滤当前审批人。企微 API 实际字段:sp_record[].sp_status(非 status)、审批人在 sp_record[].details[].approver.userid(非 approver[].userid) |
5.3 交互与数据策略相关(影响 REQ-007、REQ-003)
| # | 问题 | 说明 | 状态 |
|---|---|---|---|
| Q5 | 代办状态更新的交互方式 | 现有 ApprovalDetail 有"审批通过/拒绝/转交"按钮,TicketDetail 有"接单/处理/结单/转派"按钮。如需在服务台内操作,需对接企微审批 API 和 ITSM 工单 API 的状态变更接口 |
✅ 已确认:仅展示+跳转,不在服务台内操作 |
| Q6 | 代办详情查询策略 | 列表查询时是否缓存每条代办的详情数据(Redis)?还是点击时实时查询外部 API? | ✅ 已确认:Redis 缓存 45s,手动刷新跳过缓存 |
| Q7 | 数据刷新策略 | 每次打开/刷新代办面板都实时查询两个外部 API?还是后端缓存? | ✅ 已确认:初始+60s自动=用缓存,手动刷新=_force=1跳过缓存 |
| Q8 | ITSM 工单优先级映射 | ITSM 返回的优先级字段如何映射到 urgent/high/normal? | ⏳ 待 ITSM API 返回结构确认 |
附录:现有代码资产清单
可复用资产
| 资产 | 位置 | 复用方式 |
|---|---|---|
TokenManager |
backend/app/utils/token_manager.py |
✅ 已复用,获取企微 access_token(IT 支持应用 Secret) |
get_approval_detail() |
backend/app/api/approval.py |
✅ 已复用,获取审批单详情 |
_extract_current_approver() |
backend/app/api/approval.py |
✅ 已复用,过滤当前审批人(字段名已修正) |
_APPROVAL_TEMPLATE_IDS |
backend/app/services/todo_source_service.py |
✅ 已实现,18 个模板 ID 代码层过滤 |
TodoItem Model |
backend/app/models/todo_item.py |
可选复用(如需持久化缓存代办数据) |
TodoItemResponse Schema |
backend/app/schemas/todo_item.py |
✅ 已复用,已移除 device 类型 |
前端 TodoPanel.vue |
frontend-agent/src/components/conversation/TodoPanel.vue |
✅ 已改造 |
前端 TaskDetailView.vue |
frontend-agent/src/components/chat/TaskDetailView.vue |
✅ 已改造 |
前端 TicketDetail.vue / ApprovalDetail.vue |
frontend-agent/src/components/chat/task/ |
✅ 已改造 |
需删除/废弃资产
| 资产 | 位置 | 处理方式 |
|---|---|---|
MOCK_TODO_ITEMS |
backend/app/api/todo_items.py |
✅ 已删除 |
mockTodoListData |
frontend-agent/src/mock/data.ts |
✅ 已删除 |
| mock fallback 逻辑 | frontend-agent/src/stores/todo.ts L66-72 |
✅ 已删除 |
DeviceDetail.vue |
frontend-agent/src/components/chat/task/DeviceDetail.vue |
保留文件但不再被引用 |
| device 类型样式 | TodoPanel.vue L299-304 |
✅ 已删除 |
| device 类型映射 | TodoPanel.vue L110, TaskDetailView.vue L105 |
✅ 已删除 |