209 lines
11 KiB
Markdown
209 lines
11 KiB
Markdown
# 手术图文病历报告系统 —— AI 代理开发指南
|
||
|
||
> 本文档面向 AI 编码代理。若你正在阅读此文件,说明你对该项目一无所知,请仔细阅读后再修改代码。
|
||
|
||
---
|
||
|
||
## 1. 项目概述
|
||
|
||
**手术图文病历报告系统**是一款基于 **React 19 + TypeScript + Vite + Tailwind CSS 4** 开发的纯前端医疗图文报告管理应用。所有数据持久化在浏览器 `localStorage` 中,无需后端服务即可独立运行。
|
||
|
||
### 核心功能
|
||
- **图文报告生成**:基于 `contentEditable` 的富文本编辑器,支持插入表格、图片占位符,可从本地或手术视频中截取关键帧插入报告。
|
||
- **报告管理**:搜索、筛选、查看、编辑、打印、删除报告;支持历史版本回溯。
|
||
- **模板管理**:创建和维护报告标准模板,新建报告时自动加载默认模板。
|
||
- **用户管理**:基于角色的权限控制(超级管理员 / 管理员 / 医生)。
|
||
- **系统设置**:配置视频自动抽帧百分比、AI API 接口地址、默认模板等全局参数。
|
||
|
||
### 默认测试账号
|
||
| 账号 | 密码 | 角色 |
|
||
|---------|--------|------------|
|
||
| admin | 123456 | 超级管理员 |
|
||
| manager | 123456 | 管理员 |
|
||
| 0001 | 123456 | 医生 |
|
||
|
||
---
|
||
|
||
## 2. 技术栈与运行时架构
|
||
|
||
### 技术栈
|
||
- **框架**:React 19(函数组件 + Hooks)
|
||
- **路由**:React Router DOM 7(`BrowserRouter`)
|
||
- **构建工具**:Vite 6
|
||
- **样式**:Tailwind CSS 4(使用 `@import "tailwindcss"` 和 `@theme` 语法)
|
||
- **图标**:Lucide React
|
||
- **动画**:Motion
|
||
- **语言**:TypeScript 5.8(`tsconfig.json` 中 `jsx: "react-jsx"`、`moduleResolution: "bundler"`)
|
||
- **其他依赖**:`@google/genai`(预留 AI 功能)
|
||
|
||
### 运行时架构
|
||
- **纯前端 SPA**:无后端 API,所有业务逻辑在浏览器端执行。
|
||
- **数据存储**:全部使用 `localStorage`(通过 `src/utils/storage.ts` 封装)和少量 `sessionStorage`(用于版本恢复)。
|
||
- **安全模型**:客户端认证授权,密码以**明文**形式保存在 `localStorage` 中。项目设计用于内网或受信任环境,**切勿直接暴露到公网**。
|
||
|
||
---
|
||
|
||
## 3. 项目目录结构
|
||
|
||
```
|
||
.
|
||
├── docker-compose.yaml # Docker Compose 配置(端口 4002:80)
|
||
├── Dockerfile # 多阶段构建:node:20-alpine -> nginx:alpine
|
||
├── nginx.conf # Nginx SPA 回退配置(try_files)
|
||
├── package.json # 依赖与脚本
|
||
├── vite.config.ts # Vite 配置(含 GEMINI_API_KEY 注入)
|
||
├── tsconfig.json # TypeScript 配置(paths: "@/*": "./*")
|
||
├── index.html # Vite 入口 HTML
|
||
├── public/ # 静态资源(logo、favicon)
|
||
└── src/
|
||
├── App.tsx # 根组件与路由表
|
||
├── main.tsx # 应用入口(createRoot + StrictMode)
|
||
├── index.css # 全局样式、Tailwind 主题、打印样式、编辑器专用样式
|
||
├── types.ts # 核心 TypeScript 类型定义
|
||
├── components/
|
||
│ └── Sidebar.tsx # 左侧导航栏(按角色过滤菜单)
|
||
├── pages/
|
||
│ ├── Login.tsx # 登录页(初始化默认数据)
|
||
│ ├── Dashboard.tsx # 工作台概览(统计图表 + 快捷入口)
|
||
│ ├── ReportEditor.tsx # 图文报告编辑器(最复杂的页面,约 1400+ 行)
|
||
│ ├── ReportManage.tsx # 报告列表管理
|
||
│ ├── ReportView.tsx # 报告查看/打印
|
||
│ ├── TemplateManage.tsx # 模板管理
|
||
│ ├── UserManage.tsx # 用户管理
|
||
│ └── SystemSettings.tsx # 系统设置
|
||
└── utils/
|
||
├── storage.ts # localStorage/sessionStorage 封装
|
||
├── print.ts # 基于 iframe 的 A4 打印实现
|
||
└── defaultContent.ts # 默认手术报告模板 HTML 字符串
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 构建、运行与部署
|
||
|
||
### 本地开发
|
||
```bash
|
||
# 安装依赖
|
||
npm install
|
||
|
||
# 启动开发服务器(端口 3000,监听 0.0.0.0)
|
||
npm run dev
|
||
```
|
||
|
||
### 可用脚本(package.json)
|
||
| 脚本 | 作用 |
|
||
|-----------|-----------------------------------|
|
||
| `dev` | `vite --port=3000 --host=0.0.0.0` |
|
||
| `build` | `vite build`(输出到 `dist/`) |
|
||
| `preview` | `vite preview` |
|
||
| `lint` | `tsc --noEmit`(类型检查) |
|
||
| `clean` | `rm -rf dist` |
|
||
|
||
### 环境变量
|
||
复制 `.env.example` 为 `.env.local`(或 `.env`):
|
||
- `GEMINI_API_KEY`:Google Gemini API 密钥(预留 AI 功能,Vite 会在构建时通过 `define` 注入为 `process.env.GEMINI_API_KEY`)。
|
||
- `APP_URL`:应用部署后的访问地址。
|
||
|
||
### Docker 部署
|
||
```bash
|
||
# 构建并启动(访问 http://localhost:4002)
|
||
docker-compose up -d --build
|
||
|
||
# 停止
|
||
docker-compose down
|
||
```
|
||
- **构建阶段**:`node:20-alpine` 执行 `npm ci` + `npm run build`
|
||
- **运行阶段**:`nginx:alpine` 托管 `dist/` 静态资源
|
||
- **SPA 支持**:`nginx.conf` 已配置 `try_files $uri $uri/ /index.html;`
|
||
|
||
---
|
||
|
||
## 5. 代码组织与开发约定
|
||
|
||
### 路由结构
|
||
所有路由定义在 `src/App.tsx`:
|
||
- `/` → 登录页
|
||
- `/dashboard` → 工作台
|
||
- `/report-editor` → 新建报告(`?id=xxx` 为编辑)
|
||
- `/report-view/:id` → 查看报告
|
||
- `/report-manage` → 报告管理
|
||
- `/template-manage` → 模板管理
|
||
- `/user-manage` → 用户管理
|
||
- `/system-settings` → 系统设置
|
||
|
||
### 权限模型
|
||
角色分为三种:`super`(超级管理员)、`admin`(管理员)、`user`(医生)。
|
||
- 各页面在 `useEffect` 中读取 `storage.get('currentUser')`,未登录则 `navigate('/')`。
|
||
- `Sidebar.tsx` 的 `navItems` 按 `roles` 数组过滤菜单。
|
||
- `user` 角色只能查看/编辑自己创建的报告;`super`/`admin` 可查看全院报告。
|
||
- `admin` 只能管理同部门(`department`)的 `user` 角色用户,且一个部门只能有一个管理员。
|
||
- 用户对象包含 `visibleTemplates`(可视模板)和 `manageableTemplates`(可管理模板)数组,用于细粒度模板权限控制。
|
||
|
||
### 数据持久化约定
|
||
- **禁止直接调用 `localStorage`**,统一使用 `src/utils/storage.ts` 中的 `storage.get / storage.set / storage.remove`。
|
||
- localStorage 中存储的 key 包括:`users`、`reports`、`templates`、`systemSettings`、`currentUser`、`multiSelectOptions`、`anesthesiaOptions`、`reportEditorDraft_{username}`。
|
||
- sessionStorage 中存储的 key 包括:`restore_{reportId}`(用于历史版本恢复)。
|
||
- 报告编辑器会在 `beforeunload` 和 `visibilitychange` 时自动保存草稿到 `reportEditorDraft_{username}`。
|
||
|
||
### 样式约定
|
||
- 全局使用 Tailwind 工具类;自定义设计变量定义在 `src/index.css` 的 `@theme` 中(如 `--color-bg`、`--color-accent`)。
|
||
- 通用组件类在 `index.css` 的 `@layer components` 中定义:`.btn-accent`、`.card-minimal`、`.input-minimal`。
|
||
- **编辑器样式**(`.editor-content`、`.editor-content-wrapper`、`.image-placeholder`)和 **打印样式**(`@media print`)集中在 `index.css` 中维护。
|
||
- A4 打印尺寸为 `210mm × 297mm`,打印时通过 `visibility` 控制只显示 `.print-content` 区域。
|
||
|
||
### 编辑器实现细节
|
||
- `ReportEditor.tsx` 和 `TemplateManage.tsx` 使用原生 `contentEditable` + `document.execCommand` 实现富文本,而非第三方编辑器。
|
||
- 图片通过 `.image-placeholder` 占位符插入,支持两种填充方式:
|
||
1. 点击占位符上传本地图片(Base64 存入 HTML)。
|
||
2. 从右侧“视频分析”面板拖拽自动抽帧的截图到占位符中。
|
||
- 视频中上传后会根据 `systemSettings.framePositions` 自动抽帧(通过 `<video>` + `<canvas>` 实现)。
|
||
- 自动抽帧支持“自动帧插入”功能:开启后,抽得的帧会按延迟顺序自动填入编辑器中的空图片占位符。
|
||
|
||
### TypeScript 类型
|
||
核心类型定义在 `src/types.ts`:
|
||
- `User`:用户,角色为 `'super' | 'admin' | 'user'`,含 `visibleTemplates` 和 `manageableTemplates`
|
||
- `Report`:报告,状态为 `'draft' | 'completed'`,含 `content`(HTML 字符串)、`videos`、`capturedFrames`、`history`
|
||
- `Template`:模板,结构与报告内容类似
|
||
- `SystemSettings`:系统设置,含 `frameCount`、`framePositions`、`apiEndpoint`、`apiKey`、`defaultTemplate`、`frameMode`、`autoInsertFrames`、`autoInsertFrameIndices`、`autoInsertDelay`
|
||
- `CapturedFrame`:视频抽帧结果,含 `dataUrl`、`isManual` 等
|
||
|
||
### 路径别名
|
||
- `vite.config.ts` 和 `tsconfig.json` 均配置了 `@/` 指向项目根目录(`.`)。
|
||
- 源码中导入使用相对路径(如 `../utils/storage`)或 `@/` 均可。
|
||
|
||
---
|
||
|
||
## 6. 测试策略
|
||
|
||
**当前项目没有单元测试或 E2E 测试框架。**
|
||
|
||
- 唯一可用的质量检查命令是 `npm run lint`,它执行 `tsc --noEmit` 进行全量类型检查。
|
||
- 在修改代码后,**务必运行 `npm run lint` 确保无 TypeScript 编译错误**。
|
||
- 若你引入了新依赖或修改了复杂交互逻辑,建议在本地通过 `npm run dev` 进行手工功能验证(可快速使用登录页的“快捷登录测试账号”)。
|
||
|
||
---
|
||
|
||
## 7. 安全与部署注意事项
|
||
|
||
### 安全警告(必读)
|
||
1. **无后端哈希**:用户密码以明文保存在浏览器 `localStorage` 中。
|
||
2. **客户端鉴权**:所有权限判断都在前端执行,易被绕过。
|
||
3. **因此,该应用仅适合部署在医院内网、受信任的局域网或单人使用的环境中,严禁直接暴露于公网。**
|
||
|
||
### 部署检查清单
|
||
- [ ] `nginx.conf` 中的 `try_files` 确保 SPA 刷新不 404。
|
||
- [ ] `dist/` 构建产物已包含在 Docker 镜像中。
|
||
- [ ] 若启用 AI 功能,需正确配置 `GEMINI_API_KEY` 环境变量(Vite 在构建时注入,修改后需重新构建)。
|
||
- [ ] 确保最终运行环境可访问 `https://fonts.googleapis.com/css2?family=Inter`(否则页面字体会降级为系统默认字体)。
|
||
|
||
---
|
||
|
||
## 8. 给 AI 代理的快速备忘
|
||
|
||
- **不要直接操作 `localStorage`**,用 `src/utils/storage.ts`。
|
||
- **不要引入重型富文本编辑器**,现有方案基于 `contentEditable` + `document.execCommand`,保持轻量。
|
||
- **打印逻辑**已封装在 `src/utils/print.ts`,需要打印 A4 报告时直接调用 `printDocument(htmlContent)`。
|
||
- **修改样式时优先检查 `src/index.css`**,Tailwind v4 的主题变量和打印样式都在那里。
|
||
- **添加新页面后**,记得在 `src/App.tsx` 注册路由,并在 `src/components/Sidebar.tsx` 的 `navItems` 中配置菜单和可见角色。
|
||
- **修改 Docker 端口映射时**,同步更新 `docker-compose.yaml` 和本文件中的说明。
|