Files
wecom_it_smart_desk/docs/03-测试文档/05-缺陷单/BUG-通用-快速回复规则-路由目标筛选500-002.md
Simon facc04aa65 chore: docs 结构整改 + compose 双目录对齐(合并重建提交)
本提交为 .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-*/
2026-08-07 22:31:32 +08:00

9.8 KiB
Raw Permalink Blame History

缺陷单:快速回复规则「路由目标」筛选分类下拉菜单 500 错误

缺陷编号: BUG-通用-002 版本: v1.0 状态: [已关闭] 优先级: P1-High 发现日期: 2026-07-28 发现人: 宋献 指派人: 宋献 修复人: Duckula (AI助手) 关闭日期: 2026-07-28 处理方式: 自动处理和验证 关联需求: REQ-通用-002(快速回复规则后台管理) 关联文档:

  • PRD: docs/01-产品文档/00-产品规划/PRD-REQ-通用-002-快速回复规则后台管理-v1.2.md
  • 技术方案: docs/02-技术文档/技术方案-REQ-通用-002-快速回复规则后台管理.md
  • 任务说明书: docs/07-项目管理/任务说明书/任务说明书-131-快速回复规则后台管理.md
  • 故障手册: docs/04-运维文档/部署运维/00-标准故障排查手册.mdCASE-20260728-05

1. 基本信息

字段 内容
缺陷标题 管理后台 → 快速回复规则 → "路由目标" tab → 点击"业务分类"下拉菜单 → 提示"服务器内部错误,请稍后重试或联系管理员"
影响范围 管理员/运营人员使用「路由目标」筛选的全部场景(共 6 条 routing_target 规则无法按分类筛选)
涉及模块 管理后台(frontend-admin+ 后端 APIbackend FastAPI
涉及文件 src/backend/app/api/admin/quick_rules.pyQuickRuleResponse 模型)
src/backend/scripts/init_quick_rules.sqlrouting_target 初始数据)
触发条件 1. 登录管理后台 → /itadmin/quick-rules
2. 切换到"路由目标" Tab
3. 点击"业务分类"下拉菜单(前端会带 ?rule_type=routing_target&category=XXX/api/admin/quick-rules
预期行为 下拉菜单正常加载所有 6 条 routing_target 规则,下拉可选项覆盖已配置的 6 个分类
实际行为 下拉菜单触发 API 调用,后端返回 1005 通用错误,UI 弹窗"服务器内部错误,请稍后重试或联系管理员";其他 Tabgreeting、routing_prefilter)正常

2. 复现步骤

  1. 用管理员账号登录管理后台 https://itsupport.servyou.com.cn/itadmin/
  2. 进入「快速回复规则」页面(路由 /itadmin/quick-rules
  3. 切换到 "路由目标" Tab(默认显示 6 条记录)
  4. 点击任意筛选条件中的 "业务分类" 下拉菜单
  5. 观察前端弹窗 → 显示「服务器内部错误,请稍后重试或联系管理员」
  6. 检查浏览器 F12 → Network → /api/admin/quick-rules?rule_type=routing_target&category=XXX → HTTP 200 但 code:1005

影响截图

  • 页面:快速回复规则 → 路由目标 Tab
  • 区块:筛选条件行
  • 元素:业务分类下拉菜单

3. 根因分析

三层根因(缺一不可)

3.1 数据层(DB):routing_target 记录 priority 字段为 NULL

scripts/init_quick_rules.sql 第 80 行的 routing_target INSERT 语句 未指定 priority

-- 错误(routing_target 段):没有 priority 字段
INSERT INTO quick_rules (rule_type, category, keyword, extra_data, is_active) VALUES
('routing_target', '行政', '机票酒店前台', '{...}', true),
('routing_target', '人力资源', '人力资源共享服务咨询', '{...}', true),
...

greetingrouting_prefilter 段正确指定了 priority

-- 正确(greeting 段)
INSERT INTO quick_rules (rule_type, keyword, priority, is_active) VALUES
('greeting', '你好', 10, true),
...

结果DB 中 6 条 routing_target 记录 priorityNULL

3.2 模型层(Pydantic):QuickRuleResponse.priority 声明为非 Optional

app/api/admin/quick_rules.py:77 原始定义:

class QuickRuleResponse(BaseModel):
    """规则响应"""
    id: int
    rule_type: str
    category: Optional[str] = None
    keyword: str
    priority: int          # ← 未声明 Optional
    response_template: Optional[str] = None
    extra_data: Optional[dict] = None
    is_active: bool
    created_at: str

Pydantic 序列化时严格校验 priority 必须是 int,遇到 None → 抛 ValidationError

3.3 中间件层:catch_errors_and_log 捕获所有异常后返回 1005

全局 catch_errors_and_log 中间件捕获 Pydantic ValidationError 后,统一返回 1005 通用错误,前端无法区分 Pydantic 校验失败与其他 500 错误,被迫显示"服务器内部错误"。

错误日志(诊断依据)

pydantic_core._pydantic_core.ValidationError: 1 validation error for QuickRuleResponse
priority
  Input should be a valid integer [type=int_type, input_value=None, input_type=NoneType]

额外发现(隐藏 bug

排查中用 AST 校验发现,本地 quick_rules.py 上线前已存在 3 处遗留语法错误

  • 2 处 )) 文本多余括号
  • 1 处文件结尾 ) 缺失

若直接 upload,容器内 Python 启动会 SyntaxError。


4. 处理办法

项目 内容
处理策略 自动处理和验证
执行时机 立即(影响正常业务使用)
处理流程 1. 修复 QuickRuleResponse.priority 字段类型 + 5 个字段补 Optional
2. 修复 init_quick_rules.sql 补齐 priority
3. DB 实时回填 6 条 NULL 记录
4. 修复本地遗留语法错误
5. AST 静态校验 + 端到端 API 验证
验证方式 8 个 API 测试用例(rule_type + 6 个分类 + 1 个不存在的分类)
回滚方案 priority 字段从 v1.0int)回退到破坏前的状态会重新触发 bug;回滚 = 同步回退模型定义、SQL 脚本、DB 数据,仅建议在测试环境尝试

5. 修复方案

5.1 代码修复(3 处)

修复 1app/api/admin/quick_rules.py(第 77-89 行)

class QuickRuleResponse(BaseModel):
    """规则响应"""
    id: int
    rule_type: str
    category: Optional[str] = None
    keyword: str
    # priority 在 DB 中允许 NULLrouting_target 类型的 SQL 初始数据未指定 priority
    # 序列化时若为 None 则按 0 处理,避免 Pydantic ValidationError
    priority: Optional[int] = None
    response_template: Optional[str] = None
    extra_data: Optional[dict] = None
    is_active: bool
    created_at: str

修复 2scripts/init_quick_rules.sql(第 80 行)

-- 修复前
INSERT INTO quick_rules (rule_type, category, keyword, extra_data, is_active) VALUES

-- 修复后
INSERT INTO quick_rules (rule_type, category, keyword, extra_data, priority, is_active) VALUES

并为 6 条 routing_target 记录添加 0 作为 priority 值。

修复 3DB 实时回填

UPDATE quick_rules SET priority = 0 WHERE priority IS NULL;

修复 4(隐藏):本地语法错误

清理 2 处 )) 和 1 处 )


6. 验证结果

6.1 自动化 API 验证(8/8 通过)

测试用例 期望 实际 结果
rule_type=routing_target 6 条 6 条 PASS
category=行政 1 条 1 条 PASS
category=人力资源 1 条 1 条 PASS
category=财务 1 条 1 条 PASS
category=法务 1 条 1 条 PASS
category=行政-物业 1 条 1 条 PASS
category=IT服务 1 条 1 条 PASS
category=不存在的分类 0 条 0 条 PASS

6.2 后端日志验证

  • 修复前:pydantic_core._pydantic_core.ValidationError: ... priority Input should be a valid integer
  • 修复后:GET /admin/quick-rules?rule_type=routing_target&category=... HTTP/1.1 200 OK(无 ValidationError

6.3 真实浏览器验证

待用户在管理后台手动点击下拉菜单复测(端到端 UI 验证)。

6.4 AST 静态校验

  • 本地:python -c "import ast; ast.parse(open('quick_rules.py', encoding='utf-8').read())" OK
  • 容器内:python3 /tmp/check_syntax.py /app/app/api/admin/quick_rules.py OK

7. 关联信息

  • 关联需求: REQ-通用-002(快速回复规则后台管理)
  • 关联 PRD: docs/01-产品文档/00-产品规划/PRD-REQ-通用-002-快速回复规则后台管理-v1.2.md
  • 关联技术方案: docs/02-技术文档/技术方案-REQ-通用-002-快速回复规则后台管理.md
  • 关联任务说明书: docs/07-项目管理/任务说明书/任务说明书-131-快速回复规则后台管理.mdv1.3
  • 关联故障手册: docs/04-运维文档/部署运维/00-标准故障排查手册.mdCASE-20260728-05
  • 修复代码文件:
    • src/backend/app/api/admin/quick_rules.pyQuickRuleResponse 模型)
    • src/backend/scripts/init_quick_rules.sqlrouting_target 初始数据)
  • API 测试脚本: scripts/verify_api.py

8. 变更记录

日期 版本 变更内容 变更人 变更原因 影响范围
2026-07-28 v1.0 创建缺陷单,记录快速回复规则"路由目标"分类筛选 500 错误 宋献 / Duckula 用户反馈业务查询无法使用 管理后台 "快速回复规则" 页面
2026-07-28 v1.0 修复 QuickRuleResponse.priority 字段类型 + 修复 SQL 初始数据 + DB 实时回填 Duckula 数据库字段为 NULL 但 Pydantic 模型要求非空 后端 API + 数据库
2026-07-28 v1.0 修复本地遗留语法错误(2 处 )) + 1 处 ) Duckula AST 校验发现隐藏 bug quick_rules.py
2026-07-28 v1.0 端到端 API 验证(8/8 通过)+ AST 静态校验 Duckula 确认修复实际生效 验证脚本与容器部署
2026-07-28 v1.0 文档规范化整改:故障手册新增 CASE-20260728-05、任务说明书 v1.2→v1.3、缺陷单 README 追加清单 Duckula 规范化要求 BUG 修复需同步周边文档 文档体系

缺陷已关闭。本案例作为"CASE-20260728-05"收录于故障排查手册,供后续排查参考。