# 实现方案 — 2026-04-17-21-32-27 ## 根因分析 当前系统的时间/日期字段为「硬编码」形态: - `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

撰写时间:${smartField('reportDate')}

``` ### 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 === '时间' && (
)} ``` #### 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 字段表单渲染 保持 `` 不变,值仍为 `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 改动为增量添加,回滚时移除条件渲染块即可。