revert: 恢复误删文件(回退 81f500160)
This commit is contained in:
168
MD/specs/BACKEND_CHECKLIST.md
Executable file
168
MD/specs/BACKEND_CHECKLIST.md
Executable file
@@ -0,0 +1,168 @@
|
||||
# 后端发布前检查清单
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: 后端开发
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
## 📋 基础检查项
|
||||
|
||||
### Maven编译验证
|
||||
- [ ] 本地执行 `mvn compile` 编译通过,无ERROR
|
||||
- [ ] 执行 `mvn package -DskipTests` 打包成功
|
||||
- [ ] 依赖版本无冲突(`mvn dependency:tree` 检查)
|
||||
- [ ] 无编译警告(或已有书面说明可忽略)
|
||||
|
||||
### 构建产物验证
|
||||
- [ ] JAR/WAR包生成完整,大小合理
|
||||
- [ ] `application.yml` 等配置文件已打包进产物
|
||||
- [ ] 第三方依赖jar包完整(lib目录无缺失)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Spring Boot 配置检查
|
||||
|
||||
### 多环境配置
|
||||
- [ ] `application-dev.yml`(开发)配置正确
|
||||
- [ ] `application-test.yml`(测试)配置正确
|
||||
- [ ] `application-prod.yml`(生产)配置正确
|
||||
- [ ] 启动参数 `--spring.profiles.active` 指定正确环境
|
||||
- [ ] 生产环境未启用devtools热部署
|
||||
|
||||
### Actuator安全
|
||||
- [ ] 生产环境 `/actuator` 端点已禁用或限制访问
|
||||
- [ ] `/actuator/env`、`/actuator/heapdump` 等敏感端点已关闭
|
||||
- [ ] 健康检查端点 `/actuator/health` 返回信息已脱敏
|
||||
|
||||
### 启动校验
|
||||
- [ ] 数据库连接池配置合理(HikariCP最大/最小连接数)
|
||||
- [ ] Redis/消息中间件连接配置正确
|
||||
- [ ] 启动日志无ERROR级别异常
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ MyBatis Plus 规范检查
|
||||
|
||||
### 实体-表映射
|
||||
- [ ] 所有实体类标注 `@TableName`,表名与实际一致
|
||||
- [ ] 主键字段标注 `@TableId(type = IdType.AUTO)` 或对应策略
|
||||
- [ ] 非表字段标注 `@TableField(exist = false)`
|
||||
- [ ] 字段命名符合下划线转驼峰规则
|
||||
|
||||
### SQL安全
|
||||
- [ ] 所有查询使用参数化查询(`QueryWrapper` / `LambdaQueryWrapper`)
|
||||
- [ ] 禁止字符串拼接SQL(`"WHERE name = '" + name + "'"`)
|
||||
- [ ] 批量操作使用MyBatis Plus `saveBatch` / `updateBatchById`
|
||||
- [ ] 复杂SQL使用XML映射,避免注解内嵌长SQL
|
||||
|
||||
### 事务管理
|
||||
- [ ] 涉及多表写操作的方法标注 `@Transactional`
|
||||
- [ ] 事务边界合理,不包含外部HTTP调用
|
||||
- [ ] 异常回滚配置正确(`rollbackFor = Exception.class`)
|
||||
- [ ] 事务方法未被同一类内方法直接调用(自调用失效问题)
|
||||
|
||||
### 分页插件
|
||||
- [ ] `PaginationInnerInterceptor` 已正确配置
|
||||
- [ ] 分页查询使用 `Page<T>` 对象,非手动limit/offset
|
||||
|
||||
---
|
||||
|
||||
## 🔌 RESTful API 设计检查
|
||||
|
||||
### 统一返回格式
|
||||
- [ ] 所有接口返回 `{code, msg, data}` 统一结构
|
||||
- [ ] 成功返回 `code=200`,业务错误使用自定义错误码
|
||||
- [ ] 异常通过 `@ControllerAdvice` + `@ExceptionHandler` 统一处理
|
||||
|
||||
### HTTP状态码
|
||||
- [ ] 资源创建返回 `201 Created`
|
||||
- [ ] 资源删除返回 `204 No Content`
|
||||
- [ ] 参数校验失败返回 `400 Bad Request`
|
||||
- [ ] 未认证返回 `401 Unauthorized`
|
||||
- [ ] 无权限返回 `403 Forbidden`
|
||||
- [ ] 资源不存在返回 `404 Not Found`
|
||||
|
||||
### 参数校验
|
||||
- [ ] 请求参数使用 `@Valid` / `@Validated` 注解校验
|
||||
- [ ] 必填字段标注 `@NotBlank` / `@NotNull`
|
||||
- [ ] 数值范围标注 `@Min` / `@Max`
|
||||
- [ ] 格式校验使用 `@Pattern`(如手机号、身份证号)
|
||||
- [ ] 校验失败返回明确错误信息(非500堆栈)
|
||||
|
||||
### API版本管理
|
||||
- [ ] 接口路径包含版本号(`/api/v1/`、`/api/v2/`)
|
||||
- [ ] 废弃接口标注 `@Deprecated`,并在文档中说明
|
||||
- [ ] 不兼容变更必须升级版本号
|
||||
|
||||
---
|
||||
|
||||
## 🔒 安全与合规检查
|
||||
|
||||
### 数据脱敏
|
||||
- [ ] 患者身份证号在日志中脱敏(`***` 掩码)
|
||||
- [ ] 患者手机号在日志中脱敏(前3后4,中间`****`)
|
||||
- [ ] 敏感字段序列化时使用 `@JsonSerialize` 自定义脱敏器
|
||||
- [ ] 接口返回中非必需字段不暴露(如密码、salt)
|
||||
|
||||
### 权限控制
|
||||
- [ ] 所有涉及患者数据的接口标注 `@PreAuthorize`
|
||||
- [ ] 数据级权限校验(医生只能访问本科室患者)
|
||||
- [ ] 越权访问返回 `403`,非 `404` 或 `500`
|
||||
- [ ] 敏感操作(删除、修改诊断)需二次确认或额外权限
|
||||
|
||||
### 审计日志
|
||||
- [ ] 处方修改记录操作人、时间、变更内容
|
||||
- [ ] 病历删除操作记录完整审计链
|
||||
- [ ] 审计日志独立存储,不可被业务用户删除
|
||||
- [ ] 关键业务操作记录IP地址和操作终端
|
||||
|
||||
---
|
||||
|
||||
## ⚡ 性能检查
|
||||
|
||||
### 数据库查询
|
||||
- [ ] 无N+1查询问题(使用 `JOIN` 或批量查询)
|
||||
- [ ] 大表查询必须有分页限制
|
||||
- [ ] 慢查询已优化(执行时间 < 500ms)
|
||||
- [ ] 索引已覆盖高频查询条件
|
||||
|
||||
### 接口性能
|
||||
- [ ] 核心接口响应时间 < 1秒
|
||||
- [ ] 列表接口支持分页,无全量返回
|
||||
- [ ] 大文件下载使用流式传输,非全量加载到内存
|
||||
|
||||
---
|
||||
|
||||
## 📝 文档与发布准备
|
||||
|
||||
### 文档更新
|
||||
- [ ] API接口文档已同步更新(路径、参数、返回值)
|
||||
- [ ] 数据库变更脚本已提供(DDL/DML)
|
||||
- [ ] 配置变更说明已记录(新增/修改的配置项)
|
||||
- [ ] 影响范围说明已明确(哪些模块、哪些接口受影响)
|
||||
|
||||
### 回滚预案
|
||||
- [ ] 数据库变更可回滚(提供反向SQL脚本)
|
||||
- [ ] 配置变更可快速回退
|
||||
- [ ] 紧急回滚流程已明确(谁、怎么做、多长时间)
|
||||
- [ ] 回滚后数据一致性已验证
|
||||
|
||||
---
|
||||
|
||||
## ✅ 最终确认
|
||||
|
||||
### 发布前最后检查
|
||||
- [ ] `mvn compile` 构建成功(附终端截图)
|
||||
- [ ] 关键单元测试通过
|
||||
- [ ] 测试环境部署验证通过
|
||||
- [ ] Code Review 已完成并获得批准
|
||||
- [ ] 相关Bug已关闭或延期说明
|
||||
|
||||
---
|
||||
|
||||
**文档版本**:v1.0
|
||||
**最后更新**:2026年4月24日
|
||||
**负责人**:关羽(后端开发)
|
||||
**适用范围**:HIS 系统所有后端模块(his-server)
|
||||
**补充说明**:本清单与陈琳的《前端发布前检查清单》对称互补,共同构成HIS系统发布前完整质量保障体系
|
||||
367
MD/specs/BACKEND_DEVELOPMENT_STANDARD.md
Normal file
367
MD/specs/BACKEND_DEVELOPMENT_STANDARD.md
Normal file
@@ -0,0 +1,367 @@
|
||||
# HealthLink-HIS 后端开发规范
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: 后端 Java 开发
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
## 一、技术栈
|
||||
|
||||
| 组件 | 版本 | 说明 |
|
||||
|------|------|------|
|
||||
| JDK | 25 | OpenJDK 25 (LTS) |
|
||||
| Spring Boot | 4.0.6 | 框架核心 |
|
||||
| MyBatis-Plus | 3.5.16 | ORM框架 |
|
||||
| PostgreSQL | 15+ | 主数据库 |
|
||||
| Redis | 7.x | 缓存/会话 |
|
||||
| Maven | 3.9+ | 构建工具 |
|
||||
|
||||
---
|
||||
|
||||
## 二、项目结构
|
||||
|
||||
```
|
||||
healthlink-his-server/
|
||||
├── healthlink-his-common/ # 公共模块(枚举、常量、工具类)
|
||||
├── healthlink-his-domain/ # 领域层(实体、Mapper、Flyway迁移)
|
||||
├── healthlink-his-application/ # 应用层(Controller、Service、业务逻辑)
|
||||
├── core-common/ # 若依公共核心
|
||||
├── core-system/ # 若依系统模块
|
||||
├── core-framework/ # 若依框架核心
|
||||
├── core-quartz/ # 定时任务
|
||||
├── core-generator/ # 代码生成
|
||||
├── core-flowable/ # 工作流
|
||||
└── core-admin/ # 管理后台
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、分层架构规范
|
||||
|
||||
### 3.1 Controller 层
|
||||
- 路径:`com.healthlink.his.web.{module}.controller`
|
||||
- 职责:接收请求、参数校验、调用AppService、返回统一结果
|
||||
- 禁止:直接操作数据库、编写业务逻辑
|
||||
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/registration")
|
||||
@Api(tags = "挂号管理")
|
||||
public class RegistrationController {
|
||||
|
||||
@Autowired
|
||||
private IRegistrationAppService registrationAppService;
|
||||
|
||||
@GetMapping("/list")
|
||||
@PreAuthorize("@ss.hasPermi('registration:list')")
|
||||
public TableDataInfo list(RegistrationQueryDto query) {
|
||||
startPage();
|
||||
List<RegistrationDto> list = registrationAppService.selectList(query);
|
||||
return getDataTable(list);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 AppService 层(应用服务)
|
||||
- 路径:`com.healthlink.his.web.{module}.appservice`
|
||||
- 职责:编排业务流程、协调多个Service、事务管理
|
||||
- 命名:`XxxAppService`(接口)+ `XxxAppServiceImpl`(实现)
|
||||
|
||||
### 3.3 Service 层
|
||||
- 路径:`com.healthlink.his.web.{module}.service`
|
||||
- 职责:单表CRUD、基础业务逻辑
|
||||
- 命名:`IXxxService`(接口)+ `XxxServiceImpl`(实现)
|
||||
|
||||
### 3.4 Mapper 层
|
||||
- 路径:`com.healthlink.his.web.{module}.mapper`
|
||||
- 职责:数据访问、SQL映射
|
||||
- 命名:`XxxMapper`(接口)+ `XxxMapper.xml`(XML映射)
|
||||
|
||||
### 3.5 Entity/Domain 层
|
||||
- 路径:`com.healthlink.his.domain.{module}`
|
||||
- 职责:实体定义、数据库表映射
|
||||
- 命名:`Xxx`(实体类)
|
||||
|
||||
### 3.6 DTO 层
|
||||
- 路径:`com.healthlink.his.web.{module}.dto`
|
||||
- 职责:数据传输对象、查询参数、返回结果
|
||||
|
||||
---
|
||||
|
||||
## 四、命名规范
|
||||
|
||||
### 4.1 包命名
|
||||
```
|
||||
com.healthlink.his.web.{模块名}.{层级}
|
||||
```
|
||||
|
||||
### 4.2 类命名
|
||||
| 类型 | 命名规则 | 示例 |
|
||||
|------|---------|------|
|
||||
| Controller | `XxxController` | `RegistrationController` |
|
||||
| AppService接口 | `IXxxAppService` | `IRegistrationAppService` |
|
||||
| AppService实现 | `XxxAppServiceImpl` | `RegistrationAppServiceImpl` |
|
||||
| Service接口 | `IXxxService` | `IRegistrationService` |
|
||||
| Service实现 | `XxxServiceImpl` | `RegistrationServiceImpl` |
|
||||
| Mapper | `XxxMapper` | `RegistrationMapper` |
|
||||
| Entity | `Xxx` | `Registration` |
|
||||
| DTO | `XxxDto` / `XxxQueryDto` | `RegistrationDto` |
|
||||
| Enum | `XxxEnum` / `XxxType` | `ItemType` |
|
||||
|
||||
### 4.3 方法命名
|
||||
| 场景 | 命名规则 | 示例 |
|
||||
|------|---------|------|
|
||||
| 查询列表 | `selectList` / `queryList` | `selectList(query)` |
|
||||
| 查询详情 | `selectById` / `getById` | `selectById(id)` |
|
||||
| 新增 | `insert` / `save` / `add` | `insert(dto)` |
|
||||
| 修改 | `update` / `modify` | `update(dto)` |
|
||||
| 删除 | `delete` / `remove` | `deleteById(id)` |
|
||||
| 批量操作 | `batchXxx` | `batchInsert(list)` |
|
||||
|
||||
### 4.4 数据库命名
|
||||
| 类型 | 命名规则 | 示例 |
|
||||
|------|---------|------|
|
||||
| 表名 | `{模块}_{功能}` 小写下划线 | `reg_registration` |
|
||||
| 字段名 | 小写下划线 | `patient_id`, `create_time` |
|
||||
| 主键 | `id` 或 `{表名}_id` | `registration_id` |
|
||||
| 外键 | `{关联表}_id` | `patient_id` |
|
||||
| 时间字段 | `create_time`, `update_time` | — |
|
||||
| 软删除 | `del_flag` | — |
|
||||
| 租户 | `tenant_id` | — |
|
||||
|
||||
---
|
||||
|
||||
## 五、编码规范
|
||||
|
||||
### 5.1 Controller 规范
|
||||
```java
|
||||
// ✅ 正确
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/patient")
|
||||
@Api(tags = "患者管理")
|
||||
@Slf4j
|
||||
public class PatientController {
|
||||
|
||||
@Autowired
|
||||
private IPatientAppService patientAppService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermi('patient:query')")
|
||||
public AjaxResult getInfo(@PathVariable Long id) {
|
||||
return success(patientAppService.selectById(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermi('patient:add')")
|
||||
public AjaxResult add(@Validated @RequestBody PatientDto dto) {
|
||||
return toAjax(patientAppService.insert(dto));
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ 错误 - Controller里写业务逻辑
|
||||
public AjaxResult add(@RequestBody PatientDto dto) {
|
||||
// 不应该在这里写验证逻辑
|
||||
if (dto.getName() == null) {
|
||||
return error("名称不能为空");
|
||||
}
|
||||
// 不应该在这里写数据库操作
|
||||
patientMapper.insert(patient);
|
||||
return success();
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Service 规范
|
||||
```java
|
||||
// ✅ 正确 - 事务注解
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int insert(PatientDto dto) {
|
||||
Patient patient = BeanUtils.copyProperties(dto, Patient.class);
|
||||
patient.setCreateTime(new Date());
|
||||
patient.setCreateBy(SecurityUtils.getUsername());
|
||||
return patientMapper.insert(patient);
|
||||
}
|
||||
|
||||
// ❌ 错误 - 自调用导致事务失效
|
||||
public void batchProcess(List<PatientDto> list) {
|
||||
for (PatientDto dto : list) {
|
||||
this.insert(dto); // 自调用,事务不生效!
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 Mapper 规范
|
||||
```java
|
||||
// ✅ 正确 - 使用LambdaQueryWrapper
|
||||
public List<Patient> selectList(PatientQueryDto query) {
|
||||
LambdaQueryWrapper<Patient> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(StringUtils.isNotBlank(query.getName()), Patient::getName, query.getName())
|
||||
.eq(Patient::getDelFlag, "0")
|
||||
.orderByDesc(Patient::getCreateTime);
|
||||
return patientMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
// ❌ 错误 - 字符串拼接SQL
|
||||
public List<Patient> selectList(String name) {
|
||||
String sql = "SELECT * FROM patient WHERE name = '" + name + "'";
|
||||
return jdbcTemplate.queryForList(sql, Patient.class);
|
||||
}
|
||||
```
|
||||
|
||||
### 5.4 统一返回格式
|
||||
```java
|
||||
// 成功
|
||||
return AjaxResult.success(data);
|
||||
return AjaxResult.success("操作成功", data);
|
||||
|
||||
// 失败
|
||||
return AjaxResult.error("患者不存在");
|
||||
return AjaxResult.error(MessageUtils.message("patient.not.found"));
|
||||
|
||||
// 列表
|
||||
TableDataInfo dataPage = getDataTable(list);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、异常处理规范
|
||||
|
||||
### 6.1 业务异常
|
||||
```java
|
||||
throw new ServiceException("患者编号不能为空");
|
||||
throw new ServiceException(MessageUtils.message("patient.id.required"));
|
||||
```
|
||||
|
||||
### 6.2 全局异常处理
|
||||
- 使用 `@RestControllerAdvice` + `@ExceptionHandler`
|
||||
- 不在 Controller 中 try-catch 后返回错误
|
||||
- 所有异常最终返回统一格式 `{code, msg, data}`
|
||||
|
||||
### 6.3 日志规范
|
||||
```java
|
||||
// ✅ 正确
|
||||
log.info("患者挂号成功: patientId={}, registrationId={}", patientId, regId);
|
||||
log.error("挂号失败: patientId={}", patientId, e);
|
||||
|
||||
// ❌ 错误
|
||||
log.info("患者身份证号: " + idCard); // 敏感信息泄露
|
||||
System.out.println("debug"); // 不使用System.out
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、安全规范
|
||||
|
||||
### 7.1 数据脱敏
|
||||
- 患者身份证号:`***` 掩码
|
||||
- 患者手机号:前3后4,中间 `****`
|
||||
- 密码:BCrypt 加密,不可逆
|
||||
|
||||
### 7.2 SQL注入防护
|
||||
- 所有查询使用参数化查询
|
||||
- 禁止字符串拼接 SQL
|
||||
- 使用 MyBatis-Plus 的 `QueryWrapper` / `LambdaQueryWrapper`
|
||||
|
||||
### 7.3 权限控制
|
||||
- 所有接口标注 `@PreAuthorize`
|
||||
- 数据级权限校验(医生只能访问本科室患者)
|
||||
- 敏感操作需二次确认
|
||||
|
||||
---
|
||||
|
||||
## 八、测试规范
|
||||
|
||||
### 8.1 测试类型
|
||||
| 类型 | 工具 | 覆盖范围 |
|
||||
|------|------|---------|
|
||||
| 单元测试 | JUnit 5 + Mockito | Service/工具类 |
|
||||
| 接口测试 | MockMvc + SpringBootTest | Controller接口 |
|
||||
| 白盒测试 | Maven编译 | 全量代码 |
|
||||
| 黑盒测试 | 手动/自动化 | 核心业务流程 |
|
||||
|
||||
### 8.2 接口测试规范
|
||||
```java
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
public class PatientApiTest {
|
||||
|
||||
@Test
|
||||
public void testGetPatientInfo() throws Exception {
|
||||
mockMvc.perform(get("/healthlink-his/api/v1/patient/{id}", 1L)
|
||||
.header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").isNotEmpty())
|
||||
.andExpect(jsonPath("$.data.name").isNotEmpty());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 测试数据要求
|
||||
- 测试数据必须基于业务逻辑设计
|
||||
- 验证业务返回内容(非仅HTTP状态码)
|
||||
- 覆盖正常流程和异常流程
|
||||
- 包含边界条件测试
|
||||
|
||||
---
|
||||
|
||||
## 九、性能规范
|
||||
|
||||
### 9.1 数据库查询
|
||||
- 无N+1查询问题(使用 `JOIN` 或批量查询)
|
||||
- 大表查询必须有分页限制
|
||||
- 慢查询已优化(执行时间 < 500ms)
|
||||
- 索引已覆盖高频查询条件
|
||||
|
||||
### 9.2 接口性能
|
||||
- 核心接口响应时间 < 1秒
|
||||
- 列表接口支持分页,无全量返回
|
||||
- 大文件下载使用流式传输
|
||||
|
||||
### 9.3 缓存使用
|
||||
- 频繁查询的字典数据使用Redis缓存
|
||||
- 缓存必须设置过期时间
|
||||
- 数据变更时主动清除相关缓存
|
||||
|
||||
---
|
||||
|
||||
## 十、Git提交规范
|
||||
|
||||
### Commit Message 格式
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
### Type 类型
|
||||
| Type | 说明 |
|
||||
|------|------|
|
||||
| feat | 新功能 |
|
||||
| fix | Bug修复 |
|
||||
| docs | 文档变更 |
|
||||
| style | 代码格式(不影响功能) |
|
||||
| refactor | 重构 |
|
||||
| test | 测试相关 |
|
||||
| chore | 构建/工具变更 |
|
||||
|
||||
### 示例
|
||||
```
|
||||
feat(registration): 新增患者过敏史管理功能
|
||||
|
||||
- 新增 PatientAllergy 实体和 Mapper
|
||||
- 新增 IRegistrationAppService.getPatientAllergy()
|
||||
- 新增 /api/v1/registration/allergy 接口
|
||||
- Flyway迁移脚本: V2.0.1__add_patient_allergy.sql
|
||||
|
||||
Co-authored-by: zhangsan <zhangsan@healthlink.com>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **文档版本**: v1.0
|
||||
> **最后更新**: 2026-06-06
|
||||
72
MD/specs/BED_MANAGEMENT_DESIGN.md
Normal file
72
MD/specs/BED_MANAGEMENT_DESIGN.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 床位管理模块设计文档
|
||||
|
||||
> **文档类型**: 业务设计
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **依据标准**: 《三级医院评审标准(2022版)》床位使用率指标
|
||||
|
||||
---
|
||||
|
||||
## 一、业务背景
|
||||
|
||||
床位管理直接影响医院运营效率。三甲医院评审要求床位使用率≥85%,床位周转次数达标。需要实时掌握床位状态,支持智能分配。
|
||||
|
||||
---
|
||||
|
||||
## 二、状态流转
|
||||
|
||||
### 2.1 床位状态机
|
||||
|
||||
```
|
||||
空闲(0) → 占用(1) → 清洁中(2) → 空闲(0)
|
||||
↓
|
||||
维修中(3) → 空闲(0)
|
||||
```
|
||||
|
||||
| 状态 | 值 | 触发条件 | 允许操作 |
|
||||
|------|-----|---------|---------|
|
||||
| 空闲 | 0 | 清洁完成/新床 | 分配患者 |
|
||||
| 占用 | 1 | 患者入院分配 | 患者转科/出院 |
|
||||
| 清洁中 | 2 | 患者出院后 | 清洁完成→空闲 |
|
||||
| 维修中 | 3 | 设备故障 | 维修完成→空闲 |
|
||||
|
||||
---
|
||||
|
||||
## 三、业务规则
|
||||
|
||||
| 规则编号 | 规则名称 | 规则描述 | 触发时机 |
|
||||
|---------|---------|---------|---------|
|
||||
| BR-001 | 床位分配校验 | 只有"空闲"状态的床位才能分配 | 入院登记时 |
|
||||
| BR-002 | 科室匹配 | 床位所属科室必须与患者入院科室一致 | 入院登记时 |
|
||||
| BR-003 | 出院自动清洁 | 患者出院后床位自动变为"清洁中" | 出院结算时 |
|
||||
| BR-004 | 使用率统计 | 实时计算科室/全院床位使用率 | 定时任务 |
|
||||
| BR-005 | 床位预约 | 支持预约指定床位(限时保留) | 预约住院时 |
|
||||
|
||||
---
|
||||
|
||||
## 四、数据模型
|
||||
|
||||
### 床位使用率计算公式
|
||||
```
|
||||
科室床位使用率 = (占用床位数 / 总床位数) × 100%
|
||||
全院床位使用率 = (全院占用床位数 / 全院总床位数) × 100%
|
||||
床位周转次数 = 出院人次 / 平均开放床位数
|
||||
```
|
||||
|
||||
### 床位占用时长统计
|
||||
```
|
||||
平均住院天数 = Σ(出院日期 - 入院日期) / 出院人次
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、测试用例
|
||||
|
||||
| 用例编号 | 场景 | 预期结果 |
|
||||
|---------|------|---------|
|
||||
| TC-B001 | 正常分配 | 空闲床位→占用,状态正确 |
|
||||
| TC-B002 | 分配已占用床位 | 返回"该床位已被占用" |
|
||||
| TC-B003 | 出院自动清洁 | 出院后床位变为"清洁中" |
|
||||
| TC-B004 | 使用率计算 | 数据准确反映实际使用情况 |
|
||||
| TC-B005 | 维修中分配 | 返回"该床位维修中" |
|
||||
|
||||
226
MD/specs/CICD_GATEKEEPER.md
Executable file
226
MD/specs/CICD_GATEKEEPER.md
Executable file
@@ -0,0 +1,226 @@
|
||||
# CI/CD构建门禁规范
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: CI/CD流程
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 🎯 规范目标
|
||||
|
||||
建立自动化质量门禁,确保每次代码提交都经过严格验证,防止低质量代码进入主干分支,提升系统稳定性和开发效率。
|
||||
|
||||
## 🔒 门禁层级
|
||||
|
||||
### 1. 提交前门禁(Pre-commit)
|
||||
**触发时机**:`git commit` 执行前
|
||||
**验证内容**:
|
||||
- ESLint 代码规范检查
|
||||
- Prettier 代码格式化
|
||||
- 简单的单元测试(快速执行)
|
||||
|
||||
**工具配置**:
|
||||
- Husky + lint-staged
|
||||
- 配置文件:`.husky/pre-commit`
|
||||
|
||||
### 2. 推送前门禁(Pre-push)
|
||||
**触发时机**:`git push` 执行前
|
||||
**验证内容**:
|
||||
- 完整的单元测试套件
|
||||
- 构建验证(`npm run build:prod`)
|
||||
- 集成测试(核心流程)
|
||||
|
||||
**工具配置**:
|
||||
- Husky pre-push hook
|
||||
- 配置文件:`.husky/pre-push`
|
||||
|
||||
### 3. CI流水线门禁(CI Pipeline)
|
||||
**触发时机**:代码推送到远程仓库后
|
||||
**验证内容**:
|
||||
- 完整的测试套件(单元+集成+端到端)
|
||||
- 代码覆盖率检查(分阶段目标:Q1≥30%,Q2≥50%,Q3≥80%)
|
||||
- 安全扫描(SAST)
|
||||
- 构建产物验证
|
||||
- 部署到测试环境
|
||||
|
||||
**工具配置**:
|
||||
- Spug CI/CD 流水线
|
||||
- Gitea Webhook 触发
|
||||
|
||||
### 4. 发布前门禁(Release Gate)
|
||||
**触发时机**:准备发布到生产环境前
|
||||
**验证内容**:
|
||||
- 生产环境冒烟测试
|
||||
- 性能基准测试
|
||||
- 安全合规检查
|
||||
- 回滚预案验证
|
||||
|
||||
## ⚙️ 具体配置要求
|
||||
|
||||
### ESLint 配置
|
||||
```javascript
|
||||
// eslint.config.js 关键配置
|
||||
import globals from "globals";
|
||||
import pluginVue from "eslint-plugin-vue";
|
||||
import parserVue from "vue-eslint-parser";
|
||||
import importPlugin from "eslint-plugin-import";
|
||||
|
||||
export default [
|
||||
{
|
||||
name: "app/files-to-lint",
|
||||
files: ["**/*.{js,mjs,jsx,vue}"],
|
||||
},
|
||||
|
||||
{
|
||||
name: "app/files-to-ignore",
|
||||
ignores: ["**/dist/**", "**/node_modules/**", "**/help-center/**"],
|
||||
},
|
||||
|
||||
...pluginVue.configs["flat/recommended"],
|
||||
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
},
|
||||
parser: parserVue,
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
|
||||
plugins: {
|
||||
import: importPlugin,
|
||||
},
|
||||
|
||||
rules: {
|
||||
// 确保导入的模块实际存在(核心规则,防止构建失败)
|
||||
"import/no-unresolved": "error",
|
||||
// 确保导入的命名导出实际存在
|
||||
"import/named": "error",
|
||||
// 确保默认导出存在
|
||||
"import/default": "error",
|
||||
// 确保命名空间导出存在
|
||||
"import/namespace": "error",
|
||||
},
|
||||
},
|
||||
];
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
### Java 后端配置
|
||||
```xml
|
||||
<!-- pom.xml 关键插件 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||
<version>4.2.0</version>
|
||||
</plugin>
|
||||
```
|
||||
|
||||
### 数据库迁移配置
|
||||
```yaml
|
||||
# application.yml Flyway配置
|
||||
flyway:
|
||||
enabled: true
|
||||
locations: classpath:db/migration
|
||||
baseline-on-migrate: true
|
||||
```
|
||||
javascript
|
||||
// .eslintrc.js 关键配置
|
||||
module.exports = {
|
||||
plugins: ['import'],
|
||||
rules: {
|
||||
// 确保导入的模块实际存在
|
||||
'import/no-unresolved': 'error',
|
||||
// 确保导入的成员实际存在
|
||||
'import/named': 'error',
|
||||
// 禁止未使用的导入
|
||||
'import/no-unused-modules': 'warn'
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Husky 配置
|
||||
```bash
|
||||
# .husky/pre-commit
|
||||
#!/bin/sh
|
||||
npm run lint-staged
|
||||
|
||||
# .husky/pre-push
|
||||
#!/bin/sh
|
||||
npm run test:unit && npm run build:prod
|
||||
```
|
||||
|
||||
### lint-staged 配置
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"lint-staged": {
|
||||
"*.{js,vue}": ["eslint --fix", "prettier --write"],
|
||||
"*.{css,scss}": ["stylelint --fix", "prettier --write"]
|
||||
}
|
||||
}
|
||||
```
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"lint-staged": {
|
||||
"*.{js,vue}": ["eslint --fix", "prettier --write"],
|
||||
"*.{css,scss}": ["stylelint --fix", "prettier --write"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚫 失败处理机制
|
||||
|
||||
### 自动处理
|
||||
- **构建失败**:自动阻止 PR 合并
|
||||
- **测试失败**:标记 PR 为失败状态
|
||||
- **安全漏洞**:立即通知安全团队
|
||||
|
||||
### 人工处理
|
||||
- **紧急修复**:可申请临时绕过(需架构师批准)
|
||||
- **误报处理**:提交豁免申请并说明原因
|
||||
- **规则调整**:通过 RFC 流程申请规则变更
|
||||
|
||||
## 📊 监控与度量
|
||||
|
||||
### 关键指标
|
||||
- 门禁通过率 ≥ 95%
|
||||
- 平均修复时间 ≤ 2小时
|
||||
- 误报率 ≤ 5%
|
||||
|
||||
### 报告机制
|
||||
- 每日门禁失败统计
|
||||
- 周度质量趋势报告
|
||||
- 月度规则优化建议
|
||||
|
||||
## 🔄 持续改进
|
||||
|
||||
### 规则演进
|
||||
- 每月评审门禁规则有效性
|
||||
- 根据项目需求调整检查强度
|
||||
- 引入新的质量检查工具
|
||||
|
||||
### 团队培训
|
||||
- 新成员入职培训包含门禁规范
|
||||
- 定期分享最佳实践案例
|
||||
- 建立常见问题解决方案库
|
||||
|
||||
---
|
||||
|
||||
**文档版本**:v1.0
|
||||
**最后更新**:2026年4月24日
|
||||
**负责人**:陈琳(文档专家)
|
||||
**技术方案**:诸葛亮(架构师)
|
||||
**适用范围**:HIS 系统所有项目
|
||||
144
MD/specs/COMMIT_TEMPLATE.md
Executable file
144
MD/specs/COMMIT_TEMPLATE.md
Executable file
@@ -0,0 +1,144 @@
|
||||
# 代码提交变更说明模板
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: 代码提交
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 📝 PR/Commit 模板
|
||||
|
||||
### 标题格式
|
||||
```
|
||||
<类型>(<模块>): <简短描述>
|
||||
|
||||
示例:
|
||||
feat(patient): 添加患者基本信息编辑功能
|
||||
fix(doctor): 修复医生排班显示异常问题
|
||||
docs(api): 更新预约挂号接口文档
|
||||
refactor(nurse): 重构护士站护理记录组件
|
||||
```
|
||||
|
||||
### 正文模板
|
||||
```markdown
|
||||
## 🔍 变更背景
|
||||
- **问题描述**:详细说明要解决的问题或实现的需求
|
||||
- **影响范围**:列出受影响的模块、页面、功能
|
||||
- **相关链接**:禅道任务ID、需求文档链接等
|
||||
|
||||
## 🛠️ 变更内容
|
||||
- **主要修改**:核心代码变更点
|
||||
- **技术方案**:采用的技术方案和设计思路
|
||||
- **兼容性**:是否涉及API或数据结构变更
|
||||
|
||||
|
||||
## 🗄️ 数据库变更
|
||||
- **表结构变更**:列出新增/修改的表和字段
|
||||
- **数据迁移**:是否需要数据迁移脚本
|
||||
- **回滚方案**:数据库变更的回滚策略
|
||||
|
||||
## ✅ 验证情况
|
||||
- **测试覆盖**:单元测试、集成测试覆盖情况
|
||||
- **手动验证**:手动测试的场景和结果
|
||||
- **构建验证**:本地构建截图(必填)
|
||||
|
||||
## 📋 检查清单
|
||||
- [ ] 代码已通过 ESLint 检查
|
||||
- [ ] 本地构建成功(附截图)
|
||||
- [ ] 核心功能已测试验证
|
||||
- [ ] 文档已同步更新
|
||||
- [ ] Code Review 已完成
|
||||
|
||||
## 👥 相关人员
|
||||
- **开发者**:@开发者姓名
|
||||
- **测试者**:@测试者姓名
|
||||
- **审核人**:@架构师姓名
|
||||
```
|
||||
|
||||
## 🏷️ 提交类型说明
|
||||
|
||||
| 类型 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| feat | 新功能 | `feat: 添加用户登录功能` |
|
||||
| fix | Bug修复 | `fix: 修复表单验证错误` |
|
||||
| docs | 文档更新 | `docs: 更新API文档` |
|
||||
| style | 代码格式调整 | `style: 格式化代码` |
|
||||
| refactor | 代码重构 | `refactor: 重构组件结构` |
|
||||
| test | 测试相关 | `test: 添加单元测试` |
|
||||
| chore | 构建/依赖等 | `chore: 升级依赖版本` |
|
||||
| perf | 性能优化 | `perf: 优化列表加载速度` |
|
||||
|
||||
## 📁 模块命名规范
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| patient | 患者管理相关 |
|
||||
| doctor | 医生工作站相关 |
|
||||
| nurse | 护士站相关 |
|
||||
| admin | 后台管理相关 |
|
||||
| common | 公共组件/工具 |
|
||||
| api | API接口相关 |
|
||||
| auth | 认证授权相关 |
|
||||
| payment | 支付相关 |
|
||||
|
||||
## 🖼️ 构建验证截图要求
|
||||
|
||||
### 必须包含的信息
|
||||
1. **终端窗口**:显示 `npm run build:prod` 命令执行过程
|
||||
2. **成功标识**:明确显示构建成功的提示信息
|
||||
3. **时间戳**:截图包含当前时间,证明是最新构建
|
||||
4. **分支信息**:显示当前工作分支名称
|
||||
|
||||
### 截图示例
|
||||
```
|
||||
$ git checkout feature/patient-edit
|
||||
$ npm run build:prod
|
||||
|
||||
> his-system@1.0.0 build
|
||||
> vue-cli-service build
|
||||
|
||||
⠇ Building for production...
|
||||
|
||||
DONE Build complete. The dist directory is ready to be deployed.
|
||||
INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html
|
||||
|
||||
✨ Done in 45.23s.
|
||||
```
|
||||
|
||||
## ⚠️ 禁止行为
|
||||
|
||||
### 严重违规(直接拒绝合并)
|
||||
- 无构建验证截图
|
||||
- 代码存在 ESLint 错误
|
||||
- 未填写变更说明
|
||||
- 修改无关代码文件
|
||||
|
||||
### 轻微违规(要求修正后重新提交)
|
||||
- 描述过于简单
|
||||
- 测试覆盖不完整
|
||||
- 文档更新滞后
|
||||
- 格式不符合规范
|
||||
|
||||
## 💡 最佳实践
|
||||
|
||||
### 高质量提交特征
|
||||
- **原子性**:每次提交只解决一个问题
|
||||
- **可追溯**:关联具体的需求或Bug ID
|
||||
- **可验证**:提供完整的验证证据
|
||||
- **可理解**:描述清晰,他人能快速理解
|
||||
|
||||
### 团队协作建议
|
||||
- 提交前先在本地完整测试
|
||||
- 复杂变更提前与团队沟通
|
||||
- 及时更新相关文档
|
||||
- 主动帮助新人熟悉规范
|
||||
|
||||
---
|
||||
|
||||
**文档版本**:v1.0
|
||||
**最后更新**:2026年4月24日
|
||||
**负责人**:陈琳(文档专家)
|
||||
**适用范围**:HIS 系统所有开发人员
|
||||
178
MD/specs/CONSULTATION_MODULE_ANALYSIS.md
Normal file
178
MD/specs/CONSULTATION_MODULE_ANALYSIS.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# 会诊管理模块 — 三甲要求深度分析
|
||||
|
||||
> **文档类型**: 模块能力分析
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **三甲依据**: 《三级医院评审标准(2022版)》会诊管理制度
|
||||
|
||||
---
|
||||
|
||||
## 一、三甲对会诊管理的要求
|
||||
|
||||
### 1.1 评审标准条款
|
||||
- **核心制度**: 会诊制度是十八项医疗核心制度之一
|
||||
- **急会诊**: 急会诊10分钟内到位
|
||||
- **科间会诊**: 48小时内完成
|
||||
- **全院会诊**: 由医务部组织
|
||||
- **疑难病例**: 多学科会诊(MDT)
|
||||
- **病历要求**: 会诊记录必须写入病历
|
||||
|
||||
### 1.2 会诊类型与时限要求
|
||||
|
||||
| 会诊类型 | 时限要求 | 主持人 | 三甲依据 |
|
||||
|---------|---------|--------|---------|
|
||||
| 科间会诊 | 48小时内完成 | 主治医师以上 | 会诊制度 |
|
||||
| 急会诊 | 10分钟内到位 | 二线值班医师 | 会诊制度 |
|
||||
| 院内大会诊 | 24小时内安排 | 科主任/医务部 | 会诊制度 |
|
||||
| 多学科会诊(MDT) | 72小时内安排 | 科主任/医务部 | 疑难病例管理 |
|
||||
| 远程会诊 | 按约定时间 | 相关专科 | 互联网诊疗 |
|
||||
| 院外会诊 | 按约定时间 | 被邀医院指定 | 外出会诊管理 |
|
||||
|
||||
---
|
||||
|
||||
## 二、现有模块能力分析
|
||||
|
||||
### 2.1 后端能力(19个API)
|
||||
|
||||
| API | 功能 | 三甲要求 | 状态 |
|
||||
|-----|------|---------|------|
|
||||
| GET /list | 获取会诊列表 | 基础查询 | ✅ |
|
||||
| POST /query | 多条件查询 | 高级查询 | ✅ |
|
||||
| POST /queryPage | 分页查询 | 分页支持 | ✅ |
|
||||
| POST /save | 保存会诊申请 | 创建功能 | ✅ |
|
||||
| POST /submit | 提交会诊申请 | 流程流转 | ✅ |
|
||||
| POST /cancel | 作废会诊申请 | 流程控制 | ✅ |
|
||||
| POST /complete | 完成会诊 | 流程完结 | ✅ |
|
||||
| GET /department-tree | 科室树 | 科室选择 | ✅ |
|
||||
| GET /my-invitations | 我的邀请 | 被邀查看 | ✅ |
|
||||
| GET /activities | 会诊项目 | 费用关联 | ✅ |
|
||||
| GET /confirmation/pending | 待确认列表 | 被邀确认 | ✅ |
|
||||
| POST /confirmation/confirm | 确认会诊 | 流程流转 | ✅ |
|
||||
| POST /confirmation/cancelConfirm | 取消确认 | 流程回退 | ✅ |
|
||||
| POST /confirmation/sign | 签名会诊 | 电子签名 | ✅ |
|
||||
| GET /confirmation/detail | 确认详情 | 详情查看 | ✅ |
|
||||
| GET /confirmation/opinions | 会诊意见 | 意见记录 | ✅ |
|
||||
| GET /detail/{id} | 申请详情 | 详情查看 | ✅ |
|
||||
| POST /charge-items | 关联费用 | 费用管理 | ✅ |
|
||||
| POST /confirm-charge-items | 确认收费 | 费用确认 | ✅ |
|
||||
|
||||
### 2.2 状态流转
|
||||
|
||||
```
|
||||
新开(0) → 已提交(10) → 已确认(20) → 已签名(30) → 已完成(40)
|
||||
↓
|
||||
已取消(50)
|
||||
```
|
||||
|
||||
| 状态 | 值 | 允许操作 | 说明 |
|
||||
|------|-----|---------|------|
|
||||
| 新开 | 0 | 编辑/删除/提交 | 草稿状态 |
|
||||
| 已提交 | 10 | 作废 | 等待被邀确认 |
|
||||
| 已确认 | 20 | 签名/取消确认 | 被邀医生已确认 |
|
||||
| 已签名 | 30 | 完成 | 被邀医生已签名 |
|
||||
| 已完成 | 40 | 查看 | 会诊结束 |
|
||||
| 已取消 | 50 | 查看 | 作废状态 |
|
||||
|
||||
### 2.3 前端页面(4个,共~120KB)
|
||||
|
||||
| 页面 | 大小 | 功能 |
|
||||
|------|------|------|
|
||||
| consultationapplication | 27KB | 会诊申请管理(搜索/表格/新增弹窗/提交/作废) |
|
||||
| consultationconfirmation | 24KB | 会诊确认管理(待确认列表/确认/签名/意见) |
|
||||
| consultationconfirmation(clinic) | 21KB | 门诊会诊确认(另一套实现) |
|
||||
| consultation.vue(doctorstation) | 50KB | 医生站会诊组件(嵌入医生工作站) |
|
||||
|
||||
### 2.4 数据模型
|
||||
|
||||
| 字段 | 说明 | ✅/❌ |
|
||||
|------|------|-------|
|
||||
| consultationId | 会诊单号 | ✅ |
|
||||
| patientId/Name | 患者信息 | ✅ |
|
||||
| encounterId | 就诊ID | ✅ |
|
||||
| department | 申请科室 | ✅ |
|
||||
| requestingPhysician | 申请医生 | ✅ |
|
||||
| invitedList | 被邀医生列表 | ✅ |
|
||||
| consultationDate | 会诊日期 | ✅ |
|
||||
| consultationPurpose | 会诊目的 | ✅ |
|
||||
| provisionalDiagnosis | 初步诊断 | ✅ |
|
||||
| consultationUrgency | 紧急程度(1普通/2紧急) | ✅ |
|
||||
| consultationActivityName | 会诊类型(院内/远程等) | ✅ |
|
||||
| consultationStatus | 会诊状态 | ✅ |
|
||||
| consultationOpinion | 会诊意见 | ✅ |
|
||||
| signingPhysician | 签名医生 | ✅ |
|
||||
| signingTime | 签名时间 | ✅ |
|
||||
| submitFlag | 提交标记 | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 三、能力差距分析
|
||||
|
||||
### 3.1 已满足的三甲要求
|
||||
|
||||
| # | 要求 | 实现情况 | 评价 |
|
||||
|---|------|---------|------|
|
||||
| 1 | 会诊申请流程 | save→submit→confirm→sign→complete | ✅ 完整 |
|
||||
| 2 | 科间会诊 | 支持科室选择+被邀医生 | ✅ 完整 |
|
||||
| 3 | 会诊意见记录 | consultationOpinion字段+意见列表 | ✅ 完整 |
|
||||
| 4 | 电子签名 | signConsultation接口 | ✅ 完整 |
|
||||
| 5 | 费用关联 | chargeItems+confirmChargeItems | ✅ 完整 |
|
||||
| 6 | 分页查询 | queryPage接口 | ✅ 完整 |
|
||||
| 7 | 会诊项目管理 | activities接口 | ✅ 完整 |
|
||||
| 8 | 状态流转 | 6状态完整生命周期 | ✅ 完整 |
|
||||
|
||||
### 3.2 未满足/待完善的三甲要求
|
||||
|
||||
| # | 要求 | 当前状态 | 差距 | 优先级 |
|
||||
|---|------|---------|------|--------|
|
||||
| 1 | **急会诊时限控制** | 有紧急程度字段(1普通/2紧急),但无10分钟到位时限校验 | ❌ 缺失时限逻辑 | 🔴 高 |
|
||||
| 2 | **科间会诊48h时限** | 无48小时完成时限校验和提醒 | ❌ 缺失时限逻辑 | 🔴 高 |
|
||||
| 3 | **会诊类型细分** | 有consultationActivityName(院内/远程),但缺科间/全院/MDT分类 | ⚠️ 不够细 | 🟡 中 |
|
||||
| 4 | **会诊时限监控面板** | 无超时预警/统计面板 | ❌ 缺失 | 🔴 高 |
|
||||
| 5 | **会诊与病历集成** | 会诊记录未自动归档到病历 | ❌ 缺失 | 🟡 中 |
|
||||
| 6 | **MDT多学科会诊** | 无MDT专项流程(多科室同时参与) | ❌ 缺失 | 🟡 中 |
|
||||
| 7 | **会诊记录打印** | 无标准格式会诊记录单打印 | ❌ 缺失 | 🟡 中 |
|
||||
| 8 | **会诊统计报表** | 无会诊完成率/及时率统计 | ❌ 缺失 | 🟡 中 |
|
||||
| 9 | **会诊与医嘱联动** | 会诊完成后未自动触发后续医嘱建议 | ❌ 缺失 | 🟢 低 |
|
||||
| 10 | **远程会诊** | 有远程会诊项目,但无视频/图文远程对接 | ⚠️ 框架有 | 🟢 低 |
|
||||
|
||||
---
|
||||
|
||||
## 四、总体评价
|
||||
|
||||
### 4.1 完成度评分
|
||||
|
||||
| 维度 | 满分 | 得分 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 会诊流程 | 25 | 22 | save→submit→confirm→sign→complete完整 |
|
||||
| 数据模型 | 20 | 18 | 字段齐全,缺时限相关字段 |
|
||||
| 前端页面 | 20 | 18 | 4个页面共120KB,功能丰富 |
|
||||
| 业务规则 | 20 | 12 | 有状态校验,缺时限控制 |
|
||||
| 集成能力 | 15 | 10 | 有费用集成,缺病历/医嘱集成 |
|
||||
| **总分** | **100** | **80** | **基本可用,需补全时限控制** |
|
||||
|
||||
### 4.2 结论
|
||||
|
||||
**现有会诊管理模块已完成约80%**,核心流程(申请→确认→签名→完成)完整可用。主要差距在于:
|
||||
|
||||
1. **时限控制缺失**(最关键):急会诊10分钟到位、科间会诊48小时完成的时限校验和提醒完全没有
|
||||
2. **监控面板缺失**:无法实时查看会诊超时情况
|
||||
3. **病历集成缺失**:会诊记录未自动归档到病历
|
||||
|
||||
### 4.3 补全建议
|
||||
|
||||
**优先级1(必须做)**:增加时限控制逻辑
|
||||
- 急会诊:提交后10分钟内未确认→自动升级通知
|
||||
- 科间会诊:提交后48小时未完成→超时预警
|
||||
- 在ConsultationAppServiceImpl中增加时限校验
|
||||
|
||||
**优先级2(应该做)**:增加会诊时限监控面板
|
||||
- 前端增加超时统计卡片
|
||||
- 实时显示待处理/已超时/已完成数量
|
||||
|
||||
**优先级3(可以做)**:会诊记录打印+病历归档
|
||||
|
||||
---
|
||||
|
||||
> **结论**: 会诊管理模块基本满足三甲要求,核心差距是**时限控制**。
|
||||
> 建议在现有代码基础上增强时限校验逻辑,无需重建。
|
||||
|
||||
188
MD/specs/CSSD_AND_3D_DESIGN.md
Normal file
188
MD/specs/CSSD_AND_3D_DESIGN.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# 消毒供应中心(CSSD)追溯管理 + 影像3D重建 深度设计文档
|
||||
|
||||
> **文档类型**: 技术设计
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-07
|
||||
> **依据标准**: WS 310.1-310.3《医院消毒供应中心》、DICOM 3D重建规范
|
||||
|
||||
---
|
||||
|
||||
## 一、消毒供应中心(CSSD)追溯管理
|
||||
|
||||
### 1.1 业务背景
|
||||
|
||||
根据《医院消毒供应中心 第1部分:管理规范》(WS 310.1-2016)和《医院消毒供应中心 第3部分:清洗消毒及灭菌效果监测标准》(WS 310.3-2016),三甲医院CSSD必须实现:
|
||||
|
||||
- **全流程追溯**: 从器械回收→分类→清洗→消毒→干燥→检查→包装→灭菌→储存→发放的全链路可追溯
|
||||
- **条码管理**: 每个器械包有唯一追溯码,支持扫码追溯
|
||||
- **灭菌监测**: 生物监测、化学监测、物理监测的记录和预警
|
||||
- **有效期管理**: 灭菌后器械包的有效期自动计算和过期预警
|
||||
- **质量统计**: 清洗合格率、灭菌合格率、器械使用次数统计
|
||||
|
||||
### 1.2 业务流程
|
||||
|
||||
```
|
||||
手术室/科室 使用后器械
|
||||
↓ (回收)
|
||||
CSSD回收清点 → 扫码登记(器械包ID+数量+来源科室)
|
||||
↓
|
||||
分类 → 按器械类型分拣(手术器械/管腔器械/精密器械/普通器械)
|
||||
↓
|
||||
清洗 → 手工清洗/超声清洗/机器清洗 → 清洗效果监测(ATP/蛋白残留)
|
||||
↓
|
||||
消毒 → 湿热消毒(≥90℃/5min) 或 化学消毒
|
||||
↓
|
||||
干燥 → 热风干燥/自然干燥
|
||||
↓
|
||||
检查保养 → 功能检查+润滑+包装材料选择
|
||||
↓
|
||||
包装 → 器械放入包装袋/容器 → 封口 → 贴追溯标签(条码+灭菌日期+有效期)
|
||||
↓
|
||||
灭菌 → 压力蒸汽灭菌(134℃/4min) 或 低温灭菌 → 化学指示卡变色确认
|
||||
↓
|
||||
储存 → 无菌物品存放区 → 按效期管理(先进先出)
|
||||
↓
|
||||
发放 → 扫码出库 → 送达手术室/科室 → 签收确认
|
||||
```
|
||||
|
||||
### 1.3 数据模型
|
||||
|
||||
#### 核心实体
|
||||
|
||||
1. **CssdTray** (器械包) — 器械包基础信息
|
||||
- id, tray_code(唯一编码), tray_name, tray_type(手术/管腔/精密/普通)
|
||||
- department_source(来源科室), status(在用/清洗中/灭菌中/储存中/已发放)
|
||||
- current_location(当前位置), total_uses(使用次数)
|
||||
- sterilize_count(灭菌次数), last_sterilize_time
|
||||
|
||||
2. **CssdTraceRecord** (追溯记录) — 每次流转记录
|
||||
- id, tray_id, step_type(回收/清洗/消毒/包装/灭菌/储存/发放)
|
||||
- operator_id, operator_name, operation_time
|
||||
- device_name(设备名称), device_code
|
||||
- parameters(JSON: 温度/时间/压力等工艺参数)
|
||||
- result(合格/不合格), remark
|
||||
|
||||
3. **CssdSterilizeBatch** (灭菌批次) — 每锅灭菌记录
|
||||
- id, batch_code, sterilizer_name, sterilizer_code
|
||||
- start_time, end_time, cycle_type(预真空/下排气/快速)
|
||||
- temperature, pressure, exposure_time
|
||||
- biological_result(生物监测: 合格/不合格/待检)
|
||||
- chemical_result(化学监测: 合格/不合格)
|
||||
- physical_result(物理监测: 合格/不合格)
|
||||
- batch_status(进行中/已完成/已释放)
|
||||
|
||||
4. **CssdSterilizeItem** (灭菌包明细) — 批次内的器械包
|
||||
- id, batch_id, tray_id
|
||||
- chemical_indicator(化学指示卡颜色变化)
|
||||
- bi_indicator(生物指示剂结果)
|
||||
|
||||
5. **CssdExpiryAlert** (过期预警) — 有效期管理
|
||||
- id, tray_id, batch_id
|
||||
- sterilize_time, expiry_time, alert_time
|
||||
- status(正常/预警/过期)
|
||||
|
||||
### 1.4 业务规则
|
||||
|
||||
| 规则编号 | 规则名称 | 规则描述 |
|
||||
|---------|---------|---------|
|
||||
| R1 | 回收扫码 | 所有器械包回收时必须扫码登记 |
|
||||
| R2 | 清洗监测 | 清洗后必须进行ATP或蛋白残留检测 |
|
||||
| R3 | 包装标签 | 包装必须贴追溯标签(条码+日期+有效期) |
|
||||
| R4 | 灭菌三要素 | 生物+化学+物理三项监测全部合格才能释放 |
|
||||
| R5 | 有效期管理 | 压力蒸汽灭菌: 无菌包装180天, 无纺布14天, 棉布7天 |
|
||||
| R6 | 过期拦截 | 过期器械包禁止发放,必须重新灭菌 |
|
||||
| R7 | 使用次数 | 器械包达到最大使用次数(可配置)时提醒报废 |
|
||||
|
||||
### 1.5 接口设计
|
||||
|
||||
| API | 方法 | 说明 |
|
||||
|-----|------|------|
|
||||
| /cssd/tray/page | GET | 器械包列表 |
|
||||
| /cssd/tray/add | POST | 新建器械包 |
|
||||
| /cssd/trace/scan | POST | 扫码追溯(流转) |
|
||||
| /cssd/trace/history/{trayId} | GET | 器械包追溯历史 |
|
||||
| /cssd/sterilize/batch/page | GET | 灭菌批次列表 |
|
||||
| /cssd/sterilize/batch/add | POST | 新建灭菌批次 |
|
||||
| /cssd/sterilize/batch/complete/{id} | PUT | 完成灭菌(录入监测结果) |
|
||||
| /cssd/sterilize/batch/release/{id} | PUT | 释放批次(三项监测合格) |
|
||||
| /cssd/expiry/alerts | GET | 过期预警列表 |
|
||||
| /cssd/stats/overview | GET | 统计概览(清洗率/灭菌率/过期数) |
|
||||
|
||||
---
|
||||
|
||||
## 二、影像3D重建
|
||||
|
||||
### 2.1 业务背景
|
||||
|
||||
影像3D重建是影像诊断的高级功能,主要应用于:
|
||||
- **骨科**: 骨折三维重建,辅助手术规划
|
||||
- **心血管**: 冠脉CTA三维重建,评估狭窄程度
|
||||
- **胸腹部**: 肿瘤三维定位,评估与周围组织关系
|
||||
- **口腔**: 颌面骨三维重建,正畸/种植规划
|
||||
|
||||
### 2.2 业务流程
|
||||
|
||||
```
|
||||
CT/MRI扫描 → DICOM图像导入
|
||||
↓
|
||||
图像预处理 → 去噪/增强/分割
|
||||
↓
|
||||
三维重建 → Volume Rendering(容积渲染) / MPR(多平面重建) / MIP(最大密度投影)
|
||||
↓
|
||||
后处理 → 测量(距离/角度/体积) / 标注 / 裁剪
|
||||
↓
|
||||
生成报告 → 3D截图 + 测量数据 + 诊断结论
|
||||
↓
|
||||
审核发布 → 主治医师审核 → 发布到PACS/病历系统
|
||||
```
|
||||
|
||||
### 2.3 数据模型
|
||||
|
||||
#### 核心实体
|
||||
|
||||
1. **ReconstructionTask** (重建任务) — 3D重建任务
|
||||
- id, patient_id, patient_name, encounter_id
|
||||
- apply_id(检查申请ID), study_uid(DICOM StudyUID)
|
||||
- modality(CT/MRI), body_part, scan_range
|
||||
- task_status(PENDING/PROCESSING/COMPLETED/FAILED)
|
||||
- reconstruction_type(VR/MPR/MIP/VR+MPR)
|
||||
- result_path(重建结果存储路径)
|
||||
- slice_thickness, pixel_spacing
|
||||
- request_doctor, complete_time
|
||||
|
||||
2. **ReconstructionResult** (重建结果) — 3D重建输出
|
||||
- id, task_id, result_type(VR/MPR/MIP)
|
||||
- image_path(截图路径), volume_data_path(体数据路径)
|
||||
- measurements(JSON: 距离/角度/体积等测量数据)
|
||||
- annotations(JSON: 标注信息)
|
||||
- report_text(报告文本)
|
||||
|
||||
3. **ReconstructionReport** (重建报告) — 3D重建报告
|
||||
- id, task_id, patient_id, encounter_id
|
||||
- findings(所见), impression(印象), conclusion(结论)
|
||||
- report_doctor, report_time
|
||||
- verify_doctor, verify_time
|
||||
- status(DRAFT/REPORTED/VERIFIED)
|
||||
|
||||
### 2.4 业务规则
|
||||
|
||||
| 规则编号 | 规则名称 | 规则描述 |
|
||||
|---------|---------|---------|
|
||||
| R1 | 任务触发 | 由影像科医生从PACS工作台发起3D重建任务 |
|
||||
| R2 | 图像要求 | 至少需要50层连续断层图像才能进行3D重建 |
|
||||
| R3 | 重建类型 | 支持VR(容积渲染)/MPR(多平面)/MIP(最大密度投影) |
|
||||
| R4 | 测量功能 | 支持距离/角度/面积/体积测量 |
|
||||
| R5 | 报告审核 | 3D重建报告必须由主治以上医师审核 |
|
||||
| R6 | 图像存储 | 重建结果存储在PACS归档系统,保留期≥1年 |
|
||||
|
||||
### 2.5 接口设计
|
||||
|
||||
| API | 方法 | 说明 |
|
||||
|-----|------|------|
|
||||
| /reconstruction/task/page | GET | 重建任务列表 |
|
||||
| /reconstruction/task/add | POST | 新建重建任务 |
|
||||
| /reconstruction/task/complete/{id} | PUT | 完成重建 |
|
||||
| /reconstruction/result/list/{taskId} | GET | 重建结果列表 |
|
||||
| /reconstruction/report/add | POST | 新建报告 |
|
||||
| /reconstruction/report/verify/{id} | PUT | 审核报告 |
|
||||
| /reconstruction/stats | GET | 统计(任务数/完成率/类型分布) |
|
||||
112
MD/specs/FRONTEND_CHECKLIST.md
Executable file
112
MD/specs/FRONTEND_CHECKLIST.md
Executable file
@@ -0,0 +1,112 @@
|
||||
|
||||
# 前端发布前检查清单
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: 前端开发
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 📋 基础检查项
|
||||
|
||||
### 代码质量
|
||||
- [ ] 代码已通过 ESLint 检查,无警告和错误
|
||||
- [ ] 代码已通过 Prettier 格式化
|
||||
- [ ] 无 console.log() 等调试代码残留
|
||||
- [ ] 变量命名符合规范,语义清晰
|
||||
- [ ] 函数职责单一,复杂度适中
|
||||
|
||||
### 构建验证
|
||||
- [ ] 本地执行 `npm run build:prod` 成功完成
|
||||
- [ ] 构建产物无报错,体积合理
|
||||
- [ ] 静态资源路径正确,无404错误
|
||||
- [ ] 环境变量配置正确(开发/测试/生产)
|
||||
|
||||
### 功能验证
|
||||
- [ ] 核心功能流程完整测试通过
|
||||
- [ ] 边界条件和异常场景已覆盖
|
||||
- [ ] 表单验证逻辑正确
|
||||
- [ ] API 接口调用正常,错误处理完善
|
||||
- [ ] 路由跳转逻辑正确
|
||||
|
||||
## 🔧 技术检查项
|
||||
|
||||
### 模块导入检查
|
||||
- [ ] 所有 import 语句引用的模块实际存在
|
||||
- [ ] 无未使用的 import 导入
|
||||
- [ ] 路径别名(@/)配置正确
|
||||
- [ ] 第三方库版本兼容性确认
|
||||
|
||||
### 性能优化
|
||||
- [ ] 组件按需加载(懒加载)已配置
|
||||
- [ ] 大数据列表已实现虚拟滚动或分页
|
||||
- [ ] 图片资源已压缩,格式合适
|
||||
- [ ] 无内存泄漏风险(事件监听器、定时器等)
|
||||
|
||||
### 安全检查
|
||||
- [ ] 用户输入已做 XSS 防护
|
||||
- [ ] 敏感信息不在前端硬编码
|
||||
- [ ] API 请求已做 CSRF 防护
|
||||
- [ ] 权限控制逻辑正确
|
||||
|
||||
## 🌐 兼容性检查
|
||||
|
||||
### 浏览器兼容
|
||||
- [ ] 主流浏览器(Chrome、Firefox、Safari、Edge)显示正常
|
||||
- [ ] 移动端适配良好(如适用)
|
||||
- [ ] 分辨率适配(1366x768、1920x1080等)
|
||||
|
||||
### 设备兼容
|
||||
- [ ] 触摸设备操作体验良好
|
||||
- [ ] 键盘导航支持完整
|
||||
- [ ] 屏幕阅读器兼容性(无障碍)
|
||||
|
||||
## 📱 发布准备
|
||||
|
||||
### 文档更新
|
||||
- [ ] 相关 API 文档已同步更新
|
||||
- [ ] 用户操作手册已更新(如适用)
|
||||
- [ ] 变更日志已记录
|
||||
|
||||
### 回滚预案
|
||||
- [ ] 回滚方案已准备
|
||||
- [ ] 数据兼容性已确认
|
||||
- [ ] 紧急联系人已明确
|
||||
|
||||
|
||||
## 🔧 后端检查项
|
||||
|
||||
### 编译验证
|
||||
- [ ] Maven编译成功(`mvn clean package -DskipTests`)
|
||||
- [ ] 无编译错误,仅有可接受的警告
|
||||
- [ ] 依赖版本兼容性确认
|
||||
|
||||
### 数据库脚本
|
||||
- [ ] DDL/DML脚本语法正确
|
||||
- [ ] 回滚脚本已准备
|
||||
- [ ] 数据迁移脚本已测试
|
||||
|
||||
## 🔄 前后端协同
|
||||
|
||||
### 接口兼容性
|
||||
- [ ] API接口契约变更已双方确认
|
||||
- [ ] 前端调用后端接口正常
|
||||
- [ ] 错误码处理逻辑一致
|
||||
|
||||
## ✅ 最终确认
|
||||
|
||||
### 发布前最后检查
|
||||
- [ ] 本地构建截图已附在 PR 中
|
||||
- [ ] 测试环境部署验证通过
|
||||
- [ ] Code Review 已完成并获得批准
|
||||
- [ ] 相关 Bug 已关闭或延期说明
|
||||
|
||||
---
|
||||
|
||||
**文档版本**:v1.0
|
||||
**最后更新**:2026年4月24日
|
||||
**负责人**:陈琳(文档专家)
|
||||
**适用范围**:HIS 系统所有前端项目
|
||||
554
MD/specs/FRONTEND_DEVELOPMENT_STANDARD.md
Normal file
554
MD/specs/FRONTEND_DEVELOPMENT_STANDARD.md
Normal file
@@ -0,0 +1,554 @@
|
||||
# HealthLink-HIS 前端开发规范
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: 前端 Vue3 开发
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
## 一、技术栈
|
||||
|
||||
| 组件 | 版本 | 说明 |
|
||||
|------|------|------|
|
||||
| Vue | 3.x | 前端框架 |
|
||||
| Vite | 5.x | 构建工具 |
|
||||
| Element Plus | 2.x | UI组件库 |
|
||||
| Pinia | 2.x | 状态管理 |
|
||||
| Vue Router | 4.x | 路由管理 |
|
||||
| Axios | 1.x | HTTP客户端 |
|
||||
| RuoYi-Vue3 | 3.9.2+ | 基础框架 |
|
||||
|
||||
---
|
||||
|
||||
## 二、项目结构
|
||||
|
||||
```
|
||||
healthlink-his-ui/
|
||||
├── src/
|
||||
│ ├── api/ # API接口定义
|
||||
│ │ ├── module_name/ # 按模块分组
|
||||
│ │ │ ├── index.js # 接口入口
|
||||
│ │ │ └── *.js # 各接口文件
|
||||
│ │ └── system/ # 系统管理接口
|
||||
│ ├── views/ # 页面视图
|
||||
│ │ └── module_name/ # 按模块分组
|
||||
│ │ └── index.vue # 页面组件
|
||||
│ ├── components/ # 公共组件
|
||||
│ ├── store/ # Pinia状态管理
|
||||
│ │ ├── modules/ # 模块store
|
||||
│ │ └── store.js # store入口
|
||||
│ ├── router/ # 路由配置
|
||||
│ ├── utils/ # 工具函数
|
||||
│ ├── directive/ # 自定义指令
|
||||
│ ├── plugins/ # 插件
|
||||
│ ├── layout/ # 布局组件
|
||||
│ └── assets/ # 静态资源
|
||||
├── vite.config.js # Vite配置
|
||||
├── package.json # 依赖配置
|
||||
└── .env.dev # 开发环境变量
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、命名规范
|
||||
|
||||
### 3.1 文件命名
|
||||
| 类型 | 命名规则 | 示例 |
|
||||
|------|---------|------|
|
||||
| 页面组件 | `index.vue` | `views/registration/index.vue` |
|
||||
| 弹窗组件 | `XxxDialog.vue` | `PatientDialog.vue` |
|
||||
| 子组件 | `XxxDetail.vue` | `RegistrationDetail.vue` |
|
||||
| API文件 | `index.js` 或 `xxx.js` | `api/registration/index.js` |
|
||||
| Store模块 | `xxx.js` | `store/modules/user.js` |
|
||||
| 工具函数 | `xxx.js` | `utils/validate.js` |
|
||||
|
||||
### 3.2 组件命名
|
||||
```vue
|
||||
<!-- ✅ 正确 - PascalCase -->
|
||||
<template>
|
||||
<PatientDialog ref="dialogRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<!-- ❌ 错误 -->
|
||||
<template>
|
||||
<patient-dialog ref="dialogRef" />
|
||||
</template>
|
||||
```
|
||||
|
||||
### 3.3 变量命名
|
||||
| 类型 | 命名规则 | 示例 |
|
||||
|------|---------|------|
|
||||
| 响应式变量 | `camelCase` | `const patientList = ref([])` |
|
||||
| 常量 | `UPPER_SNAKE_CASE` | `const MAX_RETRY = 3` |
|
||||
| 事件处理函数 | `handle` 前缀 | `const handleClick = () => {}` |
|
||||
| 获取数据函数 | `getList` / `getData` | `const getList = async () => {}` |
|
||||
| 表单引用 | `xxxForm` / `ruleForm` | `const ruleForm = ref(null)` |
|
||||
| 表格引用 | `xxxTable` / `tableRef` | `const tableRef = ref(null)` |
|
||||
|
||||
---
|
||||
|
||||
## 四、API 接口规范
|
||||
|
||||
### 4.1 API文件结构
|
||||
```javascript
|
||||
// api/registration/index.js
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询挂号列表
|
||||
export function listRegistration(query) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/registration/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询挂号详情
|
||||
export function getRegistration(id) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/registration/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增挂号
|
||||
export function addRegistration(data) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/registration',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改挂号
|
||||
export function updateRegistration(data) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/registration',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除挂号
|
||||
export function delRegistration(ids) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/registration/' + ids,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 API 路径规范
|
||||
- 统一前缀:`/healthlink-his/api/v1/`
|
||||
- 使用 kebab-case:`/patient-allergy` 而非 `/patientAllergy`
|
||||
- 列表接口:`/list`
|
||||
- 详情接口:`/{id}`
|
||||
- 新增:`POST /`
|
||||
- 修改:`PUT /`
|
||||
- 删除:`DELETE /{id}`
|
||||
- 批量删除:`DELETE /{ids}`(逗号分隔)
|
||||
|
||||
---
|
||||
|
||||
## 五、页面组件规范
|
||||
|
||||
### 5.1 标准页面模板
|
||||
```vue
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索区域 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
|
||||
<el-form-item label="患者姓名" prop="patientName">
|
||||
<el-input v-model="queryParams.patientName" placeholder="请输入患者姓名" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['registration:add']">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="患者姓名" prop="patientName" />
|
||||
<el-table-column label="操作" width="180" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['registration:edit']">修改</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['registration:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
|
||||
<!-- 新增/修改弹窗 -->
|
||||
<XxxDialog ref="dialogRef" @success="getList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { listXxx, delXxx } from '@/api/xxx'
|
||||
import XxxDialog from './XxxDialog.vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const dataList = ref([])
|
||||
const loading = ref(true)
|
||||
const showSearch = ref(true)
|
||||
const total = ref(0)
|
||||
const ids = ref([])
|
||||
const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
patientName: undefined
|
||||
})
|
||||
|
||||
const dialogRef = ref(null)
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
const res = await listXxx(queryParams)
|
||||
dataList.value = res.rows
|
||||
total.value = res.total
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
/** 搜索 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNum = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置 */
|
||||
const resetQuery = () => {
|
||||
proxy.resetForm('queryForm')
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 多选 */
|
||||
const handleSelectionChange = (selection) => {
|
||||
ids.value = selection.map(item => item.id)
|
||||
}
|
||||
|
||||
/** 新增 */
|
||||
const handleAdd = () => {
|
||||
dialogRef.value.open()
|
||||
}
|
||||
|
||||
/** 修改 */
|
||||
const handleUpdate = (row) => {
|
||||
dialogRef.value.open(row.id)
|
||||
}
|
||||
|
||||
/** 删除 */
|
||||
const handleDelete = async (row) => {
|
||||
await proxy.$modal.confirm('确认删除该记录?')
|
||||
await delXxx(row.id)
|
||||
proxy.$modal.msgSuccess('删除成功')
|
||||
getList()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### 5.2 弹窗组件模板
|
||||
```vue
|
||||
<template>
|
||||
<el-dialog :title="title" v-model="open" width="600px" append-to-body>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="患者姓名" prop="patientName">
|
||||
<el-input v-model="form.patientName" placeholder="请输入患者姓名" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { getXxx, addXxx, updateXxx } from '@/api/xxx'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const title = ref('')
|
||||
const open = ref(false)
|
||||
const formRef = ref(null)
|
||||
const form = reactive({ id: undefined, patientName: '' })
|
||||
const rules = {
|
||||
patientName: [{ required: true, message: '患者姓名不能为空', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
/** 打开弹窗 */
|
||||
const openDialog = async (id) => {
|
||||
reset()
|
||||
if (id) {
|
||||
const res = await getXxx(id)
|
||||
Object.assign(form, res.data)
|
||||
title.value = '修改'
|
||||
} else {
|
||||
title.value = '新增'
|
||||
}
|
||||
open.value = true
|
||||
}
|
||||
|
||||
/** 提交 */
|
||||
const submitForm = async () => {
|
||||
await proxy.$refs.formRef.validate()
|
||||
if (form.id) {
|
||||
await updateXxx(form)
|
||||
proxy.$modal.msgSuccess('修改成功')
|
||||
} else {
|
||||
await addXxx(form)
|
||||
proxy.$modal.msgSuccess('新增成功')
|
||||
}
|
||||
open.value = false
|
||||
emit('success')
|
||||
}
|
||||
|
||||
/** 取消 */
|
||||
const cancel = () => {
|
||||
open.value = false
|
||||
reset()
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
form.id = undefined
|
||||
form.patientName = ''
|
||||
}
|
||||
|
||||
const emit = defineEmits(['success'])
|
||||
|
||||
defineExpose({ open: openDialog })
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、状态管理规范 (Pinia)
|
||||
|
||||
```javascript
|
||||
// store/modules/user.js
|
||||
import { defineStore } from 'pinia'
|
||||
import { login, logout, getInfo } from '@/api/login'
|
||||
|
||||
const useUserStore = defineStore('user', {
|
||||
state: () => ({
|
||||
token: getToken(),
|
||||
name: '',
|
||||
roles: [],
|
||||
permissions: []
|
||||
}),
|
||||
actions: {
|
||||
async loginAction(userInfo) {
|
||||
const res = await login(userInfo)
|
||||
setToken(res.token)
|
||||
this.token = res.token
|
||||
},
|
||||
async getInfoAction() {
|
||||
const res = await getInfo()
|
||||
this.name = res.user.nickName
|
||||
this.roles = res.roles
|
||||
this.permissions = res.permissions
|
||||
},
|
||||
logoutAction() {
|
||||
this.token = ''
|
||||
this.name = ''
|
||||
this.roles = []
|
||||
removeToken()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default useUserStore
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、路由配置规范
|
||||
|
||||
```javascript
|
||||
// router/index.js
|
||||
const routes = [
|
||||
{
|
||||
path: '/registration',
|
||||
component: Layout,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'Registration',
|
||||
component: () => import('@/views/registration/index.vue'),
|
||||
meta: { title: '挂号管理', icon: 'ticket' }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### 路由命名规则
|
||||
- 路径使用 kebab-case:`/patient-allergy`
|
||||
- name 使用 PascalCase:`PatientAllergy`
|
||||
- meta.title 使用中文:`患者过敏史`
|
||||
|
||||
---
|
||||
|
||||
## 八、样式规范
|
||||
|
||||
### 8.1 使用 scoped
|
||||
```vue
|
||||
<style scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### 8.2 使用 Element Plus 变量
|
||||
```css
|
||||
:deep(.el-button--primary) {
|
||||
--el-button-bg-color: #1890ff;
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 禁止事项
|
||||
- ❌ 使用内联样式(除动态绑定外)
|
||||
- ❌ 使用 `!important`
|
||||
- ❌ 全局样式污染其他组件
|
||||
|
||||
---
|
||||
|
||||
## 九、安全规范
|
||||
|
||||
### 9.1 XSS 防护
|
||||
- 用户输入使用 `v-text` 而非 `v-html`
|
||||
- 必须使用 `v-html` 时需做转义处理
|
||||
|
||||
### 9.2 敏感信息
|
||||
- 不在前端硬编码密码、密钥
|
||||
- API请求通过 `request.js` 统一拦截添加Token
|
||||
- Token 存储在 `localStorage`,设置过期时间
|
||||
|
||||
### 9.3 权限控制
|
||||
- 使用 `v-hasPermi` 指令控制按钮权限
|
||||
- 使用路由 `meta.roles` 控制页面权限
|
||||
- 接口请求在 `request.js` 中统一处理 401/403
|
||||
|
||||
---
|
||||
|
||||
## 十、性能优化
|
||||
|
||||
### 10.1 路由懒加载
|
||||
```javascript
|
||||
component: () => import('@/views/registration/index.vue')
|
||||
```
|
||||
|
||||
### 10.2 组件按需导入
|
||||
```javascript
|
||||
import { ElButton, ElTable } from 'element-plus'
|
||||
```
|
||||
|
||||
### 10.3 大列表优化
|
||||
- 超过100行使用虚拟滚动
|
||||
- 列表接口必须支持分页
|
||||
- 图片使用懒加载 `v-lazy`
|
||||
|
||||
### 10.4 内存泄漏防护
|
||||
- `onMounted` 中注册的事件在 `onUnmounted` 中移除
|
||||
- 定时器在组件销毁时清除
|
||||
- 避免在 `watch` 中创建新对象
|
||||
|
||||
---
|
||||
|
||||
## 十一、测试规范
|
||||
|
||||
### 11.1 单元测试 (Vitest)
|
||||
```javascript
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import PatientDialog from './PatientDialog.vue'
|
||||
|
||||
describe('PatientDialog', () => {
|
||||
it('renders correctly', () => {
|
||||
const wrapper = mount(PatientDialog)
|
||||
expect(wrapper.find('.el-dialog').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 11.2 E2E测试 (Playwright)
|
||||
```javascript
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('registration flow', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
await page.fill('#username', 'admin')
|
||||
await page.fill('#password', 'admin123')
|
||||
await page.click('.login-button')
|
||||
await expect(page).toHaveURL('/')
|
||||
|
||||
await page.goto('/registration')
|
||||
await expect(page.locator('.el-table')).toBeVisible()
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十二、Git提交规范
|
||||
|
||||
同后端规范(`MD/specs/IRON_RULES.md`),额外要求:
|
||||
- 提交前执行 `npm run lint` 确保无报错
|
||||
- 提交前执行 `npm run build:dev` 确保构建成功
|
||||
|
||||
---
|
||||
|
||||
> **文档版本**: v1.0
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 七、UI设计铁律法则
|
||||
|
||||
> 所有前端页面设计和开发必须遵守以下法则,详见 `MD/specs/UI_DESIGN_IRON_RULES.md`
|
||||
|
||||
### 核心设计法则速查
|
||||
|
||||
| 法则 | 核心思想 | HIS应用 |
|
||||
|------|---------|---------|
|
||||
| 希克定律 | 选项越少决策越快 | 菜单≤7项,表单≤12字段 |
|
||||
| 费茨定律 | 目标大且近操作快 | 按钮≥44px,危险操作远离安全操作 |
|
||||
| 米勒定律 | 记忆负荷≤7±2 | 信息分组,Tab≤6个 |
|
||||
| 雅各布定律 | 遵循用户已有习惯 | 若依标准布局模式 |
|
||||
| 格式塔原则 | 视觉分组要清晰 | 间距系统、颜色体系 |
|
||||
| 多赫蒂阈值 | 响应<400ms | loading态、骨架屏、分页 |
|
||||
| 尼尔森十大原则 | 全面可用性 | 操作反馈、防错、容错 |
|
||||
| 泰斯勒定律 | 复杂性守恒 | 智能默认值、常用模板 |
|
||||
| 峰终定律 | 关键时刻做好 | 成功动画、错误优雅处理 |
|
||||
| 冯·雷斯托夫 | 不同的更容易记住 | 危急值红色脉冲、徽标通知 |
|
||||
|
||||
### 设计文档必备
|
||||
|
||||
每个新页面/模块的设计文档必须包含:
|
||||
1. 页面UI布局描述(组件位置、栅格、比例)
|
||||
2. 交互效果清单(每个操作→效果→反馈)
|
||||
3. 前后端调用流程(操作→API→处理链→渲染)
|
||||
4. 状态流转图
|
||||
5. 异常/边界处理方案
|
||||
305
MD/specs/HARNESS_ENGINEERING.md
Normal file
305
MD/specs/HARNESS_ENGINEERING.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# Harness Engineering 完整方法论
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: AI Agent 协作开发
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
## 一、WalkingLabs 5 子系统模型
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 指令(Instruction)— RULES.md / AGENTS.md │
|
||||
│ 工具(Tools)— shell / 文件 / 测试 │
|
||||
│ 环境(Environment)— 依赖 / 服务 / 版本 │
|
||||
│ 状态(State)— PROGRESS.md / 功能清单 │
|
||||
│ 反馈(Feedback)— test / lint / build │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.1 指令子系统
|
||||
|
||||
| 文件 | 用途 |
|
||||
|------|------|
|
||||
| `RULES.md` | 项目铁律、约束、标准工作流 |
|
||||
| `AGENTS.md` | 子目录铁律引用 |
|
||||
| `.harness/PROGRESS.md` | 会话进度 + 已验证状态 |
|
||||
| `.harness/feature_list.json` | 功能状态唯一事实来源 |
|
||||
| `.harness/init.sh` | 统一启动入口 |
|
||||
| `.harness/clean-state-checklist.md` | 结束时的清洁检查 |
|
||||
|
||||
### 1.2 工具子系统
|
||||
|
||||
| 层级 | 工具 | 用途 |
|
||||
|------|------|------|
|
||||
| L0 开发 | `mvn compile/test` / `npm run build` | 编译、测试 |
|
||||
| L1 Agent | `agentforge executor --agent <name>` | Agent 主循环 |
|
||||
| L2 Pipeline | `agentforge pipeline` | 流水线批量修 Bug |
|
||||
| L3 集成 | Zentao REST API | 禅道操作 |
|
||||
| L4 辅助 | `rg` / `git blame` | 代码搜索、历史追溯 |
|
||||
|
||||
### 1.3 环境子系统
|
||||
|
||||
| 组件 | 配置 |
|
||||
|------|------|
|
||||
| Redis | `redis://127.0.0.1:16379` |
|
||||
| PostgreSQL | `192.168.110.252:15432` |
|
||||
| Git | `http://192.168.110.253:3000/wangyizhe/his.git` |
|
||||
|
||||
### 1.4 状态子系统
|
||||
|
||||
| 机制 | 用途 | 持久化 |
|
||||
|------|------|--------|
|
||||
| `TraceStore` (SQLite) | Agent 活动追踪 | `/var/lib/agentforge/traces.db` |
|
||||
| `fix_trajectory` | 修复轨迹 | Redis Hash |
|
||||
| `dead_letter` | 失败任务持久化 | Redis List |
|
||||
|
||||
### 1.5 反馈子系统
|
||||
|
||||
| 层级 | 速度 | 命令 | 失败处理 |
|
||||
|------|------|------|---------|
|
||||
| L1 编译检查 | <10秒 | `mvn compile` | 立即阻断 |
|
||||
| L1 单元测试 | <5分钟 | `mvn test` | 失败回退,重试 |
|
||||
| L2 代码质量 | <2分钟 | ESLint / 编译警告 | 警告可忽略,错误阻断 |
|
||||
| L3 质量门禁 | <30秒 | `run_quality_gates()` | 编译验证通过才提交 |
|
||||
| L4 人工审查 | 5-10分钟 | diff review | 驳回/指导/批准 |
|
||||
|
||||
---
|
||||
|
||||
## 二、约束系统
|
||||
|
||||
### 2.1 四类约束
|
||||
|
||||
| 类型 | 内容 | 示例 |
|
||||
|------|------|------|
|
||||
| 架构约束 | 接口合约、包结构、命名规范 | 包结构 `com.healthlink.his.web.{module}` |
|
||||
| 代码质量 | 圈复杂度、风格、类型提示 | 每函数≤50行 |
|
||||
| 安全约束 | 敏感信息、权限、输入验证 | 患者信息脱敏 |
|
||||
| 业务规则 | 领域逻辑、数据一致性 | 全链路6环验证 |
|
||||
|
||||
### 2.2 约束 DSL
|
||||
|
||||
```yaml
|
||||
constraint:
|
||||
type: "must" | "must_not" | "should" | "may"
|
||||
scope: "file" | "class" | "method" | "project"
|
||||
rule: "具体规则"
|
||||
verification: "如何验证"
|
||||
```
|
||||
|
||||
### 2.3 约束优先级
|
||||
|
||||
```
|
||||
安全(1) > 架构(2) > 业务(3) > 质量(4) > 性能(5)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、反馈系统
|
||||
|
||||
### 3.1 闭环测试
|
||||
|
||||
```
|
||||
测试失败
|
||||
→ 分析失败原因(编译/逻辑/边界/依赖)
|
||||
→ 提取可行动反馈(文件:行号:错误类型:修复方向)
|
||||
→ Agent 修复
|
||||
→ 重测
|
||||
→ 持续失败3次 → 上报人类
|
||||
```
|
||||
|
||||
### 3.2 反馈格式
|
||||
|
||||
```
|
||||
文件路径:行号 错误类型 错误描述 | 修复建议
|
||||
示例:
|
||||
src/main/java/com/.../PatientService.java:42 NullPointerException patient name | 添加空值检查
|
||||
```
|
||||
|
||||
### 3.3 失败原因分析
|
||||
|
||||
| 类型 | 占比 | 捕获门禁 |
|
||||
|------|------|---------|
|
||||
| 架构错误 | 35% | L1 编译 |
|
||||
| 业务逻辑 | 25% | L3 单元测试 |
|
||||
| 创造性偏差 | 20% | L3 + L5 |
|
||||
| Debug残留 | 15% | L2 静态分析 |
|
||||
| 其他 | 5% | L5 |
|
||||
|
||||
### 3.4 测试覆盖率目标
|
||||
|
||||
```yaml
|
||||
unit_test_coverage: 90% # 行覆盖率
|
||||
mutation_score: 80% # 变异测试通过率
|
||||
branch_coverage: 85% # 分支覆盖率
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、持久执行
|
||||
|
||||
### 4.1 检查点策略
|
||||
|
||||
**触发时机**:
|
||||
- 每完成1个关键步骤
|
||||
- 编译通过/失败后
|
||||
- 每次代码修改后
|
||||
|
||||
**检查点内容**:
|
||||
```yaml
|
||||
checkpoint:
|
||||
step_id: "string"
|
||||
status: "pending | in_progress | completed | failed"
|
||||
inputs: {}
|
||||
outputs: {}
|
||||
error_message: ""
|
||||
timestamp: "ISO8601"
|
||||
```
|
||||
|
||||
### 4.2 恢复流程
|
||||
|
||||
```
|
||||
失败 → 定位最新检查点 → 分析失败原因 → git restore → 从失败点修复 → 继续执行
|
||||
```
|
||||
|
||||
### 4.3 幂等性模式
|
||||
|
||||
| 模式 | 实现 |
|
||||
|------|------|
|
||||
| 唯一标识 | 每个操作生成唯一ID,已执行则跳过 |
|
||||
| 状态检查 | 执行前检查目标是否已达成 |
|
||||
| 补偿操作 | 不可逆操作提供 `git restore` 回滚 |
|
||||
|
||||
---
|
||||
|
||||
## 五、Agent 协作详解
|
||||
|
||||
### 5.1 管线路由
|
||||
|
||||
```
|
||||
fix_done (关羽/赵云)
|
||||
│
|
||||
▼
|
||||
诸葛亮 (分析路由)
|
||||
│── 无DB变更 ──→ 张飞 (Playwright测试)
|
||||
│── 有DB变更 ─→ 荀彧 (DB审查) → 张飞 (测试)
|
||||
│
|
||||
└── 失败 → 回退给修复者重修(最多10次)
|
||||
|
||||
张飞(测试) → 华佗(验收) → 陈琳(归档)
|
||||
```
|
||||
|
||||
### 5.2 去重机制
|
||||
|
||||
| 机制 | TTL | 用途 |
|
||||
|------|-----|------|
|
||||
| `pipeline_sent:{bug_id}` | 24h | 防重复触发管线 |
|
||||
| `pipeline_retry:{bug_id}` | — | 重试计数器 |
|
||||
| `codex_lock:{agent}` | 1h | Agent 互斥锁 |
|
||||
| `fix_active:{agent}:{bug_id}` | 30min | 防重复 fix_start |
|
||||
|
||||
### 5.3 禅道操作规则
|
||||
|
||||
| 阶段 | 智能体 | 禅道操作 |
|
||||
|------|--------|---------|
|
||||
| 分析路由 | 诸葛亮 | 添加备注(分析结果) |
|
||||
| DB审查 | 荀彧 | 添加备注(审查结果) |
|
||||
| 测试 | 张飞 | 添加测试报告 + resolve |
|
||||
| 验收 | 华佗 | 添加备注 + resolve + assign |
|
||||
| 归档 | 陈琳 | 添加备注(全流程记录) |
|
||||
|
||||
---
|
||||
|
||||
## 六、审查与审计
|
||||
|
||||
### 6.1 三层审查
|
||||
|
||||
| 层级 | 内容 | 信任度 |
|
||||
|------|------|--------|
|
||||
| L1 自审 | Agent 对照约束逐条检查 | 强制 |
|
||||
| L2 配对审查 | Agent 变更摘要 + 人类终审 | 按信任度比例 |
|
||||
| L3 合规审查 | 审计追踪,记录所有AI操作 | 强制 |
|
||||
|
||||
### 6.2 信任度比例
|
||||
|
||||
| 信任等级 | 自审 | 配对审查 | 合规审查 |
|
||||
|---------|------|---------|---------|
|
||||
| L1 怀疑 | 强制 | 逐行 | 强制 |
|
||||
| L2 试探 | 强制 | 抽样30% | 强制 |
|
||||
| L3 信任 | 强制 | 抽样10% | 按需 |
|
||||
|
||||
### 6.3 审计记录格式
|
||||
|
||||
```yaml
|
||||
audit_record:
|
||||
agent_id: "codex-v4"
|
||||
task_id: "bug-597"
|
||||
timestamp: "2026-05-28T14:30:00Z"
|
||||
actions:
|
||||
- type: "file_modify"
|
||||
path: "AdviceManageAppMapper.xml"
|
||||
diff: "+7 lines, -2 lines"
|
||||
approvals:
|
||||
- reviewer: "human"
|
||||
decision: "approved"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、BDT 方法论(Bug Driven Testing)
|
||||
|
||||
### 7.1 流程
|
||||
|
||||
```
|
||||
获取Bug → 设计用例 → 基线测试(应失败) → 修复 → 回归测试(应通过) → 扩展测试 → 提交
|
||||
```
|
||||
|
||||
### 7.2 测试用例7种检查模式
|
||||
|
||||
| # | 模式 | 适用场景 | Playwright写法 |
|
||||
|---|------|---------|---------------|
|
||||
| 1 | 页面加载 | 所有Bug | `expect(page).not.toHaveURL(/.*login.*/)` |
|
||||
| 2 | 元素可见 | 显示/缺失类 | `expect(locator).toBeVisible()` |
|
||||
| 3 | 元素可交互 | 按钮/弹窗类 | `await locator.click()` |
|
||||
| 4 | 数据正确 | 列表/回显类 | `expect(locator).toHaveText()` |
|
||||
| 5 | 无报错 | 所有Bug | `page.on('pageerror')` |
|
||||
| 6 | 流程完整 | 交互流程类 | 多步骤操作链 |
|
||||
| 7 | 状态变更 | 退回/审核类 | 操作前vs操作后状态对比 |
|
||||
|
||||
### 7.3 测试用例质量标准
|
||||
|
||||
- ✅ 有 `@bug{N}` 标签(可单独运行)
|
||||
- ✅ 有 `@regression` 标签(回归套件)
|
||||
- ✅ 操作路径来自禅道复现步骤
|
||||
- ✅ 断言覆盖期望结果
|
||||
- ✅ 检查无JS错误
|
||||
- ✅ 有截图记录
|
||||
- ✅ 独立运行(不依赖其他测试)
|
||||
|
||||
---
|
||||
|
||||
## 八、L4/L5 分析与优化
|
||||
|
||||
### 8.1 L4 量化分析
|
||||
|
||||
- TraceStore (SQLite): `/var/lib/agentforge/traces.db`
|
||||
- 指标:Agent成功率、平均修复耗时、失败模式分布、Pipeline吞吐量
|
||||
|
||||
### 8.2 L5 AI 自主优化
|
||||
|
||||
| 机制 | 触发条件 | 动作 |
|
||||
|------|---------|------|
|
||||
| 约束增强 | 成功率<50%(≥3次) | 自动补充专项约束 |
|
||||
| 智能路由 | 按bug类型匹配历史最优Agent | `best_agent_for(bug_type)` |
|
||||
| 重试策略 | 失败后换提示词/换Agent | 最多10次 |
|
||||
| 路由调整 | 某Agent成功率最低 | 减少分配 |
|
||||
|
||||
- 评分:成功率(60%) + 速度(20%) + 类型匹配(20%)
|
||||
|
||||
---
|
||||
|
||||
> **文档版本**: v1.0
|
||||
> **最后更新**: 2026-06-06
|
||||
161
MD/specs/INFORMED_CONSENT_DESIGN.md
Normal file
161
MD/specs/INFORMED_CONSENT_DESIGN.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# 知情同意管理模块设计文档
|
||||
|
||||
> **文档类型**: 深度业务设计
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **三甲依据**: 《医疗纠纷预防和处理条例》《侵权责任法》— 患者知情同意权
|
||||
|
||||
---
|
||||
|
||||
## 一、业务背景
|
||||
|
||||
知情同意是医疗行为的法律前提。依据《医疗纠纷预防和处理条例》(2018版):
|
||||
- 手术/麻醉/输血/特殊检查/特殊治疗必须取得患者或家属书面知情同意
|
||||
- 知情同意书必须由患者或其授权代理人签署
|
||||
- 知情同意书是医疗纠纷中最关键的法律证据
|
||||
- 三甲评审现场必查项
|
||||
|
||||
---
|
||||
|
||||
## 二、知情同意类型
|
||||
|
||||
| 类型 | 适用场景 | 签署人要求 | 三甲依据 |
|
||||
|------|---------|-----------|---------|
|
||||
| 手术知情同意 | 所有手术 | 患者或授权代理人 | 手术管理制度 |
|
||||
| 麻醉知情同意 | 所有麻醉操作 | 患者或授权代理人 | 麻醉管理制度 |
|
||||
| 输血知情同意 | 输血治疗 | 患者或授权代理人 | 输血管理规范 |
|
||||
| 特殊检查知情同意 | 有创检查/造影等 | 患者或授权代理人 | 检查管理规范 |
|
||||
| 特殊治疗知情同意 | 化疗/放疗/介入等 | 患者或授权代理人 | 治疗管理规范 |
|
||||
| 病危通知书 | 病危/病重 | 患者家属或代理人 | 危重患者管理 |
|
||||
| 自费项目知情同意 | 自费药品/耗材 | 患者或授权代理人 | 医保管理规范 |
|
||||
|
||||
---
|
||||
|
||||
## 三、完整业务流程
|
||||
|
||||
### 3.1 知情同意全流程
|
||||
|
||||
```
|
||||
医生发起知情同意
|
||||
│
|
||||
▼
|
||||
选择同意类型 + 关联医嘱/手术
|
||||
│
|
||||
▼
|
||||
系统自动填充模板(患者信息+诊断+拟定方案)
|
||||
│
|
||||
▼
|
||||
医生编辑知情同意内容
|
||||
├── 疾病诊断
|
||||
├── 拟实施的手术/操作名称
|
||||
├── 手术/操作目的
|
||||
├── 手术/操作方式
|
||||
├── 预期效果
|
||||
├── 可能出现的风险和并发症
|
||||
├── 替代方案及其利弊
|
||||
├── 不接受治疗的后果
|
||||
└── 其他需要说明的事项
|
||||
│
|
||||
▼
|
||||
医生电子签名
|
||||
│
|
||||
▼
|
||||
患者/家属阅读+理解确认
|
||||
│
|
||||
▼
|
||||
患者/家属电子签名(手写板/密码)
|
||||
│
|
||||
▼
|
||||
生成知情同意书(PDF)
|
||||
│
|
||||
▼
|
||||
归档到病历
|
||||
```
|
||||
|
||||
### 3.2 异常流程
|
||||
|
||||
| 场景 | 处理方式 |
|
||||
|------|---------|
|
||||
| 患者拒绝签署 | 记录拒绝原因+见证人签名,生成"拒绝知情同意"记录 |
|
||||
| 患者无签署能力 | 要求法定代理人签署+见证人签名 |
|
||||
| 紧急情况无法签署 | 记录紧急情况说明+院长/授权人批准 |
|
||||
| 签署后修改 | 生成新版本,保留原版本,记录修改原因 |
|
||||
| 超时未签署 | 系统提醒→再次通知→超过时限则禁止执行 |
|
||||
|
||||
---
|
||||
|
||||
## 四、数据模型
|
||||
|
||||
### 4.1 知情同意书表 `sys_informed_consent`
|
||||
|
||||
| 字段 | 类型 | 说明 | 必填 |
|
||||
|------|------|------|------|
|
||||
| id | BIGSERIAL | 主键 | ✅ |
|
||||
| encounter_id | BIGINT | 就诊ID | ✅ |
|
||||
| patient_id | BIGINT | 患者ID | ✅ |
|
||||
| patient_name | VARCHAR(50) | 患者姓名 | ✅ |
|
||||
| consent_type | INT | 类型(1手术 2麻醉 3输血 4特殊检查 5特殊治疗 6病危 7自费) | ✅ |
|
||||
| related_surgery_id | BIGINT | 关联手术ID(手术知情时) | ❌ |
|
||||
| related_advice_id | BIGINT | 关联医嘱ID | ❌ |
|
||||
| diagnosis | TEXT | 疾病诊断 | ✅ |
|
||||
| procedure_name | VARCHAR(200) | 拟实施手术/操作名称 | ✅ |
|
||||
| procedure_purpose | TEXT | 手术/操作目的 | ✅ |
|
||||
| procedure_method | TEXT | 手术/操作方式 | ✅ |
|
||||
| expected_outcome | TEXT | 预期效果 | ✅ |
|
||||
| risks_and_complications | TEXT | 可能出现的风险和并发症 | ✅ |
|
||||
| alternative_plans | TEXT | 替代方案及其利弊 | ✅ |
|
||||
| consequences_of_refusal | TEXT | 不接受治疗的后果 | ✅ |
|
||||
| other_notes | TEXT | 其他需要说明的事项 | ❌ |
|
||||
| doctor_user_id | BIGINT | 签署医生ID | ✅ |
|
||||
| doctor_name | VARCHAR(50) | 签署医生姓名 | ✅ |
|
||||
| doctor_sign_time | TIMESTAMP | 医生签名时间 | ✅ |
|
||||
| doctor_sign_image | TEXT | 医生签名图片(base64) | ✅ |
|
||||
| patient_sign_status | INT | 患者签名状态(0未签 1已签 2拒绝) | ✅ |
|
||||
| patient_sign_time | TIMESTAMP | 患者签名时间 | ❌ |
|
||||
| patient_sign_image | TEXT | 患者签名图片(base64) | ❌ |
|
||||
| guardian_name | VARCHAR(50) | 代理人姓名(患者无签署能力时) | ❌ |
|
||||
| guardian_relation | VARCHAR(20) | 代理人与患者关系 | ❌ |
|
||||
| witness_name | VARCHAR(50) | 见证人姓名 | ❌ |
|
||||
| reject_reason | TEXT | 拒绝原因(患者拒绝时) | ❌ |
|
||||
| status | INT | 状态(0草稿 1待患者签名 2已完成 3已归档 4已作废) | ✅ |
|
||||
| version | INT | 版本号(修改后版本递增) | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 五、业务规则
|
||||
|
||||
| 规则编号 | 规则名称 | 规则描述 |
|
||||
|---------|---------|---------|
|
||||
| IC-001 | 手术强制签署 | 手术前必须完成手术知情同意书签署 |
|
||||
| IC-002 | 麻醉强制签署 | 麻醉前必须完成麻醉知情同意书签署 |
|
||||
| IC-003 | 输血强制签署 | 输血前必须完成输血知情同意书签署 |
|
||||
| IC-004 | 紧急豁免 | 紧急情况可事后补签,需院长批准+详细记录 |
|
||||
| IC-005 | 版本管理 | 修改后生成新版本,保留原版本可追溯 |
|
||||
| IC-006 | 签署时限 | 知情同意签署后24小时内未执行需重新确认 |
|
||||
| IC-007 | 模板管理 | 支持系统模板+科室模板+个人模板 |
|
||||
| IC-008 | 归档要求 | 手术/操作完成后自动归档到病历 |
|
||||
|
||||
---
|
||||
|
||||
## 六、与手术/医嘱的集成
|
||||
|
||||
```
|
||||
手术申请(Surgery) ──1:1──→ 手术知情同意书
|
||||
麻醉记录(Anesthesia) ──1:1──→ 麻醉知情同意书
|
||||
医嘱(Advice) ──1:N──→ 输血/特殊检查知情同意书
|
||||
知情同意书 ──归档──→ 病案管理(MedicalRecord)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、测试用例
|
||||
|
||||
| 用例编号 | 场景 | 预期结果 |
|
||||
|---------|------|---------|
|
||||
| TC-IC001 | 正常签署流程 | 医生签署→患者签署→完成→归档 |
|
||||
| TC-IC002 | 手术前未签署 | 手术安排时拦截,提示"请先完成知情同意" |
|
||||
| TC-IC003 | 患者拒绝签署 | 记录拒绝原因+见证人,生成拒绝记录 |
|
||||
| TC-IC004 | 紧急情况 | 记录紧急说明+院长批准,事后补签 |
|
||||
| TC-IC005 | 修改后版本 | 生成新版本,原版本保留可查看 |
|
||||
| TC-IC006 | 签署超时 | 超过24小时未执行,系统提醒重新确认 |
|
||||
|
||||
551
MD/specs/IRON_RULES.md
Normal file
551
MD/specs/IRON_RULES.md
Normal file
@@ -0,0 +1,551 @@
|
||||
# HealthLink-HIS 执行铁律
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: 全项目开发流程
|
||||
> **版本**: v2.1
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06 (铁律18统一)
|
||||
|
||||
---
|
||||
|
||||
## 一、铁律总览
|
||||
|
||||
| 编号 | 铁律名称 | 优先级 | 适用范围 |
|
||||
|------|---------|--------|---------|
|
||||
| #1 | 修改完必须测试 | P0 | 全量代码 |
|
||||
| #2 | Flyway 数据库迁移 | P0 | 数据库变更 |
|
||||
| #3 | 先分解再行动 | P1 | 非平凡任务 |
|
||||
| #4 | 验证后信 | P1 | 编译/构建 |
|
||||
| #5 | 文档统一管理 | P1 | 文档产出 |
|
||||
| #6 | 测试通过后才提交 | P0 | 代码提交 |
|
||||
| #7 | 前后端API路径对齐 | P0 | 接口开发 |
|
||||
| #8 | 铁律和规范文档放MD目录 | P1 | 规范文档 |
|
||||
| #9 | 开发前必须审核原有代码 | P0 | 全量开发 |
|
||||
| #10 | 设计文档必须包含UI设计和调用流程 | P0 | 设计文档/前端开发 |
|
||||
| #11 | 模块设计必须分析业务逻辑,不能只做CRUD | P0 | 全量模块设计 |
|
||||
| #12 | 模块优化必须分析现有业务流并说明促进作用 | P0 | 全量模块优化 |
|
||||
| #13 | 开发必须深度分析+深度设计,禁止浅层糊弄 | P0 | 全量开发 |
|
||||
| #14 | 设计文档确认后自主开发 | P0 | 全量开发 |
|
||||
| #15 | 模块设计必须分析业务逻辑 | P0 | 全量模块设计 |
|
||||
| #16 | 模块优化必须分析业务流并说明促进作用 | P0 | 全量模块优化 |
|
||||
| #17 | 设计文档必须包含UI设计和调用流程 | P0 | 设计文档/前端开发 |
|
||||
| #18 | 禁止破坏原有功能 | P0 | 全项目(绝对) |
|
||||
|
||||
---
|
||||
|
||||
## 二、铁律详细说明
|
||||
|
||||
### 铁律 #1: 修改完必须测试
|
||||
|
||||
**任何代码修改后,必须完成以下测试才能提交:**
|
||||
|
||||
#### 白盒测试
|
||||
- `mvn clean compile` 编译通过,无ERROR
|
||||
- 单元测试全部通过(如有)
|
||||
- 代码无新增编译警告(或有书面说明可忽略)
|
||||
|
||||
#### 黑盒测试
|
||||
- 启动应用,验证无启动报错
|
||||
- 测试关键接口(登录、核心业务接口)
|
||||
- 验证请求响应结构正确(`{code, msg, data}`)
|
||||
- 验证业务逻辑正确性(非仅HTTP状态码)
|
||||
|
||||
#### 冒烟测试
|
||||
- 应用正常启动(端口监听)
|
||||
- 健康检查接口返回正常
|
||||
- 基础 CRUD 操作正常
|
||||
- 登录→获取菜单→核心业务流程通畅
|
||||
|
||||
#### 前端测试
|
||||
- `npm run build:dev` 构建成功
|
||||
- ESLint 无错误
|
||||
- 页面无控制台报错
|
||||
- 核心业务页面功能正常
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #2: Flyway 数据库迁移
|
||||
|
||||
**但凡遇到有新建表和字段的,必须通过 Flyway 框架去实现。**
|
||||
|
||||
#### 操作规范
|
||||
1. 在 `healthlink-his-domain/src/main/resources/db/migration/` 下创建迁移脚本
|
||||
2. 命名格式:`V{版本号}__{描述}.sql`(双下划线分隔)
|
||||
3. 示例:`V2.0.1__add_patient_allergy_table.sql`
|
||||
4. 迁移脚本必须包含完整的 DDL(CREATE TABLE / ALTER TABLE)
|
||||
5. 必须提供回滚方案(文档记录,非自动回滚)
|
||||
|
||||
#### 禁止事项
|
||||
- ❌ 直接在数据库执行 SQL 不走 Flyway
|
||||
- ❌ 修改已执行的迁移脚本
|
||||
- ❌ 迁移脚本中使用 `DROP TABLE`(除非明确需要)
|
||||
- ❌ 跳过版本号
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #3: 先分解再行动
|
||||
|
||||
**任何非平凡任务先出 plan 再执行。**
|
||||
|
||||
#### 触发条件
|
||||
- 修改超过 3 个文件的任务
|
||||
- 涉及多个模块的变更
|
||||
- 数据库结构变更
|
||||
- 新功能开发
|
||||
|
||||
#### 执行步骤
|
||||
1. 分析现有代码和架构
|
||||
2. 制定分步计划(使用 `update_plan`)
|
||||
3. 确认测试方案
|
||||
4. 逐步执行并验证
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #4: 验证后信
|
||||
|
||||
**每次修改后必须验证编译通过,不信记忆。**
|
||||
|
||||
#### 验证命令
|
||||
```bash
|
||||
# 后端编译
|
||||
export JAVA_HOME=/opt/jdk-25
|
||||
mvn clean compile -DskipTests
|
||||
|
||||
# 完整构建
|
||||
mvn install -DskipTests
|
||||
|
||||
# 前端构建
|
||||
cd healthlink-his-ui && npm run build:dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #5: 文档统一管理
|
||||
|
||||
**所有文档必须存储在 `MD/` 目录中,遵循文档规范。**
|
||||
|
||||
#### 目录结构
|
||||
```
|
||||
MD/
|
||||
├── DOCUMENTATION_STANDARD.md # 文档管理规范
|
||||
├── architecture/ # 架构设计
|
||||
├── development/ # 开发计划与记录
|
||||
├── standards/ # 国家/行业标准
|
||||
├── specs/ # 技术规范与流程
|
||||
├── bugs/ # Bug分析与修复记录
|
||||
├── guides/ # 使用指南
|
||||
└── upgrade/ # 升级记录
|
||||
```
|
||||
|
||||
#### 命名规范
|
||||
- 文件名使用 **大写英文+下划线**(如 `GRADE3A_DETAILED_DESIGN.md`)
|
||||
- 不使用中文作文件名
|
||||
- 不使用空格分隔单词
|
||||
- 版本号标注在文件名末尾(如 `_V2`)
|
||||
|
||||
#### 格式要求
|
||||
- 文档头部必须包含元数据块(文档类型、版本、日期)
|
||||
- 代码块必须标注语言类型
|
||||
- 表格使用标准Markdown格式
|
||||
|
||||
#### 详细规范
|
||||
参见 `MD/DOCUMENTATION_STANDARD.md`
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #6: 测试通过后才提交
|
||||
|
||||
**代码修改必须通过完整测试后才能提交到远程仓库。**
|
||||
|
||||
#### 提交前检查
|
||||
1. `mvn clean compile` 编译通过
|
||||
2. 接口测试全部通过(88/88)
|
||||
3. 前端构建成功
|
||||
4. 无新增编译警告
|
||||
5. 代码变更范围已确认(`git status`)
|
||||
|
||||
#### 提交规范
|
||||
- 使用标准 Commit Message 格式
|
||||
- 参见 `MD/specs/COMMIT_TEMPLATE.md`
|
||||
- 不提交未完成的功能
|
||||
- 不提交调试代码和临时文件
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #7: 前后端API路径对齐
|
||||
|
||||
**前后端API路径必须保持一致。**
|
||||
|
||||
#### 规范要求
|
||||
1. 后端接口路径统一前缀:`/healthlink-his/`
|
||||
2. 前端 `request.js` 中配置的 `baseURL` 必须与后端匹配
|
||||
3. 接口变更必须同步更新前后端代码
|
||||
4. 新增接口必须在 Swagger 文档中注册
|
||||
5. 接口路径命名使用小写字母和连字符(kebab-case)
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #11: 设计文档确认后自主开发(铁律)
|
||||
|
||||
**设计文档一旦确认,后续开发必须按文档自主执行。**
|
||||
|
||||
#### 核心要求
|
||||
- **禁止反复询问**"是否继续""下一步做什么""是否开始"——直接按计划推进
|
||||
- 每完成一个 Sprint,自动提交推送,然后立即开始下一个 Sprint
|
||||
- 设计文档是"**已签合同**",不是"参考意见"
|
||||
- 只在遇到**无法解决的阻塞**时才暂停询问
|
||||
|
||||
#### 触发条件
|
||||
- 设计文档已确认(如 `MD/architecture/GRADE3A_GAP_ANALYSIS_AND_DESIGN.md`)
|
||||
- Sprint 计划已制定
|
||||
- 代码编译通过
|
||||
|
||||
#### 禁止事项
|
||||
- ❌ 完成一个模块后问"继续吗?"
|
||||
- ❌ 完成一个 Sprint 后问"下一步?"
|
||||
- ❌ 每次工具调用前问"开始了吗?"
|
||||
|
||||
### 铁律 #8: 铁律和规范文档放MD目录
|
||||
|
||||
**所有铁律和规范文档统一存放在 `MD/specs/` 目录中。**
|
||||
|
||||
#### 已有规范文档
|
||||
| 文档 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| 执行铁律 | `MD/specs/IRON_RULES.md` | 本文档 |
|
||||
| 后端开发规范 | `MD/specs/BACKEND_DEVELOPMENT_STANDARD.md` | 后端编码规范 |
|
||||
| 前端开发规范 | `MD/specs/FRONTEND_DEVELOPMENT_STANDARD.md` | 前端编码规范 |
|
||||
| 后端检查清单 | `MD/specs/BACKEND_CHECKLIST.md` | 发布前检查 |
|
||||
| 前端检查清单 | `MD/specs/FRONTEND_CHECKLIST.md` | 发布前检查 |
|
||||
| CI/CD门禁 | `MD/specs/CICD_GATEKEEPER.md` | 构建门禁 |
|
||||
| 提交模板 | `MD/specs/COMMIT_TEMPLATE.md` | Commit规范 |
|
||||
| 发布清单 | `MD/specs/RELEASE_CHECKLIST.md` | 发布流程 |
|
||||
| E2E测试计划 | `MD/specs/PLAYWRIGHT_TESTING_PLAN.md` | Playwright测试 |
|
||||
|
||||
#### AGENTS.md 同步
|
||||
- 后端 `healthlink-his-server/AGENTS.md` 必须引用本文档
|
||||
- 新增铁律必须同步更新本文档和 AGENTS.md
|
||||
|
||||
---
|
||||
|
||||
## 三、违规处理
|
||||
|
||||
| 级别 | 描述 | 处理方式 |
|
||||
|------|------|---------|
|
||||
| P0 违规 | 跳过测试直接提交 | 必须回滚并重新测试 |
|
||||
| P0 违规 | 数据库变更不走Flyway | 回滚数据库变更,重新用Flyway执行 |
|
||||
| P1 违规 | 未分解就行动 | 补充分析和计划文档 |
|
||||
| P1 违规 | 文档不规范 | 补充元数据和格式 |
|
||||
|
||||
---
|
||||
|
||||
## 四、快速参考
|
||||
|
||||
### 后端开发速查
|
||||
```bash
|
||||
# 编译
|
||||
export JAVA_HOME=/opt/jdk-25 && mvn clean compile -DskipTests
|
||||
|
||||
# 完整构建
|
||||
mvn install -DskipTests
|
||||
|
||||
# 运行测试
|
||||
mvn test -pl healthlink-his-application -Dtest="ClassName" -Dsurefire.failIfNoSpecifiedTests=false
|
||||
|
||||
# 启动应用
|
||||
java -jar healthlink-his-application/target/*.jar --spring.profiles.active=dev
|
||||
```
|
||||
|
||||
### 前端开发速查
|
||||
```bash
|
||||
# 开发模式
|
||||
npm run dev
|
||||
|
||||
# 构建
|
||||
npm run build:dev
|
||||
|
||||
# 测试
|
||||
npm run test:run
|
||||
|
||||
# Lint
|
||||
npm run lint
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **文档版本**: v2.0
|
||||
> **最后更新**: 2026-06-06 (铁律18统一)
|
||||
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #9: 开发前必须审核原有代码
|
||||
|
||||
**任何新功能开发前,必须先搜索项目中是否已有相关代码。**
|
||||
|
||||
#### 搜索清单
|
||||
|
||||
| 搜索目标 | 搜索路径 | 命令 |
|
||||
|---------|---------|------|
|
||||
| 后端Controller | `healthlink-his-server/**/controller/` | `rg -l "关键词" ...` |
|
||||
| AppService | `healthlink-his-server/**/appservice/` | 同上 |
|
||||
| Service/ServiceImpl | `healthlink-his-server/**/service/` | 同上 |
|
||||
| Mapper | `healthlink-his-server/**/mapper/` | 同上 |
|
||||
| Entity/Domain | `healthlink-his-server/**/domain/` | 同上 |
|
||||
| 前端页面 | `healthlink-his-ui/src/views/` | 同上 |
|
||||
| 前端API | `healthlink-his-ui/src/api/` | 同上 |
|
||||
| 数据库表 | Flyway迁移脚本 | `rg "CREATE TABLE" ...` |
|
||||
|
||||
#### 判定规则
|
||||
|
||||
| 情况 | 处理方式 |
|
||||
|------|---------|
|
||||
| 后端+前端都已有 | 审查现有实现,找出缺陷/遗漏,在原基础上优化 |
|
||||
| 只有后端,前端缺失 | 只补前端页面,调用现有API |
|
||||
| 只有前端,后端缺失 | 只补后端接口,前端API对齐 |
|
||||
| 前端壳子存在但功能不完整 | 分析壳子现有逻辑,补充完善 |
|
||||
| 后端接口存在但业务逻辑不完整 | 在原Service基础上扩展,不新建 |
|
||||
| 完全没有 | 从零开发,但先检查是否有可复用的组件/工具类 |
|
||||
|
||||
#### 禁止行为
|
||||
- ❌ 不看代码就新建Controller/Service
|
||||
- ❌ 已有功能重复实现
|
||||
- ❌ 废弃原有代码另写一套
|
||||
- ❌ 创建与现有模块功能重叠的新模块
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #13: 开发必须深度分析+深度设计,禁止浅层糊弄
|
||||
|
||||
**如果一个模块不能在真实医院环境中使用,就不算完成。**
|
||||
|
||||
#### 禁止行为(红线)
|
||||
|
||||
| ❌ 禁止 | 说明 |
|
||||
|---------|------|
|
||||
| 写空壳页面就宣称"功能完成" | 页面有内容但没有实际业务逻辑 |
|
||||
| 只做CRUD就宣称"模块开发完毕" | 缺少业务规则/状态流转/异常处理 |
|
||||
| 设计文档只有标题没有内容 | 设计文档是"施工图纸",必须有实质内容 |
|
||||
| 接口只返回200不验证业务逻辑 | 测试必须验证业务正确性,不只是HTTP状态码 |
|
||||
| 前端只有表格没有交互 | 缺少搜索/筛选/分页/操作反馈/空状态 |
|
||||
| 后端没有参数校验 | 缺少必填校验/格式校验/业务规则校验 |
|
||||
|
||||
#### 每个模块必须达到的标准
|
||||
|
||||
| 维度 | 必须具备 | 自检方法 |
|
||||
|------|---------|---------|
|
||||
| **前端** | 搜索/筛选/分页/新增编辑弹窗/操作反馈/空状态/加载态 | 能否正常操作每个功能 |
|
||||
| **后端** | 参数校验/业务规则校验/异常处理/日志记录 | 能否处理正常+异常场景 |
|
||||
| **数据** | 完整字段/关联关系/索引/Flyway迁移 | 数据库能否支撑业务 |
|
||||
| **业务** | 正常流程/异常流程/边界场景/状态机 | 能否覆盖真实业务场景 |
|
||||
| **设计** | 业务背景/流程图/规则清单/时序图/测试用例 | 设计文档是否可执行 |
|
||||
| **测试** | 接口测试/业务逻辑测试/异常测试 | 能否在真实环境使用 |
|
||||
|
||||
#### 质量自检清单
|
||||
|
||||
开发完成后必须回答以下问题:
|
||||
|
||||
```
|
||||
□ 这个模块放到医院里,医生/护士/收费员能直接用吗?
|
||||
□ 搜索条件是否覆盖了真实使用场景?
|
||||
□ 表单校验是否覆盖了所有必填项和格式要求?
|
||||
□ 操作反馈是否清晰(成功/失败/加载中/空数据)?
|
||||
□ 后端是否有完整的参数校验和业务规则校验?
|
||||
□ 异常场景(网络断开/数据不存在/权限不足)是否处理?
|
||||
□ 状态流转是否完整(每个状态都能正确转换)?
|
||||
□ 设计文档是否足够详细,其他人能据此开发?
|
||||
□ 测试用例是否覆盖了正常流程和异常流程?
|
||||
□ 接口返回的数据结构是否前后端对齐?
|
||||
```
|
||||
|
||||
#### 深度设计文档标准
|
||||
|
||||
| 文档部分 | 最低要求 | 优秀标准 |
|
||||
|---------|---------|---------|
|
||||
| 业务背景 | 说明做什么 | 说明为什么做+参考什么标准 |
|
||||
| 业务流程 | 正常流程文字描述 | 正常+异常+边界+流程图 |
|
||||
| 状态流转 | 状态列表 | 状态机图+转换条件+权限 |
|
||||
| 业务规则 | 规则名称 | 规则编号+描述+触发时机+处理方式 |
|
||||
| 数据模型 | 表名+字段 | ER图+字段说明+索引+关联 |
|
||||
| 接口设计 | API路径 | 请求/响应示例+错误码+版本 |
|
||||
| 前端设计 | 页面列表 | UI线框+交互时序+组件选型 |
|
||||
| 测试用例 | 功能清单 | 正常/异常/边界/性能测试用例 |
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #12: 模块优化必须分析现有业务流并说明促进作用
|
||||
|
||||
**任何模块新增/优化前,必须先分析现有业务流程全貌。**
|
||||
|
||||
#### 必须回答的5个问题
|
||||
|
||||
| # | 问题 | 说明 |
|
||||
|---|------|------|
|
||||
| 1 | 该模块在整体业务流中处于什么位置? | 上游/下游/并行 |
|
||||
| 2 | 该模块与哪些现有模块有数据流转关系? | 列出所有关联模块 |
|
||||
| 3 | 优化对上下游模块有什么促进作用? | 减少重复、提升一致性、加快流程 |
|
||||
| 4 | 变更是否影响现有业务流程? | 兼容性评估 |
|
||||
| 5 | 业务规则是否与现有模块冲突? | 规则一致性检查 |
|
||||
|
||||
#### 业务逻辑分析文档模板
|
||||
|
||||
```
|
||||
# 模块名 — 业务逻辑分析
|
||||
|
||||
## 1. 整体业务流程定位
|
||||
[该模块在HIS系统中的位置,上下游关系图]
|
||||
|
||||
## 2. 关联模块分析
|
||||
| 关联模块 | 数据流向 | 交互方式 | 影响程度 |
|
||||
|---------|---------|---------|---------|
|
||||
|
||||
## 3. 优化促进作用
|
||||
| 维度 | 优化前 | 优化后 | 提升效果 |
|
||||
|------|--------|--------|---------|
|
||||
|
||||
## 4. 兼容性评估
|
||||
- 对现有模块的影响
|
||||
- 数据迁移需求
|
||||
- 接口变更影响
|
||||
|
||||
## 5. 规则一致性检查
|
||||
- 新增规则是否与现有规则冲突
|
||||
- 状态流转是否与现有状态机兼容
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #11: 模块设计必须分析业务逻辑,不能只做CRUD
|
||||
|
||||
**任何新模块/功能开发前,必须先进行业务逻辑分析和梳理。**
|
||||
|
||||
#### 禁止行为
|
||||
- ❌ 拿到需求就直接写CRUD,不思考业务流程
|
||||
- ❌ 不查阅标准规范就开发医疗业务模块
|
||||
- ❌ 没有设计文档就直接编码
|
||||
- ❌ 把"能增删改查"当成"功能完成"
|
||||
|
||||
#### 必须完成的设计步骤
|
||||
|
||||
| # | 步骤 | 产出物 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| 1 | 查阅标准规范 | 参考文档清单 | 国家卫健委标准、医保局规范、HL7/FHIR、三甲评审标准 |
|
||||
| 2 | 梳理业务流程 | 流程图/文字描述 | 正常流程 + 异常流程 + 边界场景 |
|
||||
| 3 | 设计状态流转 | 状态机图 | 每个实体的生命周期、状态转换条件 |
|
||||
| 4 | 定义业务规则 | 规则清单 | 如:药品相互作用规则、医保审核规则、危急值判定规则 |
|
||||
| 5 | 设计交互时序 | 时序图 | 用户操作 → 前端事件 → API → 后端处理 → 持久化 → 响应 |
|
||||
| 6 | 编写设计文档 | MD文件 | 保存到 `MD/specs/` 或 `MD/architecture/` |
|
||||
|
||||
#### 医疗HIS业务逻辑参考标准
|
||||
|
||||
| 标准/规范 | 适用模块 | 获取途径 |
|
||||
|----------|---------|---------|
|
||||
| 三级医院评审标准(2022版) | 全量 | 卫健委官网 |
|
||||
| 电子病历应用水平分级评价 | 电子病历/质控 | 卫健委官网 |
|
||||
| 互联互通标准化成熟度测评 | ESB/集成平台 | 卫健委官网 |
|
||||
| 医保基金使用监督管理条例 | 医保审核/结算 | 医保局官网 |
|
||||
| HL7 FHIR R4 | 数据交换/ESB | hl7.org |
|
||||
| 处方管理办法 | 合理用药/处方 | 卫健委官网 |
|
||||
| 抗菌药物临床应用管理办法 | 抗菌药物管理 | 卫健委官网 |
|
||||
| 医院感染管理办法 | 院感管理 | 卫健委官网 |
|
||||
| 病案管理与质量控制标准 | 病案管理 | 卫健委官网 |
|
||||
|
||||
#### 设计文档模板
|
||||
|
||||
```
|
||||
# 模块名 设计文档
|
||||
|
||||
## 1. 业务背景
|
||||
- 依据什么标准/规范
|
||||
- 解决什么业务问题
|
||||
|
||||
## 2. 业务流程
|
||||
### 2.1 正常流程
|
||||
[流程描述/流程图]
|
||||
|
||||
### 2.2 异常流程
|
||||
[异常场景及处理方式]
|
||||
|
||||
### 2.3 边界场景
|
||||
[特殊情况处理]
|
||||
|
||||
## 3. 状态流转
|
||||
| 状态 | 值 | 触发条件 | 下一状态 |
|
||||
|------|-----|---------|---------|
|
||||
|
||||
## 4. 业务规则
|
||||
| 规则编号 | 规则名称 | 规则描述 | 触发时机 |
|
||||
|---------|---------|---------|---------|
|
||||
|
||||
## 5. 数据模型
|
||||
[实体关系图/表结构设计]
|
||||
|
||||
## 6. 接口设计
|
||||
[API列表+参数+返回值]
|
||||
|
||||
## 7. 前端页面设计
|
||||
[UI布局+交互+调用流程]
|
||||
|
||||
## 8. 测试用例
|
||||
[关键业务场景测试]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 铁律 #10: 设计文档必须包含UI设计和调用流程
|
||||
|
||||
**所有新模块/页面的设计文档必须包含以下要素,缺一不可:**
|
||||
|
||||
#### 必备要素
|
||||
|
||||
| # | 要素 | 说明 |
|
||||
|---|------|------|
|
||||
| 1 | 页面UI布局 | 每个区域放什么组件、尺寸比例、栅格布局(文字描述或线框图) |
|
||||
| 2 | 交互效果清单 | 每个按钮/操作触发什么效果(弹窗、抽屉、跳转、动画) |
|
||||
| 3 | 前后端调用流程 | 每个用户操作 → 对应API → 参数 → 返回数据 → 前端渲染 |
|
||||
| 4 | 系统调用关系 | Controller → AppService → Service → Mapper 完整链路 |
|
||||
| 5 | 方法函数调用关系 | 关键方法签名、参数、返回值、异常处理 |
|
||||
| 6 | 状态流转图 | 数据状态变化 → UI如何响应 |
|
||||
| 7 | 异常/边界处理 | 空数据、加载中、错误状态的UI表现 |
|
||||
|
||||
#### 前后端调用流程模板
|
||||
|
||||
```
|
||||
用户操作: [具体按钮/操作]
|
||||
→ 前端: [HTTP方法] [API路径] {参数}
|
||||
→ 后端: Controller.method() → AppService.method() → Service.method() → Mapper.method()
|
||||
→ 返回: {code, msg, data}
|
||||
→ 前端: [渲染逻辑]
|
||||
```
|
||||
|
||||
#### 详细规范
|
||||
参见 `MD/specs/UI_DESIGN_IRON_RULES.md`
|
||||
|
||||
|
||||
### 铁律18: 禁止破坏原有功能(绝对铁律)
|
||||
|
||||
**原则**: 完善增加功能和流程时,绝对不能破坏或者让原有功能不能用。
|
||||
|
||||
**执行要求**:
|
||||
1. **修改已有实体前必须对比**: 用 `git show HEAD~N:./file.java` 对比原始文件,保留所有原有字段和方法
|
||||
2. **新增字段只能追加**: 在实体类末尾追加新字段,不能删除或重命名已有字段
|
||||
3. **新增方法只能追加**: 在Service接口末尾追加新方法,不能修改已有方法签名
|
||||
4. **SQL迁移只能ADD**: Flyway迁移脚本只允许 `ALTER TABLE ADD COLUMN`,不允许 `DROP COLUMN` 或 `RENAME COLUMN`
|
||||
5. **Controller新端点**: 新增 `@PostMapping` / `@GetMapping`,不能修改已有端点的路径或参数
|
||||
6. **前端新页面**: 新增页面目录,不能修改已有页面的组件结构
|
||||
7. **编译必须通过**: 每次修改后必须 `mvn clean compile -DskipTests` 验证
|
||||
8. **回归验证**: 修改后检查所有引用该类/方法的文件是否仍能编译
|
||||
|
||||
**违规判定**: 如果因为本次修改导致原有代码编译失败或运行报错,视为违反铁律18,必须立即回滚修复。
|
||||
|
||||
**铁律编号**: 18
|
||||
**优先级**: P0(绝对)
|
||||
**适用范围**: 全项目
|
||||
91
MD/specs/ORDER_MANAGEMENT_DESIGN.md
Normal file
91
MD/specs/ORDER_MANAGEMENT_DESIGN.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# 医嘱管理模块设计文档
|
||||
|
||||
> **文档类型**: 业务设计
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **依据标准**: 《三级医院评审标准(2022版)》医嘱管理制度
|
||||
|
||||
---
|
||||
|
||||
## 一、业务背景
|
||||
|
||||
医嘱管理是住院诊疗的核心环节。依据《病历书写基本规范》和《处方管理办法》,医嘱必须经过开具→审核→执行→完成的完整闭环。
|
||||
|
||||
---
|
||||
|
||||
## 二、状态流转
|
||||
|
||||
### 2.1 医嘱状态机
|
||||
|
||||
```
|
||||
新开(0) → 已签发(1) → 执行中(2) → 已完成(3)
|
||||
↓
|
||||
已停止(4) → 已取消停嘱(恢复)(2)
|
||||
↓
|
||||
已签退(5)
|
||||
```
|
||||
|
||||
| 状态 | 值 | 触发条件 | 允许操作 |
|
||||
|------|-----|---------|---------|
|
||||
| 新开 | 0 | 医生新开医嘱 | 签发/删除 |
|
||||
| 已签发 | 1 | 医生签发 | 护士执行/签退 |
|
||||
| 执行中 | 2 | 护士开始执行 | 停止/完成 |
|
||||
| 已完成 | 3 | 执行完毕 | 查看 |
|
||||
| 已停止 | 4 | 医生停止医嘱 | 恢复(取消停嘱) |
|
||||
| 已签退 | 5 | 护士签退 | 查看 |
|
||||
|
||||
---
|
||||
|
||||
## 三、业务规则
|
||||
|
||||
| 规则编号 | 规则名称 | 规则描述 | 触发时机 |
|
||||
|---------|---------|---------|---------|
|
||||
| OR-001 | 长期医嘱停止时限 | 长期医嘱停止必须在执行时间之前2小时 | 停止医嘱时 |
|
||||
| OR-002 | 用药医嘱审核 | 用药医嘱必须经过合理用药系统审核 | 签发用药医嘱时 |
|
||||
| OR-003 | 医嘱查对 | 执行医嘱前必须双人查对 | 护士执行时 |
|
||||
| OR-004 | 紧急医嘱标识 | 紧急医嘱需要特殊标识和优先执行 | 开具医嘱时 |
|
||||
| OR-005 | 医嘱修改限制 | 已签发的医嘱不能修改,只能停止后新开 | 修改医嘱时 |
|
||||
| OR-006 | 皮试医嘱联动 | 需要皮试的药物必须关联皮试医嘱 | 开具需皮试药物时 |
|
||||
|
||||
---
|
||||
|
||||
## 四、前后端交互时序
|
||||
|
||||
### 4.1 签发医嘱
|
||||
```
|
||||
用户操作: 医生点击"签发医嘱"
|
||||
→ 前端: 收集选中医嘱列表
|
||||
→ API: POST /reg-doctorstation/advice-manage/sign-reg-advice
|
||||
→ 后端: AdviceManageController.signRegAdvice()
|
||||
→ 校验医嘱状态必须为"新开"(OR-005)
|
||||
→ 用药医嘱调用合理用药系统审核(OR-002)
|
||||
→ 设置签发时间+签发人
|
||||
→ 更新状态=已签发(1)
|
||||
→ 返回: {code:200, msg:"签发成功"}
|
||||
→ 前端: 刷新医嘱列表
|
||||
```
|
||||
|
||||
### 4.2 停止医嘱
|
||||
```
|
||||
用户操作: 医生点击"停止医嘱"
|
||||
→ 前端: 弹出确认框+填写停嘱原因
|
||||
→ API: POST /reg-doctorstation/advice-manage/stop-reg-advice
|
||||
→ 后端: 校验医嘱状态必须为"执行中"
|
||||
→ 长期医嘱校验停止时限(OR-001)
|
||||
→ 设置停嘱时间+停嘱原因
|
||||
→ 更新状态=已停止(4)
|
||||
→ 返回: {code:200, msg:"停嘱成功"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、测试用例
|
||||
|
||||
| 用例编号 | 场景 | 预期结果 |
|
||||
|---------|------|---------|
|
||||
| TC-O001 | 正常签发流程 | 新开→签发→执行→完成 |
|
||||
| TC-O002 | 签发后修改 | 返回"已签发医嘱不能修改" |
|
||||
| TC-O003 | 停止后恢复 | 已停止→恢复→执行中 |
|
||||
| TC-O004 | 用药审核拦截 | 有相互作用的药物签发时被拦截 |
|
||||
| TC-O005 | 紧急医嘱优先 | 紧急医嘱在列表中高亮显示 |
|
||||
|
||||
223
MD/specs/PLAYWRIGHT_TESTING_PLAN.md
Executable file
223
MD/specs/PLAYWRIGHT_TESTING_PLAN.md
Executable file
@@ -0,0 +1,223 @@
|
||||
# HIS项目 Playwright E2E 自动化测试方案 v1.0
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: E2E测试
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 一、方案概述
|
||||
|
||||
### 1.1 选型理由
|
||||
- **Playwright** 是微软开源的端到端测试框架,完美适配 Vue 3 + Vite 技术栈
|
||||
- 自动等待机制适合HIS系统复杂交互场景(异步加载、动态渲染)
|
||||
- 支持多浏览器(Chromium/Firefox/WebKit),CI/CD集成成熟
|
||||
- 已有 `@playwright/test ^1.58.2` 依赖 installed
|
||||
|
||||
### 1.2 目标
|
||||
1. 核心业务流程自动化覆盖率达到 80%+
|
||||
2. 已修复Bug 100% 回归测试覆盖
|
||||
3. 每次代码推送自动触发测试,失败阻断发布
|
||||
|
||||
## 二、项目结构
|
||||
|
||||
```
|
||||
healthlink-his-ui/
|
||||
├── tests/
|
||||
│ ├── e2e/
|
||||
│ │ ├── fixtures/ # 测试夹具
|
||||
│ │ │ └── auth.ts # 登录认证fixture
|
||||
│ │ ├── pages/ # 页面对象模型(POM)
|
||||
│ │ │ ├── LoginPage.ts
|
||||
│ │ │ ├── DoctorStationPage.ts
|
||||
│ │ │ └── SurgeryBillingPage.ts
|
||||
│ │ ├── specs/ # 测试用例
|
||||
│ │ │ ├── login.spec.ts
|
||||
│ │ │ ├── doctor-station.spec.ts
|
||||
│ │ │ ├── surgery-billing.spec.ts
|
||||
│ │ │ └── bug-regression.spec.ts # Bug回归测试
|
||||
│ │ └── utils/
|
||||
│ │ └── test-data.ts # 测试数据
|
||||
│ └── playwright.config.ts # Playwright配置
|
||||
├── .env.test # 测试环境变量
|
||||
└── package.json # 已有playwright依赖
|
||||
```
|
||||
|
||||
## 三、环境配置
|
||||
|
||||
### 3.1 环境变量(.env.test)
|
||||
```bash
|
||||
# 测试环境配置
|
||||
VITE_APP_BASE_API=http://192.168.110.253:8080
|
||||
TEST_USERNAME=test_admin
|
||||
TEST_PASSWORD=test123456
|
||||
TEST_BASE_URL=http://localhost:80
|
||||
```
|
||||
|
||||
### 3.2 Playwright配置(playwright.config.ts)
|
||||
```typescript
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests/e2e/specs',
|
||||
timeout: 60 * 1000,
|
||||
expect: { timeout: 10000 },
|
||||
fullyParallel: false,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: 1,
|
||||
reporter: [['html', { outputFolder: 'playwright-report' }], ['list']],
|
||||
use: {
|
||||
baseURL: process.env.TEST_BASE_URL || 'http://localhost:80',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
video: 'retain-on-failure',
|
||||
},
|
||||
projects: [
|
||||
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 四、核心测试用例
|
||||
|
||||
### 4.1 登录测试(login.spec.ts)
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('用户登录成功', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.fill('input[placeholder="请输入用户名"]', process.env.TEST_USERNAME || 'admin');
|
||||
await page.fill('input[placeholder="请输入密码"]', process.env.TEST_PASSWORD || '123456');
|
||||
await page.click('button:has-text("登录")');
|
||||
await expect(page).toHaveURL(/.*dashboard.*/);
|
||||
await expect(page.locator('.user-avatar')).toBeVisible();
|
||||
});
|
||||
|
||||
test('登录失败-错误密码', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.fill('input[placeholder="请输入用户名"]', 'admin');
|
||||
await page.fill('input[placeholder="请输入密码"]', 'wrongpassword');
|
||||
await page.click('button:has-text("登录")');
|
||||
await expect(page.locator('.el-message--error')).toBeVisible();
|
||||
});
|
||||
```
|
||||
|
||||
### 4.2 门诊医生站测试(doctor-station.spec.ts)
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('门诊医生站', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// 登录
|
||||
await page.goto('/');
|
||||
await page.fill('input[placeholder="请输入用户名"]', process.env.TEST_USERNAME || 'admin');
|
||||
await page.fill('input[placeholder="请输入密码"]', process.env.TEST_PASSWORD || '123456');
|
||||
await page.click('button:has-text("登录")');
|
||||
await page.waitForURL(/.*dashboard.*/);
|
||||
});
|
||||
|
||||
test('#427 检查项目分类手风琴展开', async ({ page }) => {
|
||||
await page.goto('/doctorstation');
|
||||
// 点击第一个分类
|
||||
await page.click('.category-item >> nth=0');
|
||||
await expect(page.locator('.category-content >> nth=0')).toBeVisible();
|
||||
// 点击第二个分类,第一个应收起
|
||||
await page.click('.category-item >> nth=1');
|
||||
await expect(page.locator('.category-content >> nth=0')).not.toBeVisible();
|
||||
await expect(page.locator('.category-content >> nth=1')).toBeVisible();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 4.3 手术计费回归测试(bug-regression.spec.ts)
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Bug回归测试', () => {
|
||||
test('#437 手术计费防重复提交', async ({ page }) => {
|
||||
// 登录并导航到手术计费
|
||||
await page.goto('/');
|
||||
await page.fill('input[placeholder="请输入用户名"]', process.env.TEST_USERNAME || 'admin');
|
||||
await page.fill('input[placeholder="请输入密码"]', process.env.TEST_PASSWORD || '123456');
|
||||
await page.click('button:has-text("登录")');
|
||||
await page.waitForURL(/.*dashboard.*/);
|
||||
await page.goto('/surgery-billing');
|
||||
|
||||
// 快速连续点击新增按钮(测试防重复锁)
|
||||
const addBtn = page.locator('button:has-text("新增")');
|
||||
await addBtn.click();
|
||||
await addBtn.click(); // 第二次应被阻止
|
||||
await addBtn.click(); // 第三次应被阻止
|
||||
|
||||
// 验证只弹出一个表单
|
||||
await expect(page.locator('.el-dialog')).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 五、执行命令
|
||||
|
||||
```bash
|
||||
# 安装浏览器
|
||||
npx playwright install chromium
|
||||
|
||||
# 运行所有测试
|
||||
npm run test:e2e
|
||||
|
||||
# 运行单个测试文件
|
||||
npx playwright test login.spec.ts
|
||||
|
||||
# 生成HTML报告
|
||||
npx playwright show-report
|
||||
|
||||
# UI模式(调试用)
|
||||
npx playwright test --ui
|
||||
```
|
||||
|
||||
## 六、CI/CD集成
|
||||
|
||||
### 6.1 package.json脚本
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:ui": "playwright test --ui",
|
||||
"test:e2e:report": "playwright show-report"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 Spug流水线集成
|
||||
```yaml
|
||||
# Spug 构建后阶段添加
|
||||
- name: E2E Testing
|
||||
script: |
|
||||
cd healthlink-his-ui
|
||||
npx playwright install --with-deps chromium
|
||||
npm run test:e2e -- --reporter=html
|
||||
# 测试失败则阻断发布
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "E2E测试失败,阻断发布!"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
## 七、实施计划
|
||||
|
||||
| 阶段 | 时间 | 内容 | 负责人 |
|
||||
|------|------|------|--------|
|
||||
| Phase 1 | 第1周 | 登录+核心页面冒烟测试 | 张飞+赵云 |
|
||||
| Phase 2 | 第2-3周 | 门诊医生站+手术计费全流程 | 张飞 |
|
||||
| Phase 3 | 第4周 | Bug回归测试全覆盖 | 张飞 |
|
||||
| Phase 4 | 第5周 | CI/CD流水线集成 | 赵云+运维 |
|
||||
|
||||
## 八、注意事项
|
||||
|
||||
1. **测试数据隔离**:使用独立的测试数据库,不污染生产数据
|
||||
2. **环境变量**:敏感信息通过 `.env.test` 管理,不提交到git
|
||||
3. **截图留痕**:失败时自动截图,便于排查
|
||||
4. **测试优先**:新功能开发时同步编写测试用例
|
||||
290
MD/specs/PREOP_DISCUSSION_DESIGN.md
Normal file
290
MD/specs/PREOP_DISCUSSION_DESIGN.md
Normal file
@@ -0,0 +1,290 @@
|
||||
# 术前讨论记录模块设计文档
|
||||
|
||||
> **文档类型**: 深度业务设计
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **三甲依据**: 《三级医院评审标准(2022版)》手术分级管理制度 — 三级/四级手术必须有术前讨论记录
|
||||
> **评审条款**: 现场检查必查项,缺失则一票否决
|
||||
|
||||
---
|
||||
|
||||
## 一、业务背景
|
||||
|
||||
### 1.1 为什么要术前讨论?
|
||||
术前讨论是手术安全管理的核心制度。依据《医疗质量安全核心制度要点》(2018版):
|
||||
- **三级手术**:必须有术前讨论,由副主任医师及以上主持
|
||||
- **四级手术**:必须有科内讨论+全科讨论,由科主任主持
|
||||
- 术前讨论记录是病历的必要组成部分,评审专家现场必查
|
||||
|
||||
### 1.2 当前系统差距
|
||||
当前系统已有手术管理模块(申请→审批→安排→执行),但缺少**术前讨论记录**这一关键环节。评审时如果手术病历中没有术前讨论记录,将被判定为不合格。
|
||||
|
||||
### 1.3 参考标准
|
||||
- 《医疗质量安全核心制度要点》(2018版)第5条:术前讨论制度
|
||||
- 《病历书写基本规范》(2010版):手术记录要求
|
||||
- 《三级医院评审标准(2022版)》:手术质量安全核心指标
|
||||
- 《手术分级管理办法》:手术分级与讨论要求对应关系
|
||||
|
||||
---
|
||||
|
||||
## 二、完整业务流程
|
||||
|
||||
### 2.1 术前讨论全流程
|
||||
|
||||
```
|
||||
医生提交手术申请
|
||||
│
|
||||
▼
|
||||
系统判断手术级别
|
||||
│
|
||||
├── 一级/二级手术 → 无需术前讨论(可选)
|
||||
│
|
||||
└── 三级/四级手术 → 强制要求术前讨论
|
||||
│
|
||||
▼
|
||||
创建术前讨论记录
|
||||
│
|
||||
▼
|
||||
邀请讨论参与者(至少2人)
|
||||
│
|
||||
▼
|
||||
讨论内容录入
|
||||
├── 患者基本信息(自动带入)
|
||||
├── 术前诊断(关联诊断模块)
|
||||
├── 手术名称和指征
|
||||
├── 手术方案(主方案+备选方案)
|
||||
├── 麻醉方式
|
||||
├── 术中可能风险及对策
|
||||
├── 术后注意事项
|
||||
└── 讨论结论(同意手术/需进一步检查/暂不手术)
|
||||
│
|
||||
▼
|
||||
参与者签名(电子签名)
|
||||
│
|
||||
▼
|
||||
主持人审核确认
|
||||
│
|
||||
▼
|
||||
绑定到手术申请
|
||||
│
|
||||
▼
|
||||
手术申请可继续流转(审批→安排→执行)
|
||||
```
|
||||
|
||||
### 2.2 异常流程
|
||||
|
||||
| 场景 | 处理方式 |
|
||||
|------|---------|
|
||||
| 讨论结论为"暂不手术" | 手术申请状态变为"讨论后暂停",需修改后重新讨论 |
|
||||
| 讨论结论为"需进一步检查" | 手术申请状态变为"待补充检查",检查完成后重新讨论 |
|
||||
| 参与者不足(三级手术<2人) | 拦截提交,提示"三级手术术前讨论至少需要2名医师参与" |
|
||||
| 四级手术主持人非科主任 | 拦截提交,提示"四级手术必须由科主任主持讨论" |
|
||||
| 术前讨论记录缺失时尝试安排手术 | 系统拦截,提示"请先完成术前讨论" |
|
||||
|
||||
---
|
||||
|
||||
## 三、状态流转
|
||||
|
||||
### 3.1 术前讨论记录状态
|
||||
|
||||
```
|
||||
草稿(0) → 待签名(1) → 待审核(2) → 已完成(3) → 已归档(4)
|
||||
↓
|
||||
已驳回(5) → 草稿(0)
|
||||
```
|
||||
|
||||
| 状态 | 值 | 触发条件 | 允许操作 |
|
||||
|------|-----|---------|---------|
|
||||
| 草稿 | 0 | 创建讨论记录 | 编辑/删除/提交签名 |
|
||||
| 待签名 | 1 | 提交参与者签名 | 参与者签名 |
|
||||
| 待审核 | 2 | 所有参与者已签名 | 主持人审核 |
|
||||
| 已完成 | 3 | 主持人审核通过 | 绑定手术/查看 |
|
||||
| 已归档 | 4 | 手术完成自动归档 | 查看 |
|
||||
| 已驳回 | 5 | 主持人驳回 | 编辑后重新提交 |
|
||||
|
||||
---
|
||||
|
||||
## 四、业务规则
|
||||
|
||||
| 规则编号 | 规则名称 | 规则描述 | 触发时机 | 处理方式 |
|
||||
|---------|---------|---------|---------|---------|
|
||||
| PD-001 | 三级手术讨论 | 三级手术必须有术前讨论记录 | 手术审批时 | 缺失则拦截 |
|
||||
| PD-002 | 四级手术讨论 | 四级手术必须有科内讨论记录 | 手术审批时 | 缺失则拦截 |
|
||||
| PD-003 | 主持人资质 | 三级手术:副主任医师以上主持 | 创建讨论时 | 自动校验 |
|
||||
| PD-004 | 四级手术主持人 | 四级手术必须由科主任主持 | 创建讨论时 | 自动校验 |
|
||||
| PD-005 | 参与者人数 | 三级手术≥2人,四级手术≥3人 | 提交时 | 不足则拦截 |
|
||||
| PD-006 | 讨论时效 | 术前讨论必须在手术前24小时内完成 | 创建讨论时 | 超时则提醒 |
|
||||
| PD-007 | 电子签名 | 所有参与者必须电子签名 | 审核前 | 未签则拦截 |
|
||||
| PD-008 | 绑定手术 | 讨论完成后自动绑定到对应手术申请 | 审核通过时 | 自动关联 |
|
||||
| PD-009 | 术前诊断一致性 | 讨论中的术前诊断必须与手术申请一致 | 提交审核时 | 不一致则警告 |
|
||||
| PD-010 | 手术方案完整性 | 必须包含主方案+至少一个备选方案 | 提交时 | 缺失则拦截 |
|
||||
|
||||
---
|
||||
|
||||
## 五、数据模型
|
||||
|
||||
### 5.1 术前讨论记录表 `sys_preop_discussion`
|
||||
|
||||
| 字段 | 类型 | 说明 | 必填 |
|
||||
|------|------|------|------|
|
||||
| id | BIGSERIAL | 主键 | ✅ |
|
||||
| encounter_id | BIGINT | 就诊ID | ✅ |
|
||||
| surgery_id | BIGINT | 关联手术申请ID | ✅ |
|
||||
| patient_id | BIGINT | 患者ID | ✅ |
|
||||
| patient_name | VARCHAR(50) | 患者姓名 | ✅ |
|
||||
| discussion_type | INT | 讨论类型(1科内讨论 2全科讨论 3全院讨论) | ✅ |
|
||||
| surgery_level | INT | 手术级别(1/2/3/4) | ✅ |
|
||||
| preop_diagnosis | TEXT | 术前诊断 | ✅ |
|
||||
| surgery_name | VARCHAR(200) | 手术名称 | ✅ |
|
||||
| surgery_indication | TEXT | 手术指征 | ✅ |
|
||||
| main_plan | TEXT | 主手术方案 | ✅ |
|
||||
| backup_plan | TEXT | 备选手术方案 | ✅ |
|
||||
| anesthesia_type | VARCHAR(50) | 麻醉方式 | ✅ |
|
||||
| risks_and_countermeasures | TEXT | 术中可能风险及对策 | ✅ |
|
||||
| postop_notes | TEXT | 术后注意事项 | ✅ |
|
||||
| discussion_conclusion | INT | 讨论结论(1同意手术 2需进一步检查 3暂不手术) | ✅ |
|
||||
| discussion_result | TEXT | 讨论详细结果 | ✅ |
|
||||
| host_user_id | BIGINT | 主持人用户ID | ✅ |
|
||||
| host_user_name | VARCHAR(50) | 主持人姓名 | ✅ |
|
||||
| status | INT | 状态(0草稿 1待签名 2待审核 3已完成 4已归档 5已驳回) | ✅ |
|
||||
| discussion_time | TIMESTAMP | 讨论时间 | ✅ |
|
||||
| discussion_location | VARCHAR(200) | 讨论地点 | ✅ |
|
||||
|
||||
### 5.2 术前讨论参与者表 `sys_preop_discussion_participant`
|
||||
|
||||
| 字段 | 类型 | 说明 | 必填 |
|
||||
|------|------|------|------|
|
||||
| id | BIGSERIAL | 主键 | ✅ |
|
||||
| discussion_id | BIGINT | 关联讨论记录ID | ✅ |
|
||||
| user_id | BIGINT | 参与者用户ID | ✅ |
|
||||
| user_name | VARCHAR(50) | 参与者姓名 | ✅ |
|
||||
| role | VARCHAR(20) | 角色(主持人/参与者/记录人) | ✅ |
|
||||
| title | VARCHAR(50) | 职称(主任医师/副主任医师/主治医师) | ✅ |
|
||||
| sign_status | INT | 签名状态(0未签 1已签) | ✅ |
|
||||
| sign_time | TIMESTAMP | 签名时间 | ✅ |
|
||||
| sign_image | TEXT | 签名图片(base64) | ✅ |
|
||||
| opinion | TEXT | 个人意见 | ❌ |
|
||||
|
||||
---
|
||||
|
||||
## 六、接口设计
|
||||
|
||||
### 6.1 API列表
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| POST | /preop-discussion/add | 创建讨论记录 |
|
||||
| PUT | /preop-discussion/update | 修改讨论记录 |
|
||||
| GET | /preop-discussion/detail | 查看讨论详情 |
|
||||
| GET | /preop-discussion/list | 查询讨论列表 |
|
||||
| DELETE | /preop-discussion/delete | 删除讨论记录(仅草稿) |
|
||||
| PUT | /preop-discussion/submit | 提交讨论(草稿→待签名) |
|
||||
| PUT | /preop-discussion/sign | 参与者签名 |
|
||||
| PUT | /preop-discussion/review | 主持人审核(通过/驳回) |
|
||||
| GET | /preop-discussion/check-required | 检查手术是否需要术前讨论 |
|
||||
| GET | /preop-discussion/statistics | 讨论统计 |
|
||||
|
||||
### 6.2 核心接口时序
|
||||
|
||||
#### 创建术前讨论
|
||||
```
|
||||
前端: 弹出讨论表单 → 自动带入患者/手术信息
|
||||
API: POST /preop-discussion/add
|
||||
后端:
|
||||
1. 校验手术级别(PD-001/PD-002)
|
||||
2. 校验主持人资质(PD-003/PD-004)
|
||||
3. 校验讨论时效(PD-006)
|
||||
4. 保存讨论记录+参与者
|
||||
5. 设置状态=草稿(0)
|
||||
返回: {code:200, data:{discussionId}}
|
||||
```
|
||||
|
||||
#### 主持人审核
|
||||
```
|
||||
前端: 主持人查看讨论内容 → 点击"审核通过"
|
||||
API: PUT /preop-discussion/review
|
||||
后端:
|
||||
1. 校验当前用户是否为主持人
|
||||
2. 校验所有参与者已签名(PD-007)
|
||||
3. 校验参与者人数(PD-005)
|
||||
4. 校验手术方案完整性(PD-010)
|
||||
5. 更新状态=已完成(3)
|
||||
6. 自动绑定到手术申请(PD-008)
|
||||
返回: {code:200, msg:"审核通过"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、前端页面设计
|
||||
|
||||
### 7.1 页面布局
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 术前讨论管理 [新建讨论] │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 搜索区: [患者] [手术级别] [状态] [日期] [搜索] │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 表格: 序号|患者|手术名称|级别|主持人|状态|操作 │
|
||||
│ 1 张三 阑尾切除 三级 李主任 已完成 │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 分页: < 1 2 3 > │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 7.2 新建讨论弹窗(左右布局)
|
||||
```
|
||||
┌──────────────────────────┬────────────────────┐
|
||||
│ 患者信息(自动带入) │ 讨论内容 │
|
||||
│ 姓名: 张三 │ 术前诊断: [____] │
|
||||
│ 住院号: 2026060001 │ 手术指征: [____] │
|
||||
│ 科室: 普外科 │ 主方案: [____] │
|
||||
│ 床号: 12床 │ 备选方案: [____] │
|
||||
│ │ 麻醉方式: [____] │
|
||||
│ 手术信息(自动带入) │ 风险及对策: [____] │
|
||||
│ 手术名称: 阑尾切除术 │ 术后注意: [____] │
|
||||
│ 手术级别: 三级 │ 讨论结论: [单选] │
|
||||
│ 申请医生: 王医生 │ │
|
||||
│ │ 讨论参与者: │
|
||||
│ 讨论信息 │ □ 李主任(主持) │
|
||||
│ 讨论时间: [____] │ □ 赵副主任 │
|
||||
│ 讨论地点: [____] │ □ 孙主治 │
|
||||
│ 讨论类型: [科内讨论] │ │
|
||||
└──────────────────────────┴────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、与手术管理模块的集成
|
||||
|
||||
### 8.1 数据关联
|
||||
```
|
||||
手术申请(Surgery) ──1:N──→ 术前讨论记录(PreopDiscussion)
|
||||
术前讨论记录 ──1:N──→ 参与者(Participant)
|
||||
```
|
||||
|
||||
### 8.2 流程集成
|
||||
- **手术申请提交时**:检查三级/四级手术是否有术前讨论
|
||||
- **手术审批时**:强制校验术前讨论完成状态
|
||||
- **手术安排时**:显示术前讨论结论
|
||||
- **手术完成时**:自动归档术前讨论记录
|
||||
|
||||
### 8.3 手术管理页面改造
|
||||
在手术管理页面的"操作"列增加"术前讨论"按钮:
|
||||
- 三级/四级手术:显示"查看讨论"或"新建讨论"
|
||||
- 一级/二级手术:显示"可选讨论"
|
||||
|
||||
---
|
||||
|
||||
## 九、测试用例
|
||||
|
||||
| 用例编号 | 场景 | 操作步骤 | 预期结果 |
|
||||
|---------|------|---------|---------|
|
||||
| TC-PD001 | 正常创建讨论 | 填写完整信息→保存 | 状态=草稿,可编辑 |
|
||||
| TC-PD002 | 三级手术强制讨论 | 三级手术不创建讨论直接审批 | 拦截,提示"请先完成术前讨论" |
|
||||
| TC-PD003 | 参与者不足 | 三级手术只邀请1人 | 拦截,提示"至少需要2名医师" |
|
||||
| TC-PD004 | 四级手术非科主任主持 | 主治医师主持四级手术讨论 | 拦截,提示"必须由科主任主持" |
|
||||
| TC-PD005 | 签名流程 | 所有参与者签名→主持人审核 | 状态变为已完成 |
|
||||
| TC-PD006 | 驳回后修改 | 主持人驳回→修改→重新提交 | 状态从驳回回到草稿 |
|
||||
| TC-PD007 | 绑定手术 | 讨论完成→关联手术申请 | 手术申请可继续流转 |
|
||||
| TC-PD008 | 讨论时效校验 | 手术前48小时创建讨论 | 警告"请在手术前24小时内完成讨论" |
|
||||
|
||||
210
MD/specs/PROGRESS_NOTES_DESIGN.md
Normal file
210
MD/specs/PROGRESS_NOTES_DESIGN.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# 病程记录模块设计文档
|
||||
|
||||
> **文档类型**: 深度业务设计
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **三甲依据**: 《病历书写基本规范》《电子病历应用管理规范》
|
||||
|
||||
---
|
||||
|
||||
## 一、业务背景
|
||||
|
||||
病程记录是住院病历的核心组成部分,记录患者住院期间的诊疗过程。依据《病历书写基本规范》(2010版):
|
||||
|
||||
### 1.1 病程记录类型及时限要求
|
||||
|
||||
| 记录类型 | 书写时限 | 书写人要求 | 三甲依据 |
|
||||
|---------|---------|-----------|---------|
|
||||
| 首次病程记录 | 入院8小时内 | 住院医师及以上 | 病历书写规范 |
|
||||
| 日常病程记录 | 病危:每天至少1次 | 主治医师及以上 | 病历书写规范 |
|
||||
| | 病重:至少2天1次 | 住院医师及以上 | |
|
||||
| | 一般:至少3天1次 | 住院医师及以上 | |
|
||||
| 上级医师查房记录 | 72小时内 | 主治/副主任/主任医师 | 三级查房制度 |
|
||||
| 疑难病例讨论记录 | 确诊后及时 | 科主任主持 | 疑难病例讨论制度 |
|
||||
| 阶段小结 | 住院超过30天 | 主管医师 | 病历书写规范 |
|
||||
| 抢救记录 | 抢救后6小时内 | 参与抢救医师 | 危重患者抢救制度 |
|
||||
| 转科记录 | 转科前 | 转出科医师 | 转科制度 |
|
||||
| 接收记录 | 转科后 | 接收科医师 | 转科制度 |
|
||||
| 出院记录 | 出院当天 | 主管医师 | 出院管理制度 |
|
||||
| 死亡记录 | 死亡后24小时内 | 主管医师 | 死亡病例讨论制度 |
|
||||
| 死亡病例讨论 | 死亡后7日内 | 科主任主持 | 死亡病例讨论制度 |
|
||||
|
||||
### 1.2 当前系统差距
|
||||
当前系统有电子病历基础模块(模板+录入+签名),但缺少:
|
||||
- 病程记录的**时限监控和预警**
|
||||
- 病程记录的**自动提醒**
|
||||
- 病程记录**完整性检查**
|
||||
- 病程记录**质控统计**
|
||||
|
||||
---
|
||||
|
||||
## 二、完整业务流程
|
||||
|
||||
### 2.1 病程记录生命周期
|
||||
|
||||
```
|
||||
入院
|
||||
│
|
||||
├──→ 首次病程记录(8小时内) ──→ 主治医师审核
|
||||
│
|
||||
├──→ 日常病程记录(按频率) ──→ 上级医师查阅
|
||||
│ ├── 病危:每天1次
|
||||
│ ├── 病重:2天1次
|
||||
│ └── 一般:3天1次
|
||||
│
|
||||
├──→ 上级医师查房记录(72小时内) ──→ 签名
|
||||
│
|
||||
├──→ [可选] 疑难病例讨论记录
|
||||
├──→ [可选] 阶段小结(超过30天)
|
||||
├──→ [可选] 抢救记录(6小时内)
|
||||
├──→ [可选] 转科记录
|
||||
│
|
||||
├──→ 出院记录/死亡记录
|
||||
│
|
||||
└──→ 病历归档
|
||||
```
|
||||
|
||||
### 2.2 时限监控流程
|
||||
|
||||
```
|
||||
系统定时任务(每小时扫描)
|
||||
│
|
||||
▼
|
||||
检查每位住院患者的病程记录
|
||||
│
|
||||
├── 首次病程记录超时(>8小时)
|
||||
│ → 红色预警 → 通知主管医师+科室主任
|
||||
│
|
||||
├── 日常病程记录超时
|
||||
│ → 黄色预警 → 通知主管医师
|
||||
│
|
||||
├── 上级查房记录超时(>72小时)
|
||||
│ → 橙色预警 → 通知上级医师+科室主任
|
||||
│
|
||||
└── 阶段小结超时(>30天)
|
||||
→ 红色预警 → 通知主管医师+医务部
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、数据模型
|
||||
|
||||
### 3.1 病程记录表 `sys_progress_note`
|
||||
|
||||
| 字段 | 类型 | 说明 | 必填 |
|
||||
|------|------|------|------|
|
||||
| id | BIGSERIAL | 主键 | ✅ |
|
||||
| encounter_id | BIGINT | 就诊ID | ✅ |
|
||||
| patient_id | BIGINT | 患者ID | ✅ |
|
||||
| patient_name | VARCHAR(50) | 患者姓名 | ✅ |
|
||||
| note_type | INT | 记录类型(1首次 2日常 3上级查房 4疑难讨论 5阶段小结 6抢救 7转科 8接收 9出院 10死亡) | ✅ |
|
||||
| note_content | TEXT | 记录内容(结构化) | ✅ |
|
||||
| author_user_id | BIGINT | 书写人ID | ✅ |
|
||||
| author_name | VARCHAR(50) | 书写人姓名 | ✅ |
|
||||
| author_title | VARCHAR(50) | 书写人职称 | ✅ |
|
||||
| review_user_id | BIGINT | 审核人ID(上级查房等) | ❌ |
|
||||
| review_user_name | VARCHAR(50) | 审核人姓名 | ❌ |
|
||||
| sign_status | INT | 签名状态(0未签 1已签) | ✅ |
|
||||
| sign_time | TIMESTAMP | 签名时间 | ❌ |
|
||||
| deadline | TIMESTAMP | 时限要求(系统自动计算) | ✅ |
|
||||
| is_overdue | BOOLEAN | 是否超时 | ✅ |
|
||||
| overdue_hours | INT | 超时小时数 | ❌ |
|
||||
| template_id | BIGINT | 使用的模板ID | ❌ |
|
||||
| version | INT | 版本号 | ✅ |
|
||||
|
||||
### 3.2 病程记录提醒表 `sys_progress_note_reminder`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | BIGSERIAL | 主键 |
|
||||
| encounter_id | BIGINT | 就诊ID |
|
||||
| patient_name | VARCHAR(50) | 患者姓名 |
|
||||
| note_type | INT | 需要书写的记录类型 |
|
||||
| deadline | TIMESTAMP | 截止时间 |
|
||||
| status | INT | 状态(0待书写 1已书写 2已超时 3已提醒) |
|
||||
| remind_user_id | BIGINT | 提醒对象 |
|
||||
| remind_user_name | VARCHAR(50) | 提醒对象姓名 |
|
||||
| created_time | TIMESTAMP | 创建时间 |
|
||||
|
||||
---
|
||||
|
||||
## 四、业务规则
|
||||
|
||||
| 规则编号 | 规则名称 | 规则描述 | 时限 |
|
||||
|---------|---------|---------|------|
|
||||
| PN-001 | 首次病程记录 | 入院后必须在8小时内完成 | 8小时 |
|
||||
| PN-002 | 日常病程(病危) | 病危患者每天至少记录1次 | 24小时 |
|
||||
| PN-003 | 日常病程(病重) | 病重患者至少2天记录1次 | 48小时 |
|
||||
| PN-004 | 日常病程(一般) | 一般患者至少3天记录1次 | 72小时 |
|
||||
| PN-005 | 上级查房记录 | 入院72小时内必须有上级医师查房记录 | 72小时 |
|
||||
| PN-006 | 阶段小结 | 住院超过30天必须有阶段小结 | 30天 |
|
||||
| PN-007 | 抢救记录 | 抢救后6小时内必须完成 | 6小时 |
|
||||
| PN-008 | 出院记录 | 出院当天必须完成 | 当天 |
|
||||
| PN-009 | 死亡记录 | 死亡后24小时内完成 | 24小时 |
|
||||
| PN-010 | 死亡讨论 | 死亡后7日内完成讨论 | 7天 |
|
||||
| PN-011 | 时限预警 | 超过时限前2小时自动提醒 | -2小时 |
|
||||
| PN-012 | 超时上报 | 超过时限未完成自动上报科室主任 | 超时后 |
|
||||
|
||||
---
|
||||
|
||||
## 五、与现有模块的集成
|
||||
|
||||
### 5.1 与电子病历模块集成
|
||||
- 病程记录使用电子病历的模板引擎
|
||||
- 病程记录使用电子病历的签名机制
|
||||
- 病程记录归档到电子病历系统
|
||||
|
||||
### 5.2 与护理评估集成
|
||||
- 病危/病重标记由护理评估模块更新
|
||||
- 标记变化自动调整病程记录频率
|
||||
|
||||
### 5.3 与病案管理集成
|
||||
- 出院时自动检查病程记录完整性
|
||||
- 缺失记录的病案不允许归档
|
||||
|
||||
---
|
||||
|
||||
## 六、前端页面设计
|
||||
|
||||
### 6.1 病程记录列表页
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ 病程记录管理 [新建记录] [时限监控面板] │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ 时限监控面板(顶部): │
|
||||
│ 🔴 超时未完成: 3条 ⚠️ 即将超时: 5条 ✅ 正常: 42条│
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ 搜索: [患者] [记录类型] [书写人] [日期] [搜索] │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ 表格: 患者|类型|内容摘要|书写人|时限|状态|操作 │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ 分页 │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 6.2 时限监控面板
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ 当前住院患者病程记录监控 │
|
||||
├────────┬──────┬──────┬──────┬──────┬──────────────┤
|
||||
│ 患者 │ 病情 │ 已记录│ 待记录│ 超时 │ 操作 │
|
||||
├────────┼──────┼──────┼──────┼──────┼──────────────┤
|
||||
│ 张三 │ 病危 │ 5/5 │ 0 │ 0 │ [查看] │
|
||||
│ 李四 │ 一般 │ 2/3 │ 1 │ 0 │ [催促书写] │
|
||||
│ 王五 │ 病重 │ 1/2 │ 1 │ 1 │ [上报超时] │
|
||||
└────────┴──────┴──────┴──────┴──────┴──────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、测试用例
|
||||
|
||||
| 用例编号 | 场景 | 预期结果 |
|
||||
|---------|------|---------|
|
||||
| TC-PN001 | 首次病程记录8小时提醒 | 入院6小时后黄色预警,8小时后红色预警 |
|
||||
| TC-PN002 | 日常病程记录频率 | 病危患者24小时未记录,系统自动提醒 |
|
||||
| TC-PN003 | 上级查房记录 | 入院72小时内无上级查房记录,上报科室主任 |
|
||||
| TC-PN004 | 阶段小结 | 住院30天无阶段小结,红色预警+上报医务部 |
|
||||
| TC-PN005 | 出院病程完整性 | 出院时检查所有病程记录是否完整 |
|
||||
| TC-PN006 | 超时统计 | 科室/全院病程记录超时率统计 |
|
||||
|
||||
608
MD/specs/RECONSTRUCTION_3D_DEEP_DESIGN.md
Normal file
608
MD/specs/RECONSTRUCTION_3D_DEEP_DESIGN.md
Normal file
@@ -0,0 +1,608 @@
|
||||
# 影像3D重建 — 深度技术设计文档
|
||||
|
||||
> **文档类型**: 深度技术设计
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-07
|
||||
> **技术栈**: Cornerstone.js(DICOM解析) + VTK.js(3D渲染) + Spring Boot(后端处理)
|
||||
|
||||
---
|
||||
|
||||
## 一、技术选型分析
|
||||
|
||||
### 1.1 前端3D渲染方案对比
|
||||
|
||||
| 方案 | 优点 | 缺点 | 推荐度 |
|
||||
|------|------|------|--------|
|
||||
| **Cornerstone.js + VTK.js** | 专为医学影像设计,DICOM原生支持,WebGL GPU加速 | 学习曲线较陡 | ⭐⭐⭐⭐⭐ |
|
||||
| **Three.js** | 通用3D引擎,社区大 | 无DICOM支持,需自行解析 | ⭐⭐⭐ |
|
||||
| **OHIF Viewer** | 完整PACS查看器 | 太重,集成复杂 | ⭐⭐⭐ |
|
||||
| **MITK** | 功能全面的医学影像工具包 | C++为主,Web支持弱 | ⭐⭐ |
|
||||
|
||||
**推荐方案**: Cornerstone.js + VTK.js
|
||||
- **Cornerstone.js**: DICOM图像解析、2D查看、MPR重建
|
||||
- **VTK.js**: 容积渲染(VR)、等值面提取、3D测量
|
||||
|
||||
### 1.2 技术架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 前端 (Vue 3 + Vite) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
|
||||
│ │Cornerstone│ │ VTK.js │ │测量工具栏│ │报告编辑器│ │
|
||||
│ │ DICOM解析 │ │ 3D渲染 │ │距离/角度 │ │所见/印象 │ │
|
||||
│ │ 2D/MPR │ │VR/MIP │ │体积/面积 │ │结论 │ │
|
||||
│ └─────┬────┘ └─────┬────┘ └────┬─────┘ └────┬────┘ │
|
||||
│ └─────────────┴────────────┴──────────────┘ │
|
||||
│ ↓ HTTP/REST API │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 后端 (Spring Boot 4.0.6) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
|
||||
│ │DICOM解析 │ │任务调度 │ │结果存储 │ │PACS对接 │ │
|
||||
│ │dcm4che │ │异步处理 │ │MinIO/NFS │ │WADO-RS │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 存储层 │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │PostgreSQL │ │文件存储 │ │PACS系统 │ │
|
||||
│ │ 元数据 │ │MinIO/NFS │ │DICOM节点 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、后端深度设计
|
||||
|
||||
### 2.1 DICOM解析服务
|
||||
|
||||
#### 2.1.1 dcm4che集成
|
||||
|
||||
```java
|
||||
// DICOM文件解析流程
|
||||
public class DicomParserService {
|
||||
|
||||
// 解析DICOM文件元数据
|
||||
public DicomMetadata parseDicomFile(InputStream dicomStream) {
|
||||
// 1. 使用dcm4che读取DICOM文件
|
||||
Dataset ds = DicomInputStream.read(dicomStream);
|
||||
|
||||
// 2. 提取关键元数据
|
||||
DicomMetadata metadata = new DicomMetadata();
|
||||
metadata.setPatientName(ds.getString(Tag.PatientName)); // 患者姓名
|
||||
metadata.setPatientId(ds.getString(Tag.PatientID)); // 患者ID
|
||||
metadata.setStudyInstanceUID(ds.getString(Tag.StudyInstanceUID)); // 检查UID
|
||||
metadata.setSeriesInstanceUID(ds.getString(Tag.SeriesInstanceUID)); // 序列UID
|
||||
metadata.setSopInstanceUID(ds.getString(Tag.SOPInstanceUID)); // 实例UID
|
||||
metadata.setModality(ds.getString(Tag.Modality)); // CT/MRI/US
|
||||
metadata.setStudyDate(ds.getString(Tag.StudyDate)); // 检查日期
|
||||
metadata.setBodyPartExamined(ds.getString(Tag.BodyPartExamined)); // 检查部位
|
||||
metadata.setImageOrientationPatient(ds.getStrings(Tag.ImageOrientationPatient)); // 图像方向
|
||||
metadata.setImagePositionPatient(ds.getStrings(Tag.ImagePositionPatient)); // 图像位置
|
||||
metadata.setPixelSpacing(ds.getStrings(Tag.PixelSpacing)); // 像素间距
|
||||
metadata.setSliceThickness(ds.getString(Tag.SliceThickness)); // 层厚
|
||||
metadata.setRows(ds.getInt(Tag.Rows)); // 行数
|
||||
metadata.setColumns(ds.getInt(Tag.Columns)); // 列数
|
||||
metadata.setBitsAllocated(ds.getInt(Tag.BitsAllocated)); // 位深
|
||||
metadata.setWindowCenter(ds.getString(Tag.WindowCenter)); // 窗位
|
||||
metadata.setWindowWidth(ds.getString(Tag.WindowWidth)); // 窗宽
|
||||
|
||||
// 3. 提取像素数据
|
||||
byte[] pixelData = ds.getBytes(Tag.PixelData);
|
||||
metadata.setPixelData(pixelData);
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
// 批量解析同一Series的所有DICOM文件
|
||||
public List<DicomMetadata> parseSeries(List<InputStream> dicomFiles) {
|
||||
List<DicomMetadata> series = new ArrayList<>();
|
||||
for (InputStream file : dicomFiles) {
|
||||
series.add(parseDicomFile(file));
|
||||
}
|
||||
// 按ImagePositionPatient排序(确保层序正确)
|
||||
series.sort(Comparator.comparing(m ->
|
||||
Double.parseDouble(m.getImagePositionPatient()[2])));
|
||||
return series;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.1.2 3D重建处理服务
|
||||
|
||||
```java
|
||||
// 3D重建处理服务
|
||||
@Service
|
||||
public class ReconstructionProcessingService {
|
||||
|
||||
@Async("reconstructionExecutor")
|
||||
public void processReconstruction(Long taskId) {
|
||||
// 1. 获取任务信息
|
||||
ReconstructionTask task = taskMapper.selectById(taskId);
|
||||
task.setTaskStatus("PROCESSING");
|
||||
taskMapper.updateById(task);
|
||||
|
||||
try {
|
||||
// 2. 加载DICOM序列数据
|
||||
List<DicomMetadata> series = loadDicomSeries(task.getApplyId());
|
||||
|
||||
// 3. 预处理: 去噪 + 窗宽窗位调整
|
||||
float[][][] volumeData = preprocessVolume(series);
|
||||
|
||||
// 4. 根据重建类型执行
|
||||
switch (task.getReconstructionType()) {
|
||||
case "VR": // 容积渲染
|
||||
processVolumeRendering(task, volumeData);
|
||||
break;
|
||||
case "MPR": // 多平面重建
|
||||
processMPR(task, volumeData);
|
||||
break;
|
||||
case "MIP": // 最大密度投影
|
||||
processMIP(task, volumeData);
|
||||
break;
|
||||
case "VR+MPR": // 混合重建
|
||||
processVolumeRendering(task, volumeData);
|
||||
processMPR(task, volumeData);
|
||||
break;
|
||||
}
|
||||
|
||||
// 5. 生成结果截图
|
||||
saveResultImages(task);
|
||||
|
||||
// 6. 更新任务状态
|
||||
task.setTaskStatus("COMPLETED");
|
||||
task.setCompleteTime(new Date());
|
||||
task.setResultPath("/reconstruction/" + taskId + "/");
|
||||
taskMapper.updateById(task);
|
||||
|
||||
} catch (Exception e) {
|
||||
task.setTaskStatus("FAILED");
|
||||
taskMapper.updateById(task);
|
||||
log.error("3D重建任务失败: {}", taskId, e);
|
||||
}
|
||||
}
|
||||
|
||||
// 容积渲染(Volume Rendering)
|
||||
private void processVolumeRendering(ReconstructionTask task, float[][][] volume) {
|
||||
// 1. 建立体数据(Volume Data)
|
||||
int dimX = volume.length;
|
||||
int dimY = volume[0].length;
|
||||
int dimZ = volume[0][0].length;
|
||||
|
||||
// 2. 传递函数(Transfer Function)设置
|
||||
// CT值 → 颜色+透明度
|
||||
// 骨骼: 高CT值(>300), 不透明, 白色
|
||||
// 软组织: 中CT值(30-300), 半透明, 粉色
|
||||
// 空气: 低CT值(<-500), 全透明
|
||||
TransferFunction tf = new TransferFunction();
|
||||
tf.addMapping(-1000, 0.0f, 0.0f, 0.0f, 0.0f); // 空气: 全透明
|
||||
tf.addMapping(-500, 0.0f, 0.0f, 0.0f, 0.0f); // 肺: 全透明
|
||||
tf.addMapping(30, 0.8f, 0.2f, 0.2f, 0.4f); // 软组织: 半透明粉红
|
||||
tf.addMapping(300, 0.9f, 0.9f, 0.8f, 0.9f); // 骨骼: 不透明白
|
||||
tf.addMapping(3000, 1.0f, 1.0f, 1.0f, 1.0f); // 金属: 全不透明
|
||||
|
||||
// 3. 光线投射(Ray Casting)算法
|
||||
// 从每个像素发射光线,沿光线采样,累积颜色和透明度
|
||||
// C(积累) = Σ(Ci * αi * Π(1-αj))
|
||||
|
||||
// 4. 保存渲染结果为PNG
|
||||
saveVolumeRenderingResult(task, tf);
|
||||
}
|
||||
|
||||
// 多平面重建(Multi-Planar Reconstruction)
|
||||
private void processMPR(ReconstructionTask task, float[][][] volume) {
|
||||
// 1. 矢状面(Sagittal)重建: 沿X轴切割
|
||||
float[][] sagittalPlane = extractSagittalPlane(volume, volume.length / 2);
|
||||
|
||||
// 2. 冠状面(Coronal)重建: 沿Y轴切割
|
||||
float[][] coronalPlane = extractCoronalPlane(volume, volume[0].length / 2);
|
||||
|
||||
// 3. 轴位(Axial)重建: 沿Z轴切割(原始方向)
|
||||
float[][] axialPlane = extractAxialPlane(volume, volume[0][0].length / 2);
|
||||
|
||||
// 4. 交互式切割: 支持任意角度平面
|
||||
// 通过旋转矩阵变换采样坐标
|
||||
|
||||
saveMPRResult(task, sagittalPlane, coronalPlane, axialPlane);
|
||||
}
|
||||
|
||||
// 最大密度投影(Maximum Intensity Projection)
|
||||
private void processMIP(ReconstructionTask task, float[][][] volume) {
|
||||
int dimX = volume.length;
|
||||
int dimY = volume[0].length;
|
||||
int dimZ = volume[0][0].length;
|
||||
|
||||
float[][] mipImage = new float[dimX][dimY];
|
||||
for (int x = 0; x < dimX; x++) {
|
||||
for (int y = 0; y < dimY; y++) {
|
||||
float maxVal = Float.MIN_VALUE;
|
||||
for (int z = 0; z < dimZ; z++) {
|
||||
maxVal = Math.max(maxVal, volume[x][y][z]);
|
||||
}
|
||||
mipImage[x][y] = maxVal;
|
||||
}
|
||||
}
|
||||
saveMIPResult(task, mipImage);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 DICOM存储方案
|
||||
|
||||
```
|
||||
存储架构:
|
||||
├── PostgreSQL → 元数据(患者/检查/序列/任务/报告)
|
||||
├── MinIO/NFS → DICOM原始文件 + 重建结果(截图/体数据)
|
||||
└── PACS系统 → 通过WADO-RS/DICOMweb获取DICOM图像
|
||||
|
||||
获取DICOM数据流程:
|
||||
1. 任务创建时 → 从PACS获取StudyUID对应的DICOM文件
|
||||
2. 使用WADO-RS协议: GET /dicomweb/studies/{studyUid}/series/{seriesUid}
|
||||
3. 下载到本地临时目录 → 解析 → 处理 → 清理临时文件
|
||||
4. 重建结果保存到MinIO → 元数据保存到PostgreSQL
|
||||
```
|
||||
|
||||
### 2.3 接口设计(完整版)
|
||||
|
||||
| API | 方法 | 说明 | 参数 |
|
||||
|-----|------|------|------|
|
||||
| /reconstruction/task/page | GET | 任务列表(分页+筛选) | patientName,modality,status,pageNo,pageSize |
|
||||
| /reconstruction/task/add | POST | 新建任务(从PACS拉取) | patientId,studyUid,modality,bodyPart,reconstructionType |
|
||||
| /reconstruction/task/{id} | GET | 任务详情 | - |
|
||||
| /reconstruction/task/cancel/{id} | PUT | 取消任务 | - |
|
||||
| /reconstruction/result/list/{taskId} | GET | 重建结果列表 | - |
|
||||
| /reconstruction/result/{id}/image | GET | 获取结果截图 | width,height,window |
|
||||
| /reconstruction/result/{id}/volume | GET | 获取体数据(JSON格式) | resolution |
|
||||
| /reconstruction/report/add | POST | 新建报告 | taskId,findings,impression,conclusion |
|
||||
| /reconstruction/report/{id} | GET | 报告详情 | - |
|
||||
| /reconstruction/report/verify/{id} | PUT | 审核报告 | verifyDoctor |
|
||||
| /reconstruction/stats | GET | 统计概览 | startDate,endDate |
|
||||
|
||||
---
|
||||
|
||||
## 三、前端深度设计
|
||||
|
||||
### 3.1 技术栈
|
||||
|
||||
```json
|
||||
{
|
||||
"cornerstone-core": "^2.6.1", // DICOM图像解析与2D显示
|
||||
"cornerstone-wado-image-loader": "^4.13.2", // WADO加载器
|
||||
"cornerstone-tools": "^7.1.0", // 交互工具(测量/标注)
|
||||
"vtk.js": "^29.0.0", // 3D渲染引擎(WebGL)
|
||||
"dicom-parser": "^1.8.21" // DICOM文件解析
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 组件架构
|
||||
|
||||
```
|
||||
src/views/reconstruction/
|
||||
├── index.vue # 主页面(任务列表+工作台)
|
||||
├── api.js # API接口
|
||||
├── components/
|
||||
│ ├── DicomViewer.vue # 2D DICOM查看器(Cornerstone)
|
||||
│ ├── MprViewer.vue # MPR多平面重建查看器
|
||||
│ ├── VrViewer.vue # VR容积渲染查看器(VTK.js)
|
||||
│ ├── MipViewer.vue # MIP最大密度投影查看器
|
||||
│ ├── MeasurementToolbar.vue # 测量工具栏
|
||||
│ ├── ReconstructionTaskList.vue # 任务列表
|
||||
│ ├── ReconstructionReport.vue # 报告编辑器
|
||||
│ └── ReconstructionStats.vue # 统计面板
|
||||
```
|
||||
|
||||
### 3.3 核心组件实现
|
||||
|
||||
#### DicomViewer.vue (2D DICOM查看器)
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="dicom-viewer">
|
||||
<div ref="viewerContainer" class="viewer-container" />
|
||||
<div class="toolbar">
|
||||
<el-button-group>
|
||||
<el-button @click="setTool('windowing')">窗宽窗位</el-button>
|
||||
<el-button @click="setTool('pan')">平移</el-button>
|
||||
<el-button @click="setTool('zoom')">缩放</el-button>
|
||||
<el-button @click="setTool('length')">距离测量</el-button>
|
||||
<el-button @click="setTool('angle')">角度测量</el-button>
|
||||
<el-button @click="setTool('area')">面积测量</el-button>
|
||||
<el-button @click="setTool('ellipse')">椭圆面积</el-button>
|
||||
<el-button @click="setTool('probe')">CT值探针</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
<div class="info-overlay">
|
||||
<div>Patient: {{ patientInfo.name }}</div>
|
||||
<div>Window: {{ windowCenter }}/{{ windowWidth }}</div>
|
||||
<div>Zoom: {{ zoomLevel }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import * as cornerstoneTools from 'cornerstone-tools'
|
||||
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
|
||||
import dicomParser from 'dicom-parser'
|
||||
|
||||
// 初始化Cornerstone
|
||||
cornerstoneWADOImageLoader.external.dicomParser = dicomParser
|
||||
cornerstoneWADOImageLoader.external.cornerstone = cornerstone
|
||||
|
||||
const viewerContainer = ref(null)
|
||||
let enabledElement = null
|
||||
|
||||
onMounted(() => {
|
||||
// 启用Cornerstone
|
||||
enabledElement = cornerstone.getEnabledElement(viewerContainer.value)
|
||||
cornerstone.enable(viewerContainer.value)
|
||||
|
||||
// 加载DICOM图像
|
||||
loadDicomImage()
|
||||
})
|
||||
|
||||
const loadDicomImage = async () => {
|
||||
const imageId = `wado:${wadoRoot}?requestType=WADO&studyUID=${studyUid}&seriesUID=${seriesUid}&objectUID=${sopUid}`
|
||||
const image = await cornerstone.loadAndCacheImage(imageId)
|
||||
cornerstone.displayImage(enabledElement, image)
|
||||
|
||||
// 启用工具
|
||||
cornerstoneTools.mouseInput.enable(enabledElement)
|
||||
cornerstoneTools.mouseWheelInput.enable(enabledElement)
|
||||
cornerstoneTools.wwwc.activate(enabledElement, 1) // 左键: 窗宽窗位
|
||||
cornerstoneTools.pan.activate(enabledElement, 2) // 右键: 平移
|
||||
cornerstoneTools.zoom.activate(enabledElement, 4) // 中键: 缩放
|
||||
cornerstoneTools.length.enable(enabledElement) // 距离测量
|
||||
cornerstoneTools.angle.enable(enabledElement) // 角度测量
|
||||
cornerstoneTools.ellipseRoi.enable(enabledElement) // 椭圆面积
|
||||
cornerstoneTools.probe.enable(enabledElement) // CT值探针
|
||||
}
|
||||
|
||||
const setTool = (toolName) => {
|
||||
// 切换工具并高亮按钮
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
#### VrViewer.vue (VR容积渲染)
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="vr-viewer">
|
||||
<div ref="vtkContainer" class="vtk-container" />
|
||||
<div class="transfer-function-panel">
|
||||
<div class="preset-buttons">
|
||||
<el-button @click="applyPreset('bone')">骨骼</el-button>
|
||||
<el-button @click="applyPreset('softTissue')">软组织</el-button>
|
||||
<el-button @click="applyPreset('lung')">肺部</el-button>
|
||||
<el-button @click="applyPreset('angio')">血管</el-button>
|
||||
<el-button @click="applyPreset('skin')">皮肤</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import vtkProxyManager from 'vtk.js/Sources/Proxy/ProxyManager'
|
||||
|
||||
let proxyManager = null
|
||||
|
||||
onMounted(() => {
|
||||
initVtk()
|
||||
})
|
||||
|
||||
const initVtk = () => {
|
||||
// 创建VTK ProxyManager
|
||||
proxyManager = vtkProxyManager.newInstance({ container: vtkContainer.value })
|
||||
|
||||
// 加载体数据
|
||||
const source = proxyManager.createProxy('Sources', 'TrivialProducer')
|
||||
source.setInputData(volumeData)
|
||||
|
||||
// 创建VR表示
|
||||
const representation = proxyManager.createProxy('Representations', 'Volume')
|
||||
representation.setInput(source)
|
||||
|
||||
// 设置传递函数
|
||||
const actor = representation.getActor()
|
||||
const property = actor.getProperty()
|
||||
|
||||
// 设置预设
|
||||
applyPreset('bone')
|
||||
}
|
||||
|
||||
const applyPreset = (preset) => {
|
||||
const presets = {
|
||||
bone: [
|
||||
{ value: -1000, opacity: 0, color: [0, 0, 0] },
|
||||
{ value: -300, opacity: 0, color: [0, 0, 0] },
|
||||
{ value: 200, opacity: 0.2, color: [0.8, 0.4, 0.3] },
|
||||
{ value: 500, opacity: 0.8, color: [1, 1, 1] },
|
||||
{ value: 3000, opacity: 1, color: [1, 1, 1] }
|
||||
],
|
||||
softTissue: [
|
||||
{ value: -1000, opacity: 0, color: [0, 0, 0] },
|
||||
{ value: -500, opacity: 0, color: [0, 0, 0] },
|
||||
{ value: 30, opacity: 0.3, color: [0.8, 0.3, 0.3] },
|
||||
{ value: 100, opacity: 0.5, color: [0.9, 0.5, 0.5] },
|
||||
{ value: 300, opacity: 0.8, color: [1, 0.8, 0.7] },
|
||||
{ value: 3000, opacity: 1, color: [1, 1, 1] }
|
||||
],
|
||||
lung: [
|
||||
{ value: -1000, opacity: 0.3, color: [0.2, 0.2, 0.3] },
|
||||
{ value: -700, opacity: 0.1, color: [0.4, 0.4, 0.5] },
|
||||
{ value: -300, opacity: 0.3, color: [0.6, 0.6, 0.7] },
|
||||
{ value: 0, opacity: 0.8, color: [0.8, 0.8, 0.8] },
|
||||
{ value: 3000, opacity: 1, color: [1, 1, 1] }
|
||||
],
|
||||
angio: [
|
||||
{ value: -1000, opacity: 0, color: [0, 0, 0] },
|
||||
{ value: 100, opacity: 0, color: [0, 0, 0] },
|
||||
{ value: 200, opacity: 0.5, color: [1, 0, 0] },
|
||||
{ value: 500, opacity: 0.9, color: [1, 0.2, 0.2] },
|
||||
{ value: 3000, opacity: 1, color: [1, 0.5, 0.5] }
|
||||
],
|
||||
skin: [
|
||||
{ value: -1000, opacity: 0, color: [0, 0, 0] },
|
||||
{ value: -300, opacity: 0, color: [0, 0, 0] },
|
||||
{ value: -100, opacity: 0.2, color: [0.9, 0.7, 0.6] },
|
||||
{ value: 50, opacity: 0.5, color: [0.95, 0.8, 0.7] },
|
||||
{ value: 200, opacity: 0.8, color: [1, 0.9, 0.85] },
|
||||
{ value: 3000, opacity: 1, color: [1, 1, 1] }
|
||||
]
|
||||
}
|
||||
|
||||
// 应用传递函数到VTK actor
|
||||
const preset = presets[preset] || presets.bone
|
||||
applyTransferFunction(preset)
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
#### MeasurementToolbar.vue (测量工具)
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="measurement-toolbar">
|
||||
<el-button-group>
|
||||
<el-tooltip content="距离测量(Ctrl+D)">
|
||||
<el-button :type="activeTool==='length'?'primary':''" @click="activateTool('length')">
|
||||
<el-icon><Ruler /></el-icon> 距离
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="角度测量(Ctrl+A)">
|
||||
<el-button :type="activeTool==='angle'?'primary':''" @click="activateTool('angle')">
|
||||
<el-icon><ScaleToOriginal /></el-icon> 角度
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="面积测量(Ctrl+M)">
|
||||
<el-button :type="activeTool==='area'?'primary':''" @click="activateTool('area')">
|
||||
<el-icon><Grid /></el-icon> 面积
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="CT值探针(Ctrl+P)">
|
||||
<el-button :type="activeTool==='probe'?'primary':''" @click="activateTool('probe')">
|
||||
<el-icon><Position /></el-icon> CT值
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-button-group>
|
||||
|
||||
<!-- 测量结果列表 -->
|
||||
<div class="measurement-results" v-if="measurements.length">
|
||||
<el-table :data="measurements" size="small" border>
|
||||
<el-table-column prop="type" label="类型" width="80"/>
|
||||
<el-table-column prop="value" label="测量值" width="120"/>
|
||||
<el-table-column prop="unit" label="单位" width="60"/>
|
||||
<el-table-column label="操作" width="60">
|
||||
<template #default="{row}">
|
||||
<el-button type="danger" link size="small" @click="removeMeasurement(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import * as cornerstoneTools from 'cornerstone-tools'
|
||||
|
||||
const activeTool = ref('')
|
||||
const measurements = ref([])
|
||||
|
||||
const activateTool = (toolName) => {
|
||||
activeTool.value = toolName
|
||||
|
||||
// 禁用所有工具
|
||||
cornerstoneTools.length.deactivate(enabledElement, 1)
|
||||
cornerstoneTools.angle.deactivate(enabledElement, 1)
|
||||
cornerstoneTools.ellipseRoi.deactivate(enabledElement, 1)
|
||||
cornerstoneTools.probe.deactivate(enabledElement, 1)
|
||||
|
||||
// 激活选中工具
|
||||
switch(toolName) {
|
||||
case 'length':
|
||||
cornerstoneTools.length.activate(enabledElement, 1)
|
||||
break
|
||||
case 'angle':
|
||||
cornerstoneTools.angle.activate(enabledElement, 1)
|
||||
break
|
||||
case 'area':
|
||||
cornerstoneTools.ellipseRoi.activate(enabledElement, 1)
|
||||
break
|
||||
case 'probe':
|
||||
cornerstoneTools.probe.activate(enabledElement, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、数据库设计(补充)
|
||||
|
||||
### 4.1 补充字段
|
||||
|
||||
```sql
|
||||
-- 在reconstruction_task表补充字段
|
||||
ALTER TABLE reconstruction_task ADD COLUMN slice_count INT; -- 层数
|
||||
ALTER TABLE reconstruction_task ADD COLUMN pixel_spacing_x DECIMAL(6,3); -- X像素间距
|
||||
ALTER TABLE reconstruction_task ADD COLUMN pixel_spacing_y DECIMAL(6,3); -- Y像素间距
|
||||
ALTER TABLE reconstruction_task ADD COLUMN table_position VARCHAR(50); -- 床位位置
|
||||
ALTER TABLE reconstruction_task ADD COLUMN kvp INT; -- 管电压
|
||||
ALTER TABLE reconstruction_task ADD COLUMN mas DECIMAL(8,2); -- 管电流时间积
|
||||
|
||||
-- 在reconstruction_result表补充字段
|
||||
ALTER TABLE reconstruction_result ADD COLUMN rendering_time_ms INT; -- 渲染耗时
|
||||
ALTER TABLE reconstruction_result ADD COLUMN file_size_bytes BIGINT; -- 文件大小
|
||||
ALTER TABLE reconstruction_result ADD COLUMN thumbnail_path VARCHAR(500); -- 缩略图
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、部署架构
|
||||
|
||||
```
|
||||
前端构建: npm run build → dist/ → Nginx
|
||||
后端部署: Spring Boot JAR → Docker / 直接运行
|
||||
存储: MinIO(对象存储) / NFS(文件系统)
|
||||
PACS对接: WADO-RS / DICOM C-STORE
|
||||
GPU加速: 前端WebGL(VTK.js自带) / 后端可选CUDA加速(处理大型数据集)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、性能优化策略
|
||||
|
||||
### 6.1 前端优化
|
||||
- **LOD(Level of Detail)**: 根据缩放级别加载不同分辨率
|
||||
- **瓦片加载**: 大图像分块加载,减少内存占用
|
||||
- **Web Worker**: DICOM解析和预处理在Worker线程执行
|
||||
- **缓存策略**: Cornerstone缓存最近查看的图像
|
||||
|
||||
### 6.2 后端优化
|
||||
- **异步处理**: 3D重建任务异步执行,不阻塞请求
|
||||
- **批量解析**: 一次IO读取整个Series的DICOM文件
|
||||
- **结果缓存**: 重建结果缓存到Redis/文件系统
|
||||
- **并行处理**: 多个重建任务并行执行
|
||||
|
||||
### 6.3 存储优化
|
||||
- **压缩存储**: 体数据使用LZ4压缩
|
||||
- **增量保存**: 只保存变化部分
|
||||
- **分层存储**: 热数据SSD,冷数据HDD
|
||||
|
||||
---
|
||||
|
||||
## 七、安全设计
|
||||
|
||||
1. **访问控制**: 只有影像科医生可以发起重建任务
|
||||
2. **数据脱敏**: 患者敏感信息在非工作场景脱敏显示
|
||||
3. **操作审计**: 所有重建操作记录审计日志
|
||||
4. **数据加密**: DICOM文件传输使用HTTPS/TLS
|
||||
5. **权限分级**: 普通医生查看,主治以上审核报告
|
||||
584
MD/specs/RELEASE_CHECKLIST.md
Executable file
584
MD/specs/RELEASE_CHECKLIST.md
Executable file
@@ -0,0 +1,584 @@
|
||||
# HIS项目发布检查清单 v1.0
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
> **适用范围**: 发布流程
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
|
||||
> **文档说明**:本清单整合了提交规范、前端检查、后端检查、CI/CD门禁四个部分,作为HIS项目发布的标准化检查依据。每次发布前必须逐项确认。
|
||||
|
||||
## 目录
|
||||
- [1. 提交规范(commit-template)](#1-提交规范commit-template)
|
||||
- [2. 前端检查(frontend-checklist)](#2-前端检查frontend-checklist)
|
||||
- [3. 后端检查(backend-checklist)](#3-后端检查backend-checklist)
|
||||
- [4. CI/CD门禁(cicd-gatekeeper)](#4-cicd门禁cicd-gatekeeper)
|
||||
- [5. 发布确认与回滚预案](#5-发布确认与回滚预案)
|
||||
|
||||
---
|
||||
|
||||
## 1. 提交规范(commit-template)
|
||||
|
||||
### 📝 PR/Commit 模板
|
||||
|
||||
#### 标题格式
|
||||
```
|
||||
<类型>(<模块>): <简短描述>
|
||||
|
||||
示例:
|
||||
feat(patient): 添加患者基本信息编辑功能
|
||||
fix(doctor): 修复医生排班显示异常问题
|
||||
docs(api): 更新预约挂号接口文档
|
||||
refactor(nurse): 重构护士站护理记录组件
|
||||
```
|
||||
|
||||
#### 正文模板
|
||||
```markdown
|
||||
## 🔍 变更背景
|
||||
- **问题描述**:详细说明要解决的问题或实现的需求
|
||||
- **影响范围**:列出受影响的模块、页面、功能
|
||||
- **相关链接**:禅道任务ID、需求文档链接等
|
||||
|
||||
## 🛠️ 变更内容
|
||||
- **主要修改**:核心代码变更点
|
||||
- **技术方案**:采用的技术方案和设计思路
|
||||
- **兼容性**:是否涉及API或数据结构变更
|
||||
|
||||
## 🗄️ 数据库变更
|
||||
- **表结构变更**:列出新增/修改的表和字段
|
||||
- **数据迁移**:是否需要数据迁移脚本
|
||||
- **回滚方案**:数据库变更的回滚策略
|
||||
|
||||
## ✅ 验证情况
|
||||
- **测试覆盖**:单元测试、集成测试覆盖情况
|
||||
- **手动验证**:手动测试的场景和结果
|
||||
- **构建验证**:本地构建截图(必填)
|
||||
|
||||
## 📋 检查清单
|
||||
- [ ] 代码已通过 ESLint 检查
|
||||
- [ ] 本地构建成功(附截图)
|
||||
- [ ] 核心功能已测试验证
|
||||
- [ ] 文档已同步更新
|
||||
- [ ] Code Review 已完成
|
||||
|
||||
## 👥 相关人员
|
||||
- **开发者**:@开发者姓名
|
||||
- **测试者**:@测试者姓名
|
||||
- **审核人**:@架构师姓名
|
||||
```
|
||||
|
||||
### 🏷️ 提交类型说明
|
||||
|
||||
| 类型 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| feat | 新功能 | `feat: 添加用户登录功能` |
|
||||
| fix | Bug修复 | `fix: 修复表单验证错误` |
|
||||
| docs | 文档更新 | `docs: 更新API文档` |
|
||||
| style | 代码格式调整 | `style: 格式化代码` |
|
||||
| refactor | 代码重构 | `refactor: 重构组件结构` |
|
||||
| test | 测试相关 | `test: 添加单元测试` |
|
||||
| chore | 构建/依赖等 | `chore: 升级依赖版本` |
|
||||
| perf | 性能优化 | `perf: 优化列表加载速度` |
|
||||
|
||||
### 📁 模块命名规范
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| patient | 患者管理相关 |
|
||||
| doctor | 医生工作站相关 |
|
||||
| nurse | 护士站相关 |
|
||||
| admin | 后台管理相关 |
|
||||
| common | 公共组件/工具 |
|
||||
| api | API接口相关 |
|
||||
| auth | 认证授权相关 |
|
||||
| payment | 支付相关 |
|
||||
|
||||
### 🖼️ 构建验证截图要求
|
||||
|
||||
#### 必须包含的信息
|
||||
1. **终端窗口**:显示 `npm run build:prod` 命令执行过程
|
||||
2. **成功标识**:明确显示构建成功的提示信息
|
||||
3. **时间戳**:截图包含当前时间,证明是最新构建
|
||||
4. **分支信息**:显示当前工作分支名称
|
||||
|
||||
### ⚠️ 禁止行为
|
||||
|
||||
#### 严重违规(直接拒绝合并)
|
||||
- 无构建验证截图
|
||||
- 代码存在 ESLint 错误
|
||||
- 未填写变更说明
|
||||
- 修改无关代码文件
|
||||
|
||||
---
|
||||
|
||||
## 2. 前端检查(frontend-checklist)
|
||||
|
||||
### 📋 基础检查项
|
||||
|
||||
#### 代码质量
|
||||
- [ ] 代码已通过 ESLint 检查,无警告和错误
|
||||
- [ ] 代码已通过 Prettier 格式化
|
||||
- [ ] 无 console.log() 等调试代码残留
|
||||
- [ ] 变量命名符合规范,语义清晰
|
||||
- [ ] 函数职责单一,复杂度适中
|
||||
|
||||
#### 构建验证
|
||||
- [ ] 本地执行 `npm run build:prod` 成功完成
|
||||
- [ ] 构建产物无报错,体积合理
|
||||
- [ ] 静态资源路径正确,无404错误
|
||||
- [ ] 环境变量配置正确(开发/测试/生产)
|
||||
|
||||
#### 功能验证
|
||||
- [ ] 核心功能流程完整测试通过
|
||||
- [ ] 边界条件和异常场景已覆盖
|
||||
- [ ] 表单验证逻辑正确
|
||||
- [ ] API 接口调用正常,错误处理完善
|
||||
- [ ] 路由跳转逻辑正确
|
||||
|
||||
### 🔧 技术检查项
|
||||
|
||||
#### 模块导入检查
|
||||
- [ ] 所有 import 语句引用的模块实际存在
|
||||
- [ ] 无未使用的 import 导入
|
||||
- [ ] 路径别名(@/)配置正确
|
||||
- [ ] 第三方库版本兼容性确认
|
||||
|
||||
#### 性能优化
|
||||
- [ ] 组件按需加载(懒加载)已配置
|
||||
- [ ] 大数据列表已实现虚拟滚动或分页
|
||||
- [ ] 图片资源已压缩,格式合适
|
||||
- [ ] 无内存泄漏风险(事件监听器、定时器等)
|
||||
|
||||
#### 安全检查
|
||||
- [ ] 用户输入已做 XSS 防护
|
||||
- [ ] 敏感信息不在前端硬编码
|
||||
- [ ] API 请求已做 CSRF 防护
|
||||
- [ ] 权限控制逻辑正确
|
||||
|
||||
### 🌐 兼容性检查
|
||||
|
||||
#### 浏览器兼容
|
||||
- [ ] 主流浏览器(Chrome、Firefox、Safari、Edge)显示正常
|
||||
- [ ] 移动端适配良好(如适用)
|
||||
- [ ] 分辨率适配(1366x768、1920x1080等)
|
||||
|
||||
#### 设备兼容
|
||||
- [ ] 触摸设备操作体验良好
|
||||
- [ ] 键盘导航支持完整
|
||||
- [ ] 屏幕阅读器兼容性(无障碍)
|
||||
|
||||
### 📱 发布准备
|
||||
|
||||
#### 文档更新
|
||||
- [ ] 相关 API 文档已同步更新
|
||||
- [ ] 用户操作手册已更新(如适用)
|
||||
- [ ] 变更日志已记录
|
||||
|
||||
#### 回滚预案
|
||||
- [ ] 回滚方案已准备
|
||||
- [ ] 数据兼容性已确认
|
||||
- [ ] 紧急联系人已明确
|
||||
|
||||
### ✅ 最终确认
|
||||
|
||||
#### 发布前最后检查
|
||||
- [ ] 本地构建截图已附在 PR 中
|
||||
- [ ] 测试环境部署验证通过
|
||||
- [ ] Code Review 已完成并获得批准
|
||||
- [ ] 相关 Bug 已关闭或延期说明
|
||||
|
||||
---
|
||||
|
||||
## 3. 后端检查(backend-checklist)
|
||||
|
||||
### 📋 基础检查项
|
||||
|
||||
#### Maven编译验证
|
||||
- [ ] 本地执行 `mvn compile` 编译通过,无ERROR
|
||||
- [ ] 执行 `mvn package -DskipTests` 打包成功
|
||||
- [ ] 依赖版本无冲突(`mvn dependency:tree` 检查)
|
||||
- [ ] 无编译警告(或已有书面说明可忽略)
|
||||
|
||||
#### 构建产物验证
|
||||
- [ ] JAR/WAR包生成完整,大小合理
|
||||
- [ ] `application.yml` 等配置文件已打包进产物
|
||||
- [ ] 第三方依赖jar包完整(lib目录无缺失)
|
||||
|
||||
### 🔧 Spring Boot 配置检查
|
||||
|
||||
#### 多环境配置
|
||||
- [ ] `application-dev.yml`(开发)配置正确
|
||||
- [ ] `application-test.yml`(测试)配置正确
|
||||
- [ ] `application-prod.yml`(生产)配置正确
|
||||
- [ ] 启动参数 `--spring.profiles.active` 指定正确环境
|
||||
- [ ] 生产环境未启用devtools热部署
|
||||
|
||||
#### Actuator安全
|
||||
- [ ] 生产环境 `/actuator` 端点已禁用或限制访问
|
||||
- [ ] `/actuator/env`、`/actuator/heapdump` 等敏感端点已关闭
|
||||
- [ ] 健康检查端点 `/actuator/health` 返回信息已脱敏
|
||||
|
||||
#### 启动校验
|
||||
- [ ] 数据库连接池配置合理(HikariCP最大/最小连接数)
|
||||
- [ ] Redis/消息中间件连接配置正确
|
||||
- [ ] 启动日志无ERROR级别异常
|
||||
|
||||
### 🗄️ MyBatis Plus 规范检查
|
||||
|
||||
#### 实体-表映射
|
||||
- [ ] 所有实体类标注 `@TableName`,表名与实际一致
|
||||
- [ ] 主键字段标注 `@TableId(type = IdType.AUTO)` 或对应策略
|
||||
- [ ] 非表字段标注 `@TableField(exist = false)`
|
||||
- [ ] 字段命名符合下划线转驼峰规则
|
||||
|
||||
#### SQL安全
|
||||
- [ ] 所有查询使用参数化查询(`QueryWrapper` / `LambdaQueryWrapper`)
|
||||
- [ ] 禁止字符串拼接SQL(`"WHERE name = '" + name + "'"`)
|
||||
- [ ] 批量操作使用MyBatis Plus `saveBatch` / `updateBatchById`
|
||||
- [ ] 复杂SQL使用XML映射,避免注解内嵌长SQL
|
||||
|
||||
#### 事务管理
|
||||
- [ ] 涉及多表写操作的方法标注 `@Transactional`
|
||||
- [ ] 事务边界合理,不包含外部HTTP调用
|
||||
- [ ] 异常回滚配置正确(`rollbackFor = Exception.class`)
|
||||
- [ ] 事务方法未被同一类内方法直接调用(自调用失效问题)
|
||||
|
||||
#### 分页插件
|
||||
- [ ] `PaginationInnerInterceptor` 已正确配置
|
||||
- [ ] 分页查询使用 `Page<T>` 对象,非手动limit/offset
|
||||
|
||||
### 🔌 RESTful API 设计检查
|
||||
|
||||
#### 统一返回格式
|
||||
- [ ] 所有接口返回 `{code, msg, data}` 统一结构
|
||||
- [ ] 成功返回 `code=200`,业务错误使用自定义错误码
|
||||
- [ ] 异常通过 `@ControllerAdvice` + `@ExceptionHandler` 统一处理
|
||||
|
||||
#### HTTP状态码
|
||||
- [ ] 资源创建返回 `201 Created`
|
||||
- [ ] 资源删除返回 `204 No Content`
|
||||
- [ ] 参数校验失败返回 `400 Bad Request`
|
||||
- [ ] 未认证返回 `401 Unauthorized`
|
||||
- [ ] 无权限返回 `403 Forbidden`
|
||||
- [ ] 资源不存在返回 `404 Not Found`
|
||||
|
||||
#### 参数校验
|
||||
- [ ] 请求参数使用 `@Valid` / `@Validated` 注解校验
|
||||
- [ ] 必填字段标注 `@NotBlank` / `@NotNull`
|
||||
- [ ] 数值范围标注 `@Min` / `@Max`
|
||||
- [ ] 格式校验使用 `@Pattern`(如手机号、身份证号)
|
||||
- [ ] 校验失败返回明确错误信息(非500堆栈)
|
||||
|
||||
#### API版本管理
|
||||
- [ ] 接口路径包含版本号(`/api/v1/`、`/api/v2/`)
|
||||
- [ ] 废弃接口标注 `@Deprecated`,并在文档中说明
|
||||
- [ ] 不兼容变更必须升级版本号
|
||||
|
||||
### 🔒 安全与合规检查
|
||||
|
||||
#### 数据脱敏
|
||||
- [ ] 患者身份证号在日志中脱敏(`***` 掩码)
|
||||
- [ ] 患者手机号在日志中脱敏(前3后4,中间`****`)
|
||||
- [ ] 敏感字段序列化时使用 `@JsonSerialize` 自定义脱敏器
|
||||
- [ ] 接口返回中非必需字段不暴露(如密码、salt)
|
||||
|
||||
#### 权限控制
|
||||
- [ ] 所有涉及患者数据的接口标注 `@PreAuthorize`
|
||||
- [ ] 数据级权限校验(医生只能访问本科室患者)
|
||||
- [ ] 越权访问返回 `403`,非 `404` 或 `500`
|
||||
- [ ] 敏感操作(删除、修改诊断)需二次确认或额外权限
|
||||
|
||||
#### 审计日志
|
||||
- [ ] 处方修改记录操作人、时间、变更内容
|
||||
- [ ] 病历删除操作记录完整审计链
|
||||
- [ ] 审计日志独立存储,不可被业务用户删除
|
||||
- [ ] 关键业务操作记录IP地址和操作终端
|
||||
|
||||
### ⚡ 性能检查
|
||||
|
||||
#### 数据库查询
|
||||
- [ ] 无N+1查询问题(使用 `JOIN` 或批量查询)
|
||||
- [ ] 大表查询必须有分页限制
|
||||
- [ ] 慢查询已优化(执行时间 < 500ms)
|
||||
- [ ] 索引已覆盖高频查询条件
|
||||
|
||||
#### 接口性能
|
||||
- [ ] 核心接口响应时间 < 1秒
|
||||
- [ ] 列表接口支持分页,无全量返回
|
||||
- [ ] 大文件下载使用流式传输,非全量加载到内存
|
||||
|
||||
### 📝 文档与发布准备
|
||||
|
||||
#### 文档更新
|
||||
- [ ] API接口文档已同步更新(路径、参数、返回值)
|
||||
- [ ] 数据库变更脚本已提供(DDL/DML)
|
||||
- [ ] 配置变更说明已记录(新增/修改的配置项)
|
||||
- [ ] 影响范围说明已明确(哪些模块、哪些接口受影响)
|
||||
|
||||
#### 回滚预案
|
||||
- [ ] 数据库变更可回滚(提供反向SQL脚本)
|
||||
- [ ] 配置变更可快速回退
|
||||
- [ ] 紧急回滚流程已明确(谁、怎么做、多长时间)
|
||||
- [ ] 回滚后数据一致性已验证
|
||||
|
||||
### ✅ 最终确认
|
||||
|
||||
#### 发布前最后检查
|
||||
- [ ] `mvn compile` 构建成功(附终端截图)
|
||||
- [ ] 关键单元测试通过
|
||||
- [ ] 测试环境部署验证通过
|
||||
- [ ] Code Review 已完成并获得批准
|
||||
- [ ] 相关Bug已关闭或延期说明
|
||||
|
||||
---
|
||||
|
||||
## 4. CI/CD门禁(cicd-gatekeeper)
|
||||
|
||||
### 🎯 规范目标
|
||||
|
||||
建立自动化质量门禁,确保每次代码提交都经过严格验证,防止低质量代码进入主干分支,提升系统稳定性和开发效率。
|
||||
|
||||
### 🔒 门禁层级
|
||||
|
||||
#### 1. 提交前门禁(Pre-commit)
|
||||
**触发时机**:`git commit` 执行前
|
||||
**验证内容**:
|
||||
- ESLint 代码规范检查
|
||||
- Prettier 代码格式化
|
||||
- 简单的单元测试(快速执行)
|
||||
|
||||
**工具配置**:
|
||||
- Husky + lint-staged
|
||||
- 配置文件:`.husky/pre-commit`
|
||||
|
||||
#### 2. 推送前门禁(Pre-push)
|
||||
**触发时机**:`git push` 执行前
|
||||
**验证内容**:
|
||||
- 完整的单元测试套件
|
||||
- 构建验证(`npm run build:prod`)
|
||||
- 集成测试(核心流程)
|
||||
|
||||
**工具配置**:
|
||||
- Husky pre-push hook
|
||||
- 配置文件:`.husky/pre-push`
|
||||
|
||||
#### 3. CI流水线门禁(CI Pipeline)
|
||||
**触发时机**:代码推送到远程仓库后
|
||||
**验证内容**:
|
||||
- 完整的测试套件(单元+集成+端到端)
|
||||
- 代码覆盖率检查(分阶段目标:Q1≥30%,Q2≥50%,Q3≥80%)
|
||||
- 安全扫描(SAST)
|
||||
- 构建产物验证
|
||||
- 部署到测试环境
|
||||
|
||||
**工具配置**:
|
||||
- Spug CI/CD 流水线
|
||||
- Gitea Webhook 触发
|
||||
|
||||
#### 4. 发布前门禁(Release Gate)
|
||||
**触发时机**:准备发布到生产环境前
|
||||
**验证内容**:
|
||||
- 生产环境冒烟测试
|
||||
- 性能基准测试
|
||||
- 安全合规检查
|
||||
- 回滚预案验证
|
||||
|
||||
### ⚙️ 具体配置要求
|
||||
|
||||
#### ESLint 配置
|
||||
```javascript
|
||||
// eslint.config.js 关键配置
|
||||
import globals from "globals";
|
||||
import pluginVue from "eslint-plugin-vue";
|
||||
import parserVue from "vue-eslint-parser";
|
||||
import importPlugin from "eslint-plugin-import";
|
||||
|
||||
export default [
|
||||
{
|
||||
name: "app/files-to-lint",
|
||||
files: ["**/*.{js,mjs,jsx,vue}"],
|
||||
},
|
||||
|
||||
{
|
||||
name: "app/files-to-ignore",
|
||||
ignores: ["**/dist/**", "**/node_modules/**", "**/help-center/**"],
|
||||
},
|
||||
|
||||
...pluginVue.configs["flat/recommended"],
|
||||
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
},
|
||||
parser: parserVue,
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
|
||||
plugins: {
|
||||
import: importPlugin,
|
||||
},
|
||||
|
||||
rules: {
|
||||
// 确保导入的模块实际存在(核心规则,防止构建失败)
|
||||
"import/no-unresolved": "error",
|
||||
// 确保导入的命名导出实际存在
|
||||
"import/named": "error",
|
||||
// 确保默认导出存在
|
||||
"import/default": "error",
|
||||
// 确保命名空间导出存在
|
||||
"import/namespace": "error",
|
||||
},
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
#### Java 后端配置
|
||||
```xml
|
||||
<!-- pom.xml 关键插件 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.spotbugs</groupId>
|
||||
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||
<version>4.2.0</version>
|
||||
</plugin>
|
||||
```
|
||||
|
||||
#### 数据库迁移配置
|
||||
```yaml
|
||||
# application.yml Flyway配置
|
||||
flyway:
|
||||
enabled: true
|
||||
locations: classpath:db/migration
|
||||
baseline-on-migrate: true
|
||||
```
|
||||
|
||||
#### Husky 配置
|
||||
```bash
|
||||
# .husky/pre-commit
|
||||
#!/bin/sh
|
||||
npm run lint-staged
|
||||
|
||||
# .husky/pre-push
|
||||
#!/bin/sh
|
||||
npm run test:unit && npm run build:prod
|
||||
```
|
||||
|
||||
#### lint-staged 配置
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"lint-staged": {
|
||||
"*.{js,vue}": ["eslint --fix", "prettier --write"],
|
||||
"*.{css,scss}": ["stylelint --fix", "prettier --write"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🚫 失败处理机制
|
||||
|
||||
#### 自动处理
|
||||
- **构建失败**:自动阻止 PR 合并
|
||||
- **测试失败**:标记 PR 为失败状态
|
||||
- **安全漏洞**:立即通知安全团队
|
||||
|
||||
#### 人工处理
|
||||
- **紧急修复**:可申请临时绕过(需架构师批准)
|
||||
- **误报处理**:提交豁免申请并说明原因
|
||||
- **规则调整**:通过 RFC 流程申请规则变更
|
||||
|
||||
### 📊 监控与度量
|
||||
|
||||
#### 关键指标
|
||||
- 门禁通过率 ≥ 95%
|
||||
- 平均修复时间 ≤ 2小时
|
||||
- 误报率 ≤ 5%
|
||||
|
||||
#### 报告机制
|
||||
- 每日门禁失败统计
|
||||
- 周度质量趋势报告
|
||||
- 月度规则优化建议
|
||||
|
||||
### 🔄 持续改进
|
||||
|
||||
#### 规则演进
|
||||
- 每月评审门禁规则有效性
|
||||
- 根据项目需求调整检查强度
|
||||
- 引入新的质量检查工具
|
||||
|
||||
#### 团队培训
|
||||
- 新成员入职培训包含门禁规范
|
||||
- 定期分享最佳实践案例
|
||||
- 建立常见问题解决方案库
|
||||
|
||||
---
|
||||
|
||||
## 5. 发布确认与回滚预案
|
||||
|
||||
### 📋 发布前最终确认清单
|
||||
|
||||
#### 前端确认
|
||||
- [ ] 本地构建成功(`npm run build:prod`)
|
||||
- [ ] 核心功能流程测试通过
|
||||
- [ ] 模块导入检查通过(无import错误)
|
||||
- [ ] 兼容性测试完成
|
||||
|
||||
#### 后端确认
|
||||
- [ ] Maven编译成功(`mvn compile`)
|
||||
- [ ] 单元测试通过
|
||||
- [ ] 数据库脚本验证通过
|
||||
- [ ] API接口测试通过
|
||||
|
||||
#### 协同确认
|
||||
- [ ] 前后端接口契约一致
|
||||
- [ ] 联调测试通过
|
||||
- [ ] Code Review 已完成
|
||||
- [ ] 测试环境部署验证通过
|
||||
|
||||
### 🚨 回滚预案
|
||||
|
||||
#### 触发条件
|
||||
- [ ] 生产环境出现严重Bug
|
||||
- [ ] 性能严重下降
|
||||
- [ ] 数据一致性问题
|
||||
- [ ] 安全漏洞暴露
|
||||
|
||||
#### 回滚步骤
|
||||
1. **立即停止**:暂停新流量进入
|
||||
2. **版本回退**:部署上一个稳定版本
|
||||
3. **数据回滚**:执行数据库回滚脚本(如有)
|
||||
4. **验证恢复**:确认系统功能正常
|
||||
5. **问题分析**:记录根本原因和改进措施
|
||||
|
||||
#### 责任分工
|
||||
- **技术负责人**:执行回滚操作
|
||||
- **测试负责人**:验证回滚后功能
|
||||
- **项目经理**:协调沟通和进度同步
|
||||
- **运维团队**:监控系统状态
|
||||
|
||||
### 📞 紧急联系人
|
||||
|
||||
| 角色 | 姓名 | 联系方式 | 职责 |
|
||||
|------|------|----------|------|
|
||||
| 技术负责人 | 诸葛亮 | @诸葛亮 | 架构决策和技术指导 |
|
||||
| 前端负责人 | 赵云 | @赵云 | 前端问题处理 |
|
||||
| 后端负责人 | 关羽 | @关羽 | 后端问题处理 |
|
||||
| 测试负责人 | 张飞 | @张飞 | 质量验证和问题复现 |
|
||||
| 项目经理 | 刘备 | @刘备 | 项目协调和进度管理 |
|
||||
| 文档负责人 | 陈琳 | @陈琳 | 文档维护和知识沉淀 |
|
||||
|
||||
---
|
||||
|
||||
**文档版本**:v1.0
|
||||
**最后更新**:2026年4月25日
|
||||
**负责人**:陈琳(文档专家)
|
||||
**适用范围**:HIS 系统所有开发人员
|
||||
139
MD/specs/SURGERY_MANAGEMENT_DESIGN.md
Normal file
139
MD/specs/SURGERY_MANAGEMENT_DESIGN.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# 手术管理模块设计文档
|
||||
|
||||
> **文档类型**: 业务设计
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **依据标准**: 《三级医院评审标准(2022版)》手术质量安全核心制度
|
||||
|
||||
---
|
||||
|
||||
## 一、业务背景
|
||||
|
||||
手术管理是三甲医院评审的核心检查项。依据《医疗质量安全核心制度》中的"手术分级管理制度"和"术前讨论制度",手术必须经过完整的术前评估→审批→执行→术后跟踪流程。
|
||||
|
||||
### 参考标准
|
||||
- 三级医院评审标准(2022版) — 手术质量安全核心指标
|
||||
- 电子病历应用水平分级评价 — 4级要求手术信息全院共享
|
||||
- 《手术分级管理办法》— 手术分级授权管理
|
||||
- 《病案管理与质量控制标准》— 手术记录规范
|
||||
|
||||
---
|
||||
|
||||
## 二、状态流转
|
||||
|
||||
### 2.1 手术状态机
|
||||
|
||||
```
|
||||
待申请(0) → 待审批(1) → 已审批(2) → 待手术(3) → 手术中(4) → 已完成(5)
|
||||
↓ ↓
|
||||
已驳回(6) 已取消(7)
|
||||
```
|
||||
|
||||
| 状态 | 值 | 触发条件 | 允许操作 |
|
||||
|------|-----|---------|---------|
|
||||
| 待申请 | 0 | 医生提交手术申请 | 编辑/删除/提交审批 |
|
||||
| 待审批 | 1 | 提交审批 | 审批/驳回 |
|
||||
| 已审批 | 2 | 科主任审批通过 | 安排手术室/取消 |
|
||||
| 待手术 | 3 | 安排手术室和时间 | 开始手术/取消 |
|
||||
| 手术中 | 4 | 主刀医生确认开始 | 记录术中事件/完成 |
|
||||
| 已完成 | 5 | 主刀医生确认完成 | 查看/打印记录 |
|
||||
| 已驳回 | 6 | 科主任驳回 | 编辑后重新提交 |
|
||||
| 已取消 | 7 | 任意阶段取消 | 查看 |
|
||||
|
||||
### 2.2 手术分级
|
||||
|
||||
| 级别 | 名称 | 审批权限 | 示例 |
|
||||
|------|------|---------|------|
|
||||
| 一级 | 一级手术 | 住院医师可独立完成 | 阑尾切除术 |
|
||||
| 二级 | 二级手术 | 主治医师以上 | 胃大部切除术 |
|
||||
| 三级 | 三级手术 | 副主任医师以上 | 心脏搭桥术 |
|
||||
| 四级 | 四级手术 | 科主任审批+医务部备案 | 器官移植术 |
|
||||
|
||||
---
|
||||
|
||||
## 三、业务规则
|
||||
|
||||
| 规则编号 | 规则名称 | 规则描述 | 触发时机 |
|
||||
|---------|---------|---------|---------|
|
||||
| SR-001 | 手术分级权限校验 | 医生只能申请其权限范围内的手术级别 | 提交申请时 |
|
||||
| SR-002 | 术前讨论记录 | 三级/四级手术必须有术前讨论记录 | 提交审批时 |
|
||||
| SR-003 | 术前评估 | 必须完成麻醉评估和手术风险评估 | 安排手术时 |
|
||||
| SR-004 | 手术室冲突检查 | 同一手术室同一时间不能安排两台手术 | 安排手术室时 |
|
||||
| SR-005 | 术前禁食提醒 | 手术前8小时禁止进食,4小时禁止饮水 | 手术前1天 |
|
||||
| SR-006 | 术后随访 | 手术后24h/48h/72h必须有随访记录 | 完成手术后 |
|
||||
| SR-007 | 手术安全核查 | 术前/术中/术后三次安全核查(WS/T 313) | 手术各阶段 |
|
||||
|
||||
---
|
||||
|
||||
## 四、前后端交互时序
|
||||
|
||||
### 4.1 提交手术申请
|
||||
```
|
||||
用户操作: 医生点击"提交手术申请"
|
||||
→ 前端: 校验表单(必填项+业务规则前端预检)
|
||||
→ API: POST /clinical-manage/surgery/surgery
|
||||
→ 后端: SurgeryController.addSurgery()
|
||||
→ SurgeryAppService.addSurgery()
|
||||
→ 校验手术分级权限(SR-001)
|
||||
→ 校验三级/四级手术术前讨论(SR-002)
|
||||
→ 设置状态=待申请(0)
|
||||
→ 保存到数据库
|
||||
→ 返回: {code:200, msg:"申请已提交"}
|
||||
→ 前端: ElMessage.success → 刷新列表
|
||||
```
|
||||
|
||||
### 4.2 安排手术室
|
||||
```
|
||||
用户操作: 护士长点击"安排手术"
|
||||
→ 前端: 弹出安排弹窗(选择手术室/时间/麻醉医生)
|
||||
→ API: PUT /clinical-manage/surgery/surgery (携带手术室+时间信息)
|
||||
→ 后端: 校验手术室冲突(SR-004)
|
||||
→ 校验术前评估完成(SR-003)
|
||||
→ 更新状态=待手术(3)
|
||||
→ 返回: {code:200, msg:"安排成功"}
|
||||
```
|
||||
|
||||
### 4.3 开始/完成手术
|
||||
```
|
||||
用户操作: 主刀医生点击"开始手术"
|
||||
→ API: PUT /clinical-manage/surgery/surgery-status?id=&statusEnum=4
|
||||
→ 后端: 更新状态=手术中(4), 记录开始时间
|
||||
|
||||
用户操作: 主刀医生点击"完成手术"
|
||||
→ API: PUT /clinical-manage/surgery/surgery-status?id=&statusEnum=5
|
||||
→ 后端: 更新状态=已完成(5), 记录结束时间
|
||||
→ 触发术后随访提醒(SR-006)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、数据模型扩展
|
||||
|
||||
现有 `SurgeryDto` 需增加以下字段:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| surgeryLevel | String | 手术级别(1/2/3/4) |
|
||||
| surgeryRoom | String | 手术室 |
|
||||
| anesthesiaType | String | 麻醉方式(全麻/局麻/脊麻/硬膜外) |
|
||||
| preopDiagnosis | String | 术前诊断 |
|
||||
| postopDiagnosis | String | 术后诊断 |
|
||||
| startTime | DateTime | 实际开始时间 |
|
||||
| endTime | DateTime | 实际结束时间 |
|
||||
| complications | String | 并发症记录 |
|
||||
| bloodLoss | Integer | 术中出血量(ml) |
|
||||
| specimenSent | Boolean | 是否送检标本 |
|
||||
|
||||
---
|
||||
|
||||
## 六、测试用例
|
||||
|
||||
| 用例编号 | 场景 | 操作步骤 | 预期结果 |
|
||||
|---------|------|---------|---------|
|
||||
| TC-S001 | 正常申请流程 | 医生提交→科主任审批→护士安排→手术完成 | 状态正确流转 |
|
||||
| TC-S002 | 越级申请拒绝 | 住院医师申请四级手术 | 返回权限不足错误 |
|
||||
| TC-S003 | 手术室冲突 | 同一时间安排两台手术到同一手术室 | 返回冲突提示 |
|
||||
| TC-S004 | 驳回后重新提交 | 科主任驳回→医生修改→重新提交 | 状态从驳回回到待审批 |
|
||||
| TC-S005 | 取消手术 | 已审批的手术点击取消 | 状态变为已取消 |
|
||||
| TC-S006 | 缺少术前讨论 | 三级手术无术前讨论记录直接提交 | 拦截并提示 |
|
||||
|
||||
404
MD/specs/UI_DESIGN_IRON_RULES.md
Normal file
404
MD/specs/UI_DESIGN_IRON_RULES.md
Normal file
@@ -0,0 +1,404 @@
|
||||
# HealthLink-HIS UI 设计铁律
|
||||
|
||||
> **文档类型**: 设计规范
|
||||
> **适用范围**: 全项目前端UI设计与交互
|
||||
> **版本**: v1.0
|
||||
> **编制日期**: 2026-06-06
|
||||
> **最后更新**: 2026-06-06
|
||||
|
||||
---
|
||||
|
||||
## 一、总则
|
||||
|
||||
> **设计文档必须写清楚:前端页面UI布局、交互效果、前后端调用流程。**
|
||||
> 没有明确UI设计的模块,禁止直接编码。
|
||||
|
||||
### 设计文档必备要素
|
||||
|
||||
每个新模块/页面的设计文档必须包含:
|
||||
|
||||
| # | 要素 | 说明 |
|
||||
|---|------|------|
|
||||
| 1 | **页面线框图/布局描述** | 每个区域放什么组件、尺寸比例、栅格布局 |
|
||||
| 2 | **交互效果清单** | 每个按钮/操作触发什么效果(弹窗、抽屉、跳转、动画) |
|
||||
| 3 | **前后端调用流程** | 每个用户操作 → 对应API → 参数 → 返回数据 → 前端渲染 |
|
||||
| 4 | **状态流转图** | 数据状态变化 → UI如何响应 |
|
||||
| 5 | **异常/边界处理** | 空数据、加载中、错误状态的UI表现 |
|
||||
| 6 | **响应式断点** | 不同屏幕尺寸下的布局适配方案 |
|
||||
|
||||
---
|
||||
|
||||
## 二、十大UI设计铁律法则
|
||||
|
||||
> 以下法则源自认知心理学、人机交互学、HCI经典理论。
|
||||
> 医疗HIS系统因涉及生命安全,**全部铁律等级提升为P0**。
|
||||
|
||||
### 法则1: 希克定律 (Hick's Law) — 选择越少越好
|
||||
|
||||
> **决策时间 = a + b × log₂(选项数量)**
|
||||
|
||||
| 维度 | 规则 | HIS场景 |
|
||||
|------|------|---------|
|
||||
| 菜单层级 | 一级菜单 ≤ 7项,二级菜单 ≤ 9项 | 医生工作站左侧导航 |
|
||||
| 表单字段 | 单页表单 ≤ 12个字段,超出用分步表单 | 患者登记、医嘱录入 |
|
||||
| 按钮组 | 主要操作按钮 ≤ 3个/区域 | 处方页面:保存/提交/打印 |
|
||||
| 弹窗选项 | 弹窗内选项 ≤ 5个 | 确认对话框不超过3个按钮 |
|
||||
|
||||
**违反案例**: 某页面一次展示20个筛选条件 → 医生找不到关键字段
|
||||
**正确做法**: 默认显示5个常用条件,"更多筛选"展开高级选项
|
||||
|
||||
### 法则2: 费茨定律 (Fitts's Law) — 目标要大要近
|
||||
|
||||
> **移动时间 = a + b × log₂(距离/尺寸 + 1)**
|
||||
|
||||
| 维度 | 规则 | HIS场景 |
|
||||
|------|------|---------|
|
||||
| 可点击区域 | 最小 44×44px(移动端 48×48px) | 移动护理PDA场景 |
|
||||
| 主要操作 | 放在用户视线自然落点(右下/顶部) | 保存按钮固定在表单右下 |
|
||||
| 危险操作 | 与安全操作保持物理距离 ≥ 100px | 删除按钮远离保存按钮 |
|
||||
| 快捷入口 | 高频操作提供快捷键/快捷入口 | F2=保存, F3=打印 |
|
||||
|
||||
**违反案例**: "确认发药"和"取消发药"按钮紧挨着 → 误点
|
||||
**正确做法**: 确认按钮绿色大按钮,取消按钮灰色小按钮,间距 ≥ 80px
|
||||
|
||||
### 法则3: 米勒定律 (Miller's Law) — 记忆负荷 ≤ 7±2
|
||||
|
||||
> **短时记忆容量:7 ± 2 个信息块**
|
||||
|
||||
| 维度 | 规则 | HIS场景 |
|
||||
|------|------|---------|
|
||||
| 信息分组 | 每组 ≤ 7个条目 | 检验报告分组显示 |
|
||||
| 导航层级 | 总层级 ≤ 4层 | 菜单→子菜单→功能→详情 |
|
||||
| 表格列数 | 默认显示 ≤ 8列,其余可配置 | 处方列表核心列8个 |
|
||||
| 标签页 | Tab标签 ≤ 6个,超出用下拉 | 患者详情Tab |
|
||||
|
||||
**违反案例**: 患者信息页一次展示30个字段 → 医生记不住哪个要改
|
||||
**正确做法**: 按"基本信息/病史/过敏/诊断"分组,每组 ≤ 7个字段
|
||||
|
||||
### 法则4: 雅各布定律 (Jakob's Law) — 用户要的是熟悉感
|
||||
|
||||
> **用户把时间花在别的系统上,期望你的系统有一样的操作方式**
|
||||
|
||||
| 维度 | 规则 | HIS场景 |
|
||||
|------|------|---------|
|
||||
| 布局模式 | 遵循医疗软件行业惯例 | 左导航+顶部栏+内容区 |
|
||||
| 表格操作 | 行末操作按钮(编辑/删除/查看) | 与主流HIS系统一致 |
|
||||
| 搜索模式 | 顶部搜索栏+筛选条件+表格 | 通用管理后台模式 |
|
||||
| CRUD流程 | 列表→新增弹窗→编辑弹窗→详情抽屉 | 标准若依模式 |
|
||||
|
||||
**违反案例**: 新模块把"新增"放在表格底部 → 用户习惯在顶部找
|
||||
**正确做法**: "新增"按钮统一在表格上方左侧
|
||||
|
||||
### 法则5: 格式塔原则 (Gestalt Principles) — 分组要明确
|
||||
|
||||
| 子原则 | 规则 | HIS场景 |
|
||||
|--------|------|---------|
|
||||
| **接近性** | 相关元素间距 < 不相关元素间距 | 表单label与input间距8px,字段组间距24px |
|
||||
| **相似性** | 同类操作用相同颜色/形状 | 所有"保存"用蓝色,所有"删除"用红色 |
|
||||
| **连续性** | 视觉引导线引导阅读流 | 表单从上到下、从左到右 |
|
||||
| **封闭性** | 卡片/分组用边框或背景色区分 | 患者信息分区用卡片包裹 |
|
||||
| **图底关系** | 内容层 > 背景层,弹窗要有遮罩 | Dialog背景半透明遮罩 |
|
||||
|
||||
**违反案例**: 表单字段间距不一致 → 视觉混乱
|
||||
**正确做法**: 统一间距系统:8/12/16/24/32px
|
||||
|
||||
### 法则6: 多赫蒂阈值 (Doherty Threshold) — 响应要快
|
||||
|
||||
> **系统响应 < 400ms 时,用户生产力提升4倍**
|
||||
|
||||
| 维度 | 规则 | HIS场景 |
|
||||
|------|------|---------|
|
||||
| 接口响应 | 核心接口 ≤ 200ms,普通 ≤ 500ms | 挂号、查询必须 ≤ 200ms |
|
||||
| 加载反馈 | 等待 > 200ms 显示loading | el-table加载用v-loading |
|
||||
| 操作反馈 | 点击后 ≤ 100ms 有视觉响应 | 按钮点击立即变灰防重复提交 |
|
||||
| 列表分页 | 默认20条/页,禁止一次加载全部 | 处方列表分页 |
|
||||
| 骨架屏 | 首屏加载用Skeleton占位 | 患者列表页骨架屏 |
|
||||
|
||||
**违反案例**: 查询接口3秒无响应 → 用户反复点击
|
||||
**正确做法**: 200ms内显示loading,超时5s提示"查询超时"
|
||||
|
||||
### 法则7: 尼尔森十大可用性原则 (Nielsen's 10 Heuristics)
|
||||
|
||||
| # | 原则 | HIS应用规则 |
|
||||
|---|------|------------|
|
||||
| 1 | **系统状态可见** | 每个操作后显示结果:保存成功✓、提交成功✓、审批中⏳ |
|
||||
| 2 | **贴近真实世界** | 使用医疗术语(挂号、处方、医嘱),不用技术术语(CRUD、API) |
|
||||
| 3 | **用户控制与自由** | 每个操作可撤销:提交可撤回、删除有确认、编辑可取消 |
|
||||
| 4 | **一致性和标准** | 全系统统一:按钮颜色、弹窗样式、表格样式、表单校验 |
|
||||
| 5 | **防错优先** | 危险操作二次确认;必填字段标红*;格式校验实时提示 |
|
||||
| 6 | **识别而非记忆** | 下拉选择 > 手动输入;最近使用列表;搜索联想 |
|
||||
| 7 | **灵活高效** | 快捷键;批量操作;常用模板;收藏功能 |
|
||||
| 8 | **简洁美观** | 去掉无关信息;留白适度;视觉层次清晰 |
|
||||
| 9 | **容错帮助** | 错误信息说人话:"身份证号格式错误"而非"Invalid input" |
|
||||
| 10 | **帮助文档** | 复杂功能提供操作引导;Help Tooltip |
|
||||
|
||||
**违反案例**: 删除后无提示 → 用户不确定是否成功
|
||||
**正确做法**: 删除后 `ElMessage.success('删除成功')` 并刷新列表
|
||||
|
||||
### 法则8: 泰斯勒定律 (Tesler's Law) — 复杂性守恒
|
||||
|
||||
> **每个系统都有不可消除的复杂性,必须 somewhere 被处理**
|
||||
|
||||
| 维度 | 规则 | HIS场景 |
|
||||
|------|------|---------|
|
||||
| 简单前端复杂后端 | 用户操作尽量简单,复杂逻辑放后端 | 医保结算:用户点"结算",后端算所有费用 |
|
||||
| 智能默认值 | 80%场景用默认值,减少用户输入 | 科室默认当前科室,药品默认常用规格 |
|
||||
| 渐进式披露 | 先展示核心信息,高级选项折叠 | 医嘱默认常用,"更多选项"展开完整 |
|
||||
| 自动化 | 能自动填充的不手动输入 | 选择患者自动填充病历号、性别、年龄 |
|
||||
|
||||
**违反案例**: 开医嘱要手动输入药品剂量、频次、途径 → 复杂
|
||||
**正确做法**: 提供"常用医嘱模板",一键套用,仅需微调
|
||||
|
||||
### 法则9: 峰终定律 (Peak-End Rule) — 关键时刻要做好
|
||||
|
||||
> **用户记住的是体验的峰值和结束时刻**
|
||||
|
||||
| 维度 | 规则 | HIS场景 |
|
||||
|------|------|---------|
|
||||
| 操作峰值 | 关键操作给正向反馈 | 挂号成功→大✓动画+患者信息卡 |
|
||||
| 结束体验 | 流程结束给明确结果 | 收费完成→打印凭条+成功提示 |
|
||||
| 错误峰值 | 错误也要优雅处理 | 校验失败→精确定位错误字段+红色高亮 |
|
||||
| 批量操作 | 批量完成后给统计 | "成功导入58条,失败2条" |
|
||||
|
||||
**违反案例**: 批量导入完成后无提示 → 用户不知道是否成功
|
||||
**正确做法**: 弹出结果面板:"✓ 成功58条 / ✗ 失败2条(点击查看)"
|
||||
|
||||
### 法则10: 冯·雷斯托夫效应 (Von Restorff Effect) — 隔离记忆
|
||||
|
||||
> **在相似事物中,与众不同的那个更容易被记住**
|
||||
|
||||
| 维度 | 规则 | HIS场景 |
|
||||
|------|------|---------|
|
||||
| 紧急标记 | 危急值用红色醒目样式 | 危急值报告→红色闪烁标签 |
|
||||
| 当前选中 | 选中项明显高亮 | 菜单选中项蓝色背景+左侧条 |
|
||||
| 重要操作 | 主要按钮用强调色 | "提交处方"蓝色实心,"取消"灰色描边 |
|
||||
| 通知徽标 | 未读消息用Badge | 右上角铃铛红点+数字 |
|
||||
|
||||
**违反案例**: 危急值和普通信息用同一颜色 → 医生忽略
|
||||
**正确做法**: 危急值红色脉冲动画 + 声音提醒
|
||||
|
||||
---
|
||||
|
||||
## 三、HIS医疗系统专项UI规范
|
||||
|
||||
### 3.1 色彩体系
|
||||
|
||||
| 用途 | 颜色 | HEX | 说明 |
|
||||
|------|------|-----|------|
|
||||
| 主色 | 医疗蓝 | #1890ff | 品牌色、主要按钮 |
|
||||
| 成功 | 安全绿 | #52c41a | 操作成功、正常状态 |
|
||||
| 警告 | 警示橙 | #faad14 | 注意、待处理 |
|
||||
| 危险 | 危急红 | #ff4d4f | 危急值、删除、错误 |
|
||||
| 信息 | 信息灰 | #909399 | 辅助信息、次要文本 |
|
||||
| 背景 | 浅灰 | #f5f7fa | 页面背景 |
|
||||
| 卡片 | 白色 | #ffffff | 卡片/弹窗背景 |
|
||||
|
||||
**状态色标准**:
|
||||
```
|
||||
待诊 → #909399(灰) 已诊 → #1890ff(蓝)
|
||||
已收费 → #52c41a(绿) 已发药 → #722ed1(紫)
|
||||
危急 → #ff4d4f(红脉冲) 已完成 → #b7eb8f(浅绿)
|
||||
```
|
||||
|
||||
### 3.2 间距系统 (8px基准)
|
||||
|
||||
| Token | 值 | 用途 |
|
||||
|-------|-----|------|
|
||||
| xs | 4px | 图标与文字间距 |
|
||||
| sm | 8px | 表单项内间距、紧凑行距 |
|
||||
| md | 12px | 表单项之间间距 |
|
||||
| lg | 16px | 卡片内边距、区块间距 |
|
||||
| xl | 24px | 区域分隔 |
|
||||
| xxl | 32px | 页面级边距 |
|
||||
|
||||
### 3.3 字体规范
|
||||
|
||||
| 场景 | 字号 | 字重 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 页面标题 | 20px | 600 | h1 |
|
||||
| 区块标题 | 16px | 600 | h2 |
|
||||
| 正文 | 14px | 400 | 默认 |
|
||||
| 辅助文字 | 12px | 400 | 说明、提示 |
|
||||
| 数据突出 | 24px | 700 | 统计数字、金额 |
|
||||
| 危急值 | 16px | 700 | 红色加粗 |
|
||||
|
||||
### 3.4 表格设计规范
|
||||
|
||||
| 规则 | 说明 |
|
||||
|------|------|
|
||||
| 列数 | 默认 ≤ 8列,超出用横向滚动或配置列 |
|
||||
| 行高 | 48px(紧凑40px,宽松56px) |
|
||||
| 操作列 | 固定右侧,宽度 ≥ 160px |
|
||||
| 排序 | 默认按时间倒序,支持点击列头排序 |
|
||||
| 分页 | 20条/页,可切换10/20/50/100 |
|
||||
| 空状态 | 无数据时显示空状态插画+文字"暂无数据" |
|
||||
| 加载 | v-loading指令,骨架屏或旋转图标 |
|
||||
| 斑马纹 | 奇偶行交替背景色 #fafafa |
|
||||
|
||||
### 3.5 表单设计规范
|
||||
|
||||
| 规则 | 说明 |
|
||||
|------|------|
|
||||
| 布局 | 简单表单用inline,复杂用labelWidth=120px |
|
||||
| 必填标记 | 红色 * 号在label前 |
|
||||
| 校验时机 | blur时校验(非实时),提交时全量校验 |
|
||||
| 错误提示 | 字段下方红色文字,与字段左对齐 |
|
||||
| 按钮位置 | 表单底部右侧,主按钮在右 |
|
||||
| 禁用态 | 禁用字段灰底+灰字+禁止光标 |
|
||||
| 加载态 | 提交按钮loading态,防重复提交 |
|
||||
|
||||
### 3.6 弹窗/抽屉规范
|
||||
|
||||
| 类型 | 适用场景 | 规则 |
|
||||
|------|---------|------|
|
||||
| Dialog | 简单表单(≤6字段) | 宽度400-600px,标题+内容+底部按钮 |
|
||||
| Drawer | 复杂表单/详情查看 | 宽度60%,右侧滑入,含关闭按钮 |
|
||||
| Modal | 确认操作 | 标题+内容+确认/取消,危险操作红色确认 |
|
||||
| Fullscreen | 大表单/复杂编辑 | 全屏,顶栏标题+关闭,底部操作栏 |
|
||||
|
||||
### 3.7 交互反馈规范
|
||||
|
||||
| 操作 | 反馈方式 | 示例 |
|
||||
|------|---------|------|
|
||||
| 保存成功 | ElMessage.success | "保存成功" |
|
||||
| 保存失败 | ElMessage.error | "保存失败:XXX原因" |
|
||||
| 删除确认 | ElMessageBox.confirm | "确定要删除该记录吗?" |
|
||||
| 表单校验 | 字段下方红色文字 | "请输入患者姓名" |
|
||||
| 加载中 | v-loading | 旋转图标覆盖表格 |
|
||||
| 空数据 | 空状态组件 | 插画+"暂无挂号记录" |
|
||||
| 网络错误 | ElMessage.error | "网络异常,请重试" |
|
||||
| 无权限 | ElMessage.warning | "您没有该操作权限" |
|
||||
|
||||
### 3.8 医疗HIS特殊交互
|
||||
|
||||
| 场景 | 交互要求 |
|
||||
|------|---------|
|
||||
| **危急值** | 红色脉冲动画 + 弹窗强制确认 + 声音提醒 + 操作记录 |
|
||||
| **医嘱审核** | 双人审核弹窗,审核人签章,不可撤销提示 |
|
||||
| **处方开具** | 药品搜索联想 + 剂量自动计算 + 相互作用预警弹窗 |
|
||||
| **费用结算** | 费用明细折叠/展开 + 医保/自费分类 + 打印预览 |
|
||||
| **患者搜索** | 模糊搜索+拼音首字母+身份证号+病历号 多维度 |
|
||||
| **电子签名** | 手写板签名+密码验证 双重认证 |
|
||||
| **打印功能** | 套打对齐微调 + 批量打印 + 预览 |
|
||||
| **权限控制** | 按钮级权限 v-hasPermi + 数据权限过滤 |
|
||||
|
||||
---
|
||||
|
||||
## 四、设计文档模板
|
||||
|
||||
> 每个新模块必须按此模板编写设计文档
|
||||
|
||||
```markdown
|
||||
# 模块名 设计文档
|
||||
|
||||
## 1. 页面列表
|
||||
| 页面 | 路由 | 类型 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 列表页 | /module/list | 管理页 | ... |
|
||||
| 新增弹窗 | - | Dialog | ... |
|
||||
|
||||
## 2. 页面布局设计
|
||||
### 2.1 列表页
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ 搜索区 [关键词] [筛选] [搜索] │
|
||||
├─────────────────────────────────┤
|
||||
│ 操作区 [+新增] [导出] [批量删除] │
|
||||
├─────────────────────────────────┤
|
||||
│ 数据表格 (el-table) │
|
||||
│ 列1 | 列2 | 列3 | ... | 操作 │
|
||||
├─────────────────────────────────┤
|
||||
│ 分页 [1] [2] [3] ... │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 3. 交互效果清单
|
||||
| 操作 | 触发方式 | 效果 | 反馈 |
|
||||
|------|---------|------|------|
|
||||
| 点击"新增" | 按钮click | 打开Dialog | - |
|
||||
| 点击"保存" | 按钮click | 提交API→关闭Dialog→刷新列表 | success消息 |
|
||||
| 点击"删除" | 按钮click | 二次确认弹窗→调用API→刷新 | success消息 |
|
||||
| 表单校验 | blur/submit | 字段下方提示 | error文字 |
|
||||
|
||||
## 4. 前后端调用流程
|
||||
### 4.1 查询列表
|
||||
```
|
||||
用户操作: 页面加载/点击搜索
|
||||
→ 前端: GET /api/v1/module/list?pageNum=1&pageSize=20&keyword=xxx
|
||||
→ 后端: Controller.list() → AppService.query() → Service.page()
|
||||
→ 返回: {code:200, data:{rows:[...], total:100}}
|
||||
→ 前端: el-table渲染 rows,pagination渲染 total
|
||||
```
|
||||
|
||||
### 4.2 新增记录
|
||||
```
|
||||
用户操作: 点击"新增"→填写表单→点击"保存"
|
||||
→ 前端: POST /api/v1/module {field1, field2, ...}
|
||||
→ 后端: Controller.add() → AppService.create() → Service.save()
|
||||
→ 返回: {code:200, msg:"操作成功"}
|
||||
→ 前端: ElMessage.success → 关闭Dialog → getList()
|
||||
```
|
||||
|
||||
## 5. 状态流转
|
||||
| 状态 | 值 | 下一状态 | 触发条件 |
|
||||
|------|-----|---------|---------|
|
||||
| 草稿 | 0 | 已提交 | 用户点击提交 |
|
||||
| 已提交 | 1 | 已审核 | 审核人点击审核 |
|
||||
|
||||
## 6. 异常处理
|
||||
| 场景 | UI表现 |
|
||||
|------|--------|
|
||||
| 网络断开 | ElMessage.error("网络异常") |
|
||||
| 数据为空 | 空状态插画+"暂无数据" |
|
||||
| 权限不足 | 按钮隐藏/v-if控制 |
|
||||
| 加载中 | v-loading覆盖 |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、违反检查清单
|
||||
|
||||
> 代码审查时对照此清单逐项检查
|
||||
|
||||
```
|
||||
□ 页面布局是否遵循左导航+顶部栏+内容区?
|
||||
□ 每页功能按钮是否 ≤ 3个主要操作?
|
||||
□ 表单字段是否 ≤ 12个?超出是否分步/折叠?
|
||||
□ 可点击区域是否 ≥ 44px?
|
||||
□ 危险操作是否与安全操作保持距离?
|
||||
□ 加载等待是否显示loading?
|
||||
□ 操作成功/失败是否有明确反馈?
|
||||
□ 删除操作是否有二次确认?
|
||||
□ 表格是否分页?是否默认20条?
|
||||
□ 空数据是否有空状态提示?
|
||||
□ 色彩是否符合色彩体系?
|
||||
□ 间距是否使用8px基准系统?
|
||||
□ 字体是否符合字体规范?
|
||||
□ 弹窗类型选择是否合理?
|
||||
□ 表单校验是否blur触发?
|
||||
□ 医疗特殊交互(危急值/医嘱等)是否按规范实现?
|
||||
□ 设计文档是否包含:UI布局+交互清单+调用流程?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、参考文献
|
||||
|
||||
| 来源 | 内容 |
|
||||
|------|------|
|
||||
| Hick (1952) | Hick's Law — 选择反应时间 |
|
||||
| Fitts (1954) | Fitts's Law — 运动时间与目标尺寸 |
|
||||
| Miller (1956) | Miller's Law — 7±2信息块 |
|
||||
| Jakob Nielsen | 10 Usability Heuristics |
|
||||
| Gestalt Psychology | 接近性/相似性/连续性/封闭性/图底 |
|
||||
| Doherty & Thadhani (1982) | 400ms响应阈值 |
|
||||
| Larry Tesler | 复杂性守恒定律 |
|
||||
| Kahneman | 峰终定律 |
|
||||
| Hedwig von Restorff | 隔离效应 |
|
||||
| ISO 9241-210 | 以人为中心的交互系统设计 |
|
||||
| GB/T 33758-2017 | 人机交互系统人机界面设计原则 |
|
||||
| WS/T 500-2017 | 电子病历共享文档规范 |
|
||||
|
||||
---
|
||||
|
||||
> ⚠️ 本文件是UI设计铁律的唯一信源。所有前端模块设计文档必须遵守本规范。
|
||||
Reference in New Issue
Block a user