Files
hms/docs/audits/v3-beta/05-api-deep-test.md
iven 1e59007bd5 fix(mp): DevTools 卡死 + 主包 2MB→766KB + 代码质量 4 项全通过
根因:主包 2MB 全量组件注入导致 DevTools 渲染引擎内存渐增,
叠加离线时固定 3s 抑制期后的请求洪泛。

修复:
- app.config.ts 添加 lazyCodeLoading: requiredComponents
  主包 2.0MB→766KB,taro.js 526→131KB,vendors.js 230→28KB
- request.ts 离线抑制改为指数退避(3s→6s→12s→30s cap)
  后端不可达时自动延长抑制,防止请求风暴
- SegmentTabs Tab 接口改为 readonly,修复 TS 编译错误
- AbortController polyfill 补齐小程序运行时缺失
- 健康首页/设备同步/健康档案/报告/设置页 UI 重构
- 文章页公开端点适配游客访问
- 健康首页 Swiper 间隔优化 4s→5s,动画 500→300ms
2026-05-24 11:32:40 +08:00

160 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API 端点深度测试报告
> 测试工具: curl/Bash | 环境: http://localhost:3000
> 测试账号: admin / Admin@2026 (完整权限) | 总用例: 69
## 1. 模块通过率汇总
| 模块 | 测试数 | 通过 | 失败 | 通过率 |
|------|--------|------|------|--------|
| 认证与权限 | 8 | 8 | 0 | **100%** |
| 患者 CRUD | 11 | 10 | 1 | **90.9%** |
| 患者分页/注入 | 7 | 5 | 2 | **71.4%** |
| 患者删除 | 2 | 2 | 0 | **100%** |
| 健康数据 | 5 | 1 | 4 | **20%** |
| 预约系统 | 7 | 7 | 0 | **100%** |
| 咨询管理 | 9 | 7 | 2 | **77.8%** |
| 内容管理 | 13 | 10 | 3 | **76.9%** |
| 通用/跨切面 | 7 | 7 | 0 | **100%** |
| **总计** | **69** | **57** | **12** | **82.6%** |
## 2. 认证与权限 — 100% PASS
| ID | 测试 | 结果 |
|----|------|------|
| AUTH-01 | 错误密码 | PASS — `message=未授权` |
| AUTH-02 | 不存在的用户 | PASS — `message=未授权` |
| AUTH-03 | 无 Token 访问 | PASS — HTTP 401 |
| AUTH-04 | 无效 Token | PASS — HTTP 401 |
| AUTH-05 | 空 body 登录 | PASS — 429 限流触发 |
| AUTH-06 | SQL 注入 (`' OR 1=1 --`) | PASS — 无数据泄漏 |
| AUTH-07 | 超长密码 (10000 字符) | PASS — 429 限流触发 |
| AUTH-08 | 有效 Token | PASS — 200 + data |
**亮点:** 限流机制有效,登录端点不泄漏信息(统一返回"未授权"SQL 注入被正确处理。
## 3. 患者 CRUD — 90.9% PASS
| ID | 测试 | 结果 | 说明 |
|----|------|------|------|
| PATIENT-01 | 空名称创建 | PASS | `400: 患者姓名不能为空` |
| PATIENT-02 | 500 字符名称 | PASS | `400: 长度不能超过255` |
| PATIENT-03 | 未来出生日期 (2099) | PASS | `400: 出生日期不能是未来日期` |
| PATIENT-04 | XSS in name (`<script>`) | **FAIL** | HTTP 200, 存储原值 |
| PATIENT-05 | 无效 gender | PASS | `400: 不是有效值` |
| PATIENT-06 | 有效创建 | PASS | success, version=1 |
| PATIENT-14 | 按 ID 查询 | PASS | success |
| PATIENT-15 | 不存在的 ID | PASS | `404: 患者不存在` |
| PATIENT-16 | 有效更新 | PASS | version=2 |
| PATIENT-17 | 乐观锁冲突 | PASS | `409: 版本冲突` |
| PATIENT-18 | 未来日期更新 | PASS | `400: 出生日期不能是未来日期` |
### PATIENT-04: XSS 存储未消毒 (MEDIUM)
- `<script>alert(1)</script>` 直接存入 name 字段
- 前端 React 默认转义,但建议服务端也做消毒
- **修复:** 添加 HTML sanitize 或正则剥离标签
### 患者分页/注入测试
| ID | 测试 | 结果 |
|----|------|------|
| PATIENT-10 | limit=10000 | **FAIL (LOW)** — 无上限,可能导致性能问题 |
| PATIENT-12 | SQL 注入 in search | **FAIL (MEDIUM)** — 连接错误 (HTTP 000) |
## 4. 健康数据 — 20% PASS (最差模块)
| ID | 测试 | 结果 | 说明 |
|----|------|------|------|
| HEALTH-01 | 极端血压 (0/0) | **FAIL** | HTTP 200值存为 null |
| HEALTH-02 | 极端心率 (999) | **FAIL** | HTTP 200值存为 null |
| HEALTH-03 | 负值 (-10) | **FAIL** | HTTP 200值存为 null |
| HEALTH-04 | 无效 UUID | PASS | `422: UUID parsing failed` |
| HEALTH-05 | 未来日期 (2099) | **FAIL** | HTTP 200记录被创建 |
### H-06: 日常监测 DTO-Entity 映射断裂 (HIGH)
**这是本次测试发现的最严重的后端问题。**
- **现象:** API 接受 `indicator_type``value``systolic``diastolic` 等字段但静默忽略,创建的记录所有测量字段为 null
- **根因:** DTO 字段与 Entity 列名不匹配。DTO 使用 `systolic`/`diastolic`Entity 期望 `morning_bp_systolic`/`morning_bp_diastolic`
- **影响:** 日常监测功能实质失效 — 小程序录入的体征数据无法正确存储
- **修复:** 重构 DTO 字段映射,或统一 DTO/Entity 字段命名
- **预计工时:** 4h
**同时发现:** 无值范围校验(血压 0、心率 999 被接受)、未来 record_date 无校验。
## 5. 预约系统 — 100% PASS
| ID | 测试 | 结果 |
|----|------|------|
| APPOINT-01 | 列表查询 | PASS |
| APPOINT-02 | 空 doctor_id | PASS — 422 |
| APPOINT-03 | 无效 UUID | PASS — 422 |
| APPOINT-04 | 不存在的预约 | PASS — 404 |
| APPOINT-05 | page=0 | PASS |
| APPOINT-11 | 排班已满 | PASS — `400: 排班已满` |
| APPOINT-12 | 重复预约 | PASS — `400: 排班已满` |
**亮点:** UUID 校验、容量检查、404 处理全部正确。
## 6. 咨询管理 — 77.8% PASS
| ID | 测试 | 结果 |
|----|------|------|
| CONSULT-02 | 空描述创建 | **FAIL (LOW)** — 接受空描述 |
| CONSULT-05 | XSS in description | **FAIL (MEDIUM)** — XSS 存储原值 |
| CONSULT-06~09 | 评分范围 1-5 | **PASS** — 校验完善 |
**亮点:** 评分校验优秀1-5 范围 + 只能评已关闭会话)。
## 7. 内容管理 — 76.9% PASS
| ID | 测试 | 结果 |
|----|------|------|
| ARTICLE-04 | 500 字符标题 | **FAIL (HIGH)** — HTTP 500 内部错误 |
| CATEGORY-02 | 空分类名称 | **FAIL (MEDIUM)** — 接受空名称 |
| TAG-04 | 重复标签名 | **FAIL (LOW)** — 允许重复 |
### ARTICLE-04: 500 字符标题导致 500 错误 (HIGH)
- **现象:** 500 字符文章标题返回 HTTP 500 Internal Server Error
- **根因:** DTO 缺少 `#[validate(length(max=255))]`,数据库列长度约束违反导致未处理的 DB 错误
- **修复:** 添加 DTO 长度校验 + 全局 DB 错误映射
- **预计工时:** 30min
### CATEGORY-02: 空分类名称被接受 (MEDIUM)
- 文章标题有空校验,标签名称有空校验,但分类名称没有
- **修复:** 添加 `#[validate(length(min=1))]`
## 8. 通用/跨切面 — 100% PASS
| ID | 测试 | 结果 |
|----|------|------|
| GENERIC-01 | 3 个并发更新 | PASS — 1 成功 + 2 冲突 (409) |
| GENERIC-02 | 错误 JSON body | PASS — 400 |
| GENERIC-03 | 缺少 Content-Type | PASS — 415 |
| GENERIC-04 | GET 带 body | PASS — body 被忽略 |
| GENERIC-05 | 超大页码 | PASS — 空列表 |
| GENERIC-06 | 快速连续请求 | PASS — 全 200 |
| GENERIC-07 | 不存在的文章 ID | PASS — 404 |
**亮点:** 乐观锁在并发下表现完美1 成功 + 2 冲突HTTP 状态码使用规范。
## 9. 失败项汇总
| ID | 严重性 | 模块 | 问题 | 修复 | 工时 |
|----|--------|------|------|------|------|
| H-06 | HIGH | 健康数据 | DTO-Entity 映射断裂 | 重构字段映射 | 4h |
| H-07 | HIGH | 内容管理 | 500 字符标题 → HTTP 500 | 添加 DTO 校验 | 30min |
| M-08 | MEDIUM | 健康数据 | 极端值无校验 | 添加范围校验 | 2h |
| M-09 | MEDIUM | 健康数据 | 未来 record_date | 添加日期校验 | 30min |
| M-10 | MEDIUM | 咨询 | XSS 存储未消毒 | HTML sanitize | 1h |
| M-11 | MEDIUM | 内容管理 | 空分类名被接受 | 添加 validate | 30min |
| M-12 | MEDIUM | 患者 | SQL 注入导致连接错误 | 调查 URL 编码 | 2h |
| M-13 | MEDIUM | 患者 | XSS 存储未消毒 | HTML sanitize | 1h |
| L-04 | LOW | 患者 | limit 无上限 | 设 max=200 | 30min |
| L-05 | LOW | 咨询 | 空描述被接受 | validate 或文档 | 30min |
| L-06 | LOW | 内容管理 | 重复标签名 | 唯一约束 | 1h |