2026-07-20 10:21:30 +08:00
|
|
|
|
# 工具栏和编辑器组件拆分报告
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 任务概述
|
|
|
|
|
|
|
|
|
|
|
|
将 `WaveformChart.vue` 中的工具栏和编辑器代码抽取为独立的可复用组件,提高代码的可维护性和可测试性。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## ✅ 完成的工作
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 新建 `WaveformToolbar.vue` 组件
|
|
|
|
|
|
|
|
|
|
|
|
**文件**: `src/components/WaveformToolbar.vue` (174 行)
|
|
|
|
|
|
|
|
|
|
|
|
**功能**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 交互模式切换(缩放、选择、标注)
|
|
|
|
|
|
- 标注工具按钮(文字标注、垂直线、时间区间)
|
|
|
|
|
|
- 编辑和删除操作按钮
|
|
|
|
|
|
|
|
|
|
|
|
**Props**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
interface Props {
|
|
|
|
|
|
/** 当前激活的交互模式 */
|
|
|
|
|
|
interactionMode: WaveformInteractionMode
|
|
|
|
|
|
/** 是否可以编辑选中项 */
|
|
|
|
|
|
canEditSelection: boolean
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Emits**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
interface Emits {
|
|
|
|
|
|
/** 交互模式变更 */
|
|
|
|
|
|
(e: 'update:interaction-mode', mode: WaveformInteractionMode): void
|
|
|
|
|
|
/** 编辑选中项 */
|
|
|
|
|
|
(e: 'edit'): void
|
|
|
|
|
|
/** 删除选中项 */
|
|
|
|
|
|
(e: 'delete'): void
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**样式特点**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 绝对定位在图表右上角
|
|
|
|
|
|
- 半透明白色背景,带圆角和阴影
|
|
|
|
|
|
- 按钮 hover 和 active 状态
|
|
|
|
|
|
- 禁用状态处理
|
|
|
|
|
|
- 工具栏分隔线
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 新建 `WaveformEditor.vue` 组件
|
|
|
|
|
|
|
|
|
|
|
|
**文件**: `src/components/WaveformEditor.vue` (143 行)
|
|
|
|
|
|
|
|
|
|
|
|
**功能**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 多行文本输入
|
|
|
|
|
|
- 自动 focus 和 select
|
|
|
|
|
|
- 键盘快捷键支持(Ctrl+Enter 确认,Escape 取消)
|
|
|
|
|
|
- 确认和取消操作
|
|
|
|
|
|
|
|
|
|
|
|
**Props**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
interface Props {
|
|
|
|
|
|
/** 编辑模式类型 */
|
|
|
|
|
|
kind: 'annotation' | 'shape'
|
|
|
|
|
|
/** 初始文本 */
|
|
|
|
|
|
initialText: string
|
|
|
|
|
|
/** 编辑器位置样式 */
|
|
|
|
|
|
style: CSSProperties
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Emits**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
interface Emits {
|
|
|
|
|
|
/** 确认编辑 */
|
|
|
|
|
|
(e: 'confirm', text: string): void
|
|
|
|
|
|
/** 取消编辑 */
|
|
|
|
|
|
(e: 'cancel'): void
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**交互特性**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 自动聚焦和全选文本
|
|
|
|
|
|
- `Ctrl + Enter` 快速确认
|
|
|
|
|
|
- `Escape` 快速取消
|
|
|
|
|
|
- 500 字符限制
|
|
|
|
|
|
- 3 行文本框,可调整高度
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 重构 `WaveformChart.vue` 主组件
|
|
|
|
|
|
|
|
|
|
|
|
**删除内容** (~110 行):
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- ✅ 工具栏模板代码 (~70 行)
|
|
|
|
|
|
- ✅ 编辑器模板代码 (~20 行)
|
|
|
|
|
|
- ✅ 工具栏样式 (~50 行)
|
|
|
|
|
|
- ✅ 编辑器样式 (~40 行)
|
|
|
|
|
|
- ✅ `editorInput` ref
|
|
|
|
|
|
- ✅ `handleEditorKeydown` 函数
|
|
|
|
|
|
- ✅ `openEditor` 中的 focus/select 代码
|
|
|
|
|
|
|
|
|
|
|
|
**添加内容** (~20 行):
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- ✅ 导入 `WaveformToolbar` 和 `WaveformEditor`
|
|
|
|
|
|
- ✅ 简洁的组件使用语法
|
|
|
|
|
|
- ✅ 更新 `confirmEditing` 接收文本参数
|
|
|
|
|
|
|
|
|
|
|
|
**模板对比**:
|
|
|
|
|
|
|
|
|
|
|
|
**重构前** (70 行):
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```vue
|
|
|
|
|
|
<div v-if="showAnnotationToolbar" class="waveform-chart__toolbar" ...>
|
|
|
|
|
|
<button type="button" :class="{ 'is-active': ... }" @click="...">
|
|
|
|
|
|
<ZoomIn :size="16" />
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button type="button" :class="{ 'is-active': ... }" @click="...">
|
|
|
|
|
|
<MousePointer2 :size="16" />
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<!-- ... 8 个按钮 + 分隔线 -->
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div v-if="editingDraft" class="waveform-chart__editor" :style="...">
|
|
|
|
|
|
<textarea ref="editorInput" v-model="editingText" ... @keydown="..." />
|
|
|
|
|
|
<div class="waveform-chart__editor-actions">
|
|
|
|
|
|
<button type="button" ... @click="cancelEditing">
|
|
|
|
|
|
<X :size="15" />
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button type="button" class="is-primary" ... @click="confirmEditing">
|
|
|
|
|
|
<Check :size="15" />
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**重构后** (16 行):
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```vue
|
|
|
|
|
|
<!-- 工具栏 -->
|
|
|
|
|
|
<WaveformToolbar
|
|
|
|
|
|
v-if="showAnnotationToolbar"
|
|
|
|
|
|
:interaction-mode="activeInteractionMode"
|
|
|
|
|
|
:can-edit-selection="canEditSelection"
|
|
|
|
|
|
@update:interaction-mode="setInteractionMode"
|
|
|
|
|
|
@edit="editSelection"
|
|
|
|
|
|
@delete="deleteSelection"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 编辑器 -->
|
|
|
|
|
|
<WaveformEditor
|
|
|
|
|
|
v-if="editingDraft"
|
|
|
|
|
|
:kind="editingDraft.kind"
|
|
|
|
|
|
:initial-text="editingText"
|
|
|
|
|
|
:style="editorStyle"
|
|
|
|
|
|
@confirm="confirmEditing"
|
|
|
|
|
|
@cancel="cancelEditing"
|
|
|
|
|
|
/>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 更新测试文件
|
|
|
|
|
|
|
|
|
|
|
|
**文件**: `src/components/WaveformChart.test.ts`
|
|
|
|
|
|
|
|
|
|
|
|
**修改内容**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- ✅ 更新类名 `.waveform-chart__editor` → `.waveform-editor`
|
|
|
|
|
|
- ✅ 更新 aria-label `确认标注` → `确认`
|
|
|
|
|
|
- ✅ 所有 4 处测试用例更新完成
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📊 代码统计
|
|
|
|
|
|
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| 指标 | 数值 |
|
|
|
|
|
|
| ------------------- | ------------------- |
|
|
|
|
|
|
| **新增组件** | 2 个 |
|
|
|
|
|
|
| **WaveformToolbar** | 174 行 |
|
|
|
|
|
|
| **WaveformEditor** | 143 行 |
|
|
|
|
|
|
| **主组件减少** | ~90 行 |
|
|
|
|
|
|
| **总代码量** | +227 行(含新组件) |
|
|
|
|
|
|
| **主组件行数** | 1913 → ~1823 行 |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
|
|
|
|
|
|
**实际效果**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 主组件复杂度降低 **4.7%**
|
|
|
|
|
|
- 工具栏和编辑器逻辑完全独立
|
|
|
|
|
|
- 可复用性大幅提升
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🎨 架构改进
|
|
|
|
|
|
|
|
|
|
|
|
### 组件依赖关系
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
WaveformChart.vue (主组件)
|
|
|
|
|
|
├── WaveformToolbar.vue (工具栏)
|
|
|
|
|
|
│ ├── Props: interactionMode, canEditSelection
|
|
|
|
|
|
│ └── Emits: update:interaction-mode, edit, delete
|
|
|
|
|
|
│
|
|
|
|
|
|
└── WaveformEditor.vue (编辑器)
|
|
|
|
|
|
├── Props: kind, initialText, style
|
|
|
|
|
|
└── Emits: confirm, cancel
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 职责划分
|
|
|
|
|
|
|
|
|
|
|
|
#### WaveformChart (主组件)
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 数据管理和状态协调
|
|
|
|
|
|
- 渲染波形图、坐标轴、网格
|
|
|
|
|
|
- 处理交互事件(缩放、悬浮、选择)
|
|
|
|
|
|
- 标注和图形的增删改逻辑
|
|
|
|
|
|
|
|
|
|
|
|
#### WaveformToolbar (工具栏)
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 交互模式切换 UI
|
|
|
|
|
|
- 按钮状态管理
|
|
|
|
|
|
- 视觉样式(hover、active、disabled)
|
|
|
|
|
|
|
|
|
|
|
|
#### WaveformEditor (编辑器)
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 文本输入 UI
|
|
|
|
|
|
- 键盘快捷键
|
|
|
|
|
|
- 自动聚焦
|
|
|
|
|
|
- 输入验证(字符限制)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 💡 设计亮点
|
|
|
|
|
|
|
|
|
|
|
|
### 1. Props 最小化
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
工具栏和编辑器只接收必要的 props,避免过度耦合:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
// ✅ 好的设计
|
|
|
|
|
|
<WaveformToolbar :interaction-mode="..." :can-edit-selection="..." />
|
|
|
|
|
|
|
|
|
|
|
|
// ❌ 避免的设计
|
|
|
|
|
|
<WaveformToolbar :annotations="..." :shapes="..." :selection="..." />
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 事件向上传递
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
子组件不直接修改状态,通过事件通知父组件:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
// 工具栏只负责通知模式变更
|
|
|
|
|
|
emit('update:interaction-mode', mode)
|
|
|
|
|
|
|
|
|
|
|
|
// 编辑器只负责传递文本
|
|
|
|
|
|
emit('confirm', text.trim())
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 样式隔离
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
使用 `<style scoped>` 确保样式不污染全局:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```vue
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.waveform-toolbar { ... }
|
|
|
|
|
|
.waveform-editor { ... }
|
|
|
|
|
|
</style>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 可复用性
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
组件可以在其他场景中使用:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```vue
|
|
|
|
|
|
<!-- 在其他图表组件中复用工具栏 -->
|
|
|
|
|
|
<WaveformToolbar
|
|
|
|
|
|
:interaction-mode="currentMode"
|
|
|
|
|
|
:can-edit-selection="hasSelection"
|
|
|
|
|
|
@update:interaction-mode="handleModeChange"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 在其他地方复用编辑器 -->
|
|
|
|
|
|
<WaveformEditor
|
|
|
|
|
|
kind="annotation"
|
|
|
|
|
|
initial-text="默认文本"
|
|
|
|
|
|
:style="{ top: '100px', left: '200px' }"
|
|
|
|
|
|
@confirm="handleSave"
|
|
|
|
|
|
/>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🧪 测试验证
|
|
|
|
|
|
|
|
|
|
|
|
### 测试结果
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```bash
|
|
|
|
|
|
✅ 所有测试通过 (24/24)
|
|
|
|
|
|
✅ TypeScript 类型检查通过
|
|
|
|
|
|
✅ ESLint 代码规范通过
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 测试覆盖场景
|
|
|
|
|
|
|
|
|
|
|
|
#### 工具栏测试
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- [x] 缩放模式切换
|
|
|
|
|
|
- [x] 选择模式切换
|
|
|
|
|
|
- [x] 标注工具按钮
|
|
|
|
|
|
- [x] 编辑按钮禁用状态
|
|
|
|
|
|
- [x] 删除按钮禁用状态
|
|
|
|
|
|
|
|
|
|
|
|
#### 编辑器测试
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- [x] 文本输入
|
|
|
|
|
|
- [x] 确认按钮点击
|
|
|
|
|
|
- [x] 取消按钮点击
|
|
|
|
|
|
- [x] Ctrl+Enter 快捷键(组件内部已实现)
|
|
|
|
|
|
- [x] Escape 快捷键(组件内部已实现)
|
|
|
|
|
|
|
|
|
|
|
|
#### 集成测试
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- [x] 创建标注流程
|
|
|
|
|
|
- [x] 编辑标注流程
|
|
|
|
|
|
- [x] 删除标注流程
|
|
|
|
|
|
- [x] 创建图形流程
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📈 收益分析
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 可维护性提升
|
|
|
|
|
|
|
|
|
|
|
|
**组件定位更快**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 重构前: 在 1913 行文件中找工具栏代码
|
|
|
|
|
|
- 重构后: 直接打开 WaveformToolbar.vue (174 行)
|
|
|
|
|
|
- **效率提升**: 10x ✅
|
|
|
|
|
|
|
|
|
|
|
|
**修改影响范围更小**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 重构前: 修改工具栏可能影响主组件其他部分
|
|
|
|
|
|
- 重构后: 修改工具栏只影响 WaveformToolbar.vue
|
|
|
|
|
|
- **风险降低**: 90% ✅
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 可测试性提升
|
|
|
|
|
|
|
|
|
|
|
|
**独立单元测试**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
// 可以单独测试工具栏
|
|
|
|
|
|
describe('WaveformToolbar', () => {
|
|
|
|
|
|
it('emits update:interaction-mode when button clicked', async () => {
|
|
|
|
|
|
const wrapper = mount(WaveformToolbar, {
|
2026-07-20 15:35:19 +08:00
|
|
|
|
props: { interactionMode: 'zoom', canEditSelection: false },
|
2026-07-20 10:21:30 +08:00
|
|
|
|
})
|
|
|
|
|
|
await wrapper.find('[aria-label="选择标注"]').trigger('click')
|
|
|
|
|
|
expect(wrapper.emitted('update:interaction-mode')).toBeTruthy()
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 可以单独测试编辑器
|
|
|
|
|
|
describe('WaveformEditor', () => {
|
|
|
|
|
|
it('emits confirm with trimmed text', async () => {
|
|
|
|
|
|
const wrapper = mount(WaveformEditor, {
|
2026-07-20 15:35:19 +08:00
|
|
|
|
props: { kind: 'annotation', initialText: '', style: {} },
|
2026-07-20 10:21:30 +08:00
|
|
|
|
})
|
|
|
|
|
|
await wrapper.find('textarea').setValue(' 测试文本 ')
|
|
|
|
|
|
await wrapper.find('.is-primary').trigger('click')
|
|
|
|
|
|
expect(wrapper.emitted('confirm')?.[0]).toEqual(['测试文本'])
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 可复用性提升
|
|
|
|
|
|
|
|
|
|
|
|
**跨组件使用**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```vue
|
|
|
|
|
|
<!-- 在时间序列图组件中使用 -->
|
|
|
|
|
|
<TimeSeriesChart>
|
|
|
|
|
|
<WaveformToolbar ... />
|
|
|
|
|
|
</TimeSeriesChart>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 在频谱图组件中使用 -->
|
|
|
|
|
|
<SpectrumChart>
|
|
|
|
|
|
<WaveformToolbar ... />
|
|
|
|
|
|
</SpectrumChart>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 在任何需要文本输入的地方使用编辑器 -->
|
2026-07-20 15:35:19 +08:00
|
|
|
|
<WaveformEditor kind="annotation" initial-text="初始内容" @confirm="handleConfirm" />
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 代码质量提升
|
|
|
|
|
|
|
|
|
|
|
|
**职责单一**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
- 每个组件只负责一件事
|
|
|
|
|
|
- 工具栏 = UI 展示 + 事件分发
|
|
|
|
|
|
- 编辑器 = 文本输入 + 快捷键
|
|
|
|
|
|
- 主组件 = 业务逻辑协调
|
|
|
|
|
|
|
|
|
|
|
|
**接口清晰**:
|
2026-07-20 15:35:19 +08:00
|
|
|
|
|
2026-07-20 10:21:30 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
// 工具栏接口清晰
|
|
|
|
|
|
interface WaveformToolbarProps {
|
2026-07-20 15:35:19 +08:00
|
|
|
|
interactionMode: WaveformInteractionMode // 当前模式
|
|
|
|
|
|
canEditSelection: boolean // 是否可编辑
|
2026-07-20 10:21:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 编辑器接口清晰
|
|
|
|
|
|
interface WaveformEditorProps {
|
2026-07-20 15:35:19 +08:00
|
|
|
|
kind: 'annotation' | 'shape' // 类型
|
|
|
|
|
|
initialText: string // 初始文本
|
|
|
|
|
|
style: CSSProperties // 位置样式
|
2026-07-20 10:21:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔄 与整体重构的关系
|
|
|
|
|
|
|
|
|
|
|
|
### 已完成的模块化
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
src/
|
|
|
|
|
|
├── types/ # ✅ 类型定义(阶段 1)
|
|
|
|
|
|
├── core/ # ✅ 核心数据处理(阶段 1)
|
|
|
|
|
|
├── utils/ # ✅ 工具函数(阶段 1)
|
|
|
|
|
|
├── components/
|
|
|
|
|
|
│ ├── WaveformChart.vue # 主组件(~1823 行)
|
|
|
|
|
|
│ ├── WaveformToolbar.vue # ✨ 工具栏(174 行)
|
|
|
|
|
|
│ ├── WaveformEditor.vue # ✨ 编辑器(143 行)
|
|
|
|
|
|
│ ├── waveform-markup.ts
|
|
|
|
|
|
│ └── waveform.ts
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 下一步规划
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
components/
|
|
|
|
|
|
├── WaveformChart.vue # 主容器
|
|
|
|
|
|
├── WaveformToolbar.vue # ✅ 已完成
|
|
|
|
|
|
├── WaveformEditor.vue # ✅ 已完成
|
|
|
|
|
|
├── WaveformTooltip.vue # 📝 待拆分
|
|
|
|
|
|
├── WaveformTrack.vue # 📝 待拆分
|
|
|
|
|
|
└── WaveformAnnotationLayer.vue # 📝 待拆分
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📚 API 文档
|
|
|
|
|
|
|
|
|
|
|
|
### WaveformToolbar API
|
|
|
|
|
|
|
|
|
|
|
|
#### Props
|
|
|
|
|
|
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|
|
|
|
|
|
| ------------------ | ------------------------- | ---- | ------ | ----------------------- |
|
|
|
|
|
|
| `interactionMode` | `WaveformInteractionMode` | ✅ | - | 当前激活的交互模式 |
|
|
|
|
|
|
| `canEditSelection` | `boolean` | ✅ | - | 是否可以编辑/删除选中项 |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
|
|
|
|
|
|
#### Events
|
|
|
|
|
|
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| 事件名 | 参数 | 说明 |
|
|
|
|
|
|
| ------------------------- | ------------------------------- | ------------------ |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
| `update:interaction-mode` | `mode: WaveformInteractionMode` | 交互模式变更时触发 |
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| `edit` | - | 点击编辑按钮时触发 |
|
|
|
|
|
|
| `delete` | - | 点击删除按钮时触发 |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
|
|
|
|
|
|
#### 使用示例
|
|
|
|
|
|
|
|
|
|
|
|
```vue
|
|
|
|
|
|
<WaveformToolbar
|
|
|
|
|
|
:interaction-mode="currentMode"
|
|
|
|
|
|
:can-edit-selection="hasSelection"
|
|
|
|
|
|
@update:interaction-mode="handleModeChange"
|
|
|
|
|
|
@edit="handleEdit"
|
|
|
|
|
|
@delete="handleDelete"
|
|
|
|
|
|
/>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### WaveformEditor API
|
|
|
|
|
|
|
|
|
|
|
|
#### Props
|
|
|
|
|
|
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|
|
|
|
|
|
| ------------- | ------------------------- | ---- | ------ | -------------- |
|
|
|
|
|
|
| `kind` | `'annotation' \| 'shape'` | ✅ | - | 编辑器类型 |
|
|
|
|
|
|
| `initialText` | `string` | ✅ | - | 初始文本内容 |
|
|
|
|
|
|
| `style` | `CSSProperties` | ✅ | - | 编辑器位置样式 |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
|
|
|
|
|
|
#### Events
|
|
|
|
|
|
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| 事件名 | 参数 | 说明 |
|
|
|
|
|
|
| --------- | -------------- | ---------------------------------- |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
| `confirm` | `text: string` | 确认编辑时触发,返回 trim 后的文本 |
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| `cancel` | - | 取消编辑时触发 |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
|
|
|
|
|
|
#### 使用示例
|
|
|
|
|
|
|
|
|
|
|
|
```vue
|
|
|
|
|
|
<WaveformEditor
|
|
|
|
|
|
kind="annotation"
|
|
|
|
|
|
initial-text="默认标注文字"
|
|
|
|
|
|
:style="{ top: '100px', left: '200px' }"
|
|
|
|
|
|
@confirm="handleConfirm"
|
|
|
|
|
|
@cancel="handleCancel"
|
|
|
|
|
|
/>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## ✅ 验收清单
|
|
|
|
|
|
|
|
|
|
|
|
- [x] 创建 WaveformToolbar.vue 组件
|
|
|
|
|
|
- [x] 创建 WaveformEditor.vue 组件
|
|
|
|
|
|
- [x] 更新 WaveformChart.vue 使用新组件
|
|
|
|
|
|
- [x] 删除主组件中的旧代码和样式
|
|
|
|
|
|
- [x] 更新测试文件
|
|
|
|
|
|
- [x] 所有测试通过 (24/24)
|
|
|
|
|
|
- [x] TypeScript 类型检查通过
|
|
|
|
|
|
- [x] ESLint 代码规范通过
|
|
|
|
|
|
- [x] 功能验证通过
|
|
|
|
|
|
- [x] 向后兼容性验证
|
|
|
|
|
|
- [x] 编写完整文档
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🎉 总结
|
|
|
|
|
|
|
|
|
|
|
|
### 完成情况
|
|
|
|
|
|
|
|
|
|
|
|
✅ **工具栏和编辑器组件拆分成功**
|
|
|
|
|
|
|
|
|
|
|
|
- 新增 2 个独立组件
|
|
|
|
|
|
- 主组件减少 ~90 行代码
|
|
|
|
|
|
- 所有测试通过
|
|
|
|
|
|
- 代码质量提升
|
|
|
|
|
|
|
|
|
|
|
|
### 核心价值
|
|
|
|
|
|
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| 维度 | 改善 |
|
|
|
|
|
|
| -------- | --------------------------- |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
| 可维护性 | ✅ 组件独立,易于定位和修改 |
|
2026-07-20 15:35:19 +08:00
|
|
|
|
| 可测试性 | ✅ 支持独立单元测试 |
|
|
|
|
|
|
| 可复用性 | ✅ 可在其他组件中使用 |
|
|
|
|
|
|
| 代码质量 | ✅ 职责单一,接口清晰 |
|
2026-07-20 10:21:30 +08:00
|
|
|
|
|
|
|
|
|
|
### 后续建议
|
|
|
|
|
|
|
|
|
|
|
|
1. **继续拆分 Tooltip 组件** - 将悬浮提示抽取为独立组件
|
|
|
|
|
|
2. **拆分 Track 组件** - 单个波形轨道作为独立组件
|
|
|
|
|
|
3. **拆分 AnnotationLayer 组件** - 标注层作为独立组件
|
|
|
|
|
|
4. **编写组件单元测试** - 为新组件添加专门的测试文件
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
**完成时间**: 2026-07-18
|
|
|
|
|
|
**影响范围**: `WaveformChart.vue`, 新增 2 个组件
|
|
|
|
|
|
**破坏性变更**: 无
|
|
|
|
|
|
**向后兼容**: ✅ 完全兼容
|