Files
Mdeical_Sur_Report/工程分析/实现方案-2026-04-17-21-32-27.md

211 lines
7.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-21-32-27
## 根因分析
当前系统的时间/日期字段为「硬编码」形态:
- `date` 类型固定使用浏览器原生 `<input type="date">`smart field 中直接显示原始值。
- `time` 类型仅对 `startTime/endTime` 有表单渲染hour+minute select且固定为 24 小时制smart field 中直接拼接 `HH:MM`
- 没有「当前时间自动填充」机制,也没有「显示格式切换」能力。
- 模板底部「年 月 日」是写死文本,无法自动关联系统时间。
## 修改文件清单
| 文件 | 修改内容 |
|------|---------|
| `src/types.ts` | `FormField` 增加 `timeFormat`/`timeDefault`;更新 `DEFAULT_FORM_FIELDS`;新增 `reportDate` |
| `src/utils/defaultContent.ts` | 底部「年 月 日」→「撰写时间:${smartField('reportDate')}」 |
| `src/pages/TemplateManage.tsx` | 新增字段/编辑面板增加时间配置 UI保存逻辑扩展 |
| `src/pages/ReportEditor.tsx` | date/time 表单渲染增强smart field 同步增加格式转换;初始化自动填充 |
## 具体代码变更
### 1. types.ts
```ts
export interface FormField {
key: string;
label: string;
category: string;
type: FieldType;
visibleInForm: boolean;
isSystemLocked: boolean;
options?: string[];
timeFormat?: string; // NEW
timeDefault?: 'current' | 'specific'; // NEW
}
```
`DEFAULT_FORM_FIELDS` 更新:
- `surgeryDate` 增加 `timeFormat: 'YYYY-MM-DD', timeDefault: 'specific'`
- `startTime` 增加 `timeFormat: '24h', timeDefault: 'specific'`
- `endTime` 增加 `timeFormat: '24h', timeDefault: 'specific'`
- 新增:`reportDate`date, `YYYY年MM月DD日`, `current`, systemLocked
### 2. defaultContent.ts
尾部修改:
```html
<!-- 删除旧的 "年 月 日" 段落 -->
<p style="text-align: right; font-family: SimSun;">
撰写时间:${smartField('reportDate')}
</p>
```
### 3. TemplateManage.tsx
#### 新增状态
```ts
const [newFieldTimeFormat, setNewFieldTimeFormat] = useState('YYYY-MM-DD');
const [newFieldTimeDefault, setNewFieldTimeDefault] = useState<'current' | 'specific'>('specific');
const [editFieldTimeFormat, setEditFieldTimeFormat] = useState('');
const [editFieldTimeDefault, setEditFieldTimeDefault] = useState<'current' | 'specific'>('specific');
```
#### 点击字段进入编辑时
```ts
setEditFieldTimeFormat(field.timeFormat || '');
setEditFieldTimeDefault(field.timeDefault || 'specific');
```
#### 编辑面板editingFieldKey === field.key
在「选项输入框」之后,增加条件渲染:
```tsx
{field.category === '时间' && (
<div className="space-y-1">
<select value={editFieldTimeDefault} onChange={...}>
<option value="specific"></option>
<option value="current"></option>
</select>
<select value={editFieldTimeFormat} onChange={...}>
{field.type === 'date' && <><option value="YYYY-MM-DD">YYYY-MM-DD</option><option value="YYYY年MM月DD日">YYYY年MM月DD日</option></>}
{field.type === 'time' && <><option value="24h">24</option><option value="12h">12</option></>}
</select>
</div>
)}
```
#### saveFieldEdit
```ts
if (field.category === '时间') {
next.timeFormat = editFieldTimeFormat;
next.timeDefault = editFieldTimeDefault;
}
```
#### 新增字段表单
在 category === '时间' 条件下,增加「默认值」和「显示格式」两个 select。
#### addField
```ts
if (newFieldForm.category === '时间') {
newField.timeFormat = newFieldTimeFormat;
newField.timeDefault = newFieldTimeDefault;
}
```
### 4. ReportEditor.tsx
#### 新增辅助函数(组件内)
```ts
const formatDateDisplay = (isoDate: string, fmt?: string): string => {
if (!isoDate) return '';
if (fmt === 'YYYY年MM月DD日') {
const [y, m, d] = isoDate.split('-');
if (y && m && d) return `${y}${m}${d}`;
}
return isoDate;
};
const formatTimeDisplay = (timeStr: string, fmt?: string): string => {
if (!timeStr) return '';
if (fmt === '12h') {
const [hStr, mStr] = timeStr.split(':');
let h = parseInt(hStr);
const ampm = h >= 12 ? '下午' : '上午';
h = h % 12;
if (h === 0) h = 12;
return `${String(h).padStart(2, '0')}:${mStr} ${ampm}`;
}
return timeStr;
};
```
#### date 字段表单渲染
保持 `<input type="date">` 不变,值仍为 `YYYY-MM-DD`
#### time 字段表单渲染
重构为支持通用 time 字段:
**startTime/endTime向后兼容**
- `timeFormat === '24h'`:保持现有 hour(00-23) + minute select
- `timeFormat === '12h'`hour(01-12) + minute + AM/PM select
- 存储转换:`to24h(hour12, isPM)` → 写入 startHour/endHour
**通用 time 字段(非 startTime/endTime**
- 解析 reportData[field.key](格式 `HH:MM`)→ hour + minute
- `timeFormat === '24h'`hour(00-23) + minute
- `timeFormat === '12h'`hour(01-12) + minute + AM/PM
- onChange 时拼接为 `HH:MM` 存入 reportData[field.key]
#### smart field 同步useEffect
在拼接/取值后,增加格式转换:
```ts
if (fieldKey === 'startTime' || fieldKey === 'endTime') {
// ... 拼接 HH:MM
const fieldDef = formFields.find(f => f.key === fieldKey);
newValue = formatTimeDisplay(newValue, fieldDef?.timeFormat);
} else {
const rawValue = (reportData as any)[fieldKey];
// ... 处理 array/string
const fieldDef = formFields.find(f => f.key === fieldKey);
if (fieldDef?.type === 'date') {
newValue = formatDateDisplay(newValue, fieldDef.timeFormat);
} else if (fieldDef?.type === 'time') {
newValue = formatTimeDisplay(newValue, fieldDef.timeFormat);
}
}
```
#### 初始化自动填充
`useEffect` 初始化数据后,遍历 `formFields`
```ts
formFields.forEach(field => {
if (field.timeDefault !== 'current') return;
if (field.type === 'date') {
const current = new Date().toISOString().split('T')[0];
if (!(reportData as any)[field.key]) {
setReportData(prev => ({ ...prev, [field.key]: current }));
}
} else if (field.type === 'time') {
const now = new Date();
const hh = String(now.getHours()).padStart(2, '0');
const mm = String(now.getMinutes()).padStart(2, '0');
const current = `${hh}:${mm}`;
if (field.key === 'startTime') {
if (!reportData.startHour) setReportData(prev => ({ ...prev, startHour: hh, startMinute: mm }));
} else if (field.key === 'endTime') {
if (!reportData.endHour) setReportData(prev => ({ ...prev, endHour: hh, endMinute: mm }));
} else {
if (!(reportData as any)[field.key]) {
setReportData(prev => ({ ...prev, [field.key]: current }));
}
}
}
});
```
## 风险点与应对措施
| 风险 | 应对措施 |
|------|---------|
| 现有用户已保存的 `formFieldsConfig` 缺少新字段,导致 `timeFormat` 为 undefined | 代码中统一使用 `field.timeFormat || 默认值` 做回退 |
| 12h 表单与 24h 存储转换出错 | 增加边界单元测试12AM→00, 12PM→12, 1PM→13 等) |
| startTime/endTime 的 hour/minute 存储结构改动影响历史报告 | 保持存储结构不变,仅改动渲染和显示 |
| 自动填充当前时间在编辑已有报告时覆盖用户值 | 仅当字段值为空时才填充 |
## 回滚策略
- `types.ts` 中新增的属性为 optional回滚时删除即可不影响已有数据结构。
- `defaultContent.ts` 的修改可通过 Git revert 恢复。
- TemplateManage/ReportEditor 的 UI 改动为增量添加,回滚时移除条件渲染块即可。