# 模块文档:报告编辑器 ## 涉及文件 - `src/pages/ReportEditor.tsx` - `src/api/reports.ts` - `src/api/ai.ts` - `src/api/speech.ts` - `src/api/library.ts` - `src/api/files.ts` - `src/utils/defaultContent.ts` - `src/utils/print.ts` - `src/types.ts` ## 模块职责 报告编辑器是系统核心模块,负责新建/编辑报告、字段同步、富文本排版、视频关键帧处理、AI 辅助撰写、语音输入、草稿恢复和报告保存。 ## 页面模式 - `/report-editor`:新建报告。 - `/report-editor?id=RPT_xxx`:编辑已有报告。 - `/report-editor?id=RPT_xxx&restore=1`:从历史版本恢复内容后进入编辑器。 ## 草稿机制 编辑器会在卸载、页面隐藏和部分操作后写入 `reportEditorDraft_${username}`。草稿包含正文 HTML、表单数据、视频列表、关键帧、当前标签页、模板 ID 和 AI 聊天上下文。 保存报告后会清理草稿。 ## 智能字段 模板中的智能字段形如: ```html ``` 编辑器会把侧边表单状态同步到正文,也会在用户直接编辑正文中的绑定字段时反向更新表单。日期和时间字段会按字段配置做格式化和解析。 字段库优先从 `/api/library/fields` 读取,成功后同步 `formFieldsConfig`、`multiSelectOptions` 和 `anesthesiaOptions` 兼容缓存;只有开发模式或显式开启 `VITE_ENABLE_LOCAL_FALLBACK=true` 时,API 不可用才继续读取本地缓存。 ## 图片占位符 `.image-placeholder` 用于在模板或报告中保留图片位置。 - 普通占位符可点击选择图片,也可接收视频关键帧。 - `data-mode="manual"` 用于 Logo、签名等静态位置,不允许拖入关键帧。 - 已填充图片后会增加 `.has-image`。 模板图片资源优先从 `/api/files?kind=TEMPLATE_ASSET` 读取;只有本地回退开启时,API 不可用才继续读取本地 `imageAssets`。 ## 视频与抽帧 用户上传视频后,系统使用浏览器对象 URL 进行即时预览,同时优先通过 `POST /api/files` 以 `kind = VIDEO` 上传后端文件资源。抽帧逻辑按系统设置中的 `framePositions` 百分比定位视频时间,绘制到 canvas 后转为 JPEG,并优先以 `kind = FRAME` 上传后端文件资源。 支持: - 自动抽帧。 - 手动截帧。 - 点击关键帧跳转视频时间。 - 拖拽关键帧到报告占位符。 - 自动把选中的抽帧序号插入空置图片占位符。 报告保存前会等待当前视频和关键帧上传完成,并把 `fileId/url`、排序和抽帧信息通过 Reports API 同步到后端 `ReportMedia` 关系表。只有本地回退开启时,API 不可用才保留本地对象 URL/Data URL 回退。 ## AI 撰写 AI 面板支持两种模式: - 对话模式:根据当前报告内容和图片上下文回答问题。 - 修改模式:选中 `.ai-region` 后要求模型返回 JSON,其中包含 `reply` 和 `updatedHtml`。 模型返回 HTML 后,系统会清理换行和 `
`,生成差异预览。用户确认后才写入目标 `.ai-content`。 当前 AI 调用使用后端代理: - `/api/ai/chat` - 后端读取全局共用 Provider Key 并代理到 OpenAI 兼容 `/chat/completions` - 支持图片以 `image_url` 内容传入 ## 语音输入 讯飞听写通过后端 WebSocket 代理: - 前端连接 `/api/speech/iat`,不再生成讯飞鉴权 URL,也不读取 APPID/APIKey/APISecret。 - 浏览器采集麦克风音频,转换为 16k PCM 后发送音频帧。 - 启动前会检查浏览器是否支持 `navigator.mediaDevices.getUserMedia` 和 `AudioContext`;如果不是 `localhost` 或 HTTPS 等安全上下文,浏览器会禁止麦克风能力。Docker 演示环境可使用 `https://localhost:4443`,局域网普通 HTTP 只能通过 Chrome/Edge 演示启动参数临时标记为可信来源。 - 后端读取 Settings API 中的 `xfSpeechConfig`,连接讯飞 IAT,上游首帧由后端补齐 `common.app_id` 和默认 `business` 参数。 - 识别结果由后端转发回前端,并追加到 AI 输入框。 ## 保存规则 - 保存草稿不强制患者姓名和住院号。 - 完成报告要求患者姓名和住院号。 - 保存失败时会优先展示后端返回的真实错误;如果 Session 失效,会提示重新登录并返回登录页。 - 保存时优先调用 `POST /api/reports` 或 `PATCH /api/reports/:id`;后端会先做 HTML 白名单清洗,再写入 PostgreSQL 并维护历史版本。 - 编辑已有已完成报告时,后端会把旧内容追加到历史记录并递增 `revision`。 - 只有本地回退开启时,API 不可用才保留原有本地 `localStorage.reports` 保存逻辑;生产构建默认关闭这条路径。 - 完成报告后跳转到报告管理页。