Files
Mdeical_Sur_Report/工程分析/实现方案-2026-04-17-19-26-17.md
admin 5fee3352c1 refactor: unify image-placeholder across editors and remove image field type
- Remove surgeonSignature and hospitalLogo from DEFAULT_FORM_FIELDS.
- Replace logo and signature in default template with inline image-placeholder spans.
- Enhance insertImage() in both editors with prompt for max-width/height (px).
- Abbreviate placeholder text to '插入图片' when width < 80px.
- Force inline insertion using display:inline-flex + vertical-align:middle.
- Port image-source picker modal from ReportEditor to TemplateManage.
- Remove legacy triggerPlaceholderUpload direct upload logic.
2026-04-17 19:34:03 +08:00

155 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 实现方案 — 2026-04-17-19-26-17
## 变更文件
1. `src/types.ts`
2. `src/utils/defaultContent.ts`
3. `src/pages/TemplateManage.tsx`
4. `src/pages/ReportEditor.tsx`
---
## 一、types.ts 修改
`DEFAULT_FORM_FIELDS` 中移除以下两个字段:
- `surgeonSignature`
- `hospitalLogo`
同时从 `FieldType` 中移除 `'image'`(因为图片不再作为可插入的字段类型,仅作为占位符存在)。若移除 `'image'` 会导致大量类型错误,也可保留类型但不在 UI 中暴露。为最小侵入,保留 `'image'` 类型但不再在 `DEFAULT_FORM_FIELDS` 中使用。
实际执行:删除 `DEFAULT_FORM_FIELDS` 中的最后两项(`surgeonSignature``hospitalLogo`)。
---
## 二、defaultContent.ts 修改
### 2.1 医院Logo
将原有的 `div.image-placeholder` 替换为 `span.image-placeholder`(保持居中):
```html
<!-- 医院Logo -->
<p style="text-align: center; margin-bottom: 16px;" contenteditable="false">
<span class="image-placeholder" data-placeholder="true" contenteditable="false" style="display:inline-flex;align-items:center;justify-content:center;width:65px;height:65px;border:1px dashed #cbd5e1;background:#f8fafc;vertical-align:middle;margin:0 auto;cursor:pointer;">
<span class="delete-btn" contenteditable="false">×</span>
<span class="placeholder-text" style="color:#94a3b8;font-size:11px;pointer-events:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">插入图片</span>
</span>
</p>
```
### 2.2 手术者签名
`手术者签名:${smartField('surgeonSignature')}` 替换为:
```html
<p style="font-family: SimSun;">
手术者签名:<span class="image-placeholder" data-placeholder="true" contenteditable="false" style="display:inline-flex;align-items:center;justify-content:center;min-width:80px;min-height:24px;border:1px dashed #cbd5e1;background:#f8fafc;vertical-align:middle;margin:0 4px;cursor:pointer;"><span class="delete-btn" contenteditable="false">×</span><span class="placeholder-text" style="color:#94a3b8;font-size:11px;pointer-events:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">插入图片</span></span>
</p>
```
---
## 三、TemplateManage.tsx 修改
### 3.1 移除"图片"分类暴露
- `expandedCategories` 初始值从 `['填空','单选','多选','时间','图片']` 改为 `['填空','单选','多选','时间']`
- "插入字段"Tab 的遍历数组从 `['填空','单选','多选','时间','图片']` 改为 `['填空','单选','多选','时间']`
- "字段管理"Tab 的遍历数组同样移除 `'图片'`
- 新增字段表单的 category select 中移除 `<option value="图片">图片</option>`
- type select 的条件渲染中移除图片相关的 option。
### 3.2 改造 insertImage()
将现有的 `insertImage()` 替换为:
```typescript
const insertImage = () => {
const widthStr = prompt('请输入占位符最大宽度 (px),留空无限制:\n(提示:正文一行文字高度约为 20 像素左右)', '');
const heightStr = prompt('请输入占位符最大高度 (px),留空无限制:', '');
const width = parseInt(widthStr || '0');
const height = parseInt(heightStr || '0');
let styleStr = 'display:inline-flex;align-items:center;justify-content:center;border:1px dashed #cbd5e1;background:#f8fafc;vertical-align:middle;margin:0 4px;cursor:pointer;';
if (width > 0) styleStr += ` max-width:${width}px;`;
if (height > 0) styleStr += ` max-height:${height}px;`;
if (!width && !height) styleStr += ' padding:8px 16px;';
const showShortText = width > 0 && width < 80;
const hintText = showShortText ? '插入图片' : '插入/点击放置图片';
const id = 'ph_' + Date.now();
const html = `<span id="${id}" class="image-placeholder" data-placeholder="true" contenteditable="false" style="${styleStr}"><span class="delete-btn" contenteditable="false">×</span><span class="placeholder-text" style="color:#94a3b8;font-size:11px;pointer-events:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">${hintText}</span></span>&#8203;`;
editorRef.current?.focus();
restoreSelection();
pushHistory();
execCmd('insertHTML', html);
};
```
### 3.3 统一图片源选择弹窗
`ReportEditor.tsx` 复用以下逻辑到 `TemplateManage.tsx`
- 新增状态:`imagePickerOpen``imagePickerTarget``imageAssets`(已存在)。
- 新增 `fillPlaceholderSrc` 函数。
- 修改 `handleEditorClick` 中的 placeholder 点击逻辑:
```typescript
if (!placeholder.classList.contains('has-image')) {
e.preventDefault();
e.stopPropagation();
setImagePickerTarget(placeholder);
setImagePickerOpen(true);
}
```
- 删除原有的 `triggerPlaceholderUpload` 函数及其直接调用。
- 在 JSX 底部(`isModalOpen` 弹窗之后)新增 `imagePickerOpen` 弹窗组件(与 ReportEditor 完全一致)。
### 3.4 清理删除后的重置逻辑
当 placeholder 被删除(点击 × 后)时,重置为:
```html
<span class="delete-btn" contenteditable="false">×</span>
<span class="placeholder-text" style="color:#94a3b8;font-size:11px;pointer-events:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">插入/点击放置图片</span>
```
同时保留原有内联样式(避免把 `inline-flex` 等样式清掉)。
---
## 四、ReportEditor.tsx 修改
### 4.1 改造 insertImage()
与 TemplateManage 保持一致:
```typescript
const insertImage = () => {
editorRef.current?.focus();
const widthStr = prompt('请输入占位符最大宽度 (px),留空无限制:\n(提示:正文一行文字高度约为 20 像素左右)', '');
const heightStr = prompt('请输入占位符最大高度 (px),留空无限制:', '');
const width = parseInt(widthStr || '0');
const height = parseInt(heightStr || '0');
let styleStr = 'display:inline-flex;align-items:center;justify-content:center;border:1px dashed #cbd5e1;background:#f8fafc;vertical-align:middle;margin:0 4px;cursor:pointer;';
if (width > 0) styleStr += ` max-width:${width}px;`;
if (height > 0) styleStr += ` max-height:${height}px;`;
if (!width && !height) styleStr += ' padding:8px 16px;';
const showShortText = width > 0 && width < 80;
const hintText = showShortText ? '插入图片' : '插入/点击放置图片';
const id = 'ph_' + Date.now();
const html = `<span id="${id}" class="image-placeholder" data-placeholder="true" contenteditable="false" style="${styleStr}"><span class="delete-btn" contenteditable="false">×</span><span class="placeholder-text" style="color:#94a3b8;font-size:11px;pointer-events:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">${hintText}</span></span>&#8203;`;
execCmd('insertHTML', html);
};
```
### 4.2 删除后重置逻辑
在 `handleEditorClick` 中placeholder 删除后重置的 HTML 改为使用 `<span>` 结构并保留内联样式:
```typescript
placeholder.innerHTML = `
<span class="delete-btn" contenteditable="false">×</span>
<span class="placeholder-text" style="color: #94a3b8; font-size: 11px; pointer-events: none; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">插入/点击放置图片</span>
`;
```
### 4.3 fillPlaceholderSrc 保持兼容
已有 `fillPlaceholderSrc` 可继续使用,但建议填充的图片增加 `max-width: 100%; max-height: 100%; object-fit: contain;`。
---
## 回滚策略
修改前最新提交为 `0c57409`。若失败可 `git reset --hard 0c57409`。
## 无新增 npm 依赖