Files
waveform-analysis/SYSTEM_REFACTORING.md
李启源 ea832229da
Some checks failed
CI / verify (push) Has been cancelled
first commit
2026-07-20 10:21:30 +08:00

16 KiB
Raw Blame History

WaveformChart 按系统拆分重构完成报告

🎯 重构目标

将 WaveformChart 组件按功能系统重新组织,每个系统有独立的目录,提高代码的可维护性、可理解性和可扩展性。


完成情况

重构前的结构

src/components/
├── WaveformChart.vue              # 主容器组件 (~1143 行)
├── WaveformToolbar.vue            # 工具栏 (174 行)
├── WaveformEditor.vue             # 编辑器 (149 行)
├── WaveformTooltip.vue            # 悬浮提示 (111 行)
├── WaveformTrack.vue              # 波形轨道 (317 行)
├── WaveformAnnotationLayer.vue    # 标注层 (281 行)
├── waveform.ts                    # 类型定义
├── waveform-markup.ts             # 标注相关类型和工具
└── index.ts                       # 导出

重构后的结构

src/components/
├── WaveformChart.vue                          # 主容器组件(协调各系统)
├── index.ts                                   # 公共导出(保持向后兼容)
│
├── core/                                      # 核心系统
│   ├── constants.ts                           # 常量(颜色、边距等)
│   ├── types.ts                               # 共享类型定义
│   └── index.ts
│
├── data/                                      # 数据系统
│   ├── types.ts                               # 数据相关类型(重导出)
│   └── index.ts
│
├── rendering/                                 # 渲染系统
│   ├── WaveformTrack.vue                      # 波形轨道组件
│   └── index.ts
│
├── interaction/                               # 交互系统
│   ├── WaveformToolbar.vue                    # 工具栏组件
│   ├── WaveformTooltip.vue                    # 悬浮提示组件
│   └── index.ts
│
├── annotation/                                # 标注系统
│   ├── WaveformAnnotationLayer.vue            # 标注渲染层
│   ├── WaveformEditor.vue                     # 标注编辑器
│   ├── markup.ts                              # 标注工具函数
│   ├── types.ts                               # 标注相关类型(重导出)
│   └── index.ts
│
├── waveform.ts                                # 向后兼容(重导出)
└── waveform-markup.ts                         # 向后兼容(重导出)

📦 各系统详情

1. Core System (核心系统)

目录: src/components/core/

职责: 提供共享的类型、常量

文件:

  • constants.ts - 定义全局常量

    • channelColors - 通道颜色数组
    • margin - 图表边距
    • minimumHeight - 最小高度
  • types.ts - 核心类型定义

    • DisplaySeries - 显示系列接口
    • HoveredSeriesPoint - 悬浮点接口
    • TrackLayout - 轨道布局接口

导出: core/index.ts

export * from './constants'
export * from './types'

2. Data System (数据系统)

目录: src/components/data/

职责: 重导出数据相关类型和函数

文件:

  • types.ts - 重导出 src/types 中的所有数据类型
    • WaveformData, WaveformSeries, WaveformPoint
    • normalizeWaveformData, normalizeWaveformSeries 函数

导出: data/index.ts

export * from './types'

说明: 此系统作为桥接层,让组件内部可以通过相对路径 ../data/types 导入类型,而不是 ../../types,提高了代码的可读性。


3. Rendering System (渲染系统)

目录: src/components/rendering/

职责: 渲染波形轨道(网格、坐标轴、波形线)

文件:

  • WaveformTrack.vue - 波形轨道组件 (317 行)
    • 渲染网格(主要/次要刻度)
    • 渲染 X/Y 坐标轴(使用 D3.js
    • 渲染 Y 轴标签
    • 渲染波形线
    • 渲染十字线
    • 渲染帧编号水印
    • 独立模式下的交互覆盖层

导出: rendering/index.ts

export { default as WaveformTrack } from './WaveformTrack.vue'

4. Interaction System (交互系统)

目录: src/components/interaction/

职责: 处理用户交互(工具栏、悬浮提示)

文件:

  • WaveformToolbar.vue - 工具栏组件 (174 行)

    • 交互模式切换(缩放、选择、标注等)
    • 编辑/删除按钮
    • 快捷键支持
  • WaveformTooltip.vue - 悬浮提示组件 (111 行)

    • 显示数据点信息
    • 自动位置计算避免溢出
    • 多系列数据展示

导出: interaction/index.ts

export { default as WaveformToolbar } from './WaveformToolbar.vue'
export { default as WaveformTooltip } from './WaveformTooltip.vue'

5. Annotation System (标注系统)

目录: src/components/annotation/

职责: 管理标注和图形(创建、编辑、删除、渲染)

文件:

  • WaveformAnnotationLayer.vue - 标注渲染层 (281 行)

    • 渲染标注(箭头、文本框)
    • 渲染图形(垂直线、时间区间)
    • 渲染区间预览
    • 交互响应(选择、编辑)
  • WaveformEditor.vue - 标注编辑器 (149 行)

    • 文本输入
    • 确认/取消操作
    • 键盘快捷键
  • markup.ts - 标注工具函数

    • layoutAnnotationBox() - 标注框布局计算
    • resolveAnnotationStyle() - 标注样式解析
    • resolveShapeStyle() - 图形样式解析
    • normalizeRangeShape() - 区间标准化
    • 其他辅助函数
  • types.ts - 重导出标注相关类型

    • WaveformAnnotation, WaveformShape

导出: annotation/index.ts

export { default as WaveformAnnotationLayer } from './WaveformAnnotationLayer.vue'
export { default as WaveformEditor } from './WaveformEditor.vue'
export * from './markup'
export * from './types'

🔄 主组件更新

WaveformChart.vue 导入变化

重构前:

import WaveformToolbar from './WaveformToolbar.vue'
import WaveformEditor from './WaveformEditor.vue'
import WaveformTooltip from './WaveformTooltip.vue'
import WaveformAnnotationLayer from './WaveformAnnotationLayer.vue'
import WaveformTrack from './WaveformTrack.vue'
import { normalizeWaveformSeries, type WaveformData, ... } from './waveform'
import { layoutAnnotationBox, resolveAnnotationStyle, ... } from './waveform-markup'

const channelColors = [...]
const margin = { top: 18, right: 24, bottom: 52, left: 64 }
const minimumHeight = 180

重构后:

// 从各系统导入
import { WaveformToolbar, WaveformTooltip } from './interaction'
import { WaveformEditor, WaveformAnnotationLayer } from './annotation'
import { WaveformTrack } from './rendering'
import { normalizeWaveformSeries, type WaveformData, ... } from './data/types'
import { layoutAnnotationBox, resolveAnnotationStyle, ... } from './annotation/markup'
import { channelColors, margin as chartMargin, minimumHeight as chartMinimumHeight } from './core/constants'

// 使用导入的常量
const margin = chartMargin
const minimumHeight = chartMinimumHeight

🌉 向后兼容性

保持旧的导入路径可用

为了确保不破坏现有代码,保留了原有的导入路径:

1. waveform.ts - 向后兼容文件

// 重新导出所有类型和函数
export type { ... } from '../types'
export { normalizeWaveformData, normalizeWaveformSeries } from '../core'

2. waveform-markup.ts - 向后兼容文件

// 重新导出标注相关的所有内容
export * from './annotation/markup'
export type * from './annotation/types'

3. index.ts - 更新公共导出

export { default as WaveformChart } from './WaveformChart.vue'

// 从新路径导出类型(透明给外部使用者)
export type { ... } from './data/types'

// 可选:导出各系统的组件
export { WaveformToolbar, WaveformTooltip } from './interaction'
export { WaveformAnnotationLayer, WaveformEditor } from './annotation'
export { WaveformTrack } from './rendering'

使用示例

外部使用者(完全兼容):

// 旧的导入方式仍然有效
import { WaveformChart, type WaveformData } from '@/components'

// 新的导入方式(推荐)
import { WaveformChart } from '@/components'
import type { WaveformData } from '@/components'

// 高级用户可以直接使用子系统组件
import { WaveformToolbar, WaveformTooltip } from '@/components/interaction'
import { WaveformAnnotationLayer } from '@/components/annotation'

📊 重构收益

1. 可维护性

按系统定位代码:

  • 需要修改工具栏?→ 直接到 interaction/ 目录
  • 需要修改标注渲染?→ 直接到 annotation/ 目录
  • 需要修改轨道渲染?→ 直接到 rendering/ 目录

职责清晰:

  • 每个系统有独立的目录和明确的职责
  • 减少了跨系统的耦合
  • 降低了修改的影响范围

2. 可理解性

目录即文档:

interaction/     → 我是交互系统,负责用户交互
annotation/      → 我是标注系统,负责标注管理
rendering/       → 我是渲染系统,负责波形绘制
core/            → 我是核心系统,提供共享资源
data/            → 我是数据系统,处理数据

新人友好:

  • 从目录结构就能快速理解系统架构
  • 相关代码放在一起,容易理解上下文
  • 不需要在一个大文件中上下滚动

3. 可扩展性

添加新功能:

  • 添加新的交互模式?→ 在 interaction/ 下添加
  • 添加新的标注类型?→ 在 annotation/ 下添加
  • 添加新的渲染效果?→ 在 rendering/ 下添加

替换实现:

  • 可以替换整个系统而不影响其他部分
  • 例如:用 Canvas 替换 SVG 渲染,只需修改 rendering/ 目录

插件化潜力:

  • 各系统可以作为独立插件使用
  • 方便构建自定义版本(例如:只要渲染,不要标注)

4. 可测试性

独立测试:

// 可以单独测试各系统的组件
describe('WaveformToolbar', () => { ... })
describe('WaveformAnnotationLayer', () => { ... })
describe('WaveformTrack', () => { ... })

未来可以添加:

  • interaction/useInteraction.test.ts - 测试交互逻辑
  • annotation/useAnnotation.test.ts - 测试标注管理
  • rendering/WaveformTrack.test.ts - 测试轨道渲染

📈 代码统计

指标 数值
系统数量 5 个
Core System 3 个文件
Data System 2 个文件
Rendering System 2 个文件 (1 组件)
Interaction System 3 个文件 (2 组件)
Annotation System 5 个文件 (2 组件)
向后兼容文件 2 个 (waveform.ts, waveform-markup.ts)
总文件数 17 个

验证结果

所有检查通过

✅ TypeScript 类型检查通过
✅ ESLint 代码规范通过
✅ 所有单元测试通过 (24/24)
✅ 向后兼容性验证通过

测试详情

Test Files  1 passed (1)
     Tests  24 passed (24)
  Duration  1.74s

所有现有测试无需修改即可通过,证明重构保持了完全的向后兼容性。


🚀 后续优化建议

1. 提取组合式函数

将主组件中的逻辑提取为组合式函数:

// zoom/useZoom.ts
export function useZoom(options: ZoomOptions) {
  const sharedTransform = shallowRef<ZoomTransform>(zoomIdentity)
  const independentTransforms = shallowRef<ZoomTransform[]>([])
  // ...
  return { sharedTransform, independentTransforms, ... }
}

// interaction/useHover.ts
export function useHover(options: HoverOptions) {
  const hoveredSeriesPoints = ref<HoveredSeriesPoint[]>([])
  const hoverPosition = ref({ x: 0, y: 0 })
  // ...
  return { hoveredSeriesPoints, hoverPosition, ... }
}

// annotation/useAnnotation.ts
export function useAnnotation(options: AnnotationOptions) {
  const selection = ref<WaveformMarkupSelection>(null)
  const editingDraft = ref<EditingDraft | null>(null)
  // ...
  return { selection, editingDraft, ... }
}

然后在主组件中使用:

// WaveformChart.vue
const { sharedTransform, independentTransforms, ... } = useZoom(...)
const { hoveredSeriesPoints, hoverPosition, ... } = useHover(...)
const { selection, editingDraft, ... } = useAnnotation(...)

收益:

  • 逻辑更清晰,职责更单一
  • 易于测试(不需要挂载组件)
  • 可复用在其他组件中

2. 添加系统级文档

为每个系统添加 README.md

interaction/
├── README.md          # 交互系统说明
├── WaveformToolbar.vue
├── WaveformTooltip.vue
└── index.ts

annotation/
├── README.md          # 标注系统说明
├── WaveformAnnotationLayer.vue
├── WaveformEditor.vue
├── markup.ts
└── index.ts

3. 创建系统级测试

interaction/
├── WaveformToolbar.test.ts
├── WaveformTooltip.test.ts
└── useInteraction.test.ts

annotation/
├── WaveformAnnotationLayer.test.ts
├── WaveformEditor.test.ts
├── markup.test.ts
└── useAnnotation.test.ts

4. 进一步拆分大组件

WaveformTrack.vue (317 行) 可以拆分为:

rendering/
├── WaveformTrack.vue       # 轨道容器
├── Grid.vue                # 网格组件
├── Axis.vue                # 坐标轴组件
├── WaveformLine.vue        # 波形线组件
└── Crosshair.vue           # 十字线组件

WaveformAnnotationLayer.vue (281 行) 可以拆分为:

annotation/
├── WaveformAnnotationLayer.vue    # 标注层容器
├── AnnotationItem.vue             # 单个标注
├── ShapeItem.vue                  # 单个图形
└── RangePreview.vue               # 区间预览

🎯 重构对比

重构前

components/
├── [7 个组件文件平铺]
├── [2 个 TS 文件平铺]
└── index.ts

❌ 文件平铺,职责不清晰
❌ 难以定位相关代码
❌ 新人需要猜测文件关系

重构后

components/
├── core/          # 核心系统
├── data/          # 数据系统
├── rendering/     # 渲染系统
├── interaction/   # 交互系统
├── annotation/    # 标注系统
└── index.ts       # 统一导出

✅ 按系统组织,职责清晰
✅ 易于定位相关代码
✅ 从目录结构就能理解架构
✅ 保持向后兼容

📝 迁移指南

对外部使用者

无需任何修改!

所有原有的导入方式都保持兼容:

// ✅ 原有代码继续工作
import { WaveformChart, type WaveformData } from '@/components'

对内部开发者

推荐使用新的导入路径

// ✅ 新的推荐方式(更清晰)
import { WaveformToolbar } from './interaction'
import { WaveformAnnotationLayer } from './annotation'
import { WaveformTrack } from './rendering'
import type { WaveformData } from './data/types'
import { channelColors } from './core/constants'

添加新功能时

遵循系统划分原则

  1. 确定功能属于哪个系统
  2. 在对应系统目录下创建文件
  3. 在系统的 index.ts 中导出
  4. 在主组件中导入使用

🎉 总结

完成情况

系统拆分成功完成

  • 创建 5 个功能系统目录
  • 移动 5 个组件到对应系统
  • 提取共享常量和类型
  • 保持完全向后兼容
  • 所有测试通过

核心价值

维度 改善
可维护性 按系统组织,易于定位和修改
可理解性 目录即文档,架构清晰
可扩展性 易于添加新功能和替换实现
可测试性 系统独立,支持单独测试
向后兼容 完全兼容现有代码

项目里程碑

2026-07-17: 工具栏和编辑器组件拆分完成
2026-07-18: Tooltip、Track、AnnotationLayer 拆分完成
2026-07-18: 按系统重新组织完成 ✅

完成时间: 2026-07-18
影响范围: 重组 src/components/ 目录结构
破坏性变更: 无
向后兼容: 完全兼容
测试结果: 24/24 通过
重构方式: 渐进式、非破坏性