From e1dc961ecf11166879e115bc6f1a6efdffbbf997 Mon Sep 17 00:00:00 2001 From: Administrator Date: Sat, 18 Apr 2026 17:33:07 +0800 Subject: [PATCH] =?UTF-8?q?2026-04-18-17-27-51=20-=20=E4=BF=AE=E5=A4=8DTem?= =?UTF-8?q?plateManage=E9=9D=99=E6=80=81=E5=8D=A0=E4=BD=8D=E7=AC=A6?= =?UTF-8?q?=E6=8F=92=E5=85=A5=E3=80=81=E9=87=8D=E6=9E=84=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E6=8E=92=E7=89=88=E3=80=81=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?Logo=E5=88=A0=E9=99=A4=E6=8C=89=E9=92=AE=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/TemplateManage.tsx | 24 +++- src/utils/defaultContent.ts | 105 ++++++++------- 工程分析/实现方案-2026-04-18-17-27-51.md | 82 ++++++++++++ 工程分析/测试方案-2026-04-18-17-27-51.md | 155 +++++++++++++++++++++++ 工程分析/需求分析-2026-04-18-17-27-51.md | 29 +++++ 5 files changed, 340 insertions(+), 55 deletions(-) create mode 100644 工程分析/实现方案-2026-04-18-17-27-51.md create mode 100644 工程分析/测试方案-2026-04-18-17-27-51.md create mode 100644 工程分析/需求分析-2026-04-18-17-27-51.md diff --git a/src/pages/TemplateManage.tsx b/src/pages/TemplateManage.tsx index ea6d657..f18623e 100644 --- a/src/pages/TemplateManage.tsx +++ b/src/pages/TemplateManage.tsx @@ -1266,7 +1266,29 @@ export default function TemplateManage() { const text = showShortText ? '插图' : hintText; html = `×${text}​`; } - execCmd('insertHTML', html); + const wrapper = document.createElement('div'); + wrapper.innerHTML = html; + const fragment = document.createDocumentFragment(); + while (wrapper.firstChild) { + fragment.appendChild(wrapper.firstChild); + } + const sel2 = window.getSelection(); + if (sel2 && sel2.rangeCount > 0) { + const range = sel2.getRangeAt(0); + range.deleteContents(); + range.insertNode(fragment); + const lastNode = fragment.lastChild; + if (lastNode) { + range.setStartAfter(lastNode); + range.collapse(true); + sel2.removeAllRanges(); + sel2.addRange(range); + } + } else if (editorRef.current) { + editorRef.current.appendChild(fragment); + } + editorRef.current?.focus(); + saveTemplateContent(); setPlaceholderModal({...placeholderModal, isOpen: false}); }} className="px-4 py-2 bg-accent text-white rounded text-sm">确认插入 diff --git a/src/utils/defaultContent.ts b/src/utils/defaultContent.ts index abe6157..2192348 100644 --- a/src/utils/defaultContent.ts +++ b/src/utils/defaultContent.ts @@ -1,65 +1,62 @@ const smartField = (key: string) => ` ×​`; export const defaultReportContent = ` - -

- - × - 插入图片 - -

+ + + + + + +
+ + × + 插入图片 + + +
西 安 交 通 大 学 第 一 附 属 医 院
+
手术记录
+
- -

- 西 安 交 通 大 学 第 一 附 属 医 院 -

- - -

手术记录

- -
-

- 姓名:${smartField('patientName')} - 性别:${smartField('patientGender')} - 年龄:${smartField('patientAge')} - 科别:${smartField('department')} - 床号:${smartField('bedNumber')} +

+

+ 姓名:${smartField('patientName')}    + 性别:${smartField('patientGender')}    + 年龄:${smartField('patientAge')}    + 科别:${smartField('department')}    + 床号:${smartField('bedNumber')}    住院号:${smartField('hospitalId')}

- -

- 手术日期:${smartField('surgeryDate')} -

- -

- 术前诊断:${smartField('preoperativeDiagnosis')} -

- -

- 术后诊断:${smartField('postoperativeDiagnosis')} -

- -

- 手术名称:${smartField('title')} -

- -

- 手术开始时间:${smartField('startTime')} - 手术终止时间:${smartField('endTime')} -

- -

- 手术者:${smartField('surgeon')} - 助手:${smartField('assistant')} -

- -

- 麻醉师:${smartField('anesthesiologist')} - 麻醉方式:${smartField('anesthesiaType')} -

-

+

+ 手术日期:${smartField('surgeryDate')} +

+

+ 术前诊断:${smartField('preoperativeDiagnosis')} +

+

+ 术中诊断:${smartField('postoperativeDiagnosis')} +

+

+ 手术名称:${smartField('title')} +

+ + + + + + + + + + + + + + +
手术开始时间:${smartField('startTime')}手术终止时间:${smartField('endTime')}
手术者:${smartField('surgeon')}助手:${smartField('assistant')}
麻醉师:${smartField('anesthesiologist')}麻醉方式:${smartField('anesthesiaType')}
+ +

手术步骤、术中出现的情况及处理:

diff --git a/工程分析/实现方案-2026-04-18-17-27-51.md b/工程分析/实现方案-2026-04-18-17-27-51.md new file mode 100644 index 0000000..10f3b23 --- /dev/null +++ b/工程分析/实现方案-2026-04-18-17-27-51.md @@ -0,0 +1,82 @@ +# 实现方案 —— 2026-04-18-17-27-51 + +## 方案目标 +修复 TemplateManage 静态占位符插入 Bug,重构默认报告模板顶部排版,修复 Logo 删除按钮交互。 + +## 需求 1:修复静态图片占位符插入不显示 + +### 问题根因 +`TemplateManage.tsx` 中 `insertImage()` 使用 `document.execCommand('insertHTML', false, html)`。现代浏览器对含 `contenteditable="false"` 的复杂嵌套标签会自动修正/拍平,导致外层 `.image-placeholder` 容器丢失,DOM 仅剩零散子元素,视觉上不可见。 + +### 解决步骤 +1. **定位 `insertImage` 函数**:找到 `TemplateManage.tsx` 中通过 `document.execCommand('insertHTML')` 插入占位符的逻辑。 +2. **替换为 `Range.insertNode`**: + - 创建临时 `div`,将 HTML 字符串写入 `innerHTML`。 + - 将子节点逐个移入 `DocumentFragment`。 + - 获取当前 `Selection` 的 `RangeAt(0)`。 + - 调用 `range.deleteContents()` 清空当前选区。 + - 调用 `range.insertNode(fragment)` 精确插入。 + - 将光标移动到插入内容之后。 +3. **保持原有弹窗逻辑不变**:Modal 中的模式选择(frame/manual)、宽高输入等逻辑不受影响。 + +## 需求 2:重构默认报告模板排版 + +### 排版设计 + +#### 页眉(Logo + 医院名 + 标题) +使用 3 列 ``(左 20%、中 60%、右 20%),中间列绝对居中: +- 左列:Logo 占位符(65×65,`data-mode="manual"`,`position:relative`) +- 中列: + - 第一行:14pt SimSun「西 安 交 通 大 学 第 一 附 属 医 院」(带 `border-bottom: 1px solid #000` 下划线,使用 `display: inline-block`) + - 第二行:16pt SimSun「手术记录」 +- 右列:留空 + +#### 基本信息栏(下划线贯穿) +使用 `
` 包裹一行: +- 11pt SimSun,不加粗 +- 姓名、性别、年龄、科别、床号、住院号,用 ` ` 间隔 + +#### 诊断/手术信息(单行加粗) +每项独立 `

`: +- 12pt SimSun,`font-weight: bold` +- 手术日期、术前诊断、术中诊断、手术名称 + +#### 双列信息(两项一行,不加粗) +使用 `

`: +- 三行两列,每列 50% +- 12pt SimSun,不加粗 +- 手术开始/终止时间、手术者/助手、麻醉师/麻醉方式 + +#### 手术步骤标题 +- 12pt SimSun,`font-weight: bold` +- 「手术步骤、术中出现的情况及处理:」 + +#### 保留内容 +- 5 条手术步骤段落文字(不变) +- 手术图片说明表格(需求 3 中已替换的最新 6 图格表格) +- 手术后情况段落(术后诊断、标本描述、病理检查、冰冻病理) +- 手术者签名占位符 + 撰写时间字段 + +### 涉及文件 +`src/utils/defaultContent.ts` —— 完全重写 `defaultReportContent` 变量。 + +## 需求 3:修复顶部 Logo 删除按钮 + +### 解决步骤 +在 `defaultContent.ts` 中 Logo 占位符的 `style` 属性中增加 `position: relative;`,使绝对定位的 `.delete-btn` 相对于占位符自身定位,而非向外层逃逸。 + +```html + +``` + +## 涉及文件及修改点 +| 文件 | 修改点 | +|------|--------| +| `src/pages/TemplateManage.tsx` | `insertImage` 中 `execCommand('insertHTML')` → `Range.insertNode` | +| `src/utils/defaultContent.ts` | 完全重写顶部排版;Logo 增加 `position:relative`;保留手术步骤/表格/底部段落 | + +## 风险与注意事项 +1. `Range.insertNode` 要求编辑器有有效光标/选区。若编辑器未聚焦或选区不在编辑器内,需增加保护逻辑(fallback 到 `editorRef.current.appendChild`)。 +2. 默认模板重写后,需验证 `smartField()` 生成的所有字段占位符在新排版中是否正确渲染。 +3. 打印时需确认新排版的下划线、表格边框在 `@media print` 中正常显示。 +4. ` ` 分隔的基本信息栏在打印时可能换行,需测试实际打印效果。 diff --git a/工程分析/测试方案-2026-04-18-17-27-51.md b/工程分析/测试方案-2026-04-18-17-27-51.md new file mode 100644 index 0000000..a1e2138 --- /dev/null +++ b/工程分析/测试方案-2026-04-18-17-27-51.md @@ -0,0 +1,155 @@ +# 测试方案 —— 2026-04-18-17-27-51 + +## 测试目标 +验证 TemplateManage 静态占位符插入修复、默认模板排版重构、Logo 删除按钮修复。 + +## 测试用例 + +### TC-01:TemplateManage 插入静态图片占位符 +**前置条件**:进入 /template-manage,编辑器有焦点 +**操作步骤**: +1. 点击工具栏「插入图片占位符」 +2. 在弹窗中选择「静态图片占位」 +3. 输入宽度 200,高度 200 +4. 点击「确认插入」 + +**预期结果**: +- 编辑器中出现虚线边框的占位符框 +- 占位符带有 `class="image-placeholder"` 和 `data-mode="manual"` +- 占位符内部显示「插入/点击放置图片」文字 +- 占位符右上角显示红色「×」删除按钮 + +--- + +### TC-02:TemplateManage 插入手术影像占位符 +**前置条件**:进入 /template-manage +**操作步骤**: +1. 点击工具栏「插入图片占位符」 +2. 选择「手术影像占位」 +3. 点击「确认插入」 + +**预期结果**: +- 占位符正常显示 +- 带有 `data-mode="frame"` +- 可接受关键帧拖拽填充 + +--- + +### TC-03:TemplateManage 占位符删除按钮 +**前置条件**:已插入占位符 +**操作步骤**: +1. 鼠标悬浮在占位符上 +2. 点击右上角的红色「×」 + +**预期结果**: +- 占位符被删除 +- 撤销按钮可恢复该占位符 + +--- + +### TC-04:新建报告默认模板排版——抬头 +**前置条件**:退出重新登录,进入 /report-editor(新建报告) +**操作步骤**: +1. 查看报告顶部 + +**预期结果**: +- 左侧有 65×65 的 Logo 占位符(虚线框) +- 中间偏右有 14pt 下划线文字「西 安 交 通 大 学 第 一 附 属 医 院」 +- 下方有 16pt 文字「手术记录」 +- 整体居中对齐 + +--- + +### TC-05:新建报告默认模板排版——基本信息栏 +**前置条件**:新建报告已加载默认模板 +**操作步骤**: +1. 查看抬头下方的基本信息行 + +**预期结果**: +- 一行显示:姓名、性别、年龄、科别、床号、住院号 +- 字体 11pt,不加粗 +- 整行下方有一条黑色贯穿下划线 + +--- + +### TC-06:新建报告默认模板排版——诊断信息 +**前置条件**:新建报告已加载默认模板 +**操作步骤**: +1. 查看手术日期、术前诊断、术中诊断、手术名称 + +**预期结果**: +- 每项独立一行 +- 12pt 字体,加粗 +- 格式为:「手术日期:」+ smartField 占位符 + +--- + +### TC-07:新建报告默认模板排版——双列信息 +**前置条件**:新建报告已加载默认模板 +**操作步骤**: +1. 查看时间、人员、麻醉信息 + +**预期结果**: +- 手术开始/终止时间在同一行,左右各 50% +- 手术者/助手在同一行 +- 麻醉师/麻醉方式在同一行 +- 12pt 字体,不加粗 + +--- + +### TC-08:新建报告默认模板排版——手术步骤标题 +**前置条件**:新建报告已加载默认模板 +**操作步骤**: +1. 查看「手术步骤、术中出现的情况及处理:」 + +**预期结果**: +- 12pt 字体,加粗 +- 位于双列信息下方 + +--- + +### TC-09:Logo 占位符删除按钮可点击 +**前置条件**:新建报告已加载默认模板 +**操作步骤**: +1. 鼠标悬浮在顶部 Logo 占位符上 +2. 点击右上角的红色「×」 + +**预期结果**: +- Logo 占位符被删除 +- 可撤销恢复 + +--- + +### TC-10:Logo 占位符图片上传 +**前置条件**:新建报告已加载默认模板 +**操作步骤**: +1. 点击顶部 Logo 占位符 +2. 选择本地上传一张图片 + +**预期结果**: +- 图片正确显示在 65×65 区域内 +- 图片不溢出占位符 + +--- + +### TC-11:打印效果验证 +**前置条件**:新建报告,填写部分内容 +**操作步骤**: +1. 点击打印按钮 +2. 检查打印预览 + +**预期结果**: +- 抬头排版正确(Logo + 医院名 + 标题) +- 基本信息下划线可见 +- 双列信息左右对齐 +- 无多余虚线边框(placeholder 填充后 border 应消失) + +--- + +## 回归测试范围 +- 验证 `ReportEditor` 中已有的 `image-placeholder` 点击上传、拖拽填充功能不受影响 +- 验证 `TemplateManage` 中智能字段插入、删除、撤销/重做功能正常 +- 验证 `smart-field-wrapper` 双向绑定正常工作 + +## 测试结论 +TC-01~TC-11 全部通过,即可确认三项需求均正确实现。 diff --git a/工程分析/需求分析-2026-04-18-17-27-51.md b/工程分析/需求分析-2026-04-18-17-27-51.md new file mode 100644 index 0000000..2747400 --- /dev/null +++ b/工程分析/需求分析-2026-04-18-17-27-51.md @@ -0,0 +1,29 @@ +# 需求分析 —— 2026-04-18-17-27-51 + +## 需求来源 +用户提出 TemplateManage 功能修复与默认报告模板排版重构需求。 + +## 需求概述 + +### 需求 1:修复 TemplateManage 静态图片占位符插入不显示 +在 `template-manage` 中通过弹窗选择「静态图片占位」并点击「确认插入」后,编辑器中没有出现 `class="image-placeholder"` 的占位符框。经分析,原因是 `document.execCommand('insertHTML')` 对复杂嵌套 HTML(含 `contenteditable="false"`)的自动修正/过滤行为不可靠。 + +### 需求 2:重构默认报告模板顶部排版 +根据用户提供的视觉参考图片,重写 `defaultContent.ts` 顶部排版: +- **抬头**:左侧 Logo(65×65 静态占位),右侧 14 号字体的「西 安 交 通 大 学 第 一 附 属 医 院」(带下划线),下方 16 号字体「手术记录」。 +- **基本信息栏**:11 号字体、不加粗、带贯穿下划线的一行:姓名、性别、年龄、科别、床号、住院号。 +- **诊断/手术信息**:12 号字体、加粗的单行:手术日期、术前诊断、术中诊断、手术名称。 +- **双列信息**:12 号字体、不加粗、两项一行:手术开始/终止时间、手术者/助手、麻醉师/麻醉方式。 +- **手术步骤标题**:12 号字体、加粗的「手术步骤、术中出现的情况及处理:」。 + +### 需求 3:修复顶部 Logo 占位符删除按钮无法点击 +当前默认模板中 65px×65px 的 Logo 占位符右上角的「×」删除按钮无法点击。原因是占位符缺少 `position: relative`,导致绝对定位的删除按钮点击区域溢出或被遮挡。需保留其「静态图片占位 (`data-mode="manual"`)」逻辑。 + +## 涉及文件 +- `src/pages/TemplateManage.tsx`(需求 1:修复 insertImage 插入方式) +- `src/utils/defaultContent.ts`(需求 2、3:重构模板排版 + Logo 修复) + +## 需求影响范围 +- 模板管理页面的图片占位符插入功能 +- 新建报告时的默认模板视觉效果 +- 打印输出时的顶部排版