- 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.
155 lines
7.3 KiB
Markdown
155 lines
7.3 KiB
Markdown
# 实现方案 — 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>​`;
|
||
|
||
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>​`;
|
||
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 依赖
|