backup before modification at 2026-04-16-17-21-58

This commit is contained in:
2026-04-16 17:21:59 +08:00
parent a07e6e4e98
commit 506d042f7a
5 changed files with 206 additions and 9 deletions

View File

@@ -1316,18 +1316,16 @@ export default function ReportEditor() {
<div className="relative">
<img src={frame.dataUrl} className="w-full aspect-video object-cover rounded-lg" />
{frame.isManual && <span className="manual-frame-badge"></span>}
<button
onClick={(e) => { e.stopPropagation(); insertFrameToPlaceholder(frame); }}
className="absolute inset-0 m-auto w-fit h-fit px-3 py-1.5 bg-emerald-500 text-white text-[10px] font-bold rounded-full shadow-md opacity-0 group-hover:opacity-100 transition-opacity hover:bg-emerald-600"
>
</button>
</div>
<div className="text-[9px] font-bold text-text-muted mt-1.5 px-1 flex justify-between items-center">
<span>{frame.timeFormatted}</span>
<div className="flex items-center gap-2">
<button
onClick={(e) => { e.stopPropagation(); insertFrameToPlaceholder(frame); }}
className="text-accent opacity-0 group-hover:opacity-100 transition-opacity hover:underline"
>
</button>
<span className="text-accent opacity-0 group-hover:opacity-100 transition-opacity"></span>
</div>
<span className="text-accent opacity-0 group-hover:opacity-100 transition-opacity"></span>
</div>
<button
onClick={(e) => { e.stopPropagation(); setCapturedFrames(prev => prev.filter(f => f.id !== frame.id).sort((a, b) => a.time - b.time)); saveDraftToStorage(); }}

View File

@@ -0,0 +1,81 @@
# 实现方案 — 2026-04-16-17-15-37
## 技术思路
仅调整 `ReportEditor.tsx` 中关键帧卡片的 JSX 结构:将 "插入" 按钮从底部文字行移到图片层的相对定位容器中,并修改其 className 为实体按钮样式(绿色背景、白色文字、圆角、阴影)。
`insertFrameToPlaceholder` 等逻辑函数无需改动。
---
## 修改文件清单
| 文件 | 变更类型 | 说明 |
|------|----------|------|
| `src/pages/ReportEditor.tsx` | 修改 | 移动 "插入" 按钮位置、更新样式 className |
---
## 关键代码变更说明
### 当前 JSX 片段(约第 1303~1318 行)
```tsx
<div className="relative">
<img src={frame.dataUrl} className="w-full aspect-video object-cover rounded-lg" />
{frame.isManual && <span className="manual-frame-badge"></span>}
</div>
<div className="text-[9px] font-bold text-text-muted mt-1.5 px-1 flex justify-between items-center">
<span>{frame.timeFormatted}</span>
<div className="flex items-center gap-2">
<button
onClick={(e) => { e.stopPropagation(); insertFrameToPlaceholder(frame); }}
className="text-accent opacity-0 group-hover:opacity-100 transition-opacity hover:underline"
>
</button>
<span className="text-accent opacity-0 group-hover:opacity-100 transition-opacity"></span>
</div>
</div>
```
### 修改后 JSX 片段
```tsx
<div className="relative">
<img src={frame.dataUrl} className="w-full aspect-video object-cover rounded-lg" />
{frame.isManual && <span className="manual-frame-badge"></span>}
<button
onClick={(e) => { e.stopPropagation(); insertFrameToPlaceholder(frame); }}
className="absolute inset-0 m-auto w-fit h-fit px-3 py-1.5 bg-emerald-500 text-white text-[10px] font-bold rounded-full shadow-md opacity-0 group-hover:opacity-100 transition-opacity hover:bg-emerald-600"
>
</button>
</div>
<div className="text-[9px] font-bold text-text-muted mt-1.5 px-1 flex justify-between items-center">
<span>{frame.timeFormatted}</span>
<span className="text-accent opacity-0 group-hover:opacity-100 transition-opacity"></span>
</div>
```
### 样式说明
- `absolute inset-0 m-auto w-fit h-fit`:使按钮在图片容器内水平和垂直居中。
- `px-3 py-1.5`:实体按钮的内边距。
- `bg-emerald-500 text-white`:翠绿背景 + 白色文字,与 "可拖拽" 的蓝色(`text-accent`)形成明显区分。
- `rounded-full shadow-md`:圆角胶囊形状 + 轻微阴影,呈现按钮质感。
- `opacity-0 group-hover:opacity-100 transition-opacity`:保持 hover 显示/隐藏行为与 "可拖拽" 一致。
---
## 风险点及应对策略
| 风险 | 影响 | 应对策略 |
|------|------|----------|
| 按钮遮挡 "手动" 徽章 | 视觉冲突 | "手动" 徽章位于左上角,按钮位于正中央,空间不重叠 |
| 按钮点击触发卡片 onClick | 视频跳转 | 保留 `e.stopPropagation()` |
| 绝对定位在相对容器中未居中 | 偏位 | 使用 `inset-0 m-auto w-fit h-fit` 确保 Flex/Grid 内的居中 |
---
## 改动范围总结
- 仅做 JSX 结构和样式的微调整,不修改任何逻辑函数。
- 不引入新依赖。

View File

@@ -0,0 +1,73 @@
# 测试方案 — 2026-04-16-17-15-37
## 测试环境准备
1. 项目已完成上一次构建,无类型错误。
2. 使用测试账号 `admin / 123456`(超级管理员)登录系统。
3. 进入 **图文报告生成** 页面并上传视频完成抽帧,确保视频分析面板有关键帧截图。
---
## 测试项清单
### 测试项 1"插入" 按钮位于图片中央且为实体按钮样式
**测试步骤**
1. 将鼠标悬停到任意关键帧截图卡片上。
2. 观察按钮的位置、颜色、形状。
**预期结果**
- 按钮显示在图片的**正中央**。
- 按钮是**实体胶囊按钮**(带背景色、圆角、阴影),不是纯文字链接。
- 按钮颜色为**绿色系**`emerald-500`),与底部 "可拖拽" 的蓝色明显不同。
---
### 测试项 2"插入" 按钮显隐行为正确
**测试步骤**
1. 鼠标移入关键帧卡片。
2. 鼠标移出关键帧卡片。
**预期结果**
- 移入时按钮与 "可拖拽" 文字同时淡入显示。
- 移出时按钮与 "可拖拽" 文字同时淡出隐藏。
- 未悬停时图片上无遮挡文字。
---
### 测试项 3点击按钮功能保持正常
**测试步骤**
1. 鼠标悬停到关键帧卡片,点击中央的 **"插入"** 按钮。
**预期结果**
- 编辑器中第一个空置的 `image-placeholder` 被填充为该帧图片。
- 视频播放器时间不发生变化(未触发卡片跳转)。
- 若无可插入空位,弹出 `没有可插入图片的空位` 提示。
---
### 测试项 4"手动" 徽章不被遮挡
**测试步骤**
1. 查看手动截取的关键帧截图。
**预期结果**
- 左上角的 **"手动"** 徽章清晰可见,未被中央按钮遮挡。
---
### 测试项 5构建与类型检查回归
**测试步骤**
1. 在项目根目录执行:
```bash
npm run lint
npm run build
```
**预期结果**
- `npm run lint` 无 TypeScript 编译错误。
- `npm run build` 构建成功。
---
## 回归验证范围
- [ ] 拖拽插入功能未被破坏。
- [ ] 关键帧卡片的删除、视频跳转功能正常。
- [ ] 编辑器保存、打印功能正常。

View File

@@ -42,3 +42,23 @@
- 当同一交互效果(如填充占位符)需要支持多种触发方式(拖拽、按钮点击、快捷键等)时,应将核心逻辑抽离为独立函数,避免重复代码。
- 在可点击子元素上务必注意事件冒泡控制,防止触发父级不必要的副作用(如此处的视频跳转)。
- UI 提示文字(如 "插入"、"可拖拽")的显隐样式应尽量保持一致,减少用户认知成本。
---
## 记录 3关键帧 "插入" 按钮位置与样式优化
**A. 具体问题**
用户对已实现的 "插入" 按钮位置和样式提出优化:希望按钮位于图片中央、做成实体按钮样式、颜色与 "可拖拽" 的蓝色有明显区分。
**B. 产生问题原因**
初次实现时将 "插入" 按钮放在了卡片底部文字区域,采用纯文字链接样式(`text-accent`),视觉上不够醒目,且与 "可拖拽" 提示颜色重叠,辨识度低。
**C. 解决问题方案**
1. 将 "插入" 按钮从底部文字行移到图片层的 `<div className="relative">` 容器内,使用 `absolute inset-0 m-auto w-fit h-fit` 实现水平和垂直居中。
2. 将按钮样式改为实体胶囊按钮:`px-3 py-1.5 bg-emerald-500 text-white rounded-full shadow-md`hover 时加深为 `bg-emerald-600`
3. 底部文字区域只保留 `timeFormatted` 和 "可拖拽" 提示,"插入" 按钮不再与它们并列。
**D. 后续如何避免问题**
- 对于图片卡片上的核心操作按钮,优先考虑覆盖在图片中央或显著位置,比在底部小字中放置链接更符合用户直觉。
- 同一卡片上的多个 hover 提示元素应保持显隐动画一致(`opacity-0 group-hover:opacity-100 transition-opacity`),但颜色上要有区分,避免用户混淆不同功能。
- 使用 `absolute inset-0 m-auto w-fit h-fit` 是一种在 Tailwind 中不依赖 flex/grid 的居中技巧,适合在 `relative` 容器内居中不定宽高的元素。

View File

@@ -0,0 +1,25 @@
# 需求分析 — 2026-04-16-17-15-37
## 需求背景
上一个需求已为关键帧截图添加了 "插入" 按钮,但用户对当前按钮的呈现方式提出了优化诉求:按钮位置在底部文字区域不够醒目,且纯文字链接样式不够直观,蓝色与 "可拖拽" 提示颜色过于接近,辨识度不足。
## 功能目标
调整关键帧截图卡片上 "插入" 按钮的位置和样式:
1. **位置调整**:将 "插入" 按钮从卡片底部的文字区域移到**图片中央**(覆盖在图片之上)。
2. **样式调整**:改为**实体按钮样式**(带背景色、圆角、内边距、阴影),而非纯文字链接。
3. **颜色调整**:不再使用蓝色(`text-accent`),改用与 "可拖拽" 蓝色提示有**明显区分度**的颜色(如绿色系 `emerald-500`hover 时才显示在图片上方。
4. 保留原有行为:
- 鼠标未悬停时按钮不可见。
- 点击后仍按从前到后顺序自动填充第一个空置 `image-placeholder`
- 点击不触发卡片跳转到视频位置。
## 涉及页面/模块
- `src/pages/ReportEditor.tsx` —— 关键帧卡片 JSX 结构调整
## 验收标准
- [ ] "插入" 按钮位于关键帧图片的正中央。
- [ ] 按钮为实体按钮样式(圆角、背景色、阴影)。
- [ ] 按钮颜色不是蓝色,与 "可拖拽" 有明显区分。
- [ ] 鼠标悬停到卡片上时按钮淡入显示,移开时淡出隐藏。
- [ ] 点击按钮后插入逻辑正常工作。
- [ ] `npm run lint` 零错误,`npm run build` 构建通过。