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

7.4 KiB
Raw Blame History

实现方案 — 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

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'
  • 新增:reportDatedate, YYYY年MM月DD日, current, systemLocked

2. defaultContent.ts

尾部修改:

<!-- 删除旧的 "年 月 日" 段落 -->
<p style="text-align: right; font-family: SimSun;">
    撰写时间:${smartField('reportDate')}
</p>

3. TemplateManage.tsx

新增状态

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');

点击字段进入编辑时

setEditFieldTimeFormat(field.timeFormat || '');
setEditFieldTimeDefault(field.timeDefault || 'specific');

编辑面板editingFieldKey === field.key

在「选项输入框」之后,增加条件渲染:

{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

if (field.category === '时间') {
  next.timeFormat = editFieldTimeFormat;
  next.timeDefault = editFieldTimeDefault;
}

新增字段表单

在 category === '时间' 条件下,增加「默认值」和「显示格式」两个 select。

addField

if (newFieldForm.category === '时间') {
  newField.timeFormat = newFieldTimeFormat;
  newField.timeDefault = newFieldTimeDefault;
}

4. ReportEditor.tsx

新增辅助函数(组件内)

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

在拼接/取值后,增加格式转换:

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

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 改动为增量添加,回滚时移除条件渲染块即可。