11 KiB
11 KiB
手术图文病历报告系统 —— Agent 开发指南
本文件面向 AI 编程助手。修改项目结构、构建流程或关键配置后,请同步更新本文档。
项目概览
这是一个面向医院场景的纯前端单页应用(SPA),用于手术记录图文报告的撰写、视频关键帧抽取、模板管理以及基于角色的用户权限控制。
- 名称:手术图文病历报告生成终端 / 智能图文报告管理系统
- 架构:纯前端应用,无后端服务。所有数据(用户、报告、模板、设置、图片资源)均持久化在浏览器
localStorage/sessionStorage中。 - 技术栈:React 19 + TypeScript 5.8 + Vite 6 + Tailwind CSS 4 + React Router DOM 7 + Lucide React(图标)
- 语言:项目界面、注释、文档均为中文。
- 运行环境:现代浏览器(依赖
localStorage、URL.createObjectURL、contenteditable、MutationObserver等 Web API)。
项目结构
.
├── 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 配置(含 Tailwind CSS 插件、路径别名 @)
├── tsconfig.json # TypeScript 配置(ES2022、react-jsx、paths: {"@/*": ["./*"] })
├── index.html # Vite 入口 HTML
├── public/ # 静态资源(logo_square.png、favicon.ico)
└── src/
├── main.tsx # 应用入口(React StrictMode + createRoot)
├── App.tsx # 根组件,定义所有路由(BrowserRouter)
├── index.css # 全局样式、Tailwind 主题变量、编辑器/打印专用样式
├── types.ts # TypeScript 类型定义与常量(User、Report、Template、SystemSettings、FormField 等)
├── components/
│ └── Sidebar.tsx # 侧边导航栏(角色过滤、折叠逻辑、退出登录)
├── pages/
│ ├── Login.tsx # 登录页 + 默认数据初始化(用户、模板、表单字段、系统设置)
│ ├── Dashboard.tsx # 工作台概览(统计卡片、7 天趋势 SVG 图表、快捷入口)
│ ├── ReportEditor.tsx # 图文报告编辑器(最核心、最复杂页面,2000+ 行)
│ ├── ReportManage.tsx # 报告管理(搜索、筛选、查看、编辑、删除、历史、导出)
│ ├── ReportView.tsx # 报告只读查看 + 打印
│ ├── TemplateManage.tsx # 模板管理(富文本编辑器、字段库管理、图片占位符)
│ ├── UserManage.tsx # 用户管理(CRUD、签名上传、角色/模板权限分配)
│ └── SystemSettings.tsx # 系统设置(视频抽帧参数、API 地址、默认模板)
└── utils/
├── storage.ts # localStorage / sessionStorage 封装(JSON 自动序列化)
├── print.ts # 打印工具:通过隐藏 iframe 渲染 A4 内容并调用 window.print()
└── defaultContent.ts # 默认报告模板 HTML(含智能字段绑定语法与图片占位符)
构建与运行命令
# 安装依赖
npm install
# 本地开发(端口 3000,监听 0.0.0.0)
npm run dev
# 生产构建(输出到 dist/)
npm run build
# 预览生产构建
npm run preview
# 类型检查(不输出文件)
npm run lint
# 清理构建产物
npm run clean
Docker 部署
# 构建并运行(访问 http://localhost:4002)
docker-compose up -d --build
# 停止
docker-compose down
构建流程:
- 构建阶段:
node:20-alpine执行npm ci+npm run build - 运行阶段:
nginx:alpine托管dist/静态文件,端口 80 nginx.conf已配置try_files回退,支持 SPA 前端路由刷新不 404。
代码组织与模块划分
路由结构(src/App.tsx)
| 路径 | 页面 | 角色权限 |
|---|---|---|
/ |
Login | 公开 |
/dashboard |
Dashboard | super / admin / user |
/report-editor |
ReportEditor | super / admin / user |
/report-manage |
ReportManage | super / admin / user |
/report-view/:id |
ReportView | super / admin / user(user 只能看自己的) |
/template-manage |
TemplateManage | super / admin |
/user-manage |
UserManage | super / admin |
/system-settings |
SystemSettings | super / admin / user |
核心数据模型(src/types.ts)
User:用户(role: 'super' | 'admin' | 'user')Report:报告(含患者信息、手术信息、富文本content、视频数组、抽帧数组capturedFrames、历史记录history)Template:模板(名称、描述、富文本content)SystemSettings:系统设置(抽帧数量/位置、API 端点、默认模板、自动插帧配置)FormField/FieldType:表单字段配置(支持文本、单选、多选、时间、日期、签名、图片)CapturedFrame:视频关键帧(含视频索引、时间戳、DataURL)
存储层(src/utils/storage.ts)
所有业务数据通过 storage.get<T>(key, fallback) / storage.set<T>(key, value) 读写 localStorage(或 sessionStorage)。不存在任何后端 API 调用。
关键存储键:
users— 用户列表currentUser— 当前登录用户reports— 报告列表templates— 模板列表systemSettings— 系统设置formFieldsConfig— 表单字段配置multiSelectOptions/anesthesiaOptions— 下拉选项缓存imageAssets— 图片资源库(DataURL)reportEditorDraft_${username}— 报告编辑器自动草稿restore_${reportId}— 报告恢复临时内容(sessionStorage)
核心功能实现细节
1. 图文报告编辑器(ReportEditor.tsx)
- 富文本实现:基于原生
contenteditablediv,通过document.execCommand实现加粗、斜体、下划线、对齐、插入表格等。 - A4 纸模拟:编辑器内容区固定宽度
210mm,最小高度297mm,通过MutationObserver动态扩展为多页。 - 图片占位符:
.image-placeholder元素,支持点击上传、拖入视频关键帧、或自动插入抽帧结果。占位符分为data-mode="frame"(可拖入关键帧)和data-mode="manual"(仅手动上传,如 Logo、签名)。 - 智能字段绑定:模板中可插入
<span class="smart-field-wrapper" data-bind="key">,在报告编辑器左侧表单填写后,通过 DOM 查询同步更新编辑器内对应字段值。 - 视频抽帧:支持上传本地视频(
URL.createObjectURL),可手动截图或按百分比位置自动均匀抽帧(autoCaptureFrames)。抽帧结果支持拖入编辑器占位符。 - 自动草稿:在
beforeunload/visibilitychange/ 状态变更时自动保存草稿到localStorage。 - 打印:调用
printDocument()将编辑器 HTML 注入隐藏 iframe 并触发打印;@media print样式隐藏所有非打印元素。
2. 模板管理(TemplateManage.tsx)
- 与报告编辑器共享相似的
contenteditable编辑体验。 - 额外支持字段库管理:可插入/编辑/删除表单字段,字段变更会同步到
formFieldsConfig。 - 模板内容即为 HTML 字符串,存储在
templateslocalStorage 键中。
3. 用户与权限(Login.tsx、UserManage.tsx、Sidebar.tsx)
- 角色体系:
super(超级管理员):拥有所有权限,可管理所有用户。admin(管理员):可管理同科室的user角色用户。user(医生):只能查看/编辑自己创建的报告。
- 权限控制:路由跳转前检查
currentUser.role;Sidebar 根据角色过滤导航项;页面内根据角色隐藏按钮或重定向。 - 默认账号(首次登录或数据缺失时自动初始化):
admin/123456— 超级管理员manager/123456— 管理员0001/123456— 医生
代码风格指南
- 语言:TypeScript,严格模式未开启(
noEmit: true),但代码中广泛使用显式类型注解。 - 组件风格:函数组件 + React Hooks,所有页面组件默认导出。
- CSS:Tailwind CSS 工具类为主,复杂样式(如
contenteditable内部元素、打印样式)写在src/index.css的@layer components中。 - 路径别名:
@/指向项目根目录(vite.config.ts与tsconfig.json均已配置)。 - 图标:统一使用
lucide-react。 - 事件处理:原生 DOM 事件与 React 事件混用(编辑器内大量直接使用
document.execCommand、addEventListener)。 - 状态管理:无 Redux/Zustand,所有状态以 React
useState+useRef+useEffect管理,复杂页面(如 ReportEditor)使用useRef保存最新状态快照以绕过闭包问题。
测试说明
本项目目前未配置任何测试框架,没有单元测试、集成测试或 E2E 测试。
如需添加测试,建议:
- 单元测试:Vitest(与 Vite 生态一致)
- 组件测试:React Testing Library
- E2E 测试:Playwright(测试
localStorage持久化、文件上传、打印流程等)
安全注意事项
⚠️ 关键警告:本应用为纯前端实现,所有认证与授权逻辑均在客户端执行。
- 用户密码以明文形式存储在浏览器
localStorage中,无任何哈希或加密处理。 - 权限控制依赖客户端路由守卫和 UI 隐藏,可被技术手段绕过。
- 所有报告数据、视频对象 URL、图片 DataURL 均保存在用户本地浏览器中,无云端备份。
- 生产环境部署建议:仅限内网或受信任环境使用,不要直接暴露于公网。
- 环境变量
.env.local中的GEMINI_API_KEY仅用于预留的 AI 功能,当前主业务逻辑未实际调用 Gemini API。
常见开发注意事项
- 编辑器内容初始化:
ReportEditor.tsx中编辑器innerHTML的初始化逻辑分散在useEffect(基于 reportId / draft)和useLayoutEffect(安全兜底)中,修改时需注意两者优先级,避免内容被覆盖。 - 视频对象 URL 生命周期:通过
URL.createObjectURL()创建的视频 URL 仅在当前会话有效,刷新页面后视频需重新上传。报告保存时仅保留视频元数据(名称、时长),不保存视频文件本身。 - 打印样式:
@media print规则定义在src/index.css中,修改编辑器内元素类名时,需同步检查打印样式是否失效。 - Tailwind CSS v4:本项目使用 Tailwind CSS 4(
@import "tailwindcss"+@theme),与 v3 的tailwind.config.js方式不兼容,请勿混用旧版配置。 - HMR 特殊处理:
vite.config.ts中根据DISABLE_HMR环境变量控制 HMR 开关,该变量由 AI Studio 运行时注入,通常无需手动修改。