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 修复)
+
+## 需求影响范围
+- 模板管理页面的图片占位符插入功能
+- 新建报告时的默认模板视觉效果
+- 打印输出时的顶部排版