- Add fieldLibrary metadata to HTML template packages, including form fields, custom time formats, multi-select options, and anesthesia options. - Restore imported template field metadata into local compatibility caches and the backend field library API when available. - Preserve legacy JSON template import compatibility while keeping user-facing exports on HTML packages. - Prevent template field saves from overwriting stored multi-select and anesthesia options with empty values. - Update README, AGENTS, feature, requirement, design, module, progress, component, and testing docs for complete template export behavior. - Extend template export tests to cover field library metadata round-tripping.
12 KiB
前端组件结构
本文档描述当前 React 前端的实际组织方式、页面组件边界、API/Auth/Utils 分层,以及后续拆分建议。它不把未来计划当作已实现事实;当前系统仍以页面级组件为主,只有少量公共组件。
总体结构
src/
├── App.tsx # AuthProvider、Router 和路由守卫
├── main.tsx # React 挂载入口
├── index.css # Tailwind 主题、全局样式和组件类
├── types.ts # 核心前端类型和默认配置
├── api/ # 前端 API client 和各业务 API 封装
├── auth/ # 登录态 Context 和后端用户 DTO 映射
├── components/ # 跨页面公共组件
├── config/ # 运行时开关
├── pages/ # 页面级组件,当前主要业务 UI 都在这里
├── test/ # Vitest/jsdom 全局测试设置
└── utils/ # 存储、权限、默认模板、打印等通用工具
当前组件层级大致为:
main.tsx
└── App
└── AuthProvider
└── BrowserRouter
└── RequireAuth
├── Sidebar
└── pages/*
RequireAuth 在 src/App.tsx 中定义,负责前端路由保护和角色入口控制。真正的生产安全边界仍以后端 API 权限校验为准。
路由与页面
| 路由 | 页面组件 | 角色入口 | 主要职责 |
|---|---|---|---|
/ |
Login |
未登录 | 默认数据兼容初始化、登录表单、调用 Auth Context。 |
/dashboard |
Dashboard |
全部登录用户 | 工作台统计、趋势和快捷入口。 |
/report-editor |
ReportEditor |
全部登录用户 | 新建/编辑报告、富文本、字段同步、视频抽帧、AI、语音、保存。 |
/report-manage |
ReportManage |
全部登录用户 | 报告列表、搜索筛选、历史恢复、删除、导出。 |
/report-view/:id |
ReportView |
全部登录用户 | 报告查看、受控报告读取、浏览器打印。 |
/template-manage |
TemplateManage |
超级管理员、管理员 | 模板内容、字段库、图片资源、导入导出。 |
/user-manage |
UserManage |
超级管理员、管理员 | 用户、部门、模板授权和签名维护。 |
/audit-logs |
AuditLogs |
超级管理员、管理员 | 审计日志列表、筛选和展示。 |
/system-settings |
SystemSettings |
全部登录用户 | 全局设置和个人默认模板;超级管理员可维护 AI/语音/抽帧。 |
页面组件普遍直接组合 UI、状态、API 调用和本地兼容缓存逻辑。新增复杂功能时应优先判断是否需要抽到 api/、utils/ 或新的子组件中,避免继续扩大巨型页面。
公共组件
src/components/Sidebar.tsx
当前唯一跨页面公共组件。职责包括:
- 根据 Auth Context 中的当前用户展示导航入口。
- 在 Auth Context 不可用时回退读取
localStorage.currentUser。 - 在
/report-editor和/template-manage中自动折叠。 - 调用
auth.logout()退出登录,并清理本地登录态。
测试:src/components/Sidebar.test.tsx 覆盖角色菜单过滤。
认证层
src/auth/AuthContext.tsx
AuthProvider 是前端登录态入口:
- 启动时调用
/api/auth/me恢复后端 Session。 login调用/api/auth/login。logout调用/api/auth/logout并清理本地currentUser。syncUser把后端安全用户 DTO 转为前端User,并同步迁移期本地缓存。
src/auth/backendUser.ts
负责后端用户模型到前端历史类型的兼容映射:
- 后端
doctor映射为前端user。 - 后端
departmentName映射为前端department。 - 部门模板授权映射为
visibleTemplates和manageableTemplates。
新增用户字段时,应优先在后端 DTO、backendUser.ts、src/types.ts 和对应测试中一起更新。
API 层
src/api/client.ts 是唯一底层请求封装:
- 默认请求相对路径
/api/...。 - 请求带
credentials: 'include',用于 HttpOnly Session Cookie。 - 解包后端
{ data }响应。 - 统一抛出
ApiError。
业务 API 按资源拆分:
| 文件 | 职责 |
|---|---|
ai.ts |
AI 模型列表和聊天代理。 |
audit.ts |
审计日志查询。 |
dashboard.ts |
工作台统计。 |
files.ts |
签名、模板图片、视频、关键帧等文件资源。 |
library.ts |
字段库和选项库。 |
reports.ts |
报告列表、详情、保存和删除。 |
settings.ts |
系统设置读取、保存、重置。 |
speech.ts |
讯飞语音 WebSocket URL 生成。 |
templates.ts |
模板列表、详情、创建、更新、删除。 |
users.ts |
用户、部门和部门模板授权。 |
页面组件不应直接拼接第三方 API 或绕过 api/client.ts 调后端。新增后端接口时,优先新增或扩展对应 src/api/*.ts,再由页面调用。
工具层
| 文件 | 职责 |
|---|---|
storage.ts |
localStorage/sessionStorage JSON 封装,systemSettings 做兼容混淆读取。 |
permissions.ts |
前端角色、报告可见性和模板可见性判断。仅用于体验和开发回退。 |
defaultContent.ts |
默认报告 HTML 模板,包含 data-bind 字段、图片占位符和 AI 区域。 |
print.ts |
iframe 打印工具。 |
工具层应保持无 React UI 依赖。业务规则如果已后端化,应以后端策略为准,前端工具只做展示过滤或离线回退。
页面内部结构
Login
主要职责:
- 初始化迁移期默认数据:用户、模板、字段、图片资源、系统设置。
- 提交登录表单到
AuthContext.login。 - 展示默认测试账号。
注意:真实账号认证已由后端处理,本地 users.password 只是旧兼容数据,不是安全边界。
Dashboard
主要职责:
- 调用
getDashboardStats读取后端统计。 - 根据角色展示报告、用户、模板、近期趋势和快捷入口。
- API 不可用且本地回退开启时,从本地报告、用户、模板构造统计。
ReportEditor
当前最大页面组件,约 3000 行。它同时承担 UI、状态、富文本编辑、媒体处理和 API 调用。
主要内部区域:
- 顶部工具栏:返回、保存草稿、完成报告、打印等操作。
- 基本信息表单:由字段库和
reportData驱动。 - 报告正文编辑区:
contentEditableHTML、智能字段和图片占位符。 - 视频分析区:视频上传、预览、自动抽帧、手动截帧。
- 关键帧列表:点击插入、拖拽插入、后端文件上传状态。
- AI 撰写面板:对话、区域改写和差异确认。
- 语音输入:浏览器麦克风采集,连接
/api/speech/iat。 - 保存逻辑:优先调用 Reports API,并同步
ReportMedia所需的视频/关键帧引用。
重要状态来源:
reportData:报告结构化字段。contentRef:报告正文 DOM。videos/capturedFrames:视频和关键帧。settings:系统设置、抽帧策略、AI/语音开关。formFields:字段库。chatMessages/ AI 相关状态:AI 面板上下文。
后续拆分优先级:
- 抽出报告基本信息表单。
- 抽出富文本工具栏和正文编辑器适配层。
- 抽出视频上传/抽帧/关键帧列表。
- 抽出 AI 面板和 Diff 确认弹窗。
- 抽出报告保存 hook,例如
useReportPersistence。
拆分时要保持字段绑定、图片占位符、历史恢复和保存顺序兼容。
ReportManage 与 ReportView
ReportManage 负责列表型工作流:
- 调用 Reports API 获取权限过滤后的报告。
- 前端搜索、状态筛选和日期筛选。
- 删除报告、历史恢复、打印/PDF 导出和批量操作。
ReportView 负责只读展示:
- 调用 Reports API 获取详情。
- 渲染报告 HTML。
- 调用
printDocument进入浏览器打印。
这两个页面与 ReportEditor 通过路由和 sessionStorage.restore_${reportId} 协作。
TemplateManage
当前第二大页面组件,约 1800 行。职责包括:
- 模板列表、选择、新增、复制、删除。
- 模板正文
contentEditable编辑。 - 富文本命令、表格、字段、图片占位符、AI 区域插入。
- 字段库维护。
- 模板图片资源上传和删除。
- 模板 HTML 模板包导出和 HTML/历史 JSON 模板包导入;HTML 包内嵌模板字段和字段管理设置。
后续拆分优先级:
- 抽出模板列表和模板元信息编辑。
- 抽出模板内容编辑器和工具栏。
- 抽出字段库管理面板。
- 抽出图片资源管理面板。
- 抽出导入导出工具。
UserManage
主要职责:
- 调用 Users API 管理用户。
- 调用 Departments API 读取部门和更新模板授权。
- 管理角色、状态、密码、签名和部门模板权限。
- 校验默认超级管理员、当前用户、管理员唯一性等 UI 规则。
后端仍会做最终权限校验;前端限制只用于减少误操作。
SystemSettings
主要职责:
- 调用 Settings API 读取、保存和重置系统设置。
- 超级管理员维护抽帧、自动插入、AI Provider、讯飞配置。
- 普通用户主要维护个人默认模板。
- 本地回退开启时,API 不可用才读取或保存本地
systemSettings。
AI Key 和讯飞密钥由后端代理使用,普通用户读取设置时不会拿到真实密钥。
AuditLogs
主要职责:
- 调用 Audit API 获取审计日志。
- 支持动作、目标类型、关键字和分页筛选。
- 格式化元数据、动作名称和目标类型。
管理员只能看到后端允许范围内的日志,超级管理员可看全部。
数据流
常见后端化数据流:
Page Component
└── src/api/<resource>.ts
└── apiRequest()
└── /api/<resource>
└── NestJS module/service
└── Prisma/PostgreSQL or file storage
登录态数据流:
Login
└── AuthContext.login()
└── POST /api/auth/login
└── HttpOnly Session Cookie
└── AuthContext.refresh()
└── GET /api/auth/me
开发/迁移期兼容数据流:
Page Component
├── Try backend API first
└── If API failed and VITE_ENABLE_LOCAL_FALLBACK=true
└── localStorage/sessionStorage compatibility path
生产构建默认不应依赖本地回退作为主要数据来源。
新增组件约定
- 复用业务 API 封装,不在组件中重复写
fetch('/api/...')。 - 页面级入口继续放在
src/pages;跨页面复用 UI 放在src/components。 - 只在复杂页面拆分局部子组件时,可以先放在同目录附近;若开始跨页面复用,再移动到
src/components。 - 状态管理优先保持局部化;只有登录态使用 Auth Context。
- 业务规则优先放后端或
src/utils,不要散落在 JSX 条件里。 - 新增复杂组件应配套测试,至少覆盖权限入口、API 错误分支或关键交互之一。
- 修改
ReportEditor、TemplateManage这类大组件时,避免顺手重构无关区域;优先小步拆分并保留行为测试。
当前结构风险
ReportEditor.tsx过大,媒体、AI、语音、富文本和保存逻辑耦合高。TemplateManage.tsx同时承担编辑器、字段库、资源库和导入导出。- 多个页面仍保留本地兼容回退,阅读时要区分主后端路径和回退路径。
- 前端权限工具仍存在,但不能当作生产安全边界。
- HTML 编辑和渲染依赖
contentEditable与dangerouslySetInnerHTML,拆分时必须保持清洗、打印和字段绑定一致。