P1.UA21R1.F2-dock-5-meters-cleanup · 5 种 dock meter 整理 + useDockMeterFrame composable 抽离
Worker:ClaudeA · 前端 (frontend_vue3) / 预计:1.5d / 优先级:P1 / 状态:ready(blocked-by F1-R1) 隔离:🧵 文件隔离(同 worktree 同 branch · ADR-21-R1 fork 2 · 与 F4-R1/F6-R1 文件正交可并行)
🔍 触发与解锁链
| 触发 | 状态 | 影响 |
|---|---|---|
| 用户 11:21 二次澄清 | ✅ | "右侧dock主要对应xilink中的meter module 一共目前有五种,当前实现中有重复,请重新整理右侧dock,scope,fft,phase,rms,transfer" |
| ADR-21-R1 §2.2 5 种 dock meter 整理 | ✅ | 抽 useDockMeterFrame.ts composable 统一 WS 订阅 + 节点切换 + channelMask · 5 Drawer 薄壳化(只保留 chart 渲染差异) |
| F1-R1 zombie(blocked-by) | ⏳ | 等 F1-R1 提供 3 类 selector + 数据 tap 通路修复后 · 本 fork 用统一 selector 整理 5 meter |
| F2 4ed8699 控件增强保留 | ✅ | 9 控件(displayMode/peakHold/peakTrack/trigger/persistence/timePerDiv 等)不动 · 在 popup + dock 双端共享 |
→ 本 R1 hotfix 是清理重构性质 · 不引入新功能 · 只整理 5 个 Drawer 重复代码 · 抽 composable · 让代码更可维护 · 同时为 F4-R1/F6-R1 popup 与 dock 共享渲染逻辑铺路
任务定义(基于 ADR-AIOS-21-R1 §2.2)
实施 ADR-21-R1 §2.2 5 种 dock meter cleanup:
- 抽 useDockMeterFrame.ts composable:统一 WS 订阅(沿用 F1-R1 修复的数据 tap 通路)+ 节点切换(沿用 F1-R1 3 类 selector)+ channelMask 逻辑 · 让 5 个 Drawer 共用同一套数据获取代码
- 5 Drawer 薄壳化:DrawerDockFft / DrawerDockScope / DrawerDockRMS / DrawerDockPhase / DrawerDockTransfer 5 个组件只保留 chart 渲染差异(echarts 配置 / canvas 绘制逻辑)· 公共逻辑全调 useDockMeterFrame
- 零回归:F2 9 控件保留 · F1-R1 3 类 selector + 数据 tap 修复保留 · 用户实测"5 种 dock meter 都能拿到数据 + 共用 selector 行为一致"
- 不动:popup 路径(F4-R1 / F6-R1 范畴)· LinkEditor 双击协议(F4-R1 / F6-R1 范畴)· DSP 算法层(F3 / F5)· F2 控件增强代码(useFftScopeControls 在另一处 · 不动)
严守保留(零回归):F1-R1 3 类 selector / 数据 tap 通路 / F2 9 控件 / 现有 chart 渲染流水线(echarts 配置 / canvas 绘制)。
完整 prompt(直接复制粘贴 worker 终端)
[U-thread] P1.UA21R1.F2-dock-5-meters-cleanup
[部门] 前端 (frontend_vue3) · 推荐 skill: vuejs-typescript-best-practices
[Worker CWD] d:/work/25_claude/workspace/AlgoDepartment/04_development/
[Occupies] P1.K-xilink-dock(写 · 5 Drawer cleanup + composable 抽离)
[隔离] 🧵 文件隔离 · 与 F4-R1(LinkEditor 双击 + popup 新建)/ F6-R1(transfer popup)文件正交可并行 · 不动 stages/xitest/* / xitune/* / xiforge/* · 不动 dsp_algo/* · 不动 backend_csharp/*
[优先级] P1 · 1.5d · ADR-21-R1 fork 2 · cleanup 重构性质(blocked-by F1-R1)
[ADR] d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/ADR/ADR-AIOS-21-R1-dock-three-selectors-and-popup-entries.md(必读 §2.2 5 meter 整理 + §3.1-R1 ② 共用 selector + §4.2 F2-R1 行)
[业务行为契约引用] ADR-21-R1 §2.2 + 用户 11:21 verbatim "5 种 meter cleanup" + 5 dock 共用 useDockMeterFrame composable + chart 渲染差异保留
[参考文档](绝对路径)
- ADR 主文档:d:/.../docs/08-implementation/40-aios/ADR/ADR-AIOS-21-R1-dock-three-selectors-and-popup-entries.md
- 父 ADR:d:/.../docs/08-implementation/40-aios/ADR/ADR-AIOS-21-xilink-dock-and-analysis-modules.md(已 partially-superseded)
- F1-R1 标本(blocked-by):d:/.../docs/08-implementation/40-aios/prompts/active/P1.UA21R1.F1-dock-selector-3-categories-and-data-tap.md(看 3 类 selector + 数据 tap 修复 · 本 fork 沿用)
- F4 zombie 标本:d:/.../docs/08-implementation/40-aios/prompts/done/ADR-AIOS-21/P1.A21.F4-phase-module-frontend--2d5de9c.md(看 DrawerDockPhase 实装 · 本 fork 薄壳化)
- F6 zombie 标本:d:/.../docs/08-implementation/40-aios/prompts/done/ADR-AIOS-21/P1.A21.F6-transfer-module-frontend--50834d7.md(看 DrawerDockTransfer + 4 chart 实装 · 本 fork 薄壳化)
- F2 zombie 标本:d:/.../docs/08-implementation/40-aios/prompts/done/ADR-AIOS-21/P1.A21.F2-fft-scope-controls-enhance--4ed8699.md(看 9 控件 · 本 fork 不动)
- 现状必读:
· frontend_vue3/src/stages/xilink/drawers/DrawerDockFft.vue(F1+F2 落地版 · 看 WS 订阅 + chart 渲染分离点)
· frontend_vue3/src/stages/xilink/drawers/DrawerDockScope.vue(cce5670 后续 commit · 同 fft 模式)
· frontend_vue3/src/stages/xilink/drawers/DrawerDockRMS.vue(若存在 · 否则需基于范式新建占位)
· frontend_vue3/src/stages/xilink/drawers/DrawerDockPhase.vue(F4 2d5de9c 落地)
· frontend_vue3/src/stages/xilink/drawers/DrawerDockTransfer.vue(F6 50834d7 落地 · +4 chart 子组件)
· frontend_vue3/src/composables/useChainNodeMetadata.ts(F1-R1 修订后 · 节点 metadata 归并)
· frontend_vue3/src/composables/useDockChannelMask.ts(F1-R1 修订后 · channelMask 逻辑)
【背景】
用户 11:21 澄清"右侧dock主要对应xilink中的meter module 一共目前有五种,当前实现中有重复,请重新整理":
- 现状(F1+F2+F4+F6 落地后):5 个 Drawer 各自有独立 WS 订阅 + 节点切换逻辑 + channelMask 处理 → 重复代码严重
- F1-R1 已统一 selector 类目(3 类)+ 数据 tap 通路修复 · 但 5 个 Drawer 内部仍有独立订阅代码
- 本 fork 抽 useDockMeterFrame.ts composable 统一 5 Drawer 公共逻辑 · 让 5 个 Drawer 只保留 chart 渲染差异(echarts 配置 / canvas 绘制 / 三段图切换 / Smaart 4 chart 等)
- 不引入新功能 · 重构性质 · F1-R1 zombie 后启动
【执行步骤】
Step 0 · 真值核查(必跑 · 0.2d)
- git status / git pull origin xistudio --no-rebase
- git -C d:/work/25_claude/workspace/AlgoDepartment/04_development log --oneline -10
- 验 F1-R1 zombie:grep DASHBOARD §📋 P1.UA21R1.F1 行状态 · 必须 zombie + hash 已落
- read 5 个 Drawer 全文(DrawerDockFft/Scope/RMS/Phase/Transfer.vue)· 输出每个的"公共逻辑 vs chart 渲染差异"分离点:
· WS 订阅代码(useWebSocket / onMounted 调用)
· 节点切换响应(watch selectedNodeId 等)
· channelMask 应用逻辑
· chart 渲染独有部分(echarts options / canvas paintFrame / 三段图 / Smaart 4 chart 等)
- read F1-R1 修订后的 useChainNodeMetadata.ts + useDockChannelMask.ts(看 F1-R1 提供的 endpointUrl + nodeKind 接口)
- read F2 控件增强代码 useFftScopeControls(确认 cleanup 不动 9 控件)
- 输出真值核查到 commit body:
· 5 Drawer 重复代码量(行数估)
· useDockMeterFrame composable 抽离的接口签名草案(props / returns / WS 订阅 / channelMask 应用)
· 5 Drawer 薄壳化后行数估(应 ≤ 100 行 SFC · 只剩 chart 渲染)
· DrawerDockRMS 是否存在(若不存在 · 是否需要本 fork 创建占位 · 还是后续 ADR 创建)
Step 1 · 抽 useDockMeterFrame.ts composable(0.5d · 核心抽离)
- 新建 frontend_vue3/src/composables/useDockMeterFrame.ts
- 接口签名:
· `useDockMeterFrame(opts: { meterKind: 'scope'|'fft'|'rms'|'phase'|'transfer', selectedNodeId: Ref<string>, channelMask: Ref<boolean[]> }) => { frame: Ref<MeterFrame|null>, isConnected: Ref<boolean>, error: Ref<string|null> }`
- 内部实现:
· 调 useChainNodeMetadata(F1-R1 修订后)拿 endpointUrl
· 调 useWebSocket(VueUse · 已锁项目依赖)订阅 endpointUrl
· onmessage frame handler 解码 + 应用 channelMask + 更新 frame ref
· watch selectedNodeId 切换重订阅
· onUnmounted 反订阅清理
· 5s timeout fallback(沿用 F1-R1 ③ 失败回退)
- 不重复实现 F1-R1 已有的 3 类 selector / endpointUrl 模板 / 5s timeout · 直接复用
Step 2 · 5 Drawer 薄壳化(0.5d)
- 编辑 DrawerDockFft.vue(沿用 F1+F2 落地基础):
· 移除独立 WS 订阅代码
· 移除独立 channelMask 应用代码
· 改调 useDockMeterFrame · 取 frame ref → echarts options computed
· 保留 F2 9 控件接入(displayMode/peakHold/peakTrack 等 · useFftScopeControls 不动)
· 保留 echarts FFT 渲染独有部分(柱状/线/Both 切换 / peak 标注)
- 编辑 DrawerDockScope.vue:
· 同 fft 模式薄壳化
· 保留 scope 独有部分(trigger / persistence / timePerDiv canvas 渲染)
- 编辑 DrawerDockRMS.vue:
· 若不存在 · Step 0 评估后决定:① 创建空占位 SFC(等后续 ADR 落 RMS dock)② 跳过(不在本 fork 范围 · 在 commit body 备注)
· 若存在 · 同 fft 模式薄壳化 · 保留 RMS 独有部分(数字 meter UI / level dB 显示)
- 编辑 DrawerDockPhase.vue(F4 2d5de9c 落地版本):
· 移除独立 WS 订阅
· 改调 useDockMeterFrame
· 保留 phase 独有部分(三段图 wrapped/unwrapped/groupDelay 切换 + PhaseChart 子组件)
- 编辑 DrawerDockTransfer.vue(F6 50834d7 落地版本):
· 移除独立 WS 订阅(transfer 特殊:ref + measure 双 endpoint · 需 useDockMeterFrame 支持双 endpoint 模式 或 useTransferFrame 沿用 F6 现有 composable)
· 决策:若 useTransferFrame 已抽离 · 不动它(transfer 特例) · 仅薄壳化 chart 部分;否则 useDockMeterFrame 支持双 endpoint mode
· 保留 Smaart 4 chart(Mag/Phase/Coherence/Delay)+ 6 控件 UI
Step 3 · 验证 F1-R1 / F2 零回归(0.2d)
- 5 Drawer 薄壳化后 · 用户从 dock 切节点 → chart 刷新行为应与 F1-R1 zombie 后一致
- F2 9 控件(displayMode/peakHold/peakTrack/trigger/persistence/timePerDiv)在 fft/scope dock 中操作正常
- channelMask 切换正常(F1-R1 channelMask 自适应)
- 5s timeout fallback 在 mock WS 永不响应时正确触发
Step 4 · vitest 单测(0.2d)
- 新增 frontend_vue3/tests/composables/useDockMeterFrame.test.ts(≥ 5 case):
· case 1:订阅 endpointUrl 正确(对齐 F1-R1 模板)
· case 2:onmessage 解码 + 应用 channelMask 输出 frame
· case 3:watch selectedNodeId 切换重订阅(老订阅 cleanup)
· case 4:5s timeout 触发 error ref + isConnected=false
· case 5:onUnmounted 反订阅(测组件销毁)
- 新增 frontend_vue3/tests/components/dock-5-meters-shared-selector.test.ts(≥ 4 case):
· case 1:5 个 Drawer 都调用 useDockMeterFrame(grep import 验证)
· case 2:5 Drawer 切换 selector 行为一致(mount 5 Drawer · 切节点 · 验 frame ref 同步更新)
· case 3:5 Drawer 行数 ≤ 150 行 SFC(薄壳化验证)
· case 4:F2 9 控件在 fft/scope dock 仍可用(回归)
Step 5 · build + test + 手动 e2e(0.1d)
- cd frontend_vue3
- npm run typecheck(零错误)
- npm run test:unit(基线 +9 case 全绿 · 已知 3 fail 不增)
- 手动 e2e(浏览器):
· npm run dev
· 进 P1-xilink stage · 加载链路含 source + sink + log_module_v1
· 右 dock 依次加载 fft / scope / phase / transfer 4 种 meter(rms 视 Step 0 决策)
· 切 input/output/log_module 3 类节点 · 验 4 dock chart 都刷新数据
· 浏览器 devtools Network → WS 标签验帧推送(每 dock 1 connection · 共用 endpointUrl 模板)
· 测 F2 9 控件:fft 切 displayMode line/bar/both / 启 peakHold / 启 peakTrack · scope 切 trigger / persistence / timePerDiv
· 测 transfer 双 endpoint(ref + measure)· Smaart 4 chart 渲染正常
Step 6 · commit + push(0.05d)
- git add frontend_vue3/src/composables/useDockMeterFrame.ts(新建) \
frontend_vue3/src/stages/xilink/drawers/DrawerDockFft.vue \
frontend_vue3/src/stages/xilink/drawers/DrawerDockScope.vue \
frontend_vue3/src/stages/xilink/drawers/DrawerDockRMS.vue(若改) \
frontend_vue3/src/stages/xilink/drawers/DrawerDockPhase.vue \
frontend_vue3/src/stages/xilink/drawers/DrawerDockTransfer.vue \
frontend_vue3/tests/composables/useDockMeterFrame.test.ts \
frontend_vue3/tests/components/dock-5-meters-shared-selector.test.ts
- git commit subject + trailer 见下
- git push origin xistudio
- 反馈 Cline-AIOS:zombie hash + 5 Drawer 行数对比(cleanup 前 vs 后)+ useDockMeterFrame 接口截图 + 浏览器实测截图
【验收】
形式合规:
- [ ] npm run typecheck 零错误
- [ ] npm run test:unit 全绿(基线 +9 case · 已知 3 fail 不增)
- [ ] 仅修动 6-9 文件(1 新建 composable + 5 Drawer 薄壳化 + 2 tests)
- [ ] 不破坏 F1-R1 3 类 selector / 数据 tap 通路
- [ ] 不破坏 F2 9 控件
- [ ] 不动 popup 路径(F4-R1 / F6-R1 范畴)· 不动 LinkEditor 双击协议
- [ ] 不动 backend_csharp/ / dsp_algo/ / contracts/
业务行为契约(端到端真值 · 必跑):
- [ ] **5 Drawer 共用 useDockMeterFrame**:grep import 5 处全命中
- [ ] **5 Drawer 切 selector 行为一致**:input/output/log_module 切换 · 5 dock chart 都刷新
- [ ] 5 Drawer 行数大幅下降(每个 ≤ 150 行 SFC · 与 cleanup 前对比 ≥ 30% 减)
- [ ] F2 9 控件在 fft/scope dock 仍可用(回归)
- [ ] transfer 双 endpoint(ref + measure)Smaart 4 chart 正常
- [ ] 浏览器 devtools WS 帧推送 5 dock 都能拿到数据
【commit】
subject:`refactor(P1.UA21R1.F2-dock-5-meters-cleanup): 抽 useDockMeterFrame composable + 5 Drawer 薄壳化 · ADR-21-R1 §2.2`
trailer(必须精确):
[step=6/6] [pid=P1] [uid=UA21R1.F2-dock-5-meters-cleanup] [occupies=P1.K-xilink-dock]
[files=frontend_vue3/src/composables/useDockMeterFrame.ts, src/stages/xilink/drawers/DrawerDockFft.vue, DrawerDockScope.vue, DrawerDockRMS.vue, DrawerDockPhase.vue, DrawerDockTransfer.vue, tests/composables/useDockMeterFrame.test.ts, tests/components/dock-5-meters-shared-selector.test.ts]
[isolation] file(同 worktree 同 branch · 与 F4-R1/F6-R1 文件正交)
[adr] ADR-AIOS-21-R1 §2.2 + §4.2 F2-R1
[blocked_on] F1-R1 zombie(本 fork 启动前置)
[truth-check] 5 Drawer 重复代码量=<前后行数对比> · useDockMeterFrame 接口=<签名> · DrawerDockRMS 处理=<新建占位/沿用/跳过>
[acceptance] 5 Drawer 共用 composable + 切 selector 行为一致 + F2 9 控件零回归 + transfer 双 endpoint 正常
【禁止】
1. ❌ 不动 backend_csharp/ / dsp_algo/ / contracts/
2. ❌ 不动 F1-R1 3 类 selector / 数据 tap 通路代码(沿用即可 · 不重写)
3. ❌ 不动 F2 9 控件(useFftScopeControls 不重构)
4. ❌ 不动 popup 路径(F4-R1 PhaseModulePopup / F6-R1 TransferModulePopup 范畴)
5. ❌ 不动 LinkEditor.vue 双击协议(F4-R1 / F6-R1 范畴)
6. ❌ 不引入新功能 · 重构性质 · 5 Drawer chart 渲染差异保留 · 行为零变化
7. ❌ F1-R1 未 zombie 时不启动(blocked-by 严守)
8. ❌ 不在 vitest 基线引入新 fail
9. ❌ commit message 缺三元组 trailer 任一字段
解锁链(本任务 zombie 后)
- ✅ 5 种 dock meter 共用 useDockMeterFrame composable · 代码可维护性提升
- ✅ 为 F4-R1 / F6-R1 popup 与 dock 共享 chart 渲染逻辑铺路(popup 也可调 useDockMeterFrame)
- ✅ 配合 F1-R1 + F4-R1 + F6-R1 全 zombie → P_e2e.A21R1.F7 e2e ready
- 🏆 用户实测"5 种 dock meter 重复消除 + 共用 selector"
风险评估
| 风险 | 缓解 |
|---|---|
| ⚠️ DrawerDockRMS 可能不存在(F1 a5b52de 未落 · ADR-21 范围未含) | Step 0 评估后决定:① 创建空占位 SFC ② 跳过(在 commit body 备注 · 不阻塞本 fork) |
| ⚠️ DrawerDockTransfer 双 endpoint(ref + measure)与 useDockMeterFrame 单 endpoint 模型不匹配 | 决策:若 F6 已有 useTransferFrame 双 endpoint composable · 沿用不动(transfer 特例);否则 useDockMeterFrame 加 dual-endpoint mode 选项 |
| ⚠️ 薄壳化破坏现有 chart 渲染细节(eg. peakHold 跨帧状态 / persistence 余晖) | Step 4 vitest 单测覆盖 · Step 5 手动 e2e 测 F2 9 控件回归 · 不动 useFftScopeControls |
| ⚠️ blocked-by F1-R1 · F1-R1 不 zombie 本 fork 不启动 | DASHBOARD §📋 显式 blocked_on F1-R1 · 等 zombie hash 落地后用户拍板 start |
| ⚠️ 与 F4-R1 / F6-R1 同 ClaudeA worker 并行可能 git pull 冲突(同 worktree 同 branch · 文件正交但 commit 时序敏感) | 串行 commit · 先 pull 后 push · 文件正交时合并自动 |
| ⚠️ useDockMeterFrame 抽离后 typecheck 失败(类型签名错) | Step 1 接口签名对照 F1-R1 useChainNodeMetadata 输出类型 · TypeScript 类型严格 |
历史
| 时间 | 事件 | hash |
|---|---|---|
| 2026-06-15 11:30 | ADR-21-R1 v0.1 proposed · 起本 R1 hotfix(F2-R1 · ready 状态等 F1-R1 zombie 后用户 start) | — |
| (待) | F1-R1 zombie 触发解锁 | — |
| (待) | dispatched | — |
| (待) | zombie | — |