3.5 KiB
3.5 KiB
实现方案 — 2026-04-16-17-07-04
技术思路
在 ReportEditor.tsx 中为关键帧卡片新增一个 "插入" 按钮,点击后自动将当前帧图片填充到编辑器中第一个空置的 .image-placeholder 中。
为保持代码整洁,将现有 handleDrop 中的占位符填充逻辑抽取为可复用的 fillPlaceholder 函数,供拖拽放下和按钮点击共同调用。
修改文件清单
| 文件 | 变更类型 | 说明 |
|---|---|---|
src/pages/ReportEditor.tsx |
修改 | 新增 fillPlaceholder 函数、新增 insertFrameToPlaceholder 函数、修改关键帧卡片 JSX |
关键代码变更说明
1. 抽取公共填充函数 fillPlaceholder
将 handleDrop 中的图片填充逻辑抽离:
const fillPlaceholder = (placeholder: HTMLElement, frame: CapturedFrame) => {
placeholder.innerHTML = `
<span class="delete-btn" contenteditable="false">×</span>
<img src="${frame.dataUrl}" style="max-width: 100%; height: auto; display: block; margin: 0 auto;" draggable="false">
`;
placeholder.classList.add('has-image');
if (editorRef.current) contentRef.current = editorRef.current.innerHTML;
saveDraftToStorage();
};
并同步简化 handleDrop:
const handleDrop = (e: React.DragEvent, placeholder: HTMLElement) => {
e.preventDefault();
const frameId = e.dataTransfer.getData('frameId');
const frame = capturedFrames.find(f => f.id.toString() === frameId);
if (frame) {
fillPlaceholder(placeholder, frame);
}
};
2. 新增一键插入函数 insertFrameToPlaceholder
const insertFrameToPlaceholder = (frame: CapturedFrame) => {
if (!editorRef.current) {
alert('编辑器未准备好');
return;
}
const emptyPlaceholder = editorRef.current.querySelector('.image-placeholder:not(.has-image)') as HTMLElement | null;
if (!emptyPlaceholder) {
alert('没有可插入图片的空位');
return;
}
fillPlaceholder(emptyPlaceholder, frame);
};
3. 在关键帧卡片底部添加 "插入" 按钮
修改现有 JSX(约第 1303 行附近),在 timeFormatted 与 "可拖拽" 之间插入按钮:
<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>
按钮使用 opacity-0 group-hover:opacity-100 transition-opacity,与 "可拖拽" 显隐行为完全一致。e.stopPropagation() 避免触发卡片的 onClick(即跳转到视频位置)。
风险点及应对策略
| 风险 | 影响 | 应对策略 |
|---|---|---|
editorRef.current 为空时点击插入 |
JS 报错 | 函数开头增加判空并 alert 提示 |
| 没有空占位符时点击插入 | 用户困惑 | 未找到 .image-placeholder:not(.has-image) 时弹出友好提示 |
| 按钮点击触发卡片 onClick | 视频意外跳转 | 使用 e.stopPropagation() 阻止冒泡 |
handleDrop 抽离后功能回退 |
拖拽失效 | 保持 handleDrop 调用 fillPlaceholder,逻辑与原来一致 |
改动范围总结
- 仅修改
src/pages/ReportEditor.tsx,不触及其他文件。 - 不引入新依赖。