最近给内部的测试管理平台 QualityHub 加了一个质量报表功能——支持按项目、迭代、时间范围统计 Bug 的新建与修复情况,带趋势图和分布图。
从提出需求到功能上线,全程用 Claude Code 辅助开发。这篇文章记录一下整个过程,重点不是"AI 能写代码"这件事,而是我们如何把一个模糊的需求,一步步变成可以上线的功能。
第一步:先调研,不着急动手
需求提出来是:"统计某个项目、某个迭代当天或者一个时间范围内 Bug 的新建、修复情况。"
这个描述很宽泛。在写任何一行代码之前,先做了市场调研——Jira、禅道、TestRail 这类工具的质量报表是怎么设计的,行业共识是什么。
调研结论很清楚:最有价值的永远是两件事:
新建 vs 修复的趋势图——能直接看出这个版本的 Bug 是否在收敛 当前未解决数——今天有几个 Bug 在等我处理
其他那些复杂指标(漏测率、平均修复时长、跨版本对比),大多数团队根本用不到。
第二步:用对话收敛每一个设计决策
调研之后没有直接出方案,而是通过一问一答把每个关键决策确认清楚。
决策 1:报表入口放哪?
最初的想法是放在"项目详情页"里做成 Tab,但去读了代码之后发现判断有误——现有的"缺陷管理"是全局入口,不属于某个特定项目。报表跟着保持一致,放侧边栏,页面内用项目选择器来定位。
这个调整避免了一个不必要的重构。
决策 2:实时查询还是固化快照?
聊到业界很多平台有"质量日报"这种固化数据时,分析了两者的区别:日报是定时任务自动生成的快照,跟用户手动保存是两回事。对于我们的场景,迭代本身就是天然的时间切片,任何时候用相同日期范围重新查,结果是一样的——等价于快照,不需要额外存储。
最终决定:实时查询,不做固化,如果将来需要日报可以用 Celery 定时任务单独加。
决策 3:时间范围上限
最初定的 365 天,被质疑了——"365 天其实也过长了,我觉得 2 个月足够?"这个判断是对的。质量回顾通常是按迭代或按月进行,想看更长周期直接用迭代筛选,没有必要支持跨年查询。最终定为 60 天。
决策 4:趋势图粒度
最初方案是 31 天内按日展示,被问了一个实际问题:"31 天每天两根柱子,62 根柱子挤在一个图里,真的能看清吗?"
实际算了一下:900px 宽度 ÷ 62 根柱子 ≈ 每根 14px,确实太挤。以展示效果为准,把阈值改成 14 天——14 天每根柱子约 32px,清晰可读。
决策 5:KPI 卡片的语义问题
原始设计是四个卡片:新建、已修复、未解决、修复率。看似没问题,但被指出一个真实的混乱:
"新建 24、已修复 18" 是时间范围内发生的事 "未解决 6" 是当前的实时状态
这两种数据放在同一行,用户会困惑:这 6 个是"这段时间新建的里面还没修的",还是"整个项目历史上还没修的"?
最终把 KPI 区域拆成两组,视觉上明确区隔:
期间统计(受时间范围影响) 新建 修复 关闭 拒绝当前状态(实时,不受时间范围影响) 待处理 修复中 待验证 已关闭第三步:写设计文档,跑自动审查
所有决策确认后,输出了一份设计文档,包括:
页面结构和每个组件的职责 后端 API 接口和返回结构 每条 SQL 查询的完整逻辑 前端目录结构
文档写完后,跑了一次自动化 spec 审查。第一轮发现了 7 个问题,其中几个比较关键:
work_item_history存的是中文标签,查询时要用'已修复'而不是'resolved'——这是业务细节,不读代码根本不知道修复数需要 COUNT DISTINCT——一个 Bug 从"待处理"→"修复中"→"已修复"会产生多条历史记录,不去重会重复计数所有查询要加 item_type = 'bug'——表里将来可能有其他类型的工作项,不过滤会导致数据膨胀
文档修完再跑一次,全部通过。
第四步:生成实现计划,11 个 Task
设计文档通过后,生成了详细的实现计划:11 个 Task,从 backend schemas 到 frontend 路由全部覆盖。
每个 Task 包含:
精确的文件路径(create 还是 modify) 完整的代码(不是"添加验证"这种模糊描述) 可执行的测试命令和预期输出
计划审查也发现了两个问题:
导出按钮标签写的是"导出 PNG",但只导出趋势图,误导用户以为导出整页——改为"导出趋势图" 60 天超限时应该弹提示,不能静默截断
第五步:Subagent 驱动执行
实现阶段用了一个叫 Subagent-Driven Development 的模式:每个 Task 派发一个独立的子 Agent 来实现,完成后走两轮审查(spec 合规 + 代码质量),通过了再进入下一个 Task。
这个模式的好处是:
每个子 Agent 上下文干净,不会被之前的讨论干扰 两轮审查有明确分工:一个检查"有没有实现设计文档要求的所有内容",另一个检查"代码质量是否有问题"
最后的全量代码审查发现了几个重要问题:
权限漏洞:报表接口只验证了登录状态,没有校验用户是否是该项目的成员——任何登录用户可以查任意项目的 Bug 数据 PNG 导出方式错误:代码用了 DOM canvas 直接读取,应该用 ECharts 原生的 getDataURL()方法后端缺少服务端校验:60 天上限和日期合法性只在前端校验,API 层没有保护
这三个问题都是在 review 阶段发现并修复的,不是在开发阶段。
第六步:UI 修复
功能跑起来之后陆续发现了几个体验问题:
筛选栏高度与侧边栏不对齐(固定高度 56px 解决) KPI 卡片没有撑满页面宽度(给 .card-group加flex: 1)日期选择器太窄, 2026-05-22显示不全(从 220px 改为 260px)切换 Tab 后回来,选择的项目和迭代消失了(Vue Router 4 的 keep-alive 写法问题) 日期选择器右侧显示全灰的未来月份(调整 pickerValue控制面板初始值)点击回退后显示不连续的两个月(Arco 内部用 Dayjs 对象,用 instanceof Date判断类型失败)
最后一个问题的根因:Arco Design 的 picker-value-change 事件返回的是 Dayjs 对象,不是原生 Date,调用 .getFullYear() 直接报错。加了一个 toDate() 兜底转换解决。
一个被删掉的功能
功能做完后,发现"导出趋势图"按钮几乎没有实用价值——导出的只是图表 canvas,和截图效果一样,而截图还能把 KPI 数字、项目名、时间范围一起抓进去。
直接删掉了这个按钮,把相关死代码一并清理。
如果将来有导出需求,Excel 才是更实用的方向——把所有统计数据写进表格,适合存档和进一步分析。
总结
回顾这个功能的开发过程,有几点值得记录:
设计决策不是一次性的,是在对话中收敛的。 时间范围上限从 365 天改到 60 天、KPI 语义拆分、趋势图粒度调整——这些都是在讨论中才发现问题所在,不是一开始就能想清楚的。
读代码是设计的一部分。 最初的报表入口方案是错的,因为没有充分了解现有代码结构。调研阶段花时间读了项目的路由、布局、数据模型,才发现更合适的方案。
审查发现的问题比开发中发现的多。 权限漏洞、重复计数、类型错误——这些问题都是在自动化 spec review 和 code review 阶段发现的,开发阶段没有意识到。
删功能也是功能。 把用处不大的导出按钮删掉,比保留一个鸡肋功能更好。
夜雨聆风