# 实现方案 —— 2026-04-18-19-37-56 ## 方案目标 修复编辑器中的 4 个体验问题,提升视频面板、图片占位符和对齐功能的稳定性。 ## 需求 1:视频上传按钮位置调整 ### 修改文件 `src/pages/ReportEditor.tsx` ### 修改内容 在「视频分析」面板的缩略图滚动容器中,将 `` 从 `videos.map()` 之前移至之后。保持按钮样式和点击逻辑不变。 ## 需求 2:图片占位符提示文字绝对居中 ### 修改文件 `src/pages/ReportEditor.tsx`、`src/pages/TemplateManage.tsx`、`src/utils/defaultContent.ts` ### 修改内容 将 `.placeholder-text` 的样式改为绝对定位居中: ```css position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: block; width: 100%; ``` 需要确保 `.image-placeholder` 父容器带有 `position: relative;`(默认模板和运行时插入逻辑中已具备)。 修改位置: 1. `defaultContent.ts` 中 8 个占位符的 `.placeholder-text` style 2. `ReportEditor.tsx` 中 `placeholderModal` 确认插入时的 `.placeholder-text` style 3. `TemplateManage.tsx` 中 `placeholderModal` 确认插入时的 `.placeholder-text` style 4. `ReportEditor.tsx` 和 `TemplateManage.tsx` 中 `handleEditorClick` 删除图片后重建 `.placeholder-text` 的 innerHTML ## 需求 3:删除图片后占位符恢复原始大小 ### 修改文件 `src/pages/ReportEditor.tsx`、`src/pages/TemplateManage.tsx` ### 修改内容 在 `handleEditorClick` 中处理 `.delete-btn` 点击、恢复占位符为空的逻辑中,增加尺寸恢复: ```ts const mw = placeholder.style.maxWidth; const mh = placeholder.style.maxHeight; if (mw) placeholder.style.width = mw; if (mh) { placeholder.style.height = mh; placeholder.style.lineHeight = mh; } placeholder.style.textAlign = 'center'; ``` 同时需要恢复其他被修改的样式: - `border: 1px dashed #cbd5e1` - `background: #f8fafc` - `vertical-align: middle`(inline-block 占位符) - `justify-content: center; align-items: center`(flex 占位符) 由于无法直接区分 flex 和 inline-block,可以通过检查 `placeholder.style.display` 或简单地将 `justifyContent` 和 `alignItems` 重置为 `center`(对 inline-block 无影响)。 ## 需求 4:对齐按钮改用安全的 DOM 操作 ### 修改文件 `src/pages/ReportEditor.tsx`、`src/pages/TemplateManage.tsx` ### 修改内容 1. **新增 `changeAlignment` 方法**: ```ts const changeAlignment = (align: 'left' | 'center' | 'right' | 'justify') => { const sel = window.getSelection(); if (!sel || !sel.rangeCount) return; let node = sel.getRangeAt(0).commonAncestorContainer; if (node.nodeType === Node.TEXT_NODE) node = node.parentNode as Node; const block = (node as HTMLElement).closest('p, div, td, h1, h2, h3, h4, h5, h6, li'); if (block) { (block as HTMLElement).style.textAlign = align; if (editorRef.current) { contentRef.current = editorRef.current.innerHTML; saveDraftToStorage(); // ReportEditor // saveTemplateContent(); // TemplateManage } } }; ``` 2. **替换工具栏按钮**:将三个对齐按钮的 `onClick={() => execCmd('justifyLeft')}` 等替换为 `onClick={() => changeAlignment('left')}` 等。保留 `onMouseDown={(e) => e.preventDefault()}` 以防止编辑器失焦。 ## 涉及文件及修改点 | 文件 | 修改点 | |------|--------| | `src/pages/ReportEditor.tsx` | 视频按钮位置;placeholder-text 样式(3 处:插入、删除恢复、Modal);删除恢复时尺寸复原;新增 changeAlignment;替换对齐按钮 | | `src/pages/TemplateManage.tsx` | placeholder-text 样式(3 处);删除恢复时尺寸复原;新增 changeAlignment;替换对齐按钮 | | `src/utils/defaultContent.ts` | 8 个占位符的 placeholder-text 样式更新为绝对居中 | ## 风险与注意事项 1. `changeAlignment` 中 `closest('p, div, ...')` 如果选中了编辑器根容器(`contenteditable` div),可能会对齐整个文档。但由于工具栏按钮要求编辑器已聚焦,通常选区在正文内部,风险较低。 2. 占位符删除恢复时,`maxWidth`/`maxHeight` 的回退逻辑需确保在所有场景下(默认模板、运行时插入)都能正确读取。 3. 绝对居中的 `position:absolute` 需要父容器 `position:relative`,需验证所有占位符均满足。