Files
Mdeical_Sur_Report/AGENTS.md
admin 5a4056d899 Add reusable HTML template export
- Add template export utilities for standard JSON packages and standalone HTML template packages.

- Make the top-level JSON export use the standard surclaw template package format so it can be imported again.

- Add an HTML template package export that embeds A4/print styling and template metadata for visual preview and round-trip import.

- Extend template import to accept both JSON and HTML template package files while keeping old raw template JSON compatible.

- Add tests for package creation, HTML round-trip import, legacy JSON import, and file name cleanup.

- Update template management, feature, progress, testing, and AGENTS documentation for the new export formats.
2026-05-02 03:49:21 +08:00

19 KiB
Raw Blame History

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 首次进入时初始化。

主要业务脉络

  1. 用户进入 / 登录页。
  2. 登录页初始化默认用户、模板、字段、图片资源和系统设置。
  3. 登录页通过 AuthContext 调用后端 /api/auth/login,后端写入 HttpOnly Session Cookie。
  4. 登录成功后前端把后端安全用户 DTO 映射成兼容 User,写入 localStorage.currentUser,跳转到 /dashboard
  5. AuthProvider 启动时通过 /api/auth/me 恢复会话;侧边栏优先读取 Auth Context回退 currentUser.role 展示不同菜单。
  6. 报告编辑器使用模板 HTML 生成报告正文,通过 data-bind 字段把侧边表单和正文智能字段同步。
  7. 视频上传后使用浏览器 <video><canvas> 预览/抽帧,同时优先通过 /api/files 上传视频和关键帧文件,关键帧可插入报告图片占位符。
  8. AI 面板把消息和图片上下文发送到 /api/ai/chat,后端读取系统设置中的共用 OpenAI 兼容 Provider 并代理调用 /chat/completions,返回内容可注入 AI 可编辑区域。
  9. 语音听写把麦克风音频发送到 /api/speech/iat WebSocket后端读取系统设置中的讯飞配置、生成鉴权 URL 并转发讯飞 IAT 结果。
  10. 报告保存优先调用 POST/PATCH /api/reports,后端保存到 PostgreSQL仅开发/显式回退模式下 API 不可用时回退 localStorage.reports
  11. 报告管理页优先调用 GET /api/reports,后端按角色过滤报告;前端支持搜索、筛选、历史恢复、打印和 JSON 导出。
  12. 模板管理页优先调用 GET/POST/PATCH/DELETE /api/templates 管理模板 HTML调用 /api/library/fields 维护字段库,并通过 /api/files 上传模板图片资源。
  13. 用户管理页优先调用 GET/PATCH /api/users 等接口维护用户、角色、部门和模板授权;签名图片通过 /api/users/:id/signature 上传为后端文件资源。
  14. 系统设置页优先调用 GET/PATCH /api/settings/system 维护抽帧策略、默认模板、AI Provider 和讯飞语音配置。

功能真实性判断

详细清单见 docs/features.md。处理需求时应区分:

  • 真实可用本地初始化、字段绑定、JSON 导出等。
  • 真实集成:后端 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.mddocs/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

定义核心数据结构:

  • User
  • Report
  • CapturedFrame
  • Template
  • SystemSettings
  • AiProviderConfig
  • XfSpeechConfig
  • FormField

也包含默认字段、默认 AI Provider 和默认讯飞配置。

src/utils/storage.ts

封装浏览器存储。常规键使用 JSONsystemSettings 做 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.tsxsrc/auth/backendUser.ts

前端认证入口。AuthProvider 提供 loginlogoutrefresh,并在登录或恢复会话后把后端用户同步成当前前端 User

  • 后端 doctor 映射为前端 user
  • 后端 departmentName 映射为前端 department
  • 保留本地签名等迁移期字段;模板授权优先来自后端部门权限。

server/src

后端第一阶段骨架。当前已实现健康检查、认证接口、报告 API、报告媒体关系、模板 API、字段库 API、用户/部门 API、设置 API、通用文件/签名文件 API、AI 代理、讯飞语音代理、PrismaService 和权限策略前端登录、报告、模板、字段库、模板图片资源、用户管理、系统设置、签名上传、AI 对话和语音听写已接入后端接口/代理。新增后端功能时优先按模块拆分:authreportstemplateslibraryusersfilessettingsaispeech

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 数据模型。当前覆盖 TenantDepartmentUserUserSessionAppSessionReportReportMediaReportHistoryTemplate、模板部门授权、FileResourceSystemSettingAuditLog。Prisma 7 连接配置在根目录 prisma.config.ts 中。

数据存储键

详见 docs/data-storage.md。常见键:

  • currentUser
  • users
  • templates
  • reports
  • systemSettings
  • formFieldsConfig
  • imageAssets
  • customTimeFormats
  • multiSelectOptions
  • anesthesiaOptions
  • reportEditorDraft_${username}
  • sessionStorage.restore_${reportId}

测试现状

当前测试覆盖:

  • 登录默认初始化和后端禁用账号错误展示
  • 前端 API client 响应/错误处理、Dashboard API 封装和语音代理地址生成
  • 后端用户 DTO 到前端兼容用户映射
  • 角色菜单过滤
  • 报告管理按角色过滤
  • 管理员本部门报告范围和医生本人报告范围
  • 模板可用范围,含部门模板和医生个人模板
  • Playwright E2E 通过真实后端 API seed 覆盖登录、报告权限、报告修订版本、医生个人模板、模板管理新增保存、路由守卫和审计日志
  • 后端权限策略覆盖报告、模板、用户管理和管理员创建规则
  • 后端 Dashboard 统计按角色范围过滤
  • 后端报告 metadata 兼容映射和 ReportMedia 视频/关键帧组装
  • 后端报告 schema 区分草稿和完成状态,草稿可暂缺患者姓名/住院号,完成报告必须填写
  • 后端模板 DTO 和权限资源映射
  • 模板列表合并工具,防止新增模板被旧 localStorage.templates 覆盖
  • 模板导入导出工具,覆盖 JSON/HTML 模板包生成、回导和旧 JSON 兼容
  • 后端用户 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/ 不要手工维护。