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

17 KiB
Raw Blame History

快速回复规则后台管理 — 部署文档

需求编号: 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)

关联文档(按规范要求补全):

  • PRD01-产品文档/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/
初始化 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_rulesquick_rule_audit_log
后端 API 新增 12 个 /api/admin/quick-rules/*(见技术方案 §3
前端页面 新增 6 个 /quick-rules/*admin 端 1 个 H5/坐席端不涉及)
现有代码改造 2 处 ai_handler.pyrouting_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

服务器部署完成后必须执行:

# 通过 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 双通道)

# 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 只能逐版降)

# 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,本次只能逐版降

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 验证

-- 单一权威断言:本表数字一旦修改,§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 即可)

# 后端代码统一源:/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 启动期验证

# 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 业务侧验证(端到端、容器外,验证铁律)

# 获取 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)

# 本地路径必须纯 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

# 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

# 走 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_ENABLEDenv本次新增,必须加 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 回滚(完整三路回滚)

# 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.logquick_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

# 启动期规则加载
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:数据库表已存在错误(原文"数据库插件已存在错误"为错别字)

错误:relation "quick_rules" already exists
原因:alembic 055 已成功建表,重复执行会触发
解决:属正常现象,跳过或继续下一步

Q2:初始化数据重复插入失败

错误:duplicate key value violates unique constraint
原因:脚本已使用 ON CONFLICT DO NOTHING,重复执行安全
解决:直接忽略;如需强制重置,先 TRUNCATE quick_rules

Q3:缓存未刷新

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:规则加载后业务侧未生效

排查路径:
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

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 更新后页面没刷新

原因: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 页面信息冗余 仅管理后台前端展示,部署位置与流程不变