Files
wecom_it_smart_desk/docs/04-运维文档/快速回复规则后台管理-部署文档-v1.0.md
T
Simon 44e77dcb0e chore(docs): docs/ 目录全面重新编号 + 重组
**重构前**(旧编号 02-11):
- docs/02-产品需求/      → 00 产品规划/PRD
- docs/03-技术架构/      → 01-05 子目录散落
- docs/04-原型设计/      → 01-02 产品设计(HTML 原型)
- docs/05-原型设计/      → screens/
- docs/06-测试素材/      → 02-E2E / 03-功能 / 04-版本测试
- docs/07-项目管理/      → 任务说明书/日报/计划
- docs/08-安全审计/      → 审计报告
- docs/09-堡垒运维/      → toolbox / deploy
- docs/10-项目管理/      → 任务说明书(重复)
- docs/11-历史归档/      → deploy-nas-archived

**重构后**(新编号 00-07,语义化):
- docs/00-产品开发流程与文档管理规范.md
- docs/00-版本迭代总览.md
- docs/01-产品文档/      (PRD/原型/认证/会话/AI 服务/坐席/集成)
- docs/02-技术文档/      (技术方案/架构图/重构记录/前端改造/实现配置)
- docs/03-测试文档/      (E2E/功能用例/版本报告/缺陷单)
- docs/04-运维文档/      (部署运维/运维指南)
- docs/05-运营文档/      (品牌推广/用户手册)
- docs/06-安全审计/      (审计报告)
- docs/07-项目管理/      (任务说明书/日报/计划/看板)

**净收益**:
- 目录编号与产品文档管理规范对齐(按文档阶段 01-07 编号)
- 消除 02-产品需求 与 10-项目管理 的编号重叠
- 子目录按文档类型分组(如 01-产品文档/00-产品规划、01-产品文档/01-认证与登录)
- 把运维/安全/项目管理从 0X 散落改为 04/06/07

合计 494 文件 + 78495 行 / - 14076 行
2026-08-03 18:46:55 +08:00

398 lines
17 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.
# 快速回复规则后台管理 — 部署文档
> **需求编号**: REQ-通用-002
> **版本**: v1.22026-07-28 管理后台 UI 去重调整)
> **日期**: 2026-07-27(初版) / 2026-07-28v1.1 整改、v1.2 UI 调整)
> **状态**: [已评审]
> **作者**: Simon
> **部署服务器**: itsupport.servyou.com.cn (10.90.5.110)
>
> **关联文档**(按规范要求补全):
> - PRD`01-产品文档/00-产品规划/PRD-REQ-通用-002-快速回复规则后台管理-v1.2.md`
> - 技术方案:`02-技术文档/技术方案-REQ-通用-002-快速回复规则后台管理.md`
> - 原型图:`01-产品文档/01-02产品设计/快速回复规则后台管理-原型图.html`
> - 上游依赖:Alembic 055 迁移(`alembic upgrade 055`)、`scripts/init_quick_rules.sql`
>
> **命名规范说明**:按 `docs/00-产品开发流程与文档管理规范.md` 2.3.3 节,标准命名应为
> `DEPLOY-REQ-通用-002-快速回复规则后台管理-v1.0.md`,应放置在 `04-运维文档/部署运维/` 子目录下。
> 本次保留历史文件名/位置以避免破坏现有内部引用;**后续同类文档请按规范命名**。
---
## 0. 前置条件(部署前必须 100% 确认)
| 检查项 | 要求 | 验证方式 |
|--------|------|----------|
| 关联 PRD | 已评审、当前为 [已评审] 状态 | `Read docs/01-产品文档/00-产品规划/PRD-REQ-通用-002-快速回复规则后台管理-v1.2.md` |
| 关联技术方案 | 已评审 | `Read docs/02-技术文档/技术方案-REQ-通用-002-快速回复规则后台管理.md` |
| 关联原型图 | 已评审(本次涉及 6 个新页面,必须有) | 打开 `docs/01-产品文档/01-02产品设计/快速回复规则后台管理-原型图.html` |
| Alembic 迁移文件 | `alembic/versions/055_*.py` 已存在 | `ls alembic/versions/ | grep -i quick` |
| 初始化 SQL | `scripts/init_quick_rules.sql` 已就绪且 ≥ 53 条 | `wc -l scripts/init_quick_rules.sql` |
| jumpserver-V2 skill | 已登录且缓存有效 | 跑 `v2_ops.py status` |
| 服务器 `.env` | `.env` 已同步 `QUICK_RULE_*` 类变量(见 §1.3 | `grep -E "^QUICK_RULE_" .env` |
| 后端镜像 | `--workers 1` 已写入 `docker-compose.yml` | `grep -E "workers" docker-compose.yml` |
| 部署窗口 | 已与值班坐席同步,选低峰期 | 口头/IM 通知 |
---
## 1. 部署概览
### 1.1 部署范围
| 模块 | 状态 | 说明 |
|------|------|------|
| 数据库表 | 新增 2 张 | `quick_rules``quick_rule_audit_log` |
| 后端 API | 新增 12 个 | `/api/admin/quick-rules/*`(见技术方案 §3 |
| 前端页面 | 新增 6 个 | `/quick-rules/*`admin 端 1 个 H5/坐席端不涉及) |
| 现有代码改造 | 2 处 | `ai_handler.py``routing_service.py`(向后兼容:DB 为空时回退硬编码) |
| **本版本不涉及** | - | agent 端、H5 端、terminal 端无需重新打包 |
### 1.2 规则类型与初始数量(单一权威来源,§5 验证时直接引用此处)
| rule_type | 初始条数 | 兜底硬编码条数 |
|-----------|----------|----------------|
| `greeting` | 12 | 1 条("你好" → 引导描述问题) |
| `routing_prefilter` | 33 | 3 条 |
| `routing_target` | 6 | 2 条 |
| **合计** | **51** | **6** |
### 1.3 `.env` 变量变更清单(配置同步铁律,必须同步)
> 部署铁律:修改 `config.py` 默认值 ≠ 配置生效,必须同步更新服务器 `.env`。
| 变量名 | 用途 | 默认值 | 来源 |
|--------|------|--------|------|
| `QUICK_RULE_AUTO_APPLY_THRESHOLD` | 智能体自动应用规则的置信度阈值 | `0.85` | config.py |
| `QUICK_RULE_AUDIT_REVIEW_THRESHOLD` | 落入待审核的阈值 | `0.5` | config.py |
| `QUICK_RULE_CACHE_TTL_SECONDS` | Redis 缓存 TTL | `300` | config.py |
服务器部署完成后必须执行:
```bash
# 通过 v2_ops.py 上传 .env 增量文件
v2_ops.py upload .env.production-increment .env.production-increment
# 远端追加(注意:此处禁用 $(date),用预生成时间戳文件名)
ssh-via-jms 'cat /tmp/.env.production-increment >> /opt/wecom-it-desk/.env'
# 重载后端使新变量生效
docker compose --env-file .env restart backend
```
### 1.4 部署顺序(部署铁律)
```
DB migrationalembic upgrade)→ .env 同步 → 后端 coderestart)→ 前端 adminpsftp + restart nginx)→ 端到端验证 → 灰度
```
---
## 2. 数据库迁移
### 2.1 备份(v2_ops.py / psftp 双通道)
```bash
# 1. 登录堡垒机(jumpserver-V2 skill
v2_ops.py login
# 2. 服务器端生成备份文件名(禁用 $(...),预生成)
TIMESTAMP=$(date +%Y%m%d_%H%M%S) # 本地 PowerShell 生成后再传入
ssh-via-jms "docker exec wecom_it_postgres pg_dump -U postgres -d wecom_it_desk -Fc > /opt/wecom-it-desk/backups/before-quickrule-${TIMESTAMP}.dump"
```
### 2.2 执行迁移(按部署铁律:DB migration 只能逐版降)
```bash
# 1. 检查当前版本
ssh-via-jms "docker exec wecom_it_backend alembic current"
# 2. 升级到目标版本(升级用 head,向前兼容)
ssh-via-jms "docker exec wecom_it_backend alembic upgrade 055"
# 3. 验证:checkfirst 自动建表是否成功(主要依赖 alembic,但作为冗余验证)
ssh-via-jms "docker exec wecom_it_postgres psql -U postgres -d wecom_it_desk -c '\\dt quick_rules*'"
# 期望输出:
# quick_rule_audit_log
# quick_rules
# 4. 插入初始化数据(psftp 通道,禁用 elFinder
v2_ops.py upload scripts/init_quick_rules.sql init_quick_rules.sql
ssh-via-jms "cat /tmp/init_quick_rules.sql | docker exec -i wecom_it_postgres psql -U postgres -d wecom_it_desk -v ON_ERROR_STOP=1"
```
> ⚠️ **降级路径**(回滚时使用):蓝绿共用同一 PG,本次只能逐版降
> ```bash
> ssh-via-jms "docker exec wecom_it_backend alembic downgrade -1"
> # 重复执行直到 quick_rules 表消失
> ssh-via-jms "docker exec wecom_it_postgres psql -U postgres -d wecom_it_desk -c '\\dt quick_rules*'"
> ```
### 2.3 验证
```sql
-- 单一权威断言:本表数字一旦修改,§1.2 同步修改
SELECT rule_type, COUNT(*) FROM quick_rules WHERE is_active = true GROUP BY rule_type ORDER BY rule_type;
-- 期望:greeting=12, routing_prefilter=33, routing_target=6
```
---
## 3. 后端部署
### 3.1 部署(卷挂载 → restart 即可)
```bash
# 后端代码统一源:/opt/wecom-it-desk/app/(卷挂载)
# .py 变更仅 restart,不必 rebuild
v2_ops.py upload src/backend/app/models/quick_rule.py /tmp/quick_rule.py
v2_ops.py upload src/backend/app/models/quick_rule_audit_log.py /tmp/quick_rule_audit_log.py
v2_ops.py upload src/backend/app/services/quick_rule_service.py /tmp/quick_rule_service.py
v2_ops.py upload src/backend/app/api/admin/quick_rules.py /tmp/quick_rules.py
v2_ops.py upload src/backend/app/services/ai_handler.py /tmp/ai_handler.py
v2_ops.py upload src/backend/app/services/routing_service.py /tmp/routing_service.py
ssh-via-jms 'for f in quick_rule.py quick_rule_audit_log.py quick_rule_service.py quick_rules.py ai_handler.py routing_service.py; do
if [ -f /tmp/$f ]; then
cp /tmp/$f /opt/wecom-it-desk/app/$(echo $f | sed "s|^|models/|; s|quick_rule_audit_log.py|models/&|; s|quick_rule_service.py|services/&|; s|quick_rules.py|api/admin/&|; s|ai_handler.py|services/&|; s|routing_service.py|services/&|")
fi
done'
# 必须保证 workers=1(部署铁律:多 worker 会致 WS 消息丢失)
ssh-via-jms "docker compose --env-file .env up -d --force-recreate --no-deps backend"
# 或:ssh-via-jms "docker compose restart backend"
# 探活
sleep 5
ssh-via-jms "docker exec wecom_it_backend python -c \"from app.models.quick_rule import QuickRule; print('OK', QuickRule.__tablename__)\""
```
### 3.2 启动期验证
```bash
# 1. 后端探活(外部)
curl -fsS http://itsupport.servyou.com.cn/health
# 2. Swagger 文档(确认 quick-rules 路由注册)
curl -fsS http://itsupport.servyou.com.cn/docs | grep quick-rules
# 3. 后端日志:必须看到 QuickRuleService.load_all 成功
ssh-via-jms "docker logs wecom_it_backend --tail 200 2>&1 | grep -i 'quick_rule\\|loaded.*rules'"
# 期望:loaded 51 rules (12 greeting, 33 routing_prefilter, 6 routing_target)
```
### 3.3 业务侧验证(端到端、容器外,验证铁律)
```bash
# 获取 token
TOKEN=$(curl -s -X POST http://itsupport.servyou.com.cn/api/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"simon","password":"<OTP>"}' | jq -r .data.token)
# 1. stats 接口
curl -fsS http://itsupport.servyou.com.cn/api/admin/quick-rules/stats \
-H "Authorization: Bearer $TOKEN" | jq .
# 期望:{ "code":0, "data":{ "greeting":12, "routing_prefilter":33, "routing_target":6, "total":51 } }
# 2. 列表接口(greeting
curl -fsS "http://itsupport.servyou.com.cn/api/admin/quick-rules?rule_type=greeting&limit=5" \
-H "Authorization: Bearer $TOKEN" | jq '.data | length'
# 期望:5
```
---
## 4. 前端部署(仅 admin 端)
### 4.1 本地构建(ASCII 路径,前端构建 SOP)
```bash
# 本地路径必须纯 ASCIID:\资料\路径下 pnpm install 会卡死)
cd D:\dev\wecom\src\frontend-admin
# 多路径同步铁律:中文路径下 D:\资料\03-项目开发\wecom_it_smart_desk 也要同步改
# 否则 vite build 用的是 ASCII 路径下的旧代码
npm install # 不要用 pnpm install
npm run build # 产物在 dist/
Compress-Archive -Path dist -DestinationPath dist-quickrules-v1.0.zip
```
### 4.2 上传与部署(psftp 通道,禁止 elFinder
```bash
# 1. 上传 zip
v2_ops.py upload D:\dev\wecom\src\frontend-admin\dist-quickrules-v1.0.zip dist-quickrules-v1.0.zip
# 2. 服务器端解压到 bind mount 目录(unzip 会直接产出 assets/ + index.html
ssh-via-jms 'cd /opt/wecom-it-desk/frontend-admin/dist-new && unzip -o /tmp/dist-quickrules-v1.0.zip'
ssh-via-jms 'rm -rf /opt/wecom-it-desk/frontend-admin/dist && mv /opt/wecom-it-desk/frontend-admin/dist-new /opt/wecom-it-desk/frontend-admin/dist'
# 3. ★ 必须显式重启 nginxbind mount 不会自动刷新新文件)
ssh-via-jms 'docker restart wecom_it_nginx'
# 4. 验证
curl -fsS http://itsupport.servyou.com.cn/itadmin/quick-rules | head -c 200
# 期望:HTML 200 OKtitle 含 "快速回复"
```
### 4.3 浏览器自测(agent-browser skill
```bash
# 走 agent-browser 技能自动化测试,至少覆盖:
# 1) /itadmin/quick-rules 列表加载
# 2) /itadmin/quick-rules/greeting 编辑一条规则、断言持久化
# 3) /itadmin/quick-rules/audit 审计日志可见
# 4) 模拟"用户你好"→ 期望 AI 引导描述(不调用 Dify)
```
---
## 5. 端到端回归验证(验证铁律:容器内通过≠外部可用)
| # | 场景 | 输入 | 期望输出 | 验证方式 |
|---|------|------|----------|----------|
| T1 | 打招呼走 quick_rule,不调用 Dify | Mock 用户发"你好" | AI 回复引导描述问题,diffy_call_count=0 | WebSocket mock + logs |
| T2 | 路由触发命中 quick_rule | Mock 用户发"打印机连不上" | 命中 prefilter→target,发送名片卡片 | 卡片 payload + 路由日志 |
| T3 | 普通问题走 Dify(兼容路径) | Mock 用户发"电脑蓝屏了" | 走 Dify 主推理,diffy_call_count=1 | Dify 调用日志 |
| T4 | 兜底:清空 DB → 重启后仍可用 | `DELETE FROM quick_rules; docker compose restart backend` | 行为不中断,加载日志 "fallback to hardcoded" | 启动日志 + 业务接口 |
| T5 | 缓存刷新 | POST `/api/admin/quick-rules/refresh` | 60s 内 Redis keys 变化 | `redis-cli KEYS quick_rules:*` |
具体执行命令见配套测试用例 `TC-快速回复规则后台管理.md`**待补,需建**)。
---
## 6. 灰度上线
### 6.1 灰度开关(env + 代码双层)
| 开关 | 默认 | 启用时效果 |
|------|------|-----------|
| `QUICK_RULE_ENABLED`(env,**本次新增,必须加**) | `true` | `false` 时完全走硬编码兜底 |
| `QUICK_RULE_AUTO_APPLY_THRESHOLD` | `0.85` | 调高(如 `0.99`)等于关闭自动应用 |
| `QUICK_RULE_AUDIT_REVIEW_THRESHOLD` | `0.5` | 调高(如 `0.9`)等于全部走待审核 |
### 6.2 灰度策略
| 阶段 | 时长 | 动作 | 监控重点 |
|------|------|------|----------|
| Phase 1 观察期 | 1-3 天 | 启用新规则,日志标 `quick_rule.hit` | API 成功率、命中占比 |
| Phase 2 人工编辑期 | 4-7 天 | 运营通过后台编辑 | 误判率、日志异常 |
| Phase 3 完全替代 | 7 天+ | 保留硬编码兜底 | 同上 |
### 6.3 回滚(完整三路回滚)
```bash
# Step 1:DB 回滚(降级,按部署铁律:只 downgrade 不 drop 备份)
ssh-via-jms "docker exec wecom_it_backend alembic downgrade -1"
# Step 2:清空规则(保留表结构,使代码加载硬编码兜底)
ssh-via-jms "docker exec -i wecom_it_postgres psql -U postgres -d wecom_it_desk -c \"DELETE FROM quick_rules;\""
# Step 3:后端代码回滚(git)
ssh-via-jms "cd /opt/wecom-it-desk && git log --oneline -5"
ssh-via-jms "cd /opt/wecom-it-desk && git revert --no-edit HEAD"
# Step 4:前端 dist 回滚
v2_ops.py upload archives/frontend-admin-dist-v*.zip rollback.zip
ssh-via-jms 'cd /opt/wecom-it-desk/frontend-admin && rm -rf dist && mkdir dist && cd dist && unzip /tmp/rollback.zip'
ssh-via-jms 'docker restart wecom_it_nginx'
# Step 5:环境变量回滚(可选,但建议保持 0 风险)
# 在 .env 中 QUICK_RULE_ENABLED=falserestart backend
```
---
## 7. 监控指标
### 7.1 关键指标(明确阈值,可告警)
| 指标 | 采集方式 | 告警阈值 | 通知渠道 |
|------|---------|----------|----------|
| `/api/admin/quick-rules/*` 调用成功率 | nginx access log 5xx 占比 | > 1% | 企微机器人 |
| 规则加载耗时(启动期) | `docker logs wecom_it_backend` | > 3s | 日志告警 |
| 缓存命中率 | `INFO logs/smart_desk.log``quick_rule.hit / quick_rule.miss` | < 70%24h 均值) | 企微机器人 |
| 兜底触发次数 | 日志 `quick_rule.fallback` | 24h 内 > 100 | 企微机器人 |
| 自动应用次数突增 | `quick_rule_audit_log` | 1h 内 > 50 | 企微机器人 |
| Alembic 迁移失败 | 启动日志 | 任意 1 次 ERROR | P1 告警 |
### 7.2 日志查询 SOP
```bash
# 启动期规则加载
ssh-via-jms "docker logs wecom_it_backend --since 10m 2>&1 | grep -i 'quick_rule'"
# 命中/兜底实时监控
ssh-via-jms "tail -f /opt/wecom-it-desk/logs/wecom-it-desk.log | grep quick_rule"
# Redis 缓存
ssh-via-jms "docker exec wecom_it_redis redis-cli KEYS 'quick_rules:*'"
```
---
## 8. 常见问题
### Q1:数据库表已存在错误(原文"数据库插件已存在错误"为错别字)
```text
错误:relation "quick_rules" already exists
原因:alembic 055 已成功建表,重复执行会触发
解决:属正常现象,跳过或继续下一步
```
### Q2:初始化数据重复插入失败
```text
错误:duplicate key value violates unique constraint
原因:脚本已使用 ON CONFLICT DO NOTHING,重复执行安全
解决:直接忽略;如需强制重置,先 TRUNCATE quick_rules
```
### Q3:缓存未刷新
```bash
curl -X POST "http://itsupport.servyou.com.cn/api/admin/quick-rules/refresh" \
-H "Authorization: Bearer $TOKEN"
# 或直接清 Redis
ssh-via-jms "docker exec wecom_it_redis redis-cli DEL $(docker exec wecom_it_redis redis-cli KEYS 'quick_rules:*' | tr '\n' ' ')"
```
### Q4:规则加载后业务侧未生效
```text
排查路径:
1) docker logs wecom_it_backend | grep "loaded.*rules" 确认 51 条加载
2) curl /api/admin/quick-rules/stats 确认 DB 与 API 一致
3) tail logs/wecom-it-desk.log | grep quick_rule.fallback 看是否走兜底
4) REDIS 缓存是否过期(TTL 默认 300s),可手动 DEL 后重试
```
### Q5:缓存验证时找不到 admin token
```bash
TOKEN=$(curl -s -X POST http://itsupport.servyou.com.cn/api/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"simon","password":"<OTP>"}' | jq -r .data.token)
```
### Q6:前端 dist 更新后页面没刷新
```text
原因:bind mount 不会自动同步;nginx 也不会主动重读
解决:必须 docker restart wecom_it_nginx
```
---
## 9. 变更记录
| 日期 | 版本 | 变更内容 | 变更人 | 变更原因 | 影响范围 |
|------|------|----------|--------|----------|----------|
| 2026-07-27 | v1.0 | 初版 | Simon | 新功能首次上线 | - |
| 2026-07-28 | v1.1 | 整改:补全头部模板/关联文档/前置条件/.env变更清单/回滚三路方案/灰度开关/可执行验证命令;修复 `ssh sxn@``$(date)`、elFinder 三处命令级错误;命名规范说明追加 | Simon | 复盘发现不符合规范 §2.3/§5.2 + 命令违反部署铁律 | 本文档全部重写,零代码变更 |
| 2026-07-28 | v1.2 | 管理后台 `/quick-rules` 顶部 3 张重复统计卡片移除,仅保留标签导航及 count 徽标;后端 stats 接口与部署流程保持不变 | Simon | 页面信息冗余 | 仅管理后台前端展示,部署位置与流程不变 |