Files
Mdeical_Sur_Report/工程分析/实现方案-2026-04-17-12-34-56.md
admin f7c7270053 fix: undo stack, field insertion wrap, backspace/delete precision; feat: signature size limit & isSigned control
- Replace direct DOM remove() with Range+execCommand('delete') in TemplateManage click and keydown handlers to restore undo stack
- Append ​ zero-width space to smart-field-wrapper HTML in insertSmartField and defaultContent.ts to prevent unwanted line breaks
- Refactor ReportEditor surgeonSignature rendering to depend on isSigned field
- Add isSigned to DEFAULT_FORM_FIELDS (single_select: 已签字/未签字)
- Change surgeonSignature to visibleInForm=true, isSystemLocked=false
- Constrain signature image with max-width:120px, max-height:40px, object-fit:contain in CSS and print.ts
- Add weak-blocking signature validation prompts in saveReport('completed')
- Update experience record (#19)
2026-04-17 12:41:07 +08:00

158 lines
5.2 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-12-34-56
## 一、修改文件清单
1. `src/pages/TemplateManage.tsx` — 删除逻辑改用 `execCommand('delete')`;插入 HTML 增加零宽空格防换行
2. `src/types.ts` — 修改 `surgeonSignature` 显隐属性;新增 `isSigned` 字段
3. `src/pages/ReportEditor.tsx` — 初始值增加 `isSigned`;签名同步逻辑重构;完成报告签名校验
4. `src/index.css` — 签名图片尺寸约束
5. `src/utils/print.ts` — 打印样式同步签名尺寸约束
## 二、详细改动
### 2.1 `src/pages/TemplateManage.tsx`
#### A. 点击红 X 删除改用 `execCommand('delete')`
```ts
if (smartField && targetEl.closest('.delete-btn')) {
e.stopPropagation();
e.preventDefault();
const sel = window.getSelection();
const range = document.createRange();
range.selectNode(smartField);
sel?.removeAllRanges();
sel?.addRange(range);
document.execCommand('delete');
saveTemplateContent();
return;
}
```
#### B. 键盘 Backspace/Delete 改用 `execCommand('delete')`
`handleKeyDown` 中,当定位到 `smart-field-wrapper` 目标后:
```ts
if (target) {
e.preventDefault();
const sel = window.getSelection();
const range = document.createRange();
range.selectNode(target);
sel?.removeAllRanges();
sel?.addRange(range);
document.execCommand('delete');
saveTemplateContent();
}
```
#### C. 插入 HTML 防换行
`insertSmartField` 的 HTML 字符串末尾增加 `​`(零宽空格),作为行内锚点,防止浏览器将字段挤到新行:
```html
<span class="smart-field-wrapper" ...>...</span>&#8203;
```
### 2.2 `src/types.ts`
-`surgeonSignature` 改为:
```ts
{ key: 'surgeonSignature', label: '手术者签名', category: '图片', type: 'signature', visibleInForm: true, isSystemLocked: false }
```
- 在 `DEFAULT_FORM_FIELDS` 末尾追加(放在 `surgeonSignature` 之前或之后均可):
```ts
{ key: 'isSigned', label: '手术者签名确认', category: '单选', type: 'single_select', visibleInForm: true, isSystemLocked: false, options: ['已签字', '未签字'] },
```
### 2.3 `src/pages/ReportEditor.tsx`
#### A. 初始 `reportData` 增加 `isSigned`
```ts
const [reportData, setReportData] = useState<Partial<Report>>({
// ... 其他字段
isSigned: '未签字',
// ...
});
```
#### B. 签名同步逻辑重构
将 `surgeonSignature` 的特殊处理从 `useEffect` 移到更前面的位置,逻辑改为:
```ts
if (fieldKey === 'surgeonSignature') {
const isSigned = (reportData as any).isSigned === '已签字';
const signatureData = currentUser?.signature;
if (isSigned && 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 {
const placeholder = isSigned ? '【请上传电子签】' : '【未签字】';
if (el.innerText !== placeholder) {
el.innerText = placeholder;
el.style.border = '';
el.style.backgroundColor = '';
}
}
return;
}
```
#### C. 完成报告签名校验
在 `saveReport` 的 `status === 'completed'` 分支中,在现有患者信息校验之后追加:
```ts
const hasSignatureField = editorRef.current?.querySelector('[data-bind="surgeonSignature"]');
if (hasSignatureField) {
const isSigned = reportData.isSigned === '已签字';
const hasSignatureImage = !!currentUser?.signature;
if (!isSigned) {
const proceed = window.confirm('提示:模板中包含【手术者签名】字段,但您在基本信息中未选择"已签字"。是否继续完成报告?');
if (!proceed) return;
} else if (!hasSignatureImage) {
const proceed = window.confirm('提示:您选择了"已签字",但您的账号尚未上传电子签名图片。报告中将不显示签名图片,是否继续完成?');
if (!proceed) return;
}
}
```
### 2.4 `src/index.css`
修改 `.report-signature-img`
```css
.report-signature-img {
max-width: 120px;
max-height: 40px;
width: auto;
height: auto;
object-fit: contain;
vertical-align: middle;
display: inline-block;
}
```
在 `@media print` 中同步:
```css
@media print {
.report-signature-img {
max-width: 120px !important;
max-height: 40px !important;
width: auto !important;
height: auto !important;
object-fit: contain !important;
vertical-align: middle !important;
display: inline-block !important;
}
}
```
### 2.5 `src/utils/print.ts`
在 iframe 的 `<style>` 中,`.smart-field-wrapper` 规则之后追加:
```css
.report-signature-img { max-width: 120px; max-height: 40px; width: auto; height: auto; object-fit: contain; vertical-align: middle; display: inline-block; }
```
## 三、风险与回滚
- **风险**:改用 `execCommand('delete')` 后,少数旧版浏览器可能行为不一致,但现代 Chromium/Edge 支持良好。
- **风险**`&#8203;` 零宽空格在极少数场景下可能导致光标异常,但其为无形字符,影响极小。
- **回滚**:如出现问题,可回退上述 5 个文件的修改。