- 替换LoginUser中的getOptionJson().path()调用为新的getOptionJsonValue()方法 - 为LoginUser类添加安全的选项JSON值访问方法getOptionJsonValue() - 修复LoginUser类中乱码注释并优化代码结构 - 更新SysLoginService类中乱码注释为中文描述
438 lines
18 KiB
Markdown
438 lines
18 KiB
Markdown
# HealthLink-HIS — AI 开发规范
|
||
|
||
> 🤖 本文件供所有 AI 编码工具自动读取。进入本项目后必须遵守以下规范。
|
||
>
|
||
> **模型决定上限,Harness 决定底线。**
|
||
|
||
---
|
||
|
||
## 一、项目概览
|
||
|
||
| 属性 | 值 |
|
||
|------|------|
|
||
| 项目名 | HealthLink-HIS(医院信息系统) |
|
||
| 后端路径 | `healthlink-his-server/` |
|
||
| 前端路径 | `healthlink-his-ui/` |
|
||
| 文档路径 | `MD/` |
|
||
| JDK | 25 (OpenJDK) |
|
||
| Spring Boot | 4.0.6 |
|
||
| MyBatis-Plus | 3.5.16 |
|
||
| Vue | 3.x + Vite + Element Plus |
|
||
| 数据库 | PostgreSQL 15+ |
|
||
| 包名 | `com.healthlink.his` |
|
||
| 后端端口 | 18082 |
|
||
| 前端端口 | 81 |
|
||
|
||
---
|
||
|
||
## 二、铁律(必须遵守,违反即失败)
|
||
|
||
### 🔴 P0 铁律 — 不可违反
|
||
|
||
**铁律1: 修改完必须测试**
|
||
```
|
||
后端: mvn clean compile -DskipTests → mvn install -DskipTests → mvn test
|
||
前端: npm run build:dev → npm run lint
|
||
```
|
||
- 白盒:编译通过,无 ERROR
|
||
- 黑盒:关键接口返回 `{code:200, data:...}`,验证业务逻辑
|
||
- 冒烟:应用正常启动,核心流程通畅
|
||
|
||
**铁律2: Flyway 数据库迁移**
|
||
- 凡是新建表、新增字段,必须创建 Flyway 迁移脚本
|
||
- 路径:`healthlink-his-domain/src/main/resources/db/migration/`
|
||
- 命名:`V{版本号}__{描述}.sql`(双下划线)
|
||
|
||
**铁律3: 测试通过后才提交**
|
||
- 编译 + 测试全部通过后才能 git commit
|
||
- 不提交未完成的功能、调试代码、临时文件
|
||
|
||
**铁律4: 前后端API路径对齐**
|
||
- 后端前缀:`/healthlink-his/api/v1/`
|
||
- 前端 `request.js` 的 baseURL 必须与后端匹配
|
||
|
||
**铁律5: 状态值一致性(Bug #574 教训)**
|
||
- 修改任何状态值前,必须先列出完整的状态流转链路
|
||
- 检查项:枚举定义 → Service 设置 → 查询映射 → 前端 STATUS_CLASS_MAP → 前端 v-if → 统计SQL
|
||
- 禁止:只改一端不检查其他端
|
||
|
||
**铁律6: 禁止删除源文件(Bug #574 教训)**
|
||
- 绝对禁止删除项目中已有的 Java/Vue/SQL 源文件
|
||
- 编译错误 → 修复错误;重复文件 → 重构合并
|
||
- AI 幻觉文件 → 检查 `git ls-tree baseline -- <file>` 确认后再删除
|
||
- 唯一例外:明确由人类确认删除的文件
|
||
|
||
**铁律7: 禁止修改已有公开方法签名**
|
||
- 不能删除/重命名已有的 public 方法,不能修改参数列表
|
||
- 需要新功能 → 添加重载方法;需要改行为 → 修改内部实现
|
||
|
||
**铁律8: 验证后才宣称完成(Verification Before Completion)**
|
||
- **没有跑过验证命令,就不能说"完成了""通过了""没问题"**
|
||
- 禁止使用"应该可以""大概没问题""看起来正确"
|
||
- 必须:运行命令 → 读取输出 → 确认结果 → 才能宣称
|
||
- 这是诚实原则,不是效率问题
|
||
|
||
**铁律9: 开发前必须审核原有代码(P0 — 铁律)**
|
||
- **任何新功能开发前,必须先搜索项目中是否已有相关代码**
|
||
- 搜索路径:Controller / AppService / Service / Mapper / Entity / 前端页面 / API接口
|
||
- 如果已有部分功能 → 在原有代码基础上**升级优化完善**,禁止另起炉灶
|
||
- 如果已有接口但前端缺失 → 只补前端,不重复建后端
|
||
- 如果已有前端但后端缺失 → 只补后端,不重写前端
|
||
- 搜索命令:`rg -l "关键词" healthlink-his-server/ healthlink-his-ui/src/`
|
||
- 禁止:不看代码就新建模块、重复实现已有功能、废弃原有代码另写一套
|
||
|
||
**铁律10: 状态变更影响面分析(Bug #574→575 教训)**
|
||
- 改任何状态枚举值前,**必须**执行影响面分析
|
||
- `rg "原状态枚举名" --type java` 列出所有引用文件
|
||
- 逐个检查:设置值?查询过滤?显示映射?统计聚合?
|
||
- 检查逆向流程:退号、取消、停诊是否兼容新状态
|
||
- 检查 XML mapper 中所有查询过滤条件
|
||
- 检查前端所有 v-if/v-for/disabled 条件
|
||
- **禁止**:只改正向流程不验逆向流程
|
||
|
||
**铁律11: 逆向流程验证(Bug #575 教训)**
|
||
- 涉及状态流转的 Bug,验证时**必须**覆盖:
|
||
- 正向:预约→签到→就诊→完成
|
||
- 逆向:退号、取消预约、停诊、退费
|
||
- 边界:并发操作、重复操作、异常中断
|
||
- **禁止**:只测正向流程就标记"修复完成"
|
||
|
||
**铁律12: 全链路 6 环分析**
|
||
- 涉及数据库字段的 Bug/需求 必须走完整链路
|
||
```
|
||
前端/页面 → Controller → Service → Mapper → DB/SQL → 关联模块
|
||
①录入 ②验证 ③业务 ④持久化 ⑤存储 ⑥联动
|
||
```
|
||
- ①录入:前端有无输入入口(弹窗、表格行编辑、表单)
|
||
- ②验证:Controller 参数校验、@Valid、权限控制
|
||
- ③业务:Service 业务逻辑、事务边界、多个 Service 实现类入口
|
||
- ④持久化:Mapper XML、DTO 字段映射、类型转换
|
||
- ⑤存储:数据库表结构、索引、NOT NULL 约束
|
||
- ⑥联动:上游(医嘱→护士站)、下游(打印、计费、报表)是否同步
|
||
|
||
**铁律13: 全链路验证(状态流转 Bug 必做)**
|
||
- 修复后按以下顺序验证,**编译通过不等于修复完成**
|
||
```
|
||
① 数据库:SELECT status FROM table WHERE id = ? → 确认写入正确
|
||
② 后端接口:检查所有 if/switch 分支 → 确认映射正确
|
||
③ 前端显示:检查 STATUS_CLASS_MAP → 确认文本正确
|
||
④ 前端交互:检查 v-if/v-for/disabled → 确认按钮状态正确
|
||
⑤ 统计数据:检查聚合 SQL → 确认统计包含新状态
|
||
```
|
||
|
||
**铁律14: 池/统计表同步(Bug #574 教训)**
|
||
- **任何状态变更必须同步更新关联统计表**
|
||
- 检查清单:
|
||
1. 状态变更后,哪些统计字段需要更新?
|
||
2. 是原子递增/递减,还是全量重算?
|
||
3. 并发安全:用 `SET field = field + 1` 还是先查后改?
|
||
4. 逆向操作(退号/取消)是否正确回滚统计?
|
||
- **禁止**:只改状态不改统计,或只改统计不改状态
|
||
|
||
**铁律15: 统计变更必须验证实际值(Bug #575 教训)**
|
||
- 修改统计逻辑后,**必须查数据库验证实际值**
|
||
- 对比操作前后的值,确认统计正确
|
||
- **禁止**:改了统计逻辑不查数据库验证
|
||
|
||
**铁律16: 搜索所有相关代码路径**
|
||
- 修复前必须用 `rg` 搜索所有引用
|
||
```
|
||
rg "状态枚举名|相关方法名|相关字段名" --type java --type vue
|
||
```
|
||
- 确保不遗漏任何引用路径
|
||
|
||
**铁律17: 数据库铁律**
|
||
- **修前必须查询真实数据库** — 确认表结构、字段约束、索引
|
||
- **禁止凭猜测写 SQL** — 先查看表结构
|
||
- **修改 SQL 后必须验证** — `EXPLAIN` 或实际查询验证语法
|
||
- **NOT NULL 约束必须检查** — INSERT/UPDATE 前先查 `is_nullable`
|
||
- **关联表必须查完整** — 涉及 JOIN 查所有关联表结构和外键
|
||
|
||
**铁律18: 禁止破坏原有功能(P0绝对铁律)**
|
||
- **完善增加功能和流程时,绝对不能破坏或者让原有功能不能用**
|
||
- 修改已有实体前必须对比原始文件(`git show HEAD~N:./file.java`),保留所有原有字段和方法
|
||
- 新增字段只能追加,不能删除或重命名已有字段
|
||
- SQL迁移只允许 `ALTER TABLE ADD COLUMN`,不允许 `DROP COLUMN` 或 `RENAME COLUMN`
|
||
- Controller新端点不能修改已有端点的路径或参数
|
||
- 前端新页面不能修改已有页面的组件结构
|
||
- 每次修改后必须 `mvn clean compile -DskipTests` 验证
|
||
|
||
**铁律19: 编译错误不区分来源(Bug #698 教训)**
|
||
- `mvn compile`、`vite build`、`vue-tsc` 等构建命令报错 = 不过关,**不管是自己引入的还是历史遗留的**
|
||
- 禁止说"这是预存问题""不是我改的""原有bug"——构建通不过就不能宣称完成
|
||
- 正确做法:定位错误 → 修复 → 重新构建确认通过 → 然后才能继续
|
||
|
||
**铁律20: 数据来源必须验证(Bug #698 教训)**
|
||
- 涉及数据查询/提取时,必须先确认数据实际存储位置,不能假设
|
||
- 修复前必须:打印/检查原始数据结构 → 确认字段存在 → 再写提取逻辑
|
||
- 禁止:凭代码推断数据位置、假设"应该在这里"
|
||
|
||
**铁律21: 外部配置值必须实测验证(Bug #698 教训)**
|
||
- 使用外部服务(API、模型、数据库)的配置值,必须实际调用验证
|
||
- 配置变更后必须:发起一次真实请求 → 确认返回 200 → 再宣称配置正确
|
||
- 禁止:改完配置不测试、假设"应该能用"
|
||
|
||
**铁律22: 端到端验证必须有实际输出证据(Bug #698 教训)**
|
||
- 声称功能生效前,必须有实际的端到端输出证据
|
||
- 验证方式:运行命令 → 检查输出中包含预期关键词
|
||
- 禁止:只检查代码路径可达就算"验证通过"
|
||
|
||
**铁律23: 文件读写强制 UTF-8 编码(必遵守)**
|
||
- **禁止**使用 PowerShell Get-Content -Raw(不带 -Encoding UTF8)读取源文件
|
||
- **禁止**使用 Out-File -Encoding utf8(会写 BOM)
|
||
- **正确写法**:
|
||
- 读取:`[System.IO.File]::ReadAllText($path, [System.Text.Encoding]::UTF8)`
|
||
- 写入:`[System.IO.File]::WriteAllText($path, $content, [System.Text.UTF8Encoding]::new(False))`
|
||
- **原因**:Windows PowerShell 5.1 默认用系统 locale(GBK/CP936)读写,会把 UTF-8 中文变成乱码
|
||
|
||
**铁律24: 禁止硬编码业务默认值(Bug #617 教训)**
|
||
- **禁止**在提交参数中硬编码业务默认值(如 `contractNo: '0000'`)
|
||
- 必须使用用户在表单中选择的值,硬编码值仅作为 fallback
|
||
- 检查清单:
|
||
1. 表单字段是否有 `v-model` 绑定?
|
||
2. 构建提交参数时是否使用了绑定值?
|
||
3. 提交后是否覆盖了用户选择?
|
||
|
||
---
|
||
|
||
### 🟡 P1 铁律 — 强烈建议
|
||
|
||
**铁律25: 先分解再行动**
|
||
- 修改超过3个文件、涉及多模块、数据库变更,必须先制定计划
|
||
|
||
**铁律26: 验证后信**
|
||
- 每次修改后必须验证编译通过,不信记忆
|
||
|
||
**铁律27: 文档统一管理**
|
||
- 所有文档存储在 `MD/` 目录
|
||
- 文件名:大写英文+下划线(如 `BACKEND_CHECKLIST.md`)
|
||
- 文档头部必须包含元数据块(文档类型、版本、日期)
|
||
|
||
**铁律28: 设计文档必须包含UI设计和调用流程**
|
||
- 所有新模块/页面的设计文档必须包含:UI布局描述、交互效果清单、前后端调用流程
|
||
- 没有明确UI设计的模块,禁止直接编码
|
||
- 设计文档必须写清楚:系统调用关系、方法函数调用关系、完整业务流程
|
||
- 设计文档中每个用户操作必须对应:前端事件 → API调用 → 后端处理链路 → 返回数据 → UI渲染
|
||
|
||
**铁律29: 设计文档确认后自主开发(铁律)**
|
||
- 设计文档一旦确认,后续开发**必须按文档自主执行**
|
||
- **禁止反复询问"是否继续""下一步做什么""是否开始"**——直接按计划推进
|
||
- 每完成一个 Sprint,自动提交推送,然后立即开始下一个 Sprint
|
||
- 只在遇到**无法解决的阻塞**时才暂停询问
|
||
|
||
**铁律30: 前端验证铁律**
|
||
- **提交前必须编译前端** — `npm run build:dev` 或 `npx vite build` 通过才算完成
|
||
- **禁止只改 .vue 文件不验证编译** — 改完必须跑一次编译确认无报错
|
||
- **SCSS 括号闭合必须检查** — `<style lang="scss" scoped>` 内的所有 `{}` 必须成对闭合
|
||
- **编译报错必须当场修复** — 看到 error 立即修,不要留到下一步
|
||
|
||
**铁律31: 提交前验证铁律**
|
||
- **后端**: `mvn compile` 通过 + 无新增 warning
|
||
- **前端**: `npm run build:dev` 通过 + 无 SCSS 错误
|
||
- **禁止跳过编译直接提交** — 编译失败的代码不允许进仓库
|
||
- **提交信息格式**: `type(scope): description`(如 `fix(registration): 修复退号金额计算`)
|
||
|
||
**铁律32: 修复流程**
|
||
- **一次只修一个 Bug**,不扩大范围
|
||
- **修前必须完整获取 Bug 全部信息** — 描述、复现步骤、所有截图/附件、所有备注历史。禁止只看标题就写代码
|
||
- **修复前必须读 AGENTS.md**
|
||
- **修复后必须验证编译** — `mvn compile` / `vue-tsc --noEmit` 0 error
|
||
- **commit 前必须验证** — 编译通过 + 无新增 lint 警告
|
||
|
||
**铁律33: Bug 状态管理**
|
||
- **已关闭/已解决的 Bug 禁止处理** — 处理前检查状态,resolved/closed 直接跳过
|
||
- **人类提的 Bug 只加备注不改状态** — 不改 status、不改 assignedTo
|
||
- **智能体提的 Bug 可改分配和加备注** — 状态变更等测试通过后由华佗确认
|
||
- **每个修复必须有 git commit** — 格式: `fix(#bug_id): 简要描述`
|
||
|
||
**铁律34: 质量门禁**
|
||
- L1: 编译通过
|
||
- L2: 测试通过
|
||
- L3: DB审查通过
|
||
- L4: 验收通过
|
||
- L5: 归档完成
|
||
|
||
---
|
||
|
||
## 三、Karpathy 编码准则
|
||
|
||
> 减少 LLM 常见编码错误。偏向谨慎而非速度。
|
||
|
||
### 3.1 先想再写
|
||
- 明确陈述假设,不确定就问
|
||
- 多种解读时都列出来,不要默默选一种
|
||
- 有更简单的方案就说出来,该推回就推回
|
||
- 不清楚的地方停下来,说清楚哪里不清楚
|
||
|
||
### 3.2 简洁优先
|
||
- 不做没要求的功能,不做一次性代码的抽象
|
||
- 不加没要求的"灵活性"和"可配置性"
|
||
- 200 行能 50 行搞定就重写
|
||
- 自问:"高级工程师会不会觉得这过度设计?"
|
||
|
||
### 3.3 精准修改
|
||
- 只改必须改的,不"顺手改进"相邻代码
|
||
- 匹配现有代码风格,即使你有不同的偏好
|
||
- 每行改动都能追溯到用户的请求
|
||
- 只清理你自己改动产生的无用代码
|
||
|
||
### 3.4 目标驱动
|
||
- 把任务转化为可验证目标
|
||
- 多步任务声明计划:`[步骤] → 验证: [检查]`
|
||
- 强验收标准让 Agent 能独立循环,弱标准需要持续澄清
|
||
|
||
---
|
||
|
||
## 四、系统化调试(Systematic Debugging)
|
||
|
||
> **铁律:没有根因调查,不能提出修复方案。**
|
||
|
||
### 四阶段流程
|
||
|
||
**阶段1:根因调查**(修复前必须完成)
|
||
1. 仔细阅读错误信息(堆栈、行号、错误码)
|
||
2. 稳定复现(能否可靠触发?步骤?每次?)
|
||
3. 检查最近变更(git diff、新依赖、配置变更)
|
||
4. 多组件系统:在每个组件边界加诊断日志,定位哪一层断裂
|
||
5. 追踪数据流:坏值从哪里来?谁调用的?一直追溯到源头
|
||
|
||
**阶段2:模式分析**
|
||
- 找到同代码库中类似的正常工作代码
|
||
- 逐项对比差异
|
||
- 理解依赖关系
|
||
|
||
**阶段3:假设与测试**
|
||
- 形成单一假设:"我认为X是根因,因为Y"
|
||
- 做最小改动测试
|
||
- 有效 → 阶段4;无效 → 新假设
|
||
|
||
**阶段4:实施**
|
||
- 创建失败测试用例
|
||
- 修复根因(不是症状)
|
||
- 验证修复
|
||
|
||
---
|
||
|
||
## 五、后端开发规范
|
||
|
||
### 分层架构
|
||
```
|
||
Controller → AppService → Service → Mapper → Entity
|
||
```
|
||
|
||
### 命名规范
|
||
| 类型 | 规则 | 示例 |
|
||
|------|------|------|
|
||
| Controller | `XxxController` | `RegistrationController` |
|
||
| AppService | `IXxxAppService` / `XxxAppServiceImpl` | `IRegistrationAppService` |
|
||
| Service | `IXxxService` / `XxxServiceImpl` | `IRegistrationService` |
|
||
| Mapper | `XxxMapper` | `RegistrationMapper` |
|
||
| Entity | `Xxx` | `Registration` |
|
||
| DTO | `XxxDto` / `XxxQueryDto` | `RegistrationDto` |
|
||
|
||
### 包结构
|
||
```
|
||
com.healthlink.his.web.{module}.controller
|
||
com.healthlink.his.web.{module}.appservice
|
||
com.healthlink.his.web.{module}.service
|
||
com.healthlink.his.web.{module}.mapper
|
||
com.healthlink.his.web.{module}.dto
|
||
com.healthlink.his.domain.{module}
|
||
com.healthlink.his.common.enums
|
||
```
|
||
|
||
### 关键约束
|
||
- 所有查询使用 `LambdaQueryWrapper`,禁止字符串拼接 SQL
|
||
- `@Transactional(rollbackFor = Exception.class)` 管理事务
|
||
- 所有接口标注 `@PreAuthorize` 权限控制
|
||
- 患者敏感信息在日志中脱敏
|
||
- **扩展功能不修改原有函数签名**
|
||
- **DTO 字段类型防御**:前端传入的 Boolean 字段 → 改用 String + 业务层转换(Jackson 对 Boolean 严格校验);所有接受前端输入的 DTO 加 `@JsonIgnoreProperties(ignoreUnknown = true)`
|
||
|
||
---
|
||
|
||
## 六、前端开发规范
|
||
|
||
### 技术栈
|
||
- Vue 3 + Vite + Element Plus + Pinia + Axios(基于 RuoYi-Vue3)
|
||
|
||
### 目录结构
|
||
```
|
||
src/api/{module}/ # API接口
|
||
src/views/{module}/ # 页面组件
|
||
src/store/modules/ # Pinia状态管理
|
||
src/components/ # 公共组件
|
||
```
|
||
|
||
### 关键约束
|
||
- API前缀:`/healthlink-his/api/v1/`
|
||
- 路由懒加载:`() => import('@/views/xxx/index.vue')`
|
||
- 页面使用 `<script setup>` 语法
|
||
- 按钮权限使用 `v-hasPermi` 指令
|
||
- `onMounted` 中注册的事件在 `onUnmounted` 中移除
|
||
|
||
---
|
||
|
||
## 七、Agent 体系
|
||
|
||
### 角色与路由
|
||
|
||
| 代号 | 名称 | 角色 | 路由关键词 |
|
||
|------|------|------|-----------|
|
||
| liubei | 刘备 | 项目经理 | 协调、分派、异常升级 |
|
||
| zhugeliang | 诸葛亮 | 架构师 | 分析、路由、设计 |
|
||
| guanyu | 关羽 | 后端开发 | java, api, spring, service, controller |
|
||
| zhaoyun | 赵云 | 前端开发 | vue, 界面, 显示, 弹窗, 按钮 |
|
||
| xunyu | 荀彧 | DBA | 数据库, sql, 迁移, mapper xml |
|
||
| zhangfei | 张飞 | 测试 | 测试, QA, 回归 |
|
||
| huatuo | 华佗 | 验收 | 需求验收、质量确认 |
|
||
| chenlin | 陈琳 | 文档 | 文档、归档、Git提交 |
|
||
|
||
### 协作流水线
|
||
|
||
```
|
||
刘备(协调) → 诸葛亮(分析路由) → {关羽|赵云}(修复) → 荀彧(DB审查) → 张飞(测试) → 华佗(验收) → 陈琳(归档)
|
||
```
|
||
|
||
---
|
||
|
||
## 八、快速参考命令
|
||
|
||
```bash
|
||
# === 后端 ===
|
||
export JAVA_HOME=/opt/jdk-25
|
||
mvn clean compile -DskipTests # 编译
|
||
mvn install -DskipTests # 构建
|
||
mvn test -pl healthlink-his-application -Dtest="XxxTest" -Dsurefire.failIfNoSpecifiedTests=false
|
||
|
||
# === 前端 ===
|
||
cd healthlink-his-ui
|
||
npm run dev && npm run build:dev && npm run lint && npm run test:run
|
||
|
||
# === Git ===
|
||
git status && git add -A && git commit -m "feat(module): desc" && git push origin develop
|
||
```
|
||
|
||
---
|
||
|
||
## 九、过往教训
|
||
|
||
| Bug | 教训 | 根因 |
|
||
|---|---|---|
|
||
| #574 | 状态值 BOOKED(1)→应为 CHECKED_IN(3),前端映射缺失 | 没走完整状态链路 |
|
||
| #574 | AI 看到编译错误直接删文件 | 没检查 git baseline |
|
||
| #574 | 多次 fallback 修错文件 | 没用 rg 搜索所有引用 |
|
||
| #574 | 签到后 booked_num 未累加 | 只改状态没改统计 |
|
||
| #575 | 改了签到状态没检查退号流程 | 只验正向不验逆向 |
|
||
| #575 | booked_num 应在预约时累加而非签到时 | 统计变更未验证实际值 |
|
||
| #617 | 费用性质硬编码为 '0000'(自费),用户选医保无效 | 构建参数时写死默认值 |
|
||
| #632 | Boolean DTO 接收字符串 "肝功能12项" 导致反序列化失败 | DTO 字段类型未做防御 |
|
||
| #698 | 模型名拼写错误 mino→mimo 导致 400 | 外部配置值未实测验证 |
|
||
| — | 修复完成未提交到 develop | 框架未强制验证提交 |
|
||
| — | 退号流程只检查 BOOKED(1) 不兼容 CHECKED_IN(3) | 状态变更影响面分析缺失 |
|
||
|
||
---
|
||
|
||
> ⚠️ 本文件是 AI 开发规范的唯一信源。
|
||
>
|
||
> 📅 最后更新: 2026-06-10 | 来源: AgentForge Harness Iron Laws (39条) |