Files
Mdeical_Sur_Report/工程分析/实现方案-2026-04-17-11-34-24.md
admin 424407a17e feat: field hover highlight, e-signature upload, surgeon signature linkage
- Add signature?: string to User type and 'signature' to FieldType
- Add surgeonSignature field to DEFAULT_FORM_FIELDS (category: 图片)
- UserManage: add canvas-based image compression (max 500px) and signature upload UI
- TemplateManage: add hover highlight on field buttons via direct DOM style manipulation
- TemplateManage: add '图片' category to field library for surgeonSignature insertion
- ReportEditor: auto-fill surgeonSignature with currentUser.signature image or placeholder text
- index.css & print.ts: add .report-signature-img styling (height 2.4em, vertical-align middle)
- Update experience record (#18)
2026-04-17 12:04:23 +08:00

162 lines
5.4 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-11-34-24
## 一、修改文件清单
1. `src/types.ts` — 扩展 `User` / `FieldType` / `DEFAULT_FORM_FIELDS`
2. `src/pages/UserManage.tsx` — 电子签上传组件 + 前端压缩逻辑
3. `src/pages/TemplateManage.tsx` — 悬浮高亮 + 图片分类 + 手术者签名插入
4. `src/pages/ReportEditor.tsx``surgeonSignature` 特殊同步逻辑
5. `src/index.css` — 签名图片排版样式 + 打印样式
6. `src/utils/print.ts` — 打印样式中增加签名图片规则
## 二、详细改动
### 2.1 `src/types.ts`
- `User` 接口追加 `signature?: string`
- `FieldType` 扩展为 `'text' | 'single_select' | 'multi_select' | 'time' | 'date' | 'signature'`
- `DEFAULT_FORM_FIELDS` 末尾追加:
```ts
{ key: 'surgeonSignature', label: '手术者签名', category: '图片', type: 'signature', visibleInForm: false, isSystemLocked: true }
```
### 2.2 `src/pages/UserManage.tsx`
#### A. 前端压缩工具函数
```ts
const compressImage = (file: File, maxSize: number = 500): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (e) => {
const img = new Image();
img.src = e.target?.result as string;
img.onload = () => {
const canvas = document.createElement('canvas');
let { width, height } = img;
if (width > height && width > maxSize) {
height = Math.round((height * maxSize) / width);
width = maxSize;
} else if (height > maxSize) {
width = Math.round((width * maxSize) / height);
height = maxSize;
}
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(0, 0, width, height);
ctx.drawImage(img, 0, 0, width, height);
}
resolve(canvas.toDataURL('image/jpeg', 0.8));
};
img.onerror = reject;
};
reader.onerror = reject;
});
};
```
#### B. 上传组件与保存逻辑
- 在模态框表单中("状态"选择器下方或底部按钮上方)增加一个区块:
- 标签:"电子签名"
- 若 `formData.signature` 有值,显示压缩后的预览图(高度限制 64px
- "上传签名" 按钮(`type="button"`),触发隐藏的 `<input type="file" accept="image/*">`。
- "清除签名" 按钮(有值时显示)。
- `handleSubmit` 中保存 `signature` 字段到用户对象。
- 编辑当前登录用户时,同步更新 `storage.set('currentUser', currentCached)`,确保 ReportEditor 能立即读取到最新签名。
### 2.3 `src/pages/TemplateManage.tsx`
#### A. 悬浮高亮
在字段库按钮上增加 `onMouseEnter` 和 `onMouseLeave`
```ts
const highlightField = (key: string, active: boolean) => {
if (!editorRef.current) return;
const el = editorRef.current.querySelector(`[data-bind="${key}"]`) as HTMLElement | null;
if (!el) return;
if (active) {
el.style.transition = 'all 0.2s';
el.style.boxShadow = '0 0 0 2px #3b82f6';
el.style.backgroundColor = '#e0f2fe';
} else {
el.style.boxShadow = '';
el.style.backgroundColor = '';
}
};
```
#### B. 图片分类与手术者签名
- 插入字段分类数组从 `['填空', '单选', '多选', '时间']` 改为 `['填空', '单选', '多选', '时间', '图片']`。
- `surgeonSignature` 字段会自动出现在"图片"分类下,按钮点击逻辑复用 `insertSmartField`(已支持唯一性校验)。
### 2.4 `src/pages/ReportEditor.tsx`
在"Sync form state -> rich text field values"的 `useEffect` 中,对 `fieldKey === 'surgeonSignature'` 做特殊分支:
```ts
if (fieldKey === 'surgeonSignature') {
const signatureData = currentUser?.signature;
if (signatureData) {
const imgHtml = `<img src="${signatureData}" class="report-signature-img" alt="签名" draggable="false" />`;
if (el.innerHTML !== imgHtml) {
el.innerHTML = imgHtml;
el.style.border = 'none';
el.style.backgroundColor = 'transparent';
}
} else {
if (el.innerText !== '【请上传电子签】') {
el.innerText = '【请上传电子签】';
el.style.border = '';
el.style.backgroundColor = '';
}
}
return; // 跳过常规文本同步
}
```
### 2.5 `src/index.css`
增加签名图片样式:
```css
.report-signature-img {
height: 2.4em;
width: auto;
vertical-align: middle;
display: inline-block;
margin: -0.3em 0;
}
```
在 `@media print` 中同步增加:
```css
@media print {
.report-signature-img {
height: 2.4em !important;
width: auto !important;
vertical-align: middle !important;
display: inline-block !important;
margin: -0.3em 0 !important;
}
}
```
### 2.6 `src/utils/print.ts`
在打印 iframe 的 `<style>` 标签内,`.smart-field-wrapper` 规则之后追加:
```css
.report-signature-img {
height: 2.4em;
width: auto;
vertical-align: middle;
display: inline-block;
margin: -0.3em 0;
}
```
## 三、风险与回滚
- **风险**`localStorage` 容量有限,压缩后的签名图片通常在 10~50KB单用户存储安全。
- **风险**:旧用户的 `User` 对象没有 `signature` 字段,读取时为 `undefined`,代码中已通过可选链和默认值处理。
- **回滚**:如出现问题,可回退 6 个文件的修改。