- Extract AI region scanning into a reusable utility with unit coverage. - Refresh AI region dropdown state after drafts, reports, default templates, and selected templates write HTML into the editor. - Keep the existing MutationObserver path for later DOM edits and inserted AI regions. - Add E2E coverage for existing template AI regions appearing on initial report editor load. - Update README, AGENTS, report editor, progress, and testing docs for AI region synchronization behavior.
19 KiB
AI 编码助手项目说明
本文件面向 AI 编码助手。阅读者应假设对该项目一无所知。以下信息基于当前仓库实际文件、脚本和源码;不要把早期设计目标当作已实现事实。任何代码和功能修改都要落实到文档和测试上。如果生成 git commit 信息,要逐个列点把所有修改都列上,重要的、大的修改放前面,不重要的、小的修改列在后面。
项目一句话
这是一个“手术图文病历报告系统”。当前登录认证已接入 NestJS Session API、PostgreSQL 用户表和数据库 Session Store;工作台统计、报告、报告媒体、模板、字段库、模板图片资源、视频/关键帧文件、用户、部门权限、系统设置、签名文件、AI 对话和讯飞语音听写已优先接入后端 API/代理。开发模式仍保留本地兼容回退,不能把前端权限和本地缓存当作生产安全边界。
当前技术栈
- React 19
- TypeScript 5.8
- Vite 6
- Tailwind CSS 4
- React Router DOM 7
- Lucide React
- Vitest + jsdom + Testing Library
- Playwright
- NestJS + Prisma + PostgreSQL 后端骨架
- Docker + Nginx
运行脚本
npm install
npm run dev # Vite dev server, 0.0.0.0:3001
npm run server:dev # build and start NestJS API, 0.0.0.0:3100
npm run server:build # tsc -p server/tsconfig.json
npm run lint # tsc --noEmit
npm run test # vitest run
npm run test:e2e # playwright test
npm run build # vite build
npm run prisma:generate
npm run prisma:migrate
npm run prisma:seed
修改代码后至少运行:
npm run lint
npm run test
如果改动构建、依赖、路由、样式或部署相关内容,也运行:
npm run build
如果改动后端源码、Prisma schema、认证、权限或 API 契约,也运行:
npm run server:build
npm run prisma:generate
后端化、权限或关键用户流程变更时也运行:
npm run test:e2e
默认账号
| 用户ID | 密码 | 角色 |
|---|---|---|
admin |
123456 |
超级管理员 |
manager |
123456 |
管理员 |
0001 |
123456 |
医生 |
默认数据由 src/pages/Login.tsx 首次进入时初始化。
主要业务脉络
- 用户进入
/登录页。 - 登录页初始化默认用户、模板、字段、图片资源和系统设置。
- 登录页通过
AuthContext调用后端/api/auth/login,后端写入 HttpOnly Session Cookie。 - 登录成功后前端把后端安全用户 DTO 映射成兼容
User,写入localStorage.currentUser,跳转到/dashboard。 AuthProvider启动时通过/api/auth/me恢复会话;侧边栏优先读取 Auth Context,回退currentUser.role展示不同菜单。- 报告编辑器使用模板 HTML 生成报告正文,通过
data-bind字段把侧边表单和正文智能字段同步。 - 视频上传后使用浏览器
<video>和<canvas>预览/抽帧,同时优先通过/api/files上传视频和关键帧文件,关键帧可插入报告图片占位符。 - AI 面板把消息和图片上下文发送到
/api/ai/chat,后端读取系统设置中的共用 OpenAI 兼容 Provider 并代理调用/chat/completions,返回内容可注入 AI 可编辑区域。 - 语音听写把麦克风音频发送到
/api/speech/iatWebSocket,后端读取系统设置中的讯飞配置、生成鉴权 URL 并转发讯飞 IAT 结果。 - 报告保存优先调用
POST/PATCH /api/reports,后端保存到 PostgreSQL;仅开发/显式回退模式下 API 不可用时回退localStorage.reports。 - 报告管理页优先调用
GET /api/reports,后端按角色过滤报告;前端支持搜索、筛选、历史恢复和浏览器打印/PDF 导出。 - 模板管理页优先调用
GET/POST/PATCH/DELETE /api/templates管理模板 HTML,调用/api/library/fields维护字段库,并通过/api/files上传模板图片资源。 - 用户管理页优先调用
GET/PATCH /api/users等接口维护用户、角色、部门和模板授权;签名图片通过/api/users/:id/signature上传为后端文件资源。 - 系统设置页优先调用
GET/PATCH /api/settings/system维护抽帧策略、默认模板、AI Provider 和讯飞语音配置。
功能真实性判断
详细清单见 docs/features.md。处理需求时应区分:
- 真实可用:本地初始化、字段绑定、浏览器打印/PDF 导出等。
- 真实集成:后端 Session 登录、Dashboard API、报告 API、模板 API、用户/部门 API、设置 API、签名文件 API、审计日志 API、AI 代理、讯飞语音代理、浏览器打印/PDF、视频抽帧。它们有真实代码路径,但依赖后端服务、浏览器能力、权限、有效密钥、网络或人工保存。
- 前端体验控制:页面级角色守卫和菜单隐藏已接入 Auth Context,但不能替代后端 API 权限。
当前安全边界
本项目不能按生产安全系统理解:
- 后端账号使用 Argon2 哈希;开发回退模式下
localStorage.users仍保留兼容缓存和旧演示密码字段。 - 页面级权限在前端用于体验控制,不能抵御绕过;生产安全边界以后端 API 权限校验为准。
- 报告和模板 HTML 保存时已做服务端白名单清洗;前端仍使用 HTML 渲染,继续修改时要留意 XSS 和打印兼容。
- AI Key 和讯飞语音密钥已由后端代理使用,普通用户读取系统设置时不会返回真实密钥。
- 当前 demo mode 后端默认值包含演示用第三方服务凭据,生产化前必须替换或移除,并轮换曾经暴露过的密钥。
- 视频和关键帧文件已优先进入后端文件资源;报告保存时通过
ReportMedia关系表关联,新建报告保存前仍依赖浏览器对象 URL 预览。 VITE_ENABLE_LOCAL_FALLBACK控制生产构建是否允许本地兼容回退;开发模式默认允许,生产默认关闭。
涉及生产化、后端化、用户化时,优先阅读 docs/backendization-plan.md 和 docs/security.md。
文件结构
.
├── AGENTS.md # AI 编码助手上下文和协作约定
├── README.md # 面向开发者的项目说明
├── package.json # 依赖与 npm scripts
├── package-lock.json # npm 锁文件
├── prisma.config.ts # Prisma 7 CLI 配置
├── vite.config.ts # Vite/Tailwind/React/Vitest 配置
├── playwright.config.ts # Playwright E2E 配置,启动/复用 3001 前端和 3100 测试 API
├── tsconfig.json # TypeScript 配置
├── index.html # Vite HTML 入口
├── e2e/
│ ├── helpers.ts # E2E 真实 API 登录和造数工具
│ ├── audit-and-route-guards.spec.ts
│ ├── login.spec.ts
│ ├── report-permissions.spec.ts
│ ├── report-revision.spec.ts
│ └── personal-template.spec.ts
├── public/
│ ├── favicon.ico
│ └── logo_square.png
├── src/
│ ├── App.tsx # 路由表
│ ├── main.tsx # React 挂载入口
│ ├── index.css # 全局样式、Tailwind 主题和组件类
│ ├── types.ts # User/Report/Template/SystemSettings/FormField 等类型和默认配置
│ ├── api/
│ │ ├── audit.ts # 审计日志 API 封装
│ │ ├── client.ts # 前端 API client,统一 envelope/错误/Cookie
│ │ ├── dashboard.ts # 工作台统计 API 封装
│ │ ├── reports.ts # 报告列表、详情、保存、删除 API 封装
│ │ ├── templates.ts # 模板列表、详情、保存、删除 API 封装
│ │ ├── users.ts # 用户、部门和模板授权 API 封装
│ │ ├── settings.ts # 系统设置 API 封装
│ │ ├── files.ts # 签名文件 API 封装
│ │ ├── library.ts # 字段库 API 封装
│ │ ├── ai.ts # AI 模型列表和对话代理 API 封装
│ │ ├── speech.ts # 讯飞语音 WebSocket 代理地址封装
│ │ └── client.test.ts
│ ├── auth/
│ │ ├── AuthContext.tsx # 登录态、login/logout/me、currentUser 兼容同步
│ │ ├── backendUser.ts # 后端安全用户 DTO 到前端 User 的映射
│ │ └── backendUser.test.ts
│ ├── config/
│ │ └── runtime.ts # 本地兼容回退开关
│ ├── components/
│ │ ├── Sidebar.tsx
│ │ └── Sidebar.test.tsx
│ ├── pages/
│ │ ├── Login.tsx # 登录和默认数据初始化
│ │ ├── AuditLogs.tsx # 审计日志查看
│ │ ├── Dashboard.tsx # 工作台统计和快捷入口
│ │ ├── ReportEditor.tsx # 核心报告编辑器、抽帧、AI、语音、保存
│ │ ├── ReportManage.tsx # 报告列表、筛选、历史、导出、删除
│ │ ├── ReportView.tsx # 报告查看和打印
│ │ ├── TemplateManage.tsx# 模板、字段库、图片资源、导入导出
│ │ ├── UserManage.tsx # 用户、角色、部门、模板权限、签名
│ │ ├── SystemSettings.tsx# 抽帧、AI、语音、默认模板设置
│ │ ├── Login.test.tsx
│ │ └── ReportManage.test.tsx
│ ├── utils/
│ │ ├── storage.ts # localStorage/sessionStorage 封装
│ │ ├── permissions.ts # 前端角色/报告/模板可见性判断
│ │ ├── defaultContent.ts # 默认手术记录 HTML 模板
│ │ ├── print.ts # iframe 打印工具
│ │ ├── storage.test.ts
│ │ ├── permissions.test.ts
│ │ ├── defaultContent.test.ts
│ │ └── print.test.ts
│ └── test/
│ └── setup.ts # Vitest/jsdom 全局 mock
├── server/
│ ├── prisma/
│ │ ├── schema.prisma # PostgreSQL 数据模型
│ │ └── seed.ts # 默认医院、部门和账号 seed
│ ├── src/
│ │ ├── main.ts # NestJS API 启动入口
│ │ ├── app.module.ts
│ │ ├── audit/ # 审计日志写入和查询 API
│ │ ├── auth/ # 登录、me、logout 接口
│ │ ├── dashboard/ # 工作台统计 API
│ │ ├── demo/ # 演示模式默认模板、AI 和语音配置
│ │ ├── reports/ # 报告 API、DTO、metadata 映射和测试
│ │ ├── templates/ # 模板 API、DTO、权限映射和测试
│ │ ├── users/ # 用户、部门和模板授权 API、DTO 映射和测试
│ │ ├── settings/ # 系统设置 API 和 schema 测试
│ │ ├── files/ # 签名文件上传和受控读取 API
│ │ ├── library/ # 字段库 API、schema 和测试
│ │ ├── ai/ # OpenAI 兼容模型列表和对话代理 API
│ │ ├── speech/ # 讯飞 IAT WebSocket 代理和帧处理测试
│ │ ├── health/ # GET /api/health
│ │ ├── permissions/ # 后端权限策略和测试
│ │ ├── prisma/ # PrismaService
│ │ └── session/ # express-session 的 Prisma Store
│ └── tsconfig.json
├── docs/
│ ├── README.md
│ ├── installation.md
│ ├── requirements.md
│ ├── design.md
│ ├── component-structure.md
│ ├── permissions.md
│ ├── api-contract.md
│ ├── features.md
│ ├── testing.md
│ ├── data-storage.md
│ ├── deployment.md
│ ├── security.md
│ ├── progress.md
│ ├── backendization-plan.md
│ └── modules/
│ ├── auth-and-users.md
│ ├── report-editor.md
│ ├── report-management.md
│ ├── template-management.md
│ └── system-settings.md
├── Dockerfile
├── Dockerfile.server
├── docker-compose.yaml
└── nginx.conf
node_modules/、dist/ 是生成物或依赖目录,不应作为源码结构维护。
关键源码说明
src/types.ts
定义核心数据结构:
UserReportCapturedFrameTemplateSystemSettingsAiProviderConfigXfSpeechConfigFormField
也包含默认字段、默认 AI Provider 和默认讯飞配置。
src/utils/storage.ts
封装浏览器存储。常规键使用 JSON;systemSettings 做 XOR + Base64 混淆并兼容历史明文 JSON。注意:这不是安全加密。
src/utils/permissions.ts
集中封装当前前端权限判断。报告范围规则为:医生看本人报告,管理员看本部门报告,超级管理员和超时管理员看全部报告。模板范围规则为:超级管理员/超时管理员可见全部模板,医生和管理员可见本部门模板以及本人个人模板。
src/utils/defaultContent.ts
默认报告模板 HTML。包含:
.field-value[data-bind]智能字段.image-placeholder图片占位符.ai-region[data-ai-id]AI 可编辑区域
src/pages/ReportEditor.tsx
最大、最复杂的文件。包含:
- 报告表单状态
contentEditable富文本正文- 字段双向同步
- 图片占位符填充
- 视频上传、自动抽帧、手动截帧
- AI 对话和 AI 区域改写
- 讯飞语音听写
- 草稿保存和恢复
- 报告保存、完成、历史记录
- 打印和导出
修改它时要非常小心,优先补测试或文档说明。
src/api/client.ts
统一前端 API 请求封装:
- 默认请求相对路径
/api/...。 - Vite 开发模式通过
VITE_API_PROXY_TARGET代理 API,默认http://localhost:3100。 - 请求带
credentials: 'include',用于后端 HttpOnly Session Cookie。 - 解包后端
{ data }响应,错误时抛出ApiError。
src/auth/AuthContext.tsx 和 src/auth/backendUser.ts
前端认证入口。AuthProvider 提供 login、logout、refresh,并在登录或恢复会话后把后端用户同步成当前前端 User:
- 后端
doctor映射为前端user。 - 后端
departmentName映射为前端department。 - 保留本地签名等迁移期字段;模板授权优先来自后端部门权限。
server/src
后端第一阶段骨架。当前已实现健康检查、认证接口、报告 API、报告媒体关系、模板 API、字段库 API、用户/部门 API、设置 API、通用文件/签名文件 API、AI 代理、讯飞语音代理、PrismaService 和权限策略;前端登录、报告、模板、字段库、模板图片资源、用户管理、系统设置、签名上传、AI 对话和语音听写已接入后端接口/代理。新增后端功能时优先按模块拆分:auth、reports、templates、library、users、files、settings、ai、speech。
API 默认 JSON/urlencoded 请求体上限为 100mb,由 API_BODY_LIMIT 控制;Nginx 同步配置了 client_max_body_size 100m,用于承载迁移期报告 HTML、图片/关键帧和通用文件 Data URL 上传。
Docker 前端默认暴露 http://localhost:4002,并额外暴露自签名 HTTPS 演示入口 https://localhost:4443。浏览器麦克风 API 不能在普通局域网 HTTP 页面中由应用代码强行开启;语音听写演示优先使用 HTTPS 入口,或用 Chrome/Edge 的 --unsafely-treat-insecure-origin-as-secure 临时标记 HTTP 来源。
server/prisma/schema.prisma
PostgreSQL 数据模型。当前覆盖 Tenant、Department、User、UserSession、AppSession、Report、ReportMedia、ReportHistory、Template、模板部门授权、FileResource、SystemSetting 和 AuditLog。Prisma 7 连接配置在根目录 prisma.config.ts 中。
数据存储键
详见 docs/data-storage.md。常见键:
currentUseruserstemplatesreportssystemSettingsformFieldsConfigimageAssetscustomTimeFormatsmultiSelectOptionsanesthesiaOptionsreportEditorDraft_${username}sessionStorage.restore_${reportId}
测试现状
当前测试覆盖:
- 登录默认初始化和后端禁用账号错误展示
- 前端 API client 响应/错误处理、Dashboard API 封装和语音代理地址生成
- 后端用户 DTO 到前端兼容用户映射
- 角色菜单过滤
- 报告管理按角色过滤
- 管理员本部门报告范围和医生本人报告范围
- 模板可用范围,含部门模板和医生个人模板
- Playwright E2E 通过真实后端 API seed 覆盖登录、报告权限、报告修订版本、报告 AI 区域同步、医生个人模板、模板管理新增保存、路由守卫和审计日志
- 后端权限策略覆盖报告、模板、用户管理和管理员创建规则
- 后端 Dashboard 统计按角色范围过滤
- 后端报告 metadata 兼容映射和
ReportMedia视频/关键帧组装 - 后端报告 schema 区分草稿和完成状态,草稿可暂缺患者姓名/住院号,完成报告必须填写
- 后端模板 DTO 和权限资源映射
- 模板列表合并工具,防止新增模板被旧
localStorage.templates覆盖 - 模板导入导出工具,覆盖 HTML 模板包生成、字段库元数据回导和旧 JSON 导入兼容
- AI 区域扫描工具,覆盖从报告正文 HTML 识别
.ai-region - 后端用户 DTO 和部门模板授权映射
- 后端系统设置 schema 校验
- 后端 AI 入参和讯飞语音代理帧处理
- 后端 HTTP 集成测试覆盖 API prefix、登录 session、受保护 API actor 传递
- 后端真实 PostgreSQL 集成测试覆盖 Auth、Dashboard、Reports、ReportMedia、Templates、Files、HTML 清洗、审计写入和审计查询权限
- 存储封装
- 默认模板结构和字段契约
- 打印入口
测试文档见 docs/testing.md。
文档维护规则
如果改动功能、数据结构、脚本、部署、安全边界或测试:
- 更新对应
docs/文档。 - 如功能真实性变化,更新
docs/features.md。 - 如后端化方向变化,更新
docs/backendization-plan.md。 - 如新增/修改测试,更新
docs/testing.md。 - 如运行方式、端口、账号、部署变化,更新
README.md。
开发注意事项
- 优先使用现有风格和现有工具,不要引入大框架替换,除非任务明确需要。
- 不要把前端权限当作安全边界。
- 不要继续扩大前端内置密钥的使用面。
- 不要把大量 Base64 图片或视频数据长期作为生产方案。
- 报告/模板 HTML 改动要考虑 XSS、打印样式、字段绑定和历史兼容。
- 当前
document.execCommand虽然过时,但编辑器依赖它;替换编辑器需要单独规划。 - 生成物
dist/和依赖目录node_modules/不要手工维护。