Files
waveform-analysis/CODE_REVIEW_FIXES_2026-07-21.md
2026-07-21 12:09:00 +08:00

6.0 KiB
Raw Blame History

代码审查问题修复总结

本文档记录了2026-07-21高强度代码审查中发现的10个问题及其修复方案。

修复概览

  • 审查日期: 2026-07-21
  • 审查分支: feature-control
  • 基准分支: main
  • 审查强度: 高强度(召回优先)
  • 发现问题: 10个
  • 已修复: 10个
  • 测试状态: 所有测试通过 (180/180)
  • 类型检查: 通过
  • 代码规范: 通过

问题1: 移除边界检查允许标注标签渲染到可视区域外

严重程度: 🔴 已确认

文件: src/components/annotation/markup.ts:208

问题描述: 标注布局硬编码使用 placement: 'top'移除了智能placement选择逻辑。当标注靠近顶部边界时标签可能渲染到SVG视口外用户看不见。

失败场景:

顶部边界附近的标注y=0.95)→ placement='top' 无边界检查
→ box.y 变为负值 → 标签渲染到 SVG 视口上方,用户看不见

修复方案:

  1. 添加 isPlacementWithinBounds() 函数检查placement是否在边界内
  2. 添加 chooseBestPlacement() 函数尝试所有8个placement选项选择第一个完全在边界内的
  3. 更新 layoutAnnotations() 仅在没有手动偏移时使用智能placement选择

代码变更:

  • 新增 isPlacementWithinBounds() 函数
  • 新增 chooseBestPlacement() 函数
  • 修改 layoutAnnotations() 使用智能placement

问题2 & 9: 标注点使用最近采样而非插值,距离计算不匹配

严重程度: 🔴 已确认

文件: src/components/annotation/markup.ts:88-89

问题描述: findAnnotationSeriesCandidates() 计算了插值点和最近采样点,但使用插值点计算距离(用于选择系列),却返回最近采样点作为锚点。这导致:

  1. 连续数据丢失精度 - 标注跳到最近采样点而非用户点击位置
  2. 距离计算与锚点不匹配

修复方案: 统一使用插值点作为标注锚点,提供连续数据的精确定位。


问题3: 非移动拖动后设置零偏移会清除持久化偏移

严重程度: 🔴 已确认

文件: src/components/annotation/WaveformAnnotationLayer.vue:154

问题描述: 当 !state.moved 时会设置 dragOffsets.set(id, {x:0, y:0}),覆盖已有的持久化偏移,导致视觉跳动。

修复方案: 移除非移动拖动时设置零偏移的代码。


问题4: 移动标志使用 OR 赋值,防止意外微移动重置

严重程度: 🔴 已确认

文件: src/components/annotation/WaveformAnnotationLayer.vue:117

问题描述: moved 标志使用 ||= 赋值,一旦设为 true 就无法重置。微抖动后返回原位置仍会发出零增量的移动事件。

修复方案: 在 finishPointerDrag() 中根据最终位置重新计算 moved 标志。


问题5: handleSharedPointerMove 回退到 trackLayouts[0] 绕过 hasVisibleSeries 检查

严重程度: 🟡 可能存在

文件: src/components/WaveformChart.vue:1098

问题描述: 回退到 trackLayouts.value[0] 可能是隐藏的轨道,导致悬停计算错误。

修复方案: 回退到第一个可见轨道:trackLayouts.value.find((track) => track.hasVisibleSeries)


问题6: changeDraftSeries 使用 findNearestPointByX 而非 interpolateAnnotationPoint

严重程度: 🟡 可能存在

文件: src/components/WaveformChart.vue:853

问题描述: 切换标注系列时使用最近点而非插值对阶梯线会返回错误的Y值。

修复方案: 使用 interpolateAnnotationPoint() 替换 findNearestPointByX()


问题7: move 事件在父级确认标注存在之前发出

严重程度: 🟡 可能存在

文件: src/components/annotation/WaveformAnnotationLayer.vue:146

当前状态: 已有空检查处理

经检查,handleAnnotationMove 已经有空检查,无需额外修复。


问题8: endAnnotationDrag 期望可选的 cancelled 布尔值但事件签名允许 undefined

严重程度: 🟡 可能存在

文件: src/components/WaveformChart.vue:738

问题描述: 某些地方发出 drag-end 事件时不传参数。

修复方案: 在 finishPointerDrag() 中显式传递 false 参数:emit('drag-end', false)


问题10: commitHover 发出 nextPoints[0]?.point 但 hoveredPoint 使用 hoveredSeriesPoints[0]?.point

严重程度: 🟡 可能存在

文件: src/components/WaveformChart.vue:723

问题描述: 条件性更新后立即使用旧数组发出事件,可能导致竞态条件。

修复方案: 使用更新后的 hoveredSeriesPoints.value[0]?.point 发出事件。


验证结果

类型检查

✅ pnpm typecheck - 通过

单元测试

✅ pnpm test
  Test Files  12 passed (12)
  Tests      180 passed (180)

代码规范

✅ pnpm lint - 无警告

测试更新

  • markup.test.ts: 3个测试更新插值点期望
  • WaveformChart.test.ts: 2个测试更新智能placement期望

影响分析

功能影响

  1. 标注精度提升 - 使用插值点提供更精确的标注定位
  2. 布局智能化 - 自动选择最佳placement避免标签超出边界
  3. 拖动体验改进 - 修复视觉跳动和伪造的移动事件
  4. 边缘情况处理 - 修复隐藏轨道和竞态条件

兼容性

  • 破坏性变更: 标注现在使用插值点而非最近采样点
    • 迁移: 现有标注数据无需修改,只影响新创建的标注
    • 行为: 用户会注意到标注更精确地出现在点击位置

总结

本次代码审查共发现10个问题均已修复并通过测试验证。修复主要集中在

  • 正确性: 边界检查、插值一致性、状态管理
  • 用户体验: 智能placement、精确标注定位、消除视觉跳动
  • 健壮性: 边缘情况处理、竞态条件修复

所有修复都保持了向后兼容性(除了有意的行为改进),并通过完整的测试套件验证。