|
| 1 | +# 选集点击偏移问题的深度修复 |
| 2 | + |
| 3 | +## 问题复现 |
| 4 | + |
| 5 | +用户点击第 6 集(紫色框框),但系统选择了第 7 集(绿色填充),存在点击偏移问题。 |
| 6 | + |
| 7 | +## 深度分析与修复 |
| 8 | + |
| 9 | +### 🔍 问题根因分析 |
| 10 | + |
| 11 | +经过多轮调试,发现问题有**多个层面**: |
| 12 | + |
| 13 | +#### 1. CSS Grid 布局问题 |
| 14 | + |
| 15 | +```css |
| 16 | +/* 问题代码 */ |
| 17 | +grid-cols-[repeat(auto-fill,minmax(40px,1fr))] |
| 18 | + |
| 19 | +/* 问题分析 */ |
| 20 | +- minmax(40px,1fr) 中的 1fr 导致按钮宽度不固定 |
| 21 | +- 在不同屏幕宽度下,按钮实际宽度变化很大 |
| 22 | +- 视觉按钮位置与点击区域不匹配 |
| 23 | +``` |
| 24 | + |
| 25 | +#### 2. 事件处理逻辑问题 |
| 26 | + |
| 27 | +```javascript |
| 28 | +// 问题代码 |
| 29 | +const handleEpisodeChange = (episodeNumber: number) => { |
| 30 | + if (episodeNumber >= 0 && episodeNumber < totalEpisodes) { |
| 31 | + setCurrentEpisodeIndex(episodeNumber); // 错误! |
| 32 | + } |
| 33 | +}; |
| 34 | + |
| 35 | +// 问题分析 |
| 36 | +- EpisodeSelector传递的是显示集数(1-based): 1, 2, 3, 4, 5, 6, 7... |
| 37 | +- 但直接设置为currentEpisodeIndex(0-based): 0, 1, 2, 3, 4, 5, 6... |
| 38 | +- 导致点击第6集实际设置为index=6,对应第7集 |
| 39 | +``` |
| 40 | + |
| 41 | +#### 3. 可能的覆盖层问题 |
| 42 | + |
| 43 | +- SkipController 的固定定位面板可能覆盖选集区域 |
| 44 | +- 已移动到左下角,但可能不彻底 |
| 45 | + |
| 46 | +### 🔧 完整修复方案 |
| 47 | + |
| 48 | +#### 修复 1: CSS 布局优化 |
| 49 | + |
| 50 | +```tsx |
| 51 | +// 修复前 |
| 52 | +<div className='grid grid-cols-[repeat(auto-fill,minmax(40px,1fr))] auto-rows-[40px] gap-x-3 gap-y-3'> |
| 53 | + |
| 54 | +// 修复后 |
| 55 | +<div className='grid grid-cols-[repeat(auto-fill,48px)] justify-center gap-3'> |
| 56 | +``` |
| 57 | + |
| 58 | +**效果**: |
| 59 | + |
| 60 | +- 每个按钮固定 48px 宽度 |
| 61 | +- 使用 justify-center 居中对齐 |
| 62 | +- 消除弹性宽度导致的位置偏移 |
| 63 | + |
| 64 | +#### 修复 2: 事件处理修正 |
| 65 | + |
| 66 | +```tsx |
| 67 | +// 修复前 |
| 68 | +const handleEpisodeChange = (episodeNumber: number) => { |
| 69 | + if (episodeNumber >= 0 && episodeNumber < totalEpisodes) { |
| 70 | + setCurrentEpisodeIndex(episodeNumber); // 直接使用显示集数作为索引 |
| 71 | + } |
| 72 | +}; |
| 73 | + |
| 74 | +// 修复后 |
| 75 | +const handleEpisodeChange = (episodeNumber: number) => { |
| 76 | + const episodeIndex = episodeNumber - 1; // 转换:显示集数 -> 数组索引 |
| 77 | + if (episodeIndex >= 0 && episodeIndex < totalEpisodes) { |
| 78 | + setCurrentEpisodeIndex(episodeIndex); |
| 79 | + } |
| 80 | +}; |
| 81 | +``` |
| 82 | + |
| 83 | +**效果**: |
| 84 | + |
| 85 | +- 正确处理集数显示值到数组索引的转换 |
| 86 | +- 点击第 6 集 → episodeNumber=6 → episodeIndex=5 → 正确选择第 6 集 |
| 87 | + |
| 88 | +#### 修复 3: 增强事件控制 |
| 89 | + |
| 90 | +```tsx |
| 91 | +// 添加更强的事件控制 |
| 92 | +onClick={(e) => { |
| 93 | + e.preventDefault(); |
| 94 | + e.stopPropagation(); |
| 95 | + handleEpisodeClick(episodeNumber); |
| 96 | +}} |
| 97 | +``` |
| 98 | + |
| 99 | +### 🎯 修复验证 |
| 100 | + |
| 101 | +#### 数据流验证 |
| 102 | + |
| 103 | +1. **用户点击第 6 集按钮** |
| 104 | +2. **EpisodeSelector.tsx**: `handleEpisodeClick(6)` → `onChange(6)` |
| 105 | +3. **play/page.tsx**: `handleEpisodeChange(6)` → `episodeIndex = 6-1 = 5` |
| 106 | +4. **状态更新**: `setCurrentEpisodeIndex(5)` → 选中第 6 集(index=5) |
| 107 | +5. **UI 更新**: `value={currentEpisodeIndex + 1} = 5+1 = 6` → 第 6 集高亮 |
| 108 | + |
| 109 | +#### 布局验证 |
| 110 | + |
| 111 | +- 固定 48px 宽度确保按钮大小一致 |
| 112 | +- justify-center 确保居中对齐 |
| 113 | +- gap-3 提供合适的间距 |
| 114 | + |
| 115 | +### 📁 修改文件 |
| 116 | + |
| 117 | +1. **src/components/EpisodeSelector.tsx** |
| 118 | + |
| 119 | + - 修复 CSS Grid 布局:固定按钮宽度 |
| 120 | + - 增强点击事件处理 |
| 121 | + |
| 122 | +2. **src/app/play/page.tsx** |
| 123 | + |
| 124 | + - 修复 handleEpisodeChange 逻辑错误 |
| 125 | + - 正确处理显示集数到索引的转换 |
| 126 | + |
| 127 | +3. **src/components/SkipController.tsx** |
| 128 | + - 移动固定面板位置(之前已修复) |
| 129 | + |
| 130 | +### 🚀 预期效果 |
| 131 | + |
| 132 | +修复后的行为: |
| 133 | + |
| 134 | +- ✅ 点击第 1 集 → 选择第 1 集 |
| 135 | +- ✅ 点击第 6 集 → 选择第 6 集 |
| 136 | +- ✅ 点击第 7 集 → 选择第 7 集 |
| 137 | +- ✅ 按钮布局美观,宽度一致 |
| 138 | +- ✅ 不受屏幕宽度影响 |
| 139 | + |
| 140 | +### 💡 经验总结 |
| 141 | + |
| 142 | +1. **UI 显示值 vs 数据索引**:要区分用户看到的值(1-based)和内部索引(0-based) |
| 143 | +2. **CSS 弹性布局**:在需要精确点击的场景下,避免使用 1fr 等弹性单位 |
| 144 | +3. **多层问题**:复杂 bug 可能有多个层面的原因,需要逐层排查 |
| 145 | +4. **事件处理**:添加 preventDefault 和 stopPropagation 增强控制 |
| 146 | + |
| 147 | +这次修复解决了根本问题,确保点击精确性和用户体验。 |
0 commit comments