chore: 整理项目结构,清理归档文件,更新部署配置

This commit is contained in:
Simon
2026-07-04 21:01:39 +08:00
parent 8bd4ab0366
commit 64ff1bf7d5
508 changed files with 43575 additions and 14129 deletions
@@ -0,0 +1,296 @@
# 智能IT支持服务台 — 调试验证指南
**创建时间**: 2026-06-13
**适用环境**: 正式服务器 10.90.5.10 (itsupport.servyou.com.cn)
---
## 一、端到端验证清单
### 1.1 H5用户端验证
#### 验证项1H5登录流程
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 在企微桌面端打开 `https://itsupport.servyou.com.cn/itdesk/` | 自动跳转企微OAuth2授权页 |
| 2 | 确认授权 | 跳回H5聊天页面,显示欢迎消息 |
| 3 | 刷新页面 | 保持登录状态,无需重新授权 |
| 4 | 在浏览器(非企微)直接访问 | 显示"请在企业微信中打开"拦截页 |
**验证要点**
- JWT Token 过期检查是否生效(60秒安全余量)
- Portal Token 传递是否正常(从Portal跳转时)
- 401 处理是否正确(Token过期后自动重新授权)
#### 验证项2:消息收发
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 在H5端发送文本消息 | 消息显示在对话框,坐席端同步收到 |
| 2 | 粘贴图片到输入框 | 图片预览显示,发送后坐席端可见 |
| 3 | 上传文件(<10MB) | 文件上传成功,坐席端可下载 |
| 4 | 使用表情面板发送表情 | 表情正确显示 |
| 5 | 发送截图(系统截图+粘贴) | 截图编辑器弹出,确认后发送成功 |
#### 验证项3:排查步骤功能
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 点击右侧"排查步骤"标签 | 显示交互式排查流程 |
| 2 | 选择一个问题类型 | 显示对应的排查步骤 |
| 3 | 按步骤操作并点击"已解决" | 状态更新,记录解决时间 |
---
### 1.2 坐席工作台验证
#### 验证项4:坐席登录与接单
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 在企微桌面端打开 `https://itsupport.servyou.com.cn/itagent/` | 自动登录,显示坐席工作台 |
| 2 | 查看待办列表 | 显示当前待处理会话 |
| 3 | 点击一个会话 | 右侧显示对话内容和用户信息 |
#### 验证项5:消息收发(坐席端)
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 在坐席端回复文本消息 | H5端同步收到 |
| 2 | 发送图片/文件 | H5端可查看/下载 |
| 3 | 使用快捷回复 | 快速插入预设回复 |
| 4 | 使用表情面板 | 表情正确显示 |
#### 验证项6:会话管理
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 标记会话为"已解决" | 会话状态更新,H5端显示满意度评价 |
| 2 | 转接会话给其他坐席 | 其他坐席收到通知,可接手 |
| 3 | 查看会话历史 | 历史消息完整显示 |
---
### 1.3 邀请功能验证
#### 验证项7:邀请流程
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 坐席端点击"邀请"按钮 | 弹出邀请对话框 |
| 2 | 选择要邀请的员工/部门 | 显示选中的员工列表 |
| 3 | 确认邀请 | 发送邀请通知,参与者列表更新 |
| 4 | 被邀请员工在H5端收到通知 | 显示"XXX邀请您加入会话" |
| 5 | 员工点击"加入" | 成功加入会话,可查看历史消息 |
#### 验证项8:参与者管理
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 坐席端查看参与者列表 | 显示所有参与者(发起人/坐席/被邀请人) |
| 2 | 坐席端移除某参与者 | 该参与者被移除,收到通知 |
| 3 | 被邀请人主动退出 | 参与者列表更新,坐席端收到通知 |
---
### 1.4 管理后台验证
#### 验证项9:管理后台登录
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 在企微桌面端打开 `https://itsupport.servyou.com.cn/itadmin/` | 自动登录(需admin角色) |
| 2 | 非admin角色访问 | 显示"无权限"提示 |
#### 验证项10:功能开关
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 进入"功能开关"页面 | 显示所有功能开关列表 |
| 2 | 切换某个功能开关 | 状态保存成功 |
| 3 | 在H5/坐席端验证功能是否生效 | 功能按开关状态启用/禁用 |
#### 验证项11:仪表盘
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 进入"仪表盘"页面 | 显示今日会话数/在线坐席/平均响应时间 |
| 2 | 切换日期范围 | 数据按日期刷新 |
---
## 二、测试企微应用创建指南
### 2.1 为什么需要测试企微应用?
| 问题 | 说明 |
|------|------|
| **企微域名限制** | 每个企微应用只能配置1个可信域名 |
| **OAuth2回调** | 回调URL只能指向一个服务器 |
| **消息推送** | 接收消息回调只能配置1个URL |
| **结论** | 同一个企微应用无法同时指向两个服务器 |
### 2.2 双企微应用方案
```
┌─────────────────────────────────────────────────────────┐
│ 企微管理后台 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 智能IT支持服务台(正式) │ │ 智能IT支持服务台-测试 │ │
│ │ │ │ │ │
│ │ 可信域名: │ │ 可信域名: │ │
│ │ itsupport.xxx │ │ itdesk.amanzac │ │
│ │ │ │ │ │
│ │ 应用主页: │ │ 应用主页: │ │
│ │ /itdesk/ │ │ /itdesk/ │ │
│ └─────────────────┘ └─────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 正式环境 │ │ 测试环境 │ │
│ │ 10.90.5.10 │ │ NAS │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
```
### 2.3 创建步骤
#### 第一步:创建测试应用
1. 登录 [企微管理后台](https://work.weixin.qq.com/wework_admin/frame)
2. **应用管理****自建****创建应用**
3. 填写信息:
- **应用名称**: `智能IT支持服务台-测试`
- **应用logo**: 使用不同颜色(如橙色)区分正式应用
- **应用介绍**: "仅供IT部门测试使用"
- **可见范围**: 选择IT部门 + 测试人员
#### 第二步:配置测试应用
| 配置项 | 填写 | 说明 |
|--------|------|------|
| **可信域名** | `itdesk.amanzac.com` | OAuth2回调域名 |
| **应用主页** | `https://itdesk.amanzac.com/itdesk/` | 员工点击入口 |
| **接收消息** | `https://itdesk.amanzac.com/api/wecom/callback` | 企微消息推送 |
#### 第三步:验证域名
1. 在企微管理后台点击"可信域名"旁边的"验证"
2. 下载验证文件(如 `WW_verify_xxxxx.txt`
3. 将文件放到 `frontend-h5/dist/` 目录
4. 重新构建前端并部署
5. 点击"验证"按钮
#### 第四步:配置OAuth2
1. 在企微管理后台找到"企业微信授权登录"
2. 配置 **Web网页** 授权回调域: `itdesk.amanzac.com`
3. 记录 **CorpID****Secret**
#### 第五步:配置后端环境变量
在测试环境的 `.env` 文件中配置:
```env
# 企微配置(测试应用)
WECOM_CORP_ID=ww_test_xxxxx
WECOM_SECRET=xxxxx
WECOM_AGENT_ID=xxxxx
WECOM_TOKEN=xxxxx
WECOM_ENCODING_AES_KEY=xxxxx
# 前端配置
VITE_WECOM_CORP_ID=ww_test_xxxxx
```
#### 第六步:配置NAS Cloudflare Tunnel
1. 登录 [Cloudflare Zero Trust](https://one.dash.cloudflare.com/)
2. **Networks****Tunnels** → 找到 `itdesk-nas` Tunnel
3. **Configure****Public Hostname**
4. 确认 `itdesk.amanzac.com` 指向 NAS 的 Docker 网关
---
### 2.4 验证测试应用
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 在企微中找到"智能IT支持服务台-测试"应用 | 应用显示在工作台 |
| 2 | 点击应用 | 跳转到 `https://itdesk.amanzac.com/itdesk/` |
| 3 | 首次访问 | 跳转企微OAuth2授权页 |
| 4 | 确认授权 | 跳回H5聊天页面 |
| 5 | 发送测试消息 | 坐席端(NAS环境)收到消息 |
---
## 三、环境切换方案
### 正式上线前 → 正式上线后
```
切换前:
正式应用 → itsupport.servyou.com.cn → 10.90.5.10
测试应用 → itdesk.amanzac.com → NAS
切换后:
正式应用 → itsupport.servyou.com.cn → 高可用架构
测试应用 → itdesk.amanzac.com → 10.90.5.10
```
### 切换步骤
1. 将正式应用的 `itsupport.servyou.com.cn` DNS 指向高可用架构
2. 将测试应用的 `itdesk.amanzac.com` DNS 指向 10.90.5.10
3. 更新测试应用的 OAuth2 回调配置(如需要)
4. 验证两端都能正常访问
---
## 四、常见问题排查
### 4.1 OAuth2授权失败
| 问题 | 原因 | 解决方案 |
|------|------|---------|
| redirect_uri参数非法 | 回调URL未配置或域名不匹配 | 检查企微管理后台的回调域配置 |
| 40029 code无效 | code已过期或重复使用 | 重新发起授权流程 |
| 40163 code已使用 | code只能使用一次 | 确保后端正确处理code换取token |
### 4.2 消息推送失败
| 问题 | 原因 | 解决方案 |
|------|------|---------|
| 回调URL验证失败 | Token或EncodingAESKey不匹配 | 检查后端.env配置 |
| 消息未送达 | 企微消息推送有延迟 | 等待1-2秒,或检查WebSocket连接 |
### 4.3 H5端401错误
| 问题 | 原因 | 解决方案 |
|------|------|---------|
| Token过期 | JWT Token有效期已到 | 自动重新授权(已实现) |
| 循环重定向 | OAuth2回调处理异常 | 检查防循环计数器(最大3次) |
---
## 五、验证完成标准
### P0 验证项(必须通过)
- [ ] H5登录流程正常
- [ ] 坐席登录流程正常
- [ ] 消息收发双向正常
- [ ] 邀请功能完整闭环
- [ ] 管理后台可访问
### P1 验证项(建议通过)
- [ ] 文件上传/下载正常
- [ ] 表情发送正常
- [ ] 截图功能正常
- [ ] 排查步骤功能正常
- [ ] 功能开关生效
### P2 验证项(可选)
- [ ] 深浅色切换正常
- [ ] 会话历史完整
- [ ] 满意度评价流程
---
**文档维护**: 齐活林(Qi)· 交付总监
**最后更新**: 2026-06-13
@@ -0,0 +1,176 @@
# E2E 验收清单 v0.7.0(扫码登录 + MFA)
> 部署完 v0.7.0 后,**逐项打勾**。任何一项 ❌ 立即回滚。
> 每项给出预期结果 + 验证方法 + 失败处理。
---
## 0. 部署完成(用户跑过 DEPLOY-LOGIN-MIGRATION-v0.7.0.md 全部步骤)
- [ ] 后端 `alembic upgrade head` 跑通(head = `025_messages_id_uuid`)
- [ ] 4 端 dist 已上传到宿主机 `/opt/wecom-it-desk/frontend-*/dist/`
- [ ] nginx `nginx -t` 通过 + `nginx -s reload` 完成
- [ ] `docker restart wecom_it_backend` 成功
- [ ] 容器状态 `docker ps` 显示 backend/redis/postgres 全部 Up
---
## 1. 扫码登录(Phase 1.1 / 1.2 / 1.3)
### 1.1 门户页面加载
- [ ] 浏览器打开 `https://<生产域名>/itportal/`
- [ ] 看到 QrcodeLogin 页面(二维码 + 倒计时)
- [ ] 不再显示旧的"账号密码"登录
### 1.2 二维码生成
- [ ] 倒计时从 120 秒开始
- [ ] 刷新按钮可用
- [ ] DevTools Network: `POST /api/auth_qrcode/create` 返回 200 + ticket
### 1.3 扫码
- [ ] 用企微扫 → 企微 OAuth2 跳回 callback
- [ ] 门户页面状态从 `waiting``scanned`(显示"已扫码,等待确认")
- [ ] DevTools Network: `POST /api/auth_qrcode/scan` 成功
### 1.4 坐席确认
- [ ] 已登录坐席在 `/itagent/` 收到确认弹窗
- [ ] 点"确认"→ 门户 `waiting``confirmed` → 跳转 `/itagent/`
- [ ] localStorage 有 `agent_token` / `portal_token`
### 1.5 角色分发
- [ ] 双角色坐席(admin+agent)→ 跳 `/itportal/select`
- [ ] 仅 admin → 跳 `/itadmin/`
- [ ] 仅 agent → 跳 `/itagent/`
- [ ] 仅 user → 跳 `/itdesk/`
### 1.6 过期处理
- [ ] 120 秒不扫 → 状态变 `expired` + 提示"二维码已过期,请刷新"
---
## 2. MFA 绑定(Phase 2.4)
### 2.1 绑定入口
- [ ] 坐席登录后 → 顶栏头像 → "绑定 MFA"
- [ ]`/itagent/mfa-bind` 页面
### 2.2 扫码绑定
- [ ] 看到 TOTP 二维码(otpauth://totp/...)
- [ ] 用 Google Authenticator / 微软 Authenticator 扫
- [ ] 输入 6 位 OTP → 点"验证" → 成功
- [ ] 页面显示"已绑定" + 备份信息
### 2.3 API 验证
- [ ] `GET /api/mfa/status` 返回 `bound: true, enabled: true`
- [ ] `GET /api/mfa/users` (admin) 看到该坐席 bound=true
---
## 3. MFA 验证(高危操作守卫)
### 3.1 30 分钟有效期
- [ ] 坐席 admin 角色登录 → 绑 MFA → 调 `/api/admin/high-risk/demo/role_change`
- [ ] **未先调 /api/mfa/verify** → 返回 `2001 需要 OTP`
- [ ]`POST /api/mfa/verify {otp_code: "123456"}` → 成功
- [ ] **再调** 高危端点 → 200 通过
- [ ] 等 31 分钟 → 再次调 → 又返回 2001(TTL 失效)
### 3.2 5 类高危操作
- [ ] `POST /api/admin/high-risk/demo/role_change` → 200
- [ ] `POST /api/admin/high-risk/demo/config_change` → 200
- [ ] `POST /api/admin/high-risk/demo/data_export` → 200
- [ ] `POST /api/admin/high-risk/demo/account_disable` → 200
- [ ] `POST /api/admin/high-risk/demo/account_create_reset` → 200
### 3.3 角色拒绝
- [ ] 非 admin 角色调高危端点 → 4003 仅管理员
### 3.4 白名单查询
- [ ] `GET /api/admin/high-risk/whitelist` 返回 5 类元数据
---
## 4. P0/P1 合规验证
### 4.1 WebSocket 连接
- [ ] H5 员工端开 DevTools → Network → WS
- [ ] WS 连接建立,**没有 1006 / missing argument 错误**
- [ ] 坐席发消息 → H5 端 100ms 内收到(无轮询 3-5s 延迟)
### 4.2 消息 ID 类型
- [ ] `psql -d wecom_it -c 'SELECT id FROM messages LIMIT 1;'` 返回 UUID 格式
- [ ] 前端消息轮询不再偶发 500
- [ ] 跨会话消息不再串号
### 4.3 nginx access_log
- [ ] `docker exec wecom_it_nginx tail /var/log/nginx/access.log | head -3`
- [ ] 不包含 `Authorization:` / `Cookie:` 字样
- [ ] 只剩 IP / method / path / status
### 4.4 Gitea token
- [ ] `cat .git/config | grep 5ad83d` 返回空(token 已撤销)
- [ ] `git push` 试一下:**应该失败**(无 push 权限,符合预期)
---
## 5. 端到端业务流(回归)
### 5.1 H5 → 坐席 完整流程
- [ ] H5 员工发起会话 → 排队
- [ ] 坐席收到分配 → WS 推送
- [ ] 坐席发消息 → 员工 < 100ms 收到
- [ ] 转人工、邀请、满意度流程无 regression
### 5.2 管理员后台
- [ ] 仪表盘加载正常
- [ ] 坐席管理 CRUD 正常
- [ ] 功能开关可切换
- [ ] 集成配置 6 个系统显示完整
- [ ] MFA 管理页 `/mfa-manage` 表格可搜索/过滤/分页
- [ ] 重置 MFA 按钮可弹 ElMessageBox 二次确认
### 5.3 端点路径(临时 4 xfail)
- [ ] `POST /api/conversations/{id}/messages` **仍 404** — pre-existing,不影响生产
- [ ] 实际走 H5 的 `/api/h5/conversations/current/messages` 路径
---
## 6. 性能与稳定性
- [ ] 长时间压测(可选): `wrk -t4 -c100 -d60s https://<域>/api/auth_qrcode/create`
- [ ] 无 5xx 错误
- [ ] Redis 连接稳定(无 timeout)
- [ ] PG CPU < 50%
---
## 7. 回滚预案
如果任意 ❌ 项:
```bash
# 1. 停止后端
sudo docker stop wecom_it_backend
# 2. 恢复 4 端 dist
sudo cp -r /opt/wecom-it-desk/dist-backup-*/* /opt/wecom-it-desk/frontend-*/dist/
# 3. 回滚 alembic(只回 025,022/023 保留)
sudo docker start wecom_it_backend
sudo docker exec wecom_it_backend alembic downgrade 024
# 4. nginx 回滚
sudo docker exec wecom_it_nginx nginx -s reload
```
详见 `DEPLOY-LOGIN-MIGRATION-v0.7.0.md` 末尾"回滚预案"。
---
## ✅ 验收人签字
| 角色 | 姓名 | 日期 | 结果 |
|---|---|---|---|
| 部署 | | | |
| 验收 | | | |
| 复核 | | | |
@@ -0,0 +1,142 @@
# 智能IT支持服务台 — 综合 QA 测试报告
> 本文档合并历次 QA 测试报告,按时间倒序排列(最新在前)。
---
## 报告索引
| # | 测试日期 | 报告名称 | 测试范围 | 通过率 | 状态 |
|---|----------|----------|----------|--------|------|
| 1 | 2026-06-03 | WebSocket 实时推送功能 QA | WS 连接/心跳/重连/广播 | 10/11 (1跳过) | ✅ 通过 |
| 2 | 2025-07-04 | 坐席工作台 v5.3 QA | T01-T04 增量代码 | 36/42 (4失败/2警告) | ⚠️ 有条件通过 |
---
## 一、WebSocket 实时推送功能 QA 测试报告
> 测试日期: 2026-06-03 | QA工程师: 严过关(Edward
### 总览
- **测试对象**: WebSocket 实时推送功能(9个文件)
- **测试轮次**: 1(第2轮无需执行,所有可测试项均通过)
### 1. 代码审查结果
| # | 文件 | 检查结果 | 状态 |
|---|------|----------|------|
| 1 | `ws_manager.py` — broadcast/send_to_agent 异常处理 | send_to_agent try/except 包裹;broadcast 拷贝 keys 避免遍历异常;connect 旧连接清理 | ✅ PASS |
| 2 | `ws.py` — WebSocketDisconnect 处理 | 捕获 WebSocketDisconnect + 通用 Exception,均清理连接 | ✅ PASS |
| 3 | `useWebSocket.ts` — 断线重连逻辑 | 指数退避(1s→2s→4s→8s→16s→30s)intentionalDisconnect 标志;心跳30sWS断连自动降级轮询 | ✅ PASS |
| 4 | `message_router.py` / `session_service.py` — WS 广播位置 | 所有广播均在 `db.flush()` 后、`return` 前;try/except 包裹不阻塞主流程 | ✅ PASS |
| 5 | `conversation.ts` — handleNewMessage 消息去重 | 通过 `message_id` 去重,避免 WS 推送和轮询重复 | ✅ PASS |
| 6 | `vite.config.ts` — WS 代理配置 | `/ws` 代理 `ws: true` 配置正确,与 `/api` 不冲突 | ✅ PASS |
| 7 | `Workspace.vue` — connect 和 disconnect 处理 | onMounted 调用 connectWsonUnmounted 调用 disconnectWs + stopAllPolling;登出时先标记主动断开 | ✅ PASS |
### 2. 后端启动验证
| 检查项 | 结果 | 说明 |
|--------|------|------|
| REST API /health | ✅ PASS | 返回 `{"status":"ok","service":"wecom-it-smart-desk"}` |
| REST API /api/conversations | ✅ PASS | 正常返回会话列表 |
| WebSocket 端点 /ws/{agent_id} | ✅ PASS | 可建立连接 |
### 3. WebSocket 功能测试
| 测试项 | 结果 | 说明 |
|--------|------|------|
| TEST 1: WebSocket 连接 | ✅ PASS | ws://localhost:8000/ws/qa_test_agent1 连接成功 |
| TEST 2: Ping/Pong 心跳 | ✅ PASS | 发送 `{"type":"ping"}` → 收到 `{"type":"pong"}` |
| TEST 3: 同一坐席重连替换 | ✅ PASS | 同一 agent_id 第二个连接建立成功 |
| TEST 4: 不同坐席多连接 | ✅ PASS | 不同 agent_id 可同时连接 |
| TEST 5: WS 广播 - 接单事件 | ⏭️ SKIP | SQLite 锁定导致 API 调用失败,代码审查确认逻辑正确 |
| TEST 6: 断开连接后清理 | ✅ PASS | ws3 主动断开后,ws1 仍正常工作 |
> **TEST 5 跳过说明**: SQLite 数据库在 uvicorn 进程中被锁定,导致写操作失败。这是 SQLite 高并发已知限制,与 WebSocket 代码无关。代码审查已确认广播位置正确。
### 4. 前端集成验证
| 检查项 | 结果 | 说明 |
|--------|------|------|
| 前端编译 (vite build) | ✅ PASS | RC=03.77s 构建完成,无 TypeScript 错误 |
| Workspace.vue 包含 WS 集成 | ✅ PASS | 导入 useWebSocket,生命周期完整 |
### 5. 综合评估
- **通过项 (10/11)**: 所有代码审查项 + WS 连接/心跳/重连/多连接/清理 + 前端编译
- **跳过项 (1/11)**: WS 广播端到端验证(代码审查确认逻辑正确)
- **未发现源码 Bug**
### 6. 路由决策
**Send To: NoOne** — 所有可测试项均通过,代码审查未发现 Bug,无需发送给工程师修复。
---
## 二、坐席工作台 v5.3 QA 测试报告(历史归档)
> 测试日期: 2025-07-04 | QA工程师: 严过关(Yan| 测试范围: T01-T04 全部增量代码
### 总览
| 指标 | 值 |
|------|-----|
| 总检查项 | 42 |
| 通过 | 36 |
| 失败 | 4 |
| 警告 | 2 |
| **IS_PASS** | **YES(有条件)** |
**路由判定**: 源码有 4 处 Bug → **发送给工程师修复**
### 1. TypeScript 编译检查(7个错误)
| # | 严重度 | 文件 | 问题 | 修复方案 |
|---|--------|------|------|----------|
| BUG-1 | 🔴 严重 | `stores/quickReply.ts:153` | `replaceAll` 需要 ES2021+ | 改 `tsconfig.json` lib 为 `ES2021`,或用 `split().join()` 替代 |
| BUG-2 | 🟡 低 | `components/chat/UserInfoBar.vue:316` | `emit` 声明未使用 | 用 `emit()` 替代模板 `$emit`,或删除变量声明 |
| BUG-3 | 🟡 低 | `stores/conversation.ts:33` | `TagsResult` 导入未使用 | 从 import 移除 |
| BUG-4 | 🟡 低 | `stores/conversation.ts:770,792` | `data` 参数未使用 | 改为 `_data` |
| BUG-5 | 🟢 信息 | `main.ts:23` | element-plus locale 缺类型声明 | `env.d.ts` 添加 `declare module` |
### 2. 逻辑 Bug 检查
| # | 严重度 | 文件 | 问题 | 修复方案 |
|---|--------|------|------|----------|
| BUG-6 | 🔴 中等 | `UserInfoBar.vue:418` | `turnCount` 运算符优先级错误:`tags?.repeat_count \|\| 0 + 1` 应先计算 `0+1` | 改为 `(tags?.repeat_count \|\| 0) + 1` |
| BUG-7 | 🟡 中等 | `UserInfoBar.vue:464` | `Math.random()` 导致 UI 闪烁 | 改为基于 `conversation.id` 的确定性 Mock |
### 3. CSS 变量一致性(警告级)
多处硬编码色值未使用 CSS 变量,深色主题下可能显示异常(不影响功能,建议后续迭代统一):
| 文件 | 硬编码值 | 建议使用 CSS 变量 |
|------|----------|-----------------|
| `UserInfoBar.vue` | `#FDF6EC` / `#E6A23C` / `#FAECD8` | 黄色 chip — `--color-warning-soft` / `--color-warning` |
| `UserInfoBar.vue` | `#FEF0F0` / `#F56C6C` / `#FDE2E2` | 红色 chip — `--color-danger-soft` / `--color-danger` |
| `UserInfoBar.vue` | `#F4ECFF` / `#9B59B6` / `#E8D5F5` | 紫色 chip — 新增 `--color-purple-soft` / `--color-purple` |
| `FlowchartNode.vue` | `#FDF6EC` / `#E6A23C` / `#FAECD8` | 判断节点 — 同上 |
| `TopBar.vue` | `#2b6cb0` | 渐变深色 — `--accent-dark` |
| `TopBar.vue` | `#fef0f0` / `#c0392b` / `#e74c3c` | 应急横幅 — 未适配深色模式 |
### 4. 功能完整性检查
| 模块 | 状态 | 说明 |
|------|------|------|
| T01 主题系统 | ✅ 完成 | CSS变量 + useTheme + Pinia store + TopBar切换按钮 |
| T02 左栏改造 | ✅ 完成 | 三段折叠 + 优先级图标 + 待办面板 + TodoStore |
| T03 中栏改造 | ✅ 完成 | UserInfoBar + ItLevelBadge + AiRecommendInline + TroubleshootBar + 快捷键 |
| T04 右栏改造 | ✅ 完成 | AiAssistantPanel 重写 + QuickReplyPanel 重写 |
| 任务详情视图 | ✅ 完成 | TaskDetailView + 三种子视图 |
| 后端扩展 | ✅ 完成 | todo_items + troubleshooting_templates + employees API |
### 5. 最终判定
**IS_PASS: YES(有条件)**
**条件**: 工程师需修复 BUG-1ES2021 target)和 BUG-6turnCount 优先级),其余为低优先级警告,可在后续迭代修复。
---
*合并生成时间: 2026-06-07 | 合并人: 小米*
@@ -0,0 +1,89 @@
# 呼叫坐席功能验证指南
> 后端 `http://localhost:8000` | 前端 `http://localhost:5173`
---
## 前置条件
1. 后端 8000 端口已启动 ✅
2. 前端 H5 5173 端口已启动 ✅
3. 数据库已包含 `ai_substantive_reply_count` 列(项目用 `create_all(checkfirst=True)`,重启后端即自动添加)
## 测试流程(按顺序验证)
### 测试1:打招呼被拦截,按钮不出现
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 1 | 浏览器打开 `http://localhost:5173` | 进入会话窗口 |
| 2 | 输入 "你好" 发送 | AI回复引导话术(如"你好!请描述你遇到的IT问题..."),**按钮不出现** |
| 3 | 输入 "hi" 发送 | 同上,引导话术,按钮不出现 |
### 测试2:直接呼叫人工被拦截
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 4 | 输入 "人工坐席" 发送 | AI回复引导话术(如"请先描述你的问题,AI会先帮你分析..."),**按钮不出现** |
| 5 | 输入 "转人工" 发送 | 同上 |
### 测试3:正常问题 → AI回复1~2次,按钮不出现
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 6 | 输入 "我的打印机连不上了" | AI给出第1次实质性回复,按钮仍不出现 |
| 7 | 输入 "我试了重启还是不行" | AI给出第2次实质性回复,按钮仍不出现 |
### 测试4:AI回复满3次,按钮出现
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 8 | 输入 "驱动也重装了还是不行" | AI给出第3次实质性回复,**「👊 呼叫坐席」按钮出现** |
| 9 | 检查底部引导文案 | 变为 "👊👊 呼叫坐席通道已开启..." 橙色闪烁 |
### 测试5:点击按钮 → 弹窗动画
| 步骤 | 操作 | 预期结果 |
|------|------|---------|
| 10 | 点击「👊 呼叫坐席」按钮 | 全屏弹窗,直接进入摇人动画(7个场景SVG依次切换) |
| 11 | 等待动画播放 | 自动发送 shake 请求,成功后有"已通知坐席"提示 |
| 12 | 弹窗自动关闭 | 约4秒后自动关闭,会话进入排队状态 |
### 测试6:API 直接验证(可选)
用 curl 验证后端逻辑:
```bash
# 1. 获取/创建当前会话
curl -s http://localhost:8000/api/h5/conversations/current -H "X-Employee-Id: test001" | python -m json.tool
# 检查返回的 can_call_agent 应为 falseai_substantive_reply_count 应为 0
# 2. 发送问候语 → 应该收到引导回复
curl -s -X POST http://localhost:8000/api/h5/conversations/current/messages \
-H "Content-Type: application/json" \
-d '{"employee_id":"test001","content":"你好"}' | python -m json.tool
# 检查 is_guidance 应为 truecan_call_agent 应为 false
# 3. 发送实际问题 x3
curl -s -X POST http://localhost:8000/api/h5/conversations/current/messages \
-H "Content-Type: application/json" \
-d '{"employee_id":"test001","content":"打印机连不上"}' | python -m json.tool
# 重复3次,第3次后 can_call_agent 应为 true
# 4. 在未满3次时尝试 shake → 应返回 1003 错误
curl -s -X POST http://localhost:8000/api/h5/conversations/current/shake \
-H "Content-Type: application/json" \
-H "X-Employee-Id: test002" \
-d '{}' | python -m json.tool
```
---
## 注意事项
1. **每个会话独立计数**`ai_substantive_reply_count` 是 Conversation 级别的字段,不同用户/会话不共享
2. **切换会话会重置**:新会话从 0 开始
3. **后续可扩展**:如果用户说"谢谢"等结束语,可以重置计数;当前版本未实现此逻辑