Files
Mdeical_Sur_Report/工程分析/实现方案-2026-04-17-23-12-52.md

5.3 KiB
Raw Blame History

实现方案 — 2026-04-17-23-12-52

根因分析

问题1格式选项缺失与旧值残留

  • types.tsDEFAULT_FORM_FIELDS 中,startTimeendTimetimeFormat 仍被硬编码为 '24h'(历史遗留)。
  • TemplateManage.tsx 中的 defaultFormats 虽然已包含 HH:mmhh:mm A,但 customTimeFormats 的 datalist 未按字段类型过滤,导致 date/time 格式混在一起显示,用户体验混乱。
  • 用户的 localStoragecustomTimeFormats 可能还残留旧值 '24h''12h'

问题2报告编辑器显示 "24h"

  • formatTimeDisplay('14:30', '24h') 中,格式字符串 '24h' 不包含 HH/hh/mm/A 等任何替换 token函数直接原样返回 '24h'
  • 这是 F1 根因的直接后果:formFieldsConfig 中的 timeFormat = '24h' 被传入格式化函数。

问题3输入框点击失效

  • TemplateManage.tsx 字段管理列表位于一个 overflow-y-auto 的滚动容器中。
  • 点击字段卡片后,卡片内部展开编辑表单,高度瞬间增加。如果卡片原本位于可视区域底部,展开后的输入框可能刚好处于容器边缘之外。
  • 浏览器的 hit-testing 在布局突变时可能无法正确将点击事件路由到新出现的输入框上,导致需要手动滚动后才能点击。

修改文件清单

文件 修改内容
src/types.ts DEFAULT_FORM_FIELDSstartTime/endTimetimeFormat'24h' 改为 'HH:mm'
src/pages/ReportEditor.tsx formatTimeDisplay 开头增加 if (fmt === '24h') fmt = 'HH:mm'; 兼容兜底
src/pages/TemplateManage.tsx defaultFormats 初始化时过滤掉旧脏数据 '24h'/'12h';② datalist 渲染时按字段类型date/time过滤选项③ 字段编辑卡片 onClick 中增加 scrollIntoView

具体代码变更

1. types.ts

// 修改前
{ key: 'startTime', label: '手术开始时间', category: '时间', type: 'time', visibleInForm: true, isSystemLocked: true, timeFormat: '24h', timeDefault: 'specific' },
{ key: 'endTime', label: '手术终止时间', category: '时间', type: 'time', visibleInForm: true, isSystemLocked: true, timeFormat: '24h', timeDefault: 'specific' },

// 修改后
{ key: 'startTime', label: '手术开始时间', category: '时间', type: 'time', visibleInForm: true, isSystemLocked: true, timeFormat: 'HH:mm', timeDefault: 'specific' },
{ key: 'endTime', label: '手术终止时间', category: '时间', type: 'time', visibleInForm: true, isSystemLocked: true, timeFormat: 'HH:mm', timeDefault: 'specific' },

2. ReportEditor.tsx

// 在 formatTimeDisplay 函数开头增加一行兼容兜底
const formatTimeDisplay = (timeStr: string, fmt?: string): string => {
  if (!timeStr || !fmt) return timeStr || '';
  if (fmt === '24h') fmt = 'HH:mm'; // 兼容旧脏数据
  // ... 后续代码不变
};

3. TemplateManage.tsx

3.1 清理旧脏数据(初始化时)

// 修改前
const savedFormats = storage.get<string[]>('customTimeFormats', []);
const defaultFormats = ['YYYY-MM-DD', 'YYYY年MM月DD日', 'MM-DD', 'MM月DD日', 'HH:mm', 'hh:mm A'];
setCustomTimeFormats(Array.from(new Set([...defaultFormats, ...savedFormats])));

// 修改后
const savedFormats = storage.get<string[]>('customTimeFormats', []);
const defaultFormats = ['YYYY-MM-DD', 'YYYY年MM月DD日', 'MM-DD', 'MM月DD日', 'HH:mm', 'hh:mm A'];
// 过滤掉历史遗留的无效旧格式
const cleanedSaved = savedFormats.filter(f => f !== '24h' && f !== '12h');
setCustomTimeFormats(Array.from(new Set([...defaultFormats, ...cleanedSaved])));

3.2 按字段类型过滤 datalist 在编辑字段和新增字段的 format <datalist> 渲染处,增加按 field.type / newFieldForm.type 过滤:

<datalist id={`edit-format-list-${field.key}`}>
  {customTimeFormats
    .filter(fmt => {
      const isDateFormat = /YYYY|MM|DD/.test(fmt);
      const isTimeFormat = /HH|hh|mm|A/.test(fmt);
      if (field.type === 'date') return isDateFormat;
      if (field.type === 'time') return isTimeFormat;
      return true;
    })
    .map(fmt => <option key={fmt} value={fmt} />)}
</datalist>

新增字段的 datalist 同理。

3.3 编辑卡片点击后自动滚动对齐

onClick={(e) => {
  setEditingFieldKey(field.key);
  // ... 其他 setState
  
  const target = e.currentTarget;
  setTimeout(() => {
    target.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  }, 50);
}}

风险点与应对措施

风险 应对措施
清理 customTimeFormats 中的 '24h'/'12h' 可能误删用户真正想保留的自定义格式 仅过滤精确匹配 '24h''12h' 两个字符串,不影响其他自定义格式
按类型过滤 datalist 可能误过滤 使用正则 `/YYYY
scrollIntoView 在极端短容器中频繁触发 使用 block: 'nearest' 而非 'start'减少不必要的滚动50ms 延迟确保 DOM 已撑开

回滚策略

  • types.ts 的修改可直接回退两个字段的 timeFormat 字符串。
  • ReportEditor.tsx 的修改仅增加一行,删除即可。
  • TemplateManage.tsx 的修改均为增量逻辑,回滚时移除条件块即可。