Files
Mdeical_Sur_Report/AGENTS.md

306 lines
16 KiB
Markdown
Raw Permalink 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.
# AGENTS.md — 手术图文病历报告系统AI手术图文报告系统 V2.0
> 本文档面向 AI 编程助手。如果你正在阅读本文件,说明你对本项目一无所知。以下内容全部基于项目实际代码与配置,请勿假设任何未在本文中显式说明的内容。
---
## 1. 项目概述
本项目是一个**纯前端**的医疗图文报告管理应用,面向医院手术记录场景。核心能力包括:
- 通过富文本编辑器撰写手术图文报告
- 上传手术视频并自动/手动截取关键帧插入报告
- 模板管理(创建、维护标准模板,新建报告时自动加载默认模板)
- 基于角色的权限控制(超级管理员 / 管理员 / 普通用户)
- AI 辅助撰写(支持 Kimi、DeepSeek、OpenAI 及自定义兼容接口)
- 报告批量操作(删除、导出 PDF / JSON
- 讯飞语音输入WebSocket 实时转写)
**重要前提**:本项目没有任何后端服务。所有数据(用户、报告、模板、视频帧、系统配置)全部持久化在浏览器 `localStorage` 中。认证与授权逻辑完全在客户端执行。
默认测试账号:
- `admin` / `123456`
- `manager` / `123456`
- `doctor` / `123456`
---
## 2. 技术栈
| 层级 | 技术 |
|------|------|
| 框架 | React 19 + TypeScript ~5.8.2 |
| 构建工具 | Vite 6.2.0`@vitejs/plugin-react` |
| 路由 | React Router DOM v7`BrowserRouter` |
| 样式 | Tailwind CSS v4.1.14(通过 `@tailwindcss/vite` 插件引入,非 PostCSS |
| 图标 | `lucide-react` |
| 动画 | `motion`Framer Motion 继任者) |
| AI SDK | `@google/genai`(依赖列表中,实际主要使用 OpenAI 兼容 API |
| 其他关键依赖 | `diff`(字符级差异比对)、`crypto-js`(讯飞 HMAC-SHA256 鉴权) |
`package.json` 中虽然声明了 `express``@types/express`,但源码中未见服务端代码,推测为历史遗留或未使用的依赖。
---
## 3. 项目结构
```
src/
├── App.tsx # 根组件,定义所有路由
├── main.tsx # 应用入口React 19 + StrictMode
├── types.ts # 全局类型定义与默认值常量
├── index.css # Tailwind v4 引入 + 自定义编辑器/打印/A4 样式
├── components/
│ └── Sidebar.tsx # 全局侧边导航栏(带角色过滤、自动收起)
├── pages/ # 所有页面均为大而整的单文件组件
│ ├── Login.tsx # 登录 + 初始数据种子写入
│ ├── Dashboard.tsx # 统计看板、SVG 趋势图、快捷入口
│ ├── ReportEditor.tsx # 核心编辑器(~2900 行富文本、视频、AI、Diff、表单
│ ├── ReportManage.tsx # 报告列表、检索、批量操作、历史版本恢复
│ ├── ReportView.tsx # 只读报告展示 + 打印触发
│ ├── TemplateManage.tsx # 模板编辑器(~1700 行)+ 字段库侧边栏
│ ├── UserManage.tsx # RBAC 用户 CRUD + 电子签名
│ └── SystemSettings.tsx # 抽帧配置、AI 服务商、讯飞语音参数
└── utils/
├── storage.ts # localStorage/sessionStorage 封装(含 XOR 加密)
├── print.ts # iframe 静默渲染 + window.print() 实现 A4 打印
└── defaultContent.ts # 默认手术报告 HTML 模板(含 data-bind 占位)
```
**架构特点**
- 无外部状态管理库,全部使用 React 原生 `useState` / `useRef` / `useEffect`
- 无组件拆分策略,页面级组件体积巨大(`ReportEditor.tsx``TemplateManage.tsx` 均超 1500 行)
- 无懒加载,所有页面在 `App.tsx` 中直接静态导入
- 共享布局仅有 `Sidebar.tsx` 一处
---
## 4. 构建与运行命令
```bash
# 安装依赖
npm install
# 本地开发(端口 3000监听 0.0.0.0
npm run dev
# 类型检查(无单元测试)
npm run lint # 等价于 tsc --noEmit
# 生产构建
npm run build
# 预览生产构建(端口 4173
npm run preview
# 清理构建产物
npm run clean # rm -rf dist
```
**环境变量**(复制 `.env.example``.env.local`
- `GEMINI_API_KEY`Gemini AI API 密钥(构建时通过 Vite `define` 注入为 `process.env.GEMINI_API_KEY`
- `APP_URL`:部署后的访问地址,用于自引用链接
**Windows 特别注意**:重新部署前若使用 `npm run preview`,需手动终止旧的 `vite preview` 进程,避免端口冲突。
---
## 5. 开发规范与代码风格
以下规范全部来自 `过往经验/` 中的踩坑记录,**必须遵守**
### 5.1 contentEditable 编辑器规范
- **插入 HTML 时,模板字符串必须为紧凑单行**,禁止多行缩进/换行,否则浏览器会解析出额外文本节点破坏排版。
- **删除特殊节点**优先使用 `Range.selectNode(target) + document.execCommand('delete')`,而非直接 `target.remove()`,以保留浏览器原生撤销栈。
- **所有工具栏/侧边栏按钮**必须加 `onMouseDown={(e) => e.preventDefault()}`,防止点击时编辑器失焦导致光标位置丢失。
- **自定义 Undo/Redo**:结构性变更(插入/删除智能字段、表格等)应基于 `innerHTML` 快照实现自定义历史栈(`undoStack` / `redoStack`),并在操作前执行 `pushHistory()`
- **键盘事件拦截**:对 `contenteditable="false"` 的内联控件,若处于块级边界,必须拦截 Backspace/Delete以及 Ctrl+Z/Ctrl+Y防止浏览器误删父级 `<p>`
- **防换行技巧**:在 `inline-block` / `inline-flex` 控件后追加 `&#8203;`(零宽空格)作为行内锚点。
### 5.2 自动保存与草稿机制(高频踩坑区)
- **禁止单独依赖 `useRef` 作为自动保存的唯一数据源**。React 18 `StrictMode` 的模拟卸载会导致 ref 仍保持初始空值,从而用空数据覆盖有效的 `localStorage` 草稿。
-`ReportEditor.tsx` 中新增任何 `useState` 时,必须三问:
1. 是否需要持久化到 draft
2. 是否已加入 `stateRef` 初始化?
3. 是否已在 `saveDraftToStorage`、所有恢复分支、以及 state→ref 同步 effect 中补齐?
- `contentRef.current = editorRef.current.innerHTML` 必须紧跟在任何直接操作 DOM 修改编辑器内容的代码之后。
### 5.3 图片与视频处理
- **LocalStorage 容量预警**:视频抽帧必须使用 Canvas 等比压缩(最大宽度 800pxJPEG 质量 0.6),单张控制在 30KB~80KB避免 5MB 上限静默失败。
- **存储层异常捕获绝不应静默吞掉**,至少输出 `console.error`
- **占位符体系**:所有 `.image-placeholder` 必须携带 `data-mode="frame|manual"` 属性。修改占位符的创建/填充/删除逻辑时,必须同步检索所有入口:`fillPlaceholderSrc``fillPlaceholder``autoCaptureFrames`、拖拽填充、`TemplateManage.tsx`,以及 `defaultContent.ts` 中的预置模板。
- 填充图片后需将占位符外壳的固定 `width/height` 改为 `auto`,同时保留 `max-width/max-height` 作为硬限制。
### 5.4 智能字段与动态表单
- **DOM 三层结构**`<span class="smart-field-wrapper" contenteditable="false">``<span class="field-label">``<span class="field-value" contenteditable="true" data-bind="xxx">`
- **双向绑定**:富文本→表单通过 `handleEditorInput``e.target.hasAttribute('data-bind')` 实时更新;表单→富文本通过 `useEffect` 监听 `reportData`,仅在 `el.innerText !== newValue` 时才重写 DOM防止光标跳动。
- **时间/日期字段**显示格式与存储格式必须分离且同时实现正向格式化与反向解析12h/24h 判断使用 `includes('hh') || includes('A')` 等包含性判断,兼容自定义格式。
### 5.5 AI 功能开发规范
- **模型兼容性**:调用 OpenAI 兼容 API 时,必须根据「是否有图片附件」动态决定 `content` 类型(`string` vs `array`),纯文本模型发送数组会 400。
- **System Prompt 设计**
- 条件应只依赖用户意图开关(如 `aiModifyEnabled`),不应依赖具体 UI 状态。
- 向大模型发送局部修改请求时,必须提供全局上下文,但同时设置**严格的内容边界Fencing**,明确声明"全局参考仅供理解,严禁输出"其他模块内容。
- 对关键输出字段(如 `updatedHtml`)使用「绝对强制」「绝对不允许」等最强措辞,并在前端增加缺失校验兜底。
- **降级机制**:目标区域注入必须配备降级方案(如光标处 `execCommand('insertHTML')`);修改模式开启后应自动兜底锁定第一个可用 AI 区域。
- **DOM 结构修复**:在读取 `.ai-content` 数据前,必须将因用户回车而溢出为兄弟节点的 `<p>` 重新移回容器内。
- **样式与撤销**AI 内容注入必须使用 `Range.selectNodeContents + execCommand('insertHTML')` 以保留撤销栈;返回的 HTML 需在后处理阶段统一注入内联字体样式(`font-family: SimSun; font-size: 12pt;`);注入前需清洗(去掉 `<br>`、段落间空白)。
- **Diff 对比**:使用 `diff` 库做字符级差异比对,并在注入前去掉 diff 高亮标签。
### 5.6 数据迁移与类型安全
- 任何涉及 `localStorage` 数据结构变更的重构,必须在初始化入口提供**自动迁移逻辑**,使用 `(obj as any).oldField` 安全访问旧字段,避免类型污染和配置丢失。
- 从持久化存储读取的数组类型数据,渲染前务必做 `Array.isArray` 校验,防止历史脏数据导致整页崩溃。
- 当将格式简写迁移为标准 token 时,必须全局搜索所有硬编码默认值,并在初始化时建立无效值清理机制。
### 5.7 UI/UX 通用规范
- **禁用原生 `prompt`/`confirm`/`alert`**,统一使用项目风格的自定义 Modal 组件。
- **URL 拼接**:必须对基础路径做尾部斜杠移除 `.replace(/\/+$/, '')`
- **打印边距**:使用 `@page { margin: ... }` 为每一页物理纸张独立分配边距,切勿依赖 `body { padding: ... }`
- **滚动容器内展开**:点击展开/折叠的交互组件,应考虑增加 `scrollIntoView` 兜底,防止布局突变导致点击失效。
- **表格列变更**:保持 `<thead>``<tbody>` 列顺序严格一致。
- **大文件修改策略**:对于超过 1500 行的单文件组件采用「Grep 定位 → 精确读取 → 最小化替换」的三段式策略,避免盲目滚动。
---
## 6. 测试说明
**本项目没有任何测试框架或测试用例**
- `npm run lint``tsc --noEmit`)是唯一的自动化质量门禁。
- 确保 `tsconfig.json` 已正确 `exclude` 非源码目录(如 `参考信息``dist``node_modules`),否则参考文件会导致类型检查失败。
- 由于无后端、无测试,所有功能验证依赖手动端到端测试。
---
## 7. 部署流程
### 7.1 Docker 部署(推荐)
```bash
docker-compose up -d --build
```
- 构建阶段:`node:20-alpine` 执行 `npm ci` + `npm run build`
- 运行阶段:`nginx:alpine` 托管静态产物,暴露容器端口 `80`
- 宿主机端口映射:`4002``80`
- 服务名:`tuwen_system`,重启策略:`unless-stopped`
### 7.2 无 Docker 静态部署
```bash
npm run build
npm run preview
```
构建产物输出到 `dist/` 目录,可直接作为静态站点托管到任意 Web 服务器。
### 7.3 Nginx 配置要点(`nginx.conf`
- **SPA 路由**`try_files $uri $uri/ /index.html`,确保客户端路由正常工作。
- **Gzip 压缩**对文本、CSS、JS、XML、JSON 启用。
- **静态资源缓存**JS、CSS、图片、字体等设置 `immutable` 1 年缓存。
---
## 8. 安全注意事项
**本项目为纯前端应用,不存在服务端安全层。以下风险必须在部署前被充分理解:**
1. **用户密码以明文形式保存在浏览器 `localStorage` 中**,无后端哈希处理。
2. **API 密钥与凭证通过源码混淆存放**字符码数组、XOR 加密),但仍在客户端可还原。
3. **所有认证与授权逻辑在客户端执行**,可通过开发者工具绕过。
4. **若用于生产环境,必须部署在内网或受信任环境中**,严禁直接暴露于公网。
5. `storage.ts` 中对 `systemSettings` 使用 XOR 加密,密钥硬编码于源码,仅提供最低限度的防窥视保护。
---
## 9. 关键架构决策
| 决策 | 说明 |
|------|------|
| 纯前端 / 无后端 | 所有数据存 `localStorage`,零服务端依赖,开箱即用 |
| 原生 `contentEditable` | 不使用第三方富文本库,通过 `document.execCommand` 和自定义 DOM 操作实现 |
| 单文件大组件 | 页面逻辑、状态、副作用全部内聚在同一文件中,无细粒度组件拆分 |
| localStorage 即数据库 | 用户、报告、模板、配置、视频帧全部序列化后存入浏览器本地存储 |
| iframe 打印 | 通过隐藏 iframe 独立渲染 A4 尺寸 HTML隔离打印样式与交互样式 |
| OpenAI 兼容 API | AI 功能不绑定特定厂商,通过统一接口支持多服务商切换 |
---
*最后更新:基于当前代码库实际内容生成。若项目结构或依赖发生变更,请同步更新本文件。*
---
## 10. 代码编纂工作流(强制执行)
> 以下工作流由项目所有者定义,**所有涉及项目代码修改的需求必须严格执行**,不允许跳过任何步骤。
### 工作流触发条件
- 用户提出任何与项目修改相关的需求功能新增、Bug 修复、重构、优化等)
- 用户明确说"按照工作流执行"或类似指令
### 工作流 7 步骤
#### Step 0记录开始时间
在对话开头记录时间戳:`{Year}-{Mon}-{Day}-{Hour}-{Min}-{Sec}`
#### Step 1阅读工程分析
- 阅读 `.\工程分析\` 文件夹下所有已有文档(需求分析、实现方案、测试方案、经验记录)。
- 若文件夹为空,基于当前代码库做一次整体工程分析并写入 `.\工程分析\` 留存。
#### Step 2整理需求
- 将用户原始需求结构化拆解。
- 写入 `.\工程分析\需求分析-{Year}-{Mon}-{Day}-{Hour}-{Min}-{Sec}.md`
- 模板见 `.\工程分析\需求分析-模板.md`
#### Step 3制定实现方案
- 基于需求分析和代码理解,制定详细实现方案。
- 写入 `.\工程分析\实现方案-{Year}-{Mon}-{Day}-{Hour}-{Min}-{Sec}.md`
- 模板见 `.\工程分析\实现方案-模板.md`
- **⚠️ 写完后必须停止,等待用户二次人工审核确认,严禁擅自继续。**
#### Step 4制定测试方案
- 基于实现方案,制定可执行的测试验证方案。
- 写入 `.\工程分析\测试方案-{Year}-{Mon}-{Day}-{Hour}-{Min}-{Sec}.md`
- 模板见 `.\工程分析\测试方案-模板.md`
- **⚠️ 写完后必须停止,等待用户二次人工审核确认,严禁擅自继续。**
#### Step 5执行前检查 + 经验沉淀
1. **执行前必读** `.\工程分析\经验记录.md`,避免重复踩坑。
2. 严格按照已审核的实现方案执行代码修改。
3. 按已审核的测试方案执行验证。
4. 若执行过程中遇到任何问题,在 `.\工程分析\经验记录.md` 中以四段式追加:
- **A. 具体问题**
- **B. 产生问题原因**
- **C. 解决问题方案**
- **D. 后续如何避免问题**
#### Step 6Git 备份
```bash
git add .
git commit -m "{Year}-{Mon}-{Day}-{Hour}-{Min}-{Sec} - 本次修改简要描述"
git push origin main
```
- 完成后向用户报告:"已完成对文档的备份 commit。"
#### Step 7重新部署
```bash
npm install # 如需
npm run lint
npm run build
npm run preview # 如需预览
```
- 确保构建成功无错误,向用户报告部署完成。
### 不可跳过的硬性要求
| 要求 | 说明 |
|------|------|
| 时间戳贯穿 | 同一需求的所有文档使用同一时间戳 |
| 用户审核卡点 | 实现方案、测试方案文档写完后必须人工确认 |
| 经验沉淀 | 遇到问题必须写入经验记录.md四段式格式 |
| Git 备份 | 每次修改完成后必须 commit + push |
| 构建验证 | 必须执行 `npm run build` 并确保成功 |
| 规范兼容 | 实现方案必须自检 AGENTS.md 第 5 章规范清单 |