chore: sync changes
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
# 5 阶段路线图 — 阶段 2-3 任务拆解
|
||||
|
||||
**生成日期**: 2026-06-14
|
||||
**生成人**: Claude
|
||||
**状态**: 待 workbuddy 接入执行(workbuddy-claude user 创好后启动)
|
||||
**关联**: PRD.md §5 五阶段演进路径
|
||||
|
||||
---
|
||||
|
||||
## 阶段 1 完成度盘点(对照 PRD.md §5.1)
|
||||
|
||||
| 阶段 1 项 | 状态 | 备注 |
|
||||
|---|---|---|
|
||||
| 员工端 H5 WebView | ✅ 完成 | `frontend-h5/` |
|
||||
| OAuth2 静默授权 + 身份识别 | ✅ 完成 | `backend/app/api/h5.py` |
|
||||
| 坐席工作台 MVP | ✅ 完成 | `frontend-agent/` |
|
||||
| 三栏工作台 | ✅ 完成 | 会话列表 / 对话区 / AI 助手 |
|
||||
| 6 分区会话列表 | ✅ 完成 | 待接单/我的/协作/其他坐席/AI处理/已结单 |
|
||||
| 快速回复 7 大类 | ✅ 完成 | 28 子类 180 模板 |
|
||||
| 转人工触发 | ✅ 完成 | 关键字检测 → 推 H5 链接 |
|
||||
| WebSocket 实时推送 | ✅ 完成 | P0 鉴权修复后 |
|
||||
| 应急模式 | ✅ 完成 | 系统故障时手动开 |
|
||||
| Alembic 迁移 | 🟡 部分 | 008 (agent password) + 009 (message status) 已加,初始 001 缺 |
|
||||
|
||||
**剩余扫尾**:
|
||||
- [ ] 初始 alembic 迁移(把当前 schema 导出成 001 基准,后续 migrations 增量)
|
||||
- [ ] pytest 基础配置(README 已知问题 #2)
|
||||
- [ ] P1-1 优化(named volume → host bind mount,任务 #25)
|
||||
- [ ] P0 二次评审 5 遗留(浏览器 WS API / nginx access_log / 类型 bug / 降级放行 / 缺依赖)
|
||||
|
||||
---
|
||||
|
||||
## 阶段 2: H5 员工端完整体验 + 双通道消息推送
|
||||
|
||||
**目标**: 员工 H5 端从 MVP 升级到完整体验,加 摇人 / 评分 / 排队,推送到企微应用消息
|
||||
|
||||
**对应 PRD.md**: §5.2 阶段二,§痛点1(分散渠道)
|
||||
|
||||
### 2.1 任务清单(8 项)
|
||||
|
||||
| # | 任务 | 优先级 | 文件位置 | 阻塞 |
|
||||
|---|---|---|---|---|
|
||||
| 2-1.1 | 摇人按钮(H5 输入框左侧,7 种 SVG 动画) | 🟡 重要 | `frontend-h5/src/components/KnockButton.vue` | 无 |
|
||||
| 2-1.2 | 满意度评价(会话结束 → 弹 5 星 + 文字反馈) | 🟡 重要 | `frontend-h5/src/components/ConversationRating.vue` | 无 |
|
||||
| 2-1.3 | 排队系统(多员工同时咨询,显示"前面 N 位") | 🟡 重要 | `backend/app/api/conversations.py` + `frontend-h5/src/views/QueueStatus.vue` | 无 |
|
||||
| 2-1.4 | 快速回复 7 大类 28 子类 180 模板(已有,需补完) | 🟢 常规 | `backend/app/models/quick_reply.py` | 无 |
|
||||
| 2-1.5 | 知识库基础(FAQ 手动维护,坐席/员工可查) | 🟡 重要 | `backend/app/api/knowledge.py` (新) | 无 |
|
||||
| 2-1.6 | 企微应用消息推送(双通道:企微应用消息 + WebSocket) | 🟡 重要 | `backend/app/services/wecom_push.py` | WECOM 应用 secret |
|
||||
| 2-1.7 | 消息已读回执(员工读完 → 推 message_status) | 🟡 重要 | `backend/app/api/messages.py:mark_read` | 已有 ws_manager.broadcast |
|
||||
| 2-1.8 | 会话转接(坐席 A → 坐席 B,带交接说明) | 🟢 常规 | `backend/app/api/conversations.py:transfer` | 无 |
|
||||
|
||||
### 2.2 验收标准
|
||||
|
||||
- [ ] 员工在 H5 看到会话输入框左侧"摇人"按钮,点击 → 7 种动画之一 + 企微应用消息推送
|
||||
- [ ] 会话结束 → 员工看到 5 星评价 + 文字反馈框 → 提交 → 落库
|
||||
- [ ] 多员工并发咨询 → 排队显示"您前面有 N 位" + 预计等待时间
|
||||
- [ ] 坐席/员工可查 FAQ,输入关键字 → 命中模板
|
||||
- [ ] 员工 1 分钟内未读 → 推企微应用消息"您有一条新消息"
|
||||
- [ ] 员工点开消息 → mark_read 调 → ws_manager 广播 → 坐席端"已读"标识
|
||||
|
||||
### 2.3 与 P0/P1 修复的关联
|
||||
|
||||
- 2-1.6 推送用到 P0 已修的 WS 鉴权
|
||||
- 2-1.7 已读回执用到 P1-4 已实现的 `broadcast_message_status`
|
||||
- 2-1.5 知识库要等阶段 4 闭环,先做基础 CRUD
|
||||
|
||||
### 2.4 预估工时
|
||||
|
||||
| 任务 | 预估人天 | 难度 |
|
||||
|---|---|---|
|
||||
| 2-1.1 摇人 | 2 | 低(Vue 组件 + 已有 SVG 库) |
|
||||
| 2-1.2 满意度 | 1.5 | 低(弹窗 + 后端落库) |
|
||||
| 2-1.3 排队 | 3 | 中(后端排队算法 + 前端轮询) |
|
||||
| 2-1.4 快速回复补完 | 2 | 低(数据导入 + CRUD) |
|
||||
| 2-1.5 知识库基础 | 5 | 中(模型 + 检索 + UI) |
|
||||
| 2-1.6 企微应用消息 | 3 | 中(企微 API + 降级) |
|
||||
| 2-1.7 已读回执 | 1 | 低(接 P1-4) |
|
||||
| 2-1.8 会话转接 | 2 | 低(已有 transfer 端点) |
|
||||
| **合计** | **19.5** | |
|
||||
|
||||
---
|
||||
|
||||
## 阶段 3: 坐席工作台 AI Wingman
|
||||
|
||||
**目标**: 给坐席端加 AI 辅助(草稿回复 / 自动摘要 / 知识推荐 / 排查步骤)
|
||||
**对应 PRD.md**: §5.2 阶段三,§痛点2(坐席重复劳动)
|
||||
|
||||
### 3.1 任务清单(6 项)
|
||||
|
||||
| # | 任务 | 优先级 | 文件位置 | 阻塞 |
|
||||
|---|---|---|---|---|
|
||||
| 3-1.1 | AI 草稿回复(坐席输入 → AI 给回复草稿 → 坐席改/发) | 🟡 重要 | `backend/app/api/ai_wingman.py` (新) | Dify 集成 |
|
||||
| 3-1.2 | 自动摘要(会话结束 → AI 生成 200 字摘要) | 🟡 重要 | `backend/app/services/summarizer.py` (新) | Dify 集成 |
|
||||
| 3-1.3 | 知识推荐(对话中识别关键字 → 推 FAQ / 排查步骤) | 🟡 重要 | `backend/app/api/knowledge.py:recommend` | 2-1.5 知识库 |
|
||||
| 3-1.4 | 排查步骤生成(员工描述问题 → AI 给 step-by-step) | 🟡 重要 | `backend/app/api/ai_wingman.py:troubleshoot` | Dify 集成 |
|
||||
| 3-1.5 | 会话标注(坐席标"AI 推荐有用/无用") | 🟢 常规 | `backend/app/models/annotation.py` (新) | 无 |
|
||||
| 3-1.6 | 坐席端 AI 助手面板(右侧栏,实时显示 AI 草稿) | 🟡 重要 | `frontend-agent/src/components/AIWingmanPanel.vue` | 3-1.1~4 后端 |
|
||||
|
||||
### 3.2 验收标准
|
||||
|
||||
- [ ] 坐席输入框打字 → 右侧 AI 面板显示 3 条草稿回复(实时)
|
||||
- [ ] 坐席点"采用" → 草稿填入输入框 → 可改后发送
|
||||
- [ ] 会话结束 → 自动生成 200 字摘要存库
|
||||
- [ ] 对话中员工说"VPN 连不上" → AI 推 5 条排查步骤
|
||||
- [ ] 坐席标注"有用/无用" → 落库 → 用于阶段 4 知识库迭代
|
||||
|
||||
### 3.3 Dify 集成前置
|
||||
|
||||
- 阶段 3 强依赖 Dify 工作流(已有 `docs/现有系统交接文档内容.txt` 描述)
|
||||
- workbuddy W-4 任务 = Dify API 集成预研(POC),阶段 3 启动前完成
|
||||
- 风险: 企微 AI 机器人已在用 Dify,要确认是否新开 app / 共用
|
||||
|
||||
### 3.4 预估工时
|
||||
|
||||
| 任务 | 预估人天 | 难度 |
|
||||
|---|---|---|
|
||||
| 3-1.1 草稿回复 | 5 | 高(Dify 流式 + 实时推送) |
|
||||
| 3-1.2 自动摘要 | 3 | 中(异步任务 + 触发时机) |
|
||||
| 3-1.3 知识推荐 | 3 | 中(向量检索 + 评分) |
|
||||
| 3-1.4 排查步骤 | 4 | 中(Dify prompt 工程) |
|
||||
| 3-1.5 会话标注 | 2 | 低(模型 + UI) |
|
||||
| 3-1.6 右侧栏 | 3 | 中(实时更新 + 草稿交互) |
|
||||
| **合计** | **20** | |
|
||||
|
||||
---
|
||||
|
||||
## 阶段 2-3 总工时 + 关键路径
|
||||
|
||||
```
|
||||
阶段 2 累计: 19.5 人天
|
||||
阶段 3 累计: 20 人天
|
||||
合计: 39.5 人天
|
||||
```
|
||||
|
||||
**关键路径**:
|
||||
1. Dify 集成预研(W-4)→ 阶段 3 启动前置
|
||||
2. 知识库基础(2-1.5)→ 阶段 3 知识推荐(3-1.3)前置
|
||||
3. 摇人 / 评分 / 排队(2-1.1~3)可并行
|
||||
|
||||
---
|
||||
|
||||
## 启动条件(给 workbuddy)
|
||||
|
||||
workbuddy-claude user account 创好后,把这份文档读进 `.workbuddy/memory/`,按以下顺序接任务:
|
||||
|
||||
1. **先收尾 P1-1 优化 + 5 P0 遗留 + 初始 alembic**(#25 + 5 遗留 + 001 基准)
|
||||
2. **阶段 2.1** → 2-1.1 摇人(Vue 组件简单,热身)
|
||||
3. **阶段 2.2~3** → 满意度 / 排队
|
||||
4. **阶段 2.5~6** → 知识库基础 + 企微应用消息(企微 secret 需用户给)
|
||||
5. **Dify 集成预研**(W-4)→ 阶段 3 启动
|
||||
6. **阶段 3 全部**
|
||||
|
||||
每完成一项 → 提交 commit → 推 Gitea(走 pre-commit-check.sh 4 件套)→ Claude 评审 → 合 main
|
||||
|
||||
---
|
||||
|
||||
## 风险与依赖
|
||||
|
||||
| 风险 | 等级 | 缓解 |
|
||||
|---|---|---|
|
||||
| Dify API 限流 | 🟡 | 加 Redis 缓存 + 异步队列 |
|
||||
| 企微应用消息配额 | 🟡 | 双通道降级(WS 优先) |
|
||||
| 知识库检索召回率 | 🟡 | 阶段 4 闭环后优化 |
|
||||
| workbuddy token 不稳定 | 🟠 | 用户创 workbuddy-claude user 解决 |
|
||||
| 阶段 2 推 main 冲突 | 🟡 | 强制走 PR + 评审 |
|
||||
+104
-1
@@ -798,7 +798,110 @@ location /api/ {
|
||||
|
||||
| 编号 | 状态 |
|
||||
|---|---|
|
||||
| H-12 (P1-1) upload 路径 | 🔄 评审闭环中 |
|
||||
| H-12 (P1-1) upload 路径 | 🔄 评审闭环中(留 P2 优化,任务 #25) |
|
||||
| H-13 (P1-2) Alembic 迁移 | 🔄 评审闭环中 |
|
||||
| H-14 (P1-3) healthcheck | 🔄 评审闭环中 |
|
||||
| H-15 (P1-4) ws 状态广播 | 🔄 评审闭环中 |
|
||||
|
||||
---
|
||||
|
||||
## 第十二节: 2026-06-14 Gitea 卸载清空事故 + 重建复盘 ⚠️ 教训重灾区
|
||||
|
||||
**触发时间**: 2026-06-14 晚
|
||||
**触发原因**: 用户在 DSM 套件中心用 "卸载清空" 选项卸载 Gitea
|
||||
**影响范围**: Gitea 服务停 + Web 不可达 + 仓裸仓库可能残留
|
||||
**恢复时长**: ~30 分钟
|
||||
**任务编号**: #26
|
||||
|
||||
### 12.1 事故时序
|
||||
|
||||
| 时刻 | 事件 |
|
||||
|---|---|
|
||||
| T+0 | 用户在 DSM 套件中心 → Gitea → 卸载 → 勾选"清空" |
|
||||
| T+1m | Gitea 服务停止,8418 端口无响应 |
|
||||
| T+1m | 外部 Funnel 域名 `ds923plus.tail58d872.ts.net` 无法访问 |
|
||||
| T+5m | 本地仓 `D:\资料\03-项目开发\wecom_it_smart_desk` 检查 11 commit 完整 |
|
||||
| T+10m | 用户发现"创仓报已存在文件" → 数据没清干净 |
|
||||
| T+15m | 用户用 Gitea Web "删除仓库" → "创建新仓库" |
|
||||
| T+20m | 用户创新 token `9754e1d8c8a0...` (权限含 admin) |
|
||||
| T+22m | 我改 `.git/config` URL 清旧 token(走 wincred 缓存) |
|
||||
| T+25m | PowerShell 推 main 成功(639 对象 / 3.67 MiB) |
|
||||
| T+28m | 配 main 分支保护 (PR + 1 reviewer) |
|
||||
| T+30m | 全部恢复,功能等价 |
|
||||
|
||||
### 12.2 教训 + 防御
|
||||
|
||||
#### 🛑 教训 1: 卸载"清空" 不等于 数据清除
|
||||
- **现象**: 套件"卸载清空"清了 app + 数据库,**但仓裸仓库目录残留**(`/volume1/@appdata/gitea/gitea/repos/`)
|
||||
- **后果**: 重装 Gitea 后创仓冲突("已存在文件")
|
||||
- **修复**: 用户手动"删除仓库 → 创建新仓库"解决
|
||||
- **防御**:
|
||||
- ✅ 部署 `scripts/backup-gitea.sh`(本次新增,C-2 任务)
|
||||
- ✅ 卸载前**强制备份**
|
||||
- ✅ 评估"卸载清空" vs "卸载保留数据"
|
||||
|
||||
#### 🛑 教训 2: token 嵌入 `.git/config` URL 是反模式
|
||||
- **现象**: 之前为 workbuddy 推 Gitea,把 token `ae236991c3d5...` 直接嵌入 `origin.url`
|
||||
- **后果**: workbuddy-claude token 失效后,URL 里有死凭据 + auto-classifier 拒绝重写 URL
|
||||
- **修复**: URL 改回 `https://simon@...`,用 `git credential approve` 存 wincred
|
||||
- **防御**:
|
||||
- ✅ **永远不**在 URL 里嵌 token(写进 [[locked-decisions]] 候选)
|
||||
- ✅ 推 Gitea 走 `git credential approve` + wincred
|
||||
- ✅ workbuddy-claude 创独立 user account(避免 token 跟 simon 账号混)
|
||||
|
||||
#### 🛑 教训 3: PowerShell 弹窗在后台易丢
|
||||
- **现象**: 用户推 main 时第一次"fatal: User cancelled dialog"(可能弹窗在后台没看到)
|
||||
- **修复**: 用 `git credential approve` 预先存 wincred,推时不弹窗
|
||||
- **防御**:
|
||||
- ✅ **CI / workbuddy / 脚本** 永远走 wincred(不弹)
|
||||
- ✅ 交互推送前先 `git credential approve`
|
||||
|
||||
#### 🛑 教训 4: main 分支保护配置需考虑"评审员有谁"
|
||||
- **现象**: 配 `block_admin_merge: true` + `required_approvals: 1` + 只有 simon 一个 user → **simon 永远合不进自己 PR**
|
||||
- **修复**: 临时改 `block_admin_merge: false`,等 workbuddy 接入再开
|
||||
- **防御**:
|
||||
- ✅ 配保护前**确认有 ≥2 个 user**(评审员 + 推送者)
|
||||
- ✅ 创 workbuddy-claude user account(本次未做,等用户睡前安排)
|
||||
|
||||
### 12.3 数据保全审计
|
||||
|
||||
| 资源 | 卸载清空前 | 卸载清空后 | 重建后 | 完整性 |
|
||||
|---|---|---|---|---|
|
||||
| Gitea 服务 | ✅ 运行 | ❌ 停止 | ✅ 启动 | ✅ 100% |
|
||||
| Gitea 数据库 (SQLite) | ✅ 完整 | ⚠️ 残留可能 | ✅ 全新 | ✅ 100%(旧数据丢) |
|
||||
| 仓裸仓库 (repos/) | ✅ 11 commit | ⚠️ 残留 | ✅ 0 commit | ⚠️ 0%(待重推) |
|
||||
| 本地仓 (windows) | ✅ 11 commit | ✅ 11 commit | ✅ 11 commit | ✅ 100% |
|
||||
| Token 表 | ✅ 3 token | ⚠️ 残留 | ✅ 1 token(simon's) | ⚠️ 旧 token 全失效 |
|
||||
| wincred 缓存 | ✅ workbuddy-claude | ⚠️ 残留 | ✅ simon 新 | ✅ 重置 |
|
||||
|
||||
### 12.4 待办
|
||||
|
||||
| # | 项 | 阻塞 |
|
||||
|---|---|---|
|
||||
| 1 | **Gitea 备份脚本部署**(`scripts/backup-gitea.sh` 推到 NAS) | 用户需 SCP |
|
||||
| 2 | **备份 cron 配置**(每天 3 点) | SSH 进 NAS |
|
||||
| 3 | **创 workbuddy-claude user** | 用户睡前做 |
|
||||
| 4 | **workbuddy-claude token 替换** | 等 #3 |
|
||||
| 5 | **`block_admin_merge` 改回 `true`**(workbuddy 接入后) | 等 #3 |
|
||||
| 6 | **删旧 workbuddy-claude token 残留** | 等 #3 |
|
||||
| 7 | **Gitea 部署文档**(`docs/Gitea部署指南.md` 含备份恢复) | 我写 |
|
||||
| 8 | **风险跟踪表加 "数据丢失" 风险项** | 我写(下面) |
|
||||
|
||||
### 12.5 新增风险项
|
||||
|
||||
| 编号 | 严重度 | 内容 | 状态 |
|
||||
|---|---|---|---|
|
||||
| **M-1 (新)** | 🟠 中高 | **Gitea 数据无异地备份** —— 一旦 NAS 硬盘故障,Gitea 全失 | 🆕 本节新增 |
|
||||
| **M-2 (新)** | 🟡 中 | **套件卸载误操作风险** —— 误勾"清空"导致数据全失 | 🆕 本节新增 |
|
||||
| **L-2 (新)** | 🟢 低 | **PowerShell 弹窗后台丢失** —— 关键推送可能因弹窗丢失而失败 | 🆕 本节新增 |
|
||||
|
||||
### 12.6 推送约定升级 (写进 [[locked-decisions]] 候选)
|
||||
|
||||
> **所有 Gitea 推送凭据走 wincred,禁止明文嵌入 `.git/config` URL**
|
||||
|
||||
具体:
|
||||
1. `.git/config` 的 `origin.url` **只写用户名**(`https://simon@...`),不写 token
|
||||
2. 首次推 / 换 token → `git credential approve` 一次性存 wincred
|
||||
3. workbuddy 推送 → 创独立 user account + 自己的 token(不跟 simon 共用)
|
||||
4. CI / 自动化推送 → 用环境变量 + `git -c credential.helper=!gh auth git-credential`(gh CLI) 或 secret store
|
||||
5. **违反 → auto-classifier 拒绝**(已成事实)
|
||||
|
||||
Reference in New Issue
Block a user