12 KiB
bench 实施计划
new-api-key-bench 施工执行计划。设计依据:
bench交互设计文档.md(已定稿,决策不再开放)。本文档回答「怎么干」:阶段划分、每步产出、验收标准。与设计文档的分工——设计文档说「是什么」,本文档说「怎么做、做到什么程度算完成」。
0. 施工前置认知
- 遵循的规范(生效中,施工时不可违背):
- 文件名 kebab-case 且语义化完整(
json-text-view.vue而非jtv.vue);模板引用大驼峰(<JsonTextView />) - prettier
semi: true/ 单引号 / 100 宽(已配置,bun run format兜底) - composable 一律 setup 顶层调用(VueUse / pinia / vue-query 均适用)
- 代码内标识符语义化(
endpointList优于epList)
- 文件名 kebab-case 且语义化完整(
- 可用的能力:TDesign MCP(组件文档/DOM/图标)、antfu skills(vue / pinia / vitest / vueuse 等,写前查)
- 验收基线:lint ✅ + type-check ✅ + build ✅ + vitest ✅,缺一不可
1. 阶段划分(六阶段,严格按序)
阶段一:工程配置收尾 ✅(已完成 2026-09-07)
验收记录:type-check / test(冒烟 1 用例)/ lint(oxlint 0 警告)/ build(63.08 kB)四绿通过;dev server 5199 端口起服务正常。 施工决策:vitest 配置独立为
vitest.config.ts(Vite 8UserConfig类型不收test字段,TS2769);src/lib/smoke.spec.ts冒烟测试守护管线。
| # | 任务 | 产出 |
|---|---|---|
| 1.1 | vite.config.ts 补网关代理(/api、/v1 → GATEWAY 环境变量可覆盖)+ vitest include 配置 |
vite.config.ts 更新 |
| 1.2 | 清模板残留:src/stores/counter.ts、src/router/ 空路由及 main.ts 引用、无用 assets |
src/ 干净 |
| 1.3 | package.json scripts 增补 test(vitest run) |
scripts 齐备 |
验收:bun run dev 起服务无报错;bunx vitest run(空测试集)退出码 0。
阶段二:数据层(纯 TS,无 UI)✅(已完成 2026-09-07)
验收记录:32 用例全绿(endpoints 8 / gateway-client 4 / json-text-processor 19 / smoke 1);type-check / lint / build 三绿。 施工决策:
formatJsonOrRawText对null显式降级(JSON.stringify(null)会返回字面量"null");computeVisibleRowWindow增加 scrollTop 超界钳制(惯性滚动 shrink 场景);tokenize 输出结构化 span 而非 HTML 字符串(转义与着色归 UI 层,杜绝注入)。
| # | 任务 | 产出 |
|---|---|---|
| 2.1 | src/api/endpoints.ts:5 接口静态元数据(路径/方法/鉴权/注意事项文案/示例响应),按设计文档 §1 顺序 |
endpoints.ts |
| 2.2 | src/api/gateway-client.ts:fetch wrapper——拼 Authorization: Bearer 头、performance 计时、返回 { status, ms, bytes, text, json };无重试无拦截 |
gateway-client.ts |
| 2.3 | src/lib/json-text-processor.ts:JSON pretty-print 行切分、可视窗口计算(scrollTop / rowHeight → 起止行号)、行级语法高亮(仅对可视区行执行正则) |
json-text-processor.ts |
| 2.4 | vitest 单测:endpoints 数据完整性(5 项、路径唯一、顺序正确)、client 的 URL/头拼装、json-processor 的窗口边界(0 行、超界、恰好整除) | 同目录 .spec.ts |
验收:bunx vitest run 全绿;纯函数 100% 可脱离 Vue 运行(node 环境可 import)。
阶段三:状态与请求集成 ✅(已完成 2026-09-07)
验收记录:43 用例全绿(新增 bench-store 10 + endpoint-queries 集成冒烟 1);type-check / lint / build 三绿。 施工决策:endpoint-queries 走
useQuery+enabled门控 +refetch()显式触发的组合(方案 A 落地,fetchQuery备选未启用);集成冒烟测试用 jsdom 单文件环境(@vitest-environment jsdom注释),node 环境测试不受影响;jsdom 进 devDependencies。 TDD 战果:store 单测抓出「关中间 tab 后激活态断言」用例自身的设计错误(重开去重导致顺序与预期不符),拆成两个语义纯净的用例修复。
| # | 任务 | 产出 |
|---|---|---|
| 3.1 | src/stores/bench-store.ts:openTabs: string[](endpoint 路径数组)、activeTab: string | null、open/close/activate actions(Postman 语义:已开则激活;关激活 tab 则激活相邻) |
bench-store.ts |
| 3.2 | src/api/endpoint-queries.ts:TanStack Query 接入——queryKey: [endpointPath, skKey]、staleTime: Infinity、enabled 由「发送」动作置位 |
endpoint-queries.ts |
| 3.3 | src/main.ts 装配:TDesign(按需引 style)、Pinia、VueQueryPlugin、暗色主题注入 |
main.ts |
验收:type-check 过;bench-store 的 tab 开关逻辑配 vitest(store 单测不依赖组件)。
阶段四:UI 骨架(布局可跑)✅(已完成 2026-09-07)
验收记录:type-check / lint / test 43 / build 四绿;dev server 起服务正常。 产出:app-shell(双栏)+ side-nav(5 路径平铺)+ request-tabs(t-tabs 卡片风、destroyOnHide=false 保 tab 状态)+ endpoint-panel(信息行/sk-key/发送/响应占位)+ endpoint-info-line(method/路径/鉴权徽标带 title 提示)。 施工决策:暗色用
:root { theme-mode: dark }(TDesign 官方暗色变量挂载点)而非暗色 class 包裹;t-tabs 全量 CSS 引入暂不按需(阶段六再评估 tree-shake);endpoint-panel 已接 useManualEndpointQuery(响应区为原文占位,阶段五换 json-text-view)。 补充交互(2026-09-07):t-tabs 拖拽排序——store 加 reorderTab(含越界/路径不匹配防御),request-tabs 开 :drag-sort + @drag-sort,7 个重排单测(前移/后移/相邻/原位/防御/激活态不变)。TDesign drag-sort 只发事件不改数据,重排由 store splice 落地。 Bug 修复(2026-09-07,手测发现):①「所有 tab 内容挤同一面板」——destroyOnHide=false 让全部 panel 常驻 DOM 靠 display:none 隐藏,而我的样式把 .t-tab-panel 覆盖成 flex,破坏了隐藏机制;②「关 tab 无效」——受控 value 与 remove 事件的内部状态打架。修复:去掉 destroyOnHide,panel 内容改为v-if="tabPath === activeTab"只挂激活 tab,状态保留交给 Query 缓存(queryKey 含 path+skKey),样式不再覆盖 .t-tab-panel 的 display。 Bug 修复二(2026-09-07,「选项卡与内容都没关掉」):插槽写法(t-tab-panel 子组件)经 getSlotPanels() 从 vnode 反挖 panel 列表,在受控 value + 动态增删下与 openTabs 脱钩,remove 后 nav 不更新。弃用插槽,改官方 list prop 数据驱动(Tabs + tabPanelList computed,panel 用 h() 渲染),显式 import Tabs 绕开 resolveComponent。@remove 事件签名按源码修正为 { value, index, e }。
| # | 任务 | 产出 |
|---|---|---|
| 4.1 | src/app-shell.vue:双栏布局(左 ~300px sider + 右自适应),暗色底 |
app-shell.vue |
| 4.2 | src/components/side-nav.vue:5 路径平铺列表,选中态高亮,点击 → store.openTab |
side-nav.vue |
| 4.3 | src/components/request-tabs.vue:t-tabs 容器,tab 标签即路径,可关闭 |
request-tabs.vue |
| 4.4 | src/components/endpoint-panel.vue:单接口面板骨架(请求行 + 调试行 + 响应区占位);sk-key 为组件局部 ref(无持久化) |
endpoint-panel.vue |
| 4.5 | src/components/endpoint-info-line.vue:method 徽标 + 路径 + 鉴权徽标(宽松/严格) |
endpoint-info-line.vue |
验收:浏览器手测——点 sider 开 tab、切 tab、关 tab(含关激活 tab、关光),布局不塌。
阶段五:核心组件(性能决战)✅(已完成 2026-09-07,性能验收留待真机)
产出:json-text-view.vue(虚拟滚动 + 懒高亮 + token-gap CSS 间隙)+ endpoint-panel 响应区完整化(元信息/复制 useClipboard legacy 降级/下载 Blob)+ 注意事项 t-collapse 折叠。 验收记录:四绿(type-check / lint / test 53 / build);dev server 正常。性能硬指标(1000 条滚动不掉帧、首屏小于 200ms)待真机验收(需真实 sk-key)。 施工决策:eslint vue 模板解析器把注释里「< 200ms」当标签开头(invalid-first-character-of-tag-name),改中文「小于」; 直接写模板会被 prettier 折叠搞坏,改 .token-gap(width: 1ch);vitest.config 补 @vitejs/plugin-vue 才能编译组件测试;复制用 useClipboard legacy 降级(localhost 非 https 环境 execCommand 兜底)。
| # | 任务 | 产出 |
|---|---|---|
| 5.1 | src/components/json-text-view.vue:虚拟滚动 JSON 视图——useElementSize(容器尺寸)+ useThrottleFn(滚动节流)+ 行窗口渲染 + 行号列 + 可视区行懒高亮 |
json-text-view.vue ✅ |
| 5.2 | 响应区完整化:状态码/耗时/字节数元信息行、useClipboard 复制、.json 下载、空态(未发送)、错误态(网络错误 / 非 2xx 仍展示响应体) |
endpoint-panel.vue 扩展 |
| 5.3 | 注意事项折叠(t-collapse):每接口的坑文档(累计值/占位值/单位换算等,文案来自 endpoints.ts) |
endpoint-info-line.vue 扩展 |
验收(硬指标):/api/log/token 真实响应(1000 条)渲染 + 全程滚动不掉帧;performance.now() 量测从「收到响应」到「首屏渲染」< 200ms。
阶段六:打磨与全量验证 ✅(已完成 2026-09-07,真机调通留待用户)
产出:README 重写(运行/使用/架构/已知边界);TODO/console.log 残留扫描零命中。 验收记录:四绿收官——type-check / lint(oxlint 0 警告 + eslint 0 错误)/ test 53 用例 / build(1.36MB JS + 449KB CSS,TDesign 全量引入的代价,单工具可接受;按需引入留作后续优化)。 待用户完成的验收:真机调通 5 接口(需真实 sk-key)+ /api/log/token 大响应性能手感(滚动帧率/首屏耗时)。
| # | 任务 | 产出 |
|---|---|---|
| 6.1 | 暗色主题细调(TDesign CSS 变量)、空 tab 引导页(t-empty)、响应区各状态视觉统一 |
UI 打磨 |
| 6.2 | 全量验证:bun run lint + bun run build(含 type-check)+ bunx vitest run |
验证记录 |
| 6.3 | 真机调通 5 接口(真实 sk-key 全链路) | 截图/记录 |
| 6.4 | README 重写(运行说明、代理配置、已知边界) | README.md |
验收:四绿(lint/type-check/build/test)+ 5 接口真机可用。
2. 风险与预案
| 风险 | 概率 | 预案 |
|---|---|---|
| 虚拟滚动行高不齐(tab/空格混排)导致窗口计算偏差 | 中 | 固定 line-height、等宽字体,行高取像素常量;超长行 overflow-x 平铺 |
TanStack Query enabled 手动触发模式与 v5 API 的契合度 |
中 | 若 enabled 模式别扭,改用 queryClient.fetchQuery 在点击处理器里显式调用(语义更直白) |
| TDesign 暗色 CSS 变量与自定义样式冲突 | 低 | 优先用 TDesign token;覆盖样式集中在 src/styles/ 单文件 |
大 JSON JSON.stringify 本身的耗时(2~4MB) |
低 | 阶段五实测;若 > 50ms 再考虑 Web Worker 切行 |
3. 里程碑与提交策略
- 每阶段一次提交(等你逐阶段验收,不擅自 commit):
阶段一+二:工程配置 + 数据层(含单测)→「bench 数据层与工程配置」阶段三+四:状态集成 + UI 骨架 →「bench UI 骨架」阶段五:虚拟滚动核心 →「bench 虚拟滚动响应区」阶段六:打磨 + 验证 →「bench 全量验证与打磨」
- 提交信息格式:
bench xxx,正文列该阶段产出与验收结果 - push 永远由你手工执行
4. 完成定义(DoD)
- 六阶段全部完成,四绿通过(真机验收两项留待用户:5 接口调通 + 大响应性能)
- 5 接口真机调通(含
/api/log/token大响应性能达标)——待用户验收 - 设计文档 §7 决策记录中 11 项决策在实现中全部落实,无偏离
- 无 TODO/FIXME 残留;无 console.log 残留
- README 反映真实运行方式