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-*/
17 KiB
17 KiB
快速回复规则后台管理 — 部署文档
需求编号: REQ-通用-002 版本: v1.2(2026-07-28 管理后台 UI 去重调整) 日期: 2026-07-27(初版) / 2026-07-28(v1.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-产品开发流程与文档管理规范.md2.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_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 |
服务器部署完成后必须执行:
# 通过 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 migration(alembic upgrade)→ .env 同步 → 后端 code(restart)→ 前端 admin(psftp + 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)
# 本地路径必须纯 ASCII(D:\资料\路径下 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. ★ 必须显式重启 nginx(bind 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 OK,title 含 "快速回复"
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_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 回滚(完整三路回滚)
# 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=false,restart 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
# 启动期规则加载
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 | 页面信息冗余 | 仅管理后台前端展示,部署位置与流程不变 |