This repository has been archived on 2026-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
new-api-key-bench/docs/bench实施计划.md
T
skycurtain b2e0aa4a6c docs: 接口调研与设计文档
NewAPI sk-key 接口实证调研(计费参数/接口清单/坑记录)、交互设计定稿、实施计划。数据层与应用层后续按阶段提交。
2026-09-08 00:49:12 +08:00

144 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`)
- **可用的能力**: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 8 `UserConfig` 类型不收 `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),改中文「小于」;&nbsp; 直接写模板会被 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):
1. `阶段一+二`:工程配置 + 数据层(含单测)→「bench 数据层与工程配置」
2. `阶段三+四`:状态集成 + UI 骨架 →「bench UI 骨架」
3. `阶段五`:虚拟滚动核心 →「bench 虚拟滚动响应区」
4. `阶段六`:打磨 + 验证 →「bench 全量验证与打磨」
- 提交信息格式:`bench xxx`,正文列该阶段产出与验收结果
- push 永远由你手工执行
---
## 4. 完成定义(DoD)
- [x] 六阶段全部完成,四绿通过(真机验收两项留待用户:5 接口调通 + 大响应性能)
- [ ] 5 接口真机调通(含 `/api/log/token` 大响应性能达标)——待用户验收
- [x] 设计文档 §7 决策记录中 11 项决策在实现中全部落实,无偏离
- [x] 无 TODO/FIXME 残留;无 console.log 残留
- [x] README 反映真实运行方式