Files
Mdeical_Sur_Report/docs/component-structure.md
admin bc235b2358 Document frontend component structure
- Add docs/component-structure.md covering the current React component hierarchy, page routes, public components, API/Auth/Utils boundaries, and data flow.

- Document the internal responsibilities and split risks for large pages including ReportEditor and TemplateManage.

- Link the new component structure guide from README, docs index, AGENTS file tree, and progress notes.
2026-05-02 02:36:55 +08:00

296 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端组件结构
本文档描述当前 React 前端的实际组织方式、页面组件边界、API/Auth/Utils 分层,以及后续拆分建议。它不把未来计划当作已实现事实;当前系统仍以页面级组件为主,只有少量公共组件。
## 总体结构
```text
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/ # 存储、权限、默认模板、打印等通用工具
```
当前组件层级大致为:
```text
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` 驱动。
- 报告正文编辑区:`contentEditable` HTML、智能字段和图片占位符。
- 视频分析区:视频上传、预览、自动抽帧、手动截帧。
- 关键帧列表:点击插入、拖拽插入、后端文件上传状态。
- AI 撰写面板:对话、区域改写、差异确认和 AI 日志导出。
- 语音输入:浏览器麦克风采集,连接 `/api/speech/iat`
- 保存逻辑:优先调用 Reports API并同步 `ReportMedia` 所需的视频/关键帧引用。
重要状态来源:
- `reportData`:报告结构化字段。
- `contentRef`:报告正文 DOM。
- `videos` / `capturedFrames`:视频和关键帧。
- `settings`系统设置、抽帧策略、AI/语音开关。
- `formFields`:字段库。
- `chatMessages` / AI 相关状态AI 面板上下文。
后续拆分优先级:
1. 抽出报告基本信息表单。
2. 抽出富文本工具栏和正文编辑器适配层。
3. 抽出视频上传/抽帧/关键帧列表。
4. 抽出 AI 面板和 Diff 确认弹窗。
5. 抽出报告保存 hook例如 `useReportPersistence`
拆分时要保持字段绑定、图片占位符、历史恢复和保存顺序兼容。
### `ReportManage` 与 `ReportView`
`ReportManage` 负责列表型工作流:
- 调用 Reports API 获取权限过滤后的报告。
- 前端搜索、状态筛选和日期筛选。
- 删除报告、历史恢复、JSON 导出和批量操作。
`ReportView` 负责只读展示:
- 调用 Reports API 获取详情。
- 渲染报告 HTML。
- 调用 `printDocument` 进入浏览器打印。
这两个页面与 `ReportEditor` 通过路由和 `sessionStorage.restore_${reportId}` 协作。
### `TemplateManage`
当前第二大页面组件,约 1800 行。职责包括:
- 模板列表、选择、新增、复制、删除。
- 模板正文 `contentEditable` 编辑。
- 富文本命令、表格、字段、图片占位符、AI 区域插入。
- 字段库维护。
- 模板图片资源上传和删除。
- 模板 JSON 导入导出。
后续拆分优先级:
1. 抽出模板列表和模板元信息编辑。
2. 抽出模板内容编辑器和工具栏。
3. 抽出字段库管理面板。
4. 抽出图片资源管理面板。
5. 抽出导入导出工具。
### `UserManage`
主要职责:
- 调用 Users API 管理用户。
- 调用 Departments API 读取部门和更新模板授权。
- 管理角色、状态、密码、签名和部门模板权限。
- 校验默认超级管理员、当前用户、管理员唯一性等 UI 规则。
后端仍会做最终权限校验;前端限制只用于减少误操作。
### `SystemSettings`
主要职责:
- 调用 Settings API 读取、保存和重置系统设置。
- 超级管理员维护抽帧、自动插入、AI Provider、讯飞配置。
- 普通用户主要维护个人默认模板。
- 本地回退开启时API 不可用才读取或保存本地 `systemSettings`
AI Key 和讯飞密钥由后端代理使用,普通用户读取设置时不会拿到真实密钥。
### `AuditLogs`
主要职责:
- 调用 Audit API 获取审计日志。
- 支持动作、目标类型、关键字和分页筛选。
- 格式化元数据、动作名称和目标类型。
管理员只能看到后端允许范围内的日志,超级管理员可看全部。
## 数据流
常见后端化数据流:
```text
Page Component
└── src/api/<resource>.ts
└── apiRequest()
└── /api/<resource>
└── NestJS module/service
└── Prisma/PostgreSQL or file storage
```
登录态数据流:
```text
Login
└── AuthContext.login()
└── POST /api/auth/login
└── HttpOnly Session Cookie
└── AuthContext.refresh()
└── GET /api/auth/me
```
开发/迁移期兼容数据流:
```text
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`,拆分时必须保持清洗、打印和字段绑定一致。