Explorar o código

docs(health-data): 删除健康数据模块设计文档

- 删除血糖数据类型枚举设计文档
- 删除健康数据API接口规范文档
- 删除健康数据模块整体设计文档
- 移除相关模块设计说明和代码示例
mcbaiyun hai 1 mes
pai
achega
10de13f2be

+ 0 - 245
docs/DevDesign/HealthData/BloodGlucoseTypeEnumDesign.md

@@ -1,245 +0,0 @@
-# 血糖数据类型枚举设计
-
-## 概述
-
-本设计文档详细定义了血糖数据的分类标准和枚举设计。按照医疗专业规范,将血糖数据分为7个测量时间点,便于医生进行病情分析和诊断。
-
-## 血糖测量分类标准
-
-### 测量时间点定义
-
-1. **空腹血糖 (Fasting Blood Glucose)**
-   - 测量时间:早餐前(通常早上6:00-9:00)
-   - 临床意义:反映基础血糖水平,是糖尿病诊断的重要指标
-   - 正常范围:3.9-6.1 mmol/L
-   - 糖尿病诊断标准:≥7.0 mmol/L
-
-2. **早餐后血糖 (Postprandial Blood Glucose - Breakfast)**
-   - 测量时间:早餐后2小时
-   - 临床意义:反映碳水化合物摄入后的血糖反应
-   - 正常范围:≤7.8 mmol/L
-   - 糖尿病诊断标准:≥11.1 mmol/L
-
-3. **午餐前血糖 (Pre-lunch Blood Glucose)**
-   - 测量时间:午餐前(通常11:00-13:00)
-   - 临床意义:反映早餐后血糖控制情况
-   - 正常范围:3.9-7.2 mmol/L
-
-4. **午餐后血糖 (Postprandial Blood Glucose - Lunch)**
-   - 测量时间:午餐后2小时
-   - 临床意义:反映午餐碳水化合物摄入后的血糖反应
-   - 正常范围:≤7.8 mmol/L
-   - 糖尿病诊断标准:≥11.1 mmol/L
-
-5. **晚餐前血糖 (Pre-dinner Blood Glucose)**
-   - 测量时间:晚餐前(通常17:00-19:00)
-   - 临床意义:反映全天血糖控制趋势
-   - 正常范围:3.9-7.2 mmol/L
-
-6. **晚餐后血糖 (Postprandial Blood Glucose - Dinner)**
-   - 测量时间:晚餐后2小时
-   - 临床意义:反映晚餐碳水化合物摄入后的血糖反应
-   - 正常范围:≤7.8 mmol/L
-   - 糖尿病诊断标准:≥11.1 mmol/L
-
-7. **睡前血糖 (Bedtime Blood Glucose)**
-   - 测量时间:睡前(通常21:00-23:00)
-   - 临床意义:反映夜间血糖控制情况,影响晨起空腹血糖
-   - 正常范围:3.9-7.2 mmol/L
-
-## 枚举设计
-
-### 血糖类型枚举
-
-```java
-// BloodGlucoseType.java
-package work.baiyun.chronicdiseaseapp.enums;
-
-import com.baomidou.mybatisplus.annotation.EnumValue;
-import io.swagger.v3.oas.annotations.media.Schema;
-
-/**
- * 血糖测量类型枚举
- */
-@Schema(description = "血糖测量类型")
-public enum BloodGlucoseType {
-
-    @EnumValue
-    FASTING(1, "空腹", "早餐前测量", "mmol/L", "3.9-6.1"),
-
-    @EnumValue
-    AFTER_BREAKFAST(2, "早餐后", "早餐后2小时测量", "mmol/L", "≤7.8"),
-
-    @EnumValue
-    BEFORE_LUNCH(3, "午餐前", "午餐前测量", "mmol/L", "3.9-7.2"),
-
-    @EnumValue
-    AFTER_LUNCH(4, "午餐后", "午餐后2小时测量", "mmol/L", "≤7.8"),
-
-    @EnumValue
-    BEFORE_DINNER(5, "晚餐前", "晚餐前测量", "mmol/L", "3.9-7.2"),
-
-    @EnumValue
-    AFTER_DINNER(6, "晚餐后", "晚餐后2小时测量", "mmol/L", "≤7.8"),
-
-    @EnumValue
-    BEFORE_BED(7, "睡前", "睡前测量", "mmol/L", "3.9-7.2");
-
-    @Schema(description = "枚举值")
-    private final Integer code;
-
-    @Schema(description = "类型名称")
-    private final String name;
-
-    @Schema(description = "测量说明")
-    private final String description;
-
-    @Schema(description = "单位")
-    private final String unit;
-
-    @Schema(description = "正常参考范围")
-    private final String normalRange;
-
-    BloodGlucoseType(Integer code, String name, String description, String unit, String normalRange) {
-        this.code = code;
-        this.name = name;
-        this.description = description;
-        this.unit = unit;
-        this.normalRange = normalRange;
-    }
-
-    // Getters
-    public Integer getCode() {
-        return code;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public String getUnit() {
-        return unit;
-    }
-
-    public String getNormalRange() {
-        return normalRange;
-    }
-
-    /**
-     * 根据code获取枚举
-     */
-    public static BloodGlucoseType getByCode(Integer code) {
-        for (BloodGlucoseType type : values()) {
-            if (type.getCode().equals(code)) {
-                return type;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * 获取所有测量时间点的显示顺序
-     */
-    public static List<BloodGlucoseType> getOrderedTypes() {
-        return Arrays.asList(
-            FASTING,
-            AFTER_BREAKFAST,
-            BEFORE_LUNCH,
-            AFTER_LUNCH,
-            BEFORE_DINNER,
-            AFTER_DINNER,
-            BEFORE_BED
-        );
-    }
-}
-```
-
-### 血糖数据存储设计
-
-由于每个用户每天可能记录多个时间点的血糖数据,我们采用以下存储策略:
-
-1. **单表存储**:所有血糖数据存储在同一张表中,通过`measure_time`和用户ID区分
-2. **灵活录入**:用户可以选择录入任意时间点的血糖数据,不强制要求录入所有时间点
-3. **时间关联**:同一天的数据可以通过日期进行关联分析
-
-### 数据验证规则
-
-```java
-// 血糖数据验证注解示例
-@Schema(description = "血糖数据录入请求")
-public class AddBloodGlucoseDataRequest {
-
-    @Schema(description = "空腹血糖(mmol/L)", minimum = "1.0", maximum = "30.0")
-    @DecimalMin(value = "1.0", message = "血糖值不能低于1.0 mmol/L")
-    @DecimalMax(value = "30.0", message = "血糖值不能高于30.0 mmol/L")
-    private BigDecimal fastingBloodGlucose;
-
-    @Schema(description = "早餐后血糖(mmol/L)", minimum = "1.0", maximum = "30.0")
-    @DecimalMin(value = "1.0", message = "血糖值不能低于1.0 mmol/L")
-    @DecimalMax(value = "30.0", message = "血糖值不能高于30.0 mmol/L")
-    private BigDecimal afterBreakfastBloodGlucose;
-
-    // ... 其他字段
-
-    @Schema(description = "测量时间")
-    @NotNull(message = "测量时间不能为空")
-    private LocalDateTime measureTime;
-
-    // 自定义验证:至少填写一个血糖值
-    @AssertTrue(message = "至少需要录入一个血糖测量值")
-    public boolean isAtLeastOneValueProvided() {
-        return fastingBloodGlucose != null ||
-               afterBreakfastBloodGlucose != null ||
-               beforeLunchBloodGlucose != null ||
-               afterLunchBloodGlucose != null ||
-               beforeDinnerBloodGlucose != null ||
-               afterDinnerBloodGlucose != null ||
-               beforeBedBloodGlucose != null;
-    }
-
-    // getters and setters
-}
-```
-
-## 临床应用价值
-
-### 诊断价值
-1. **糖尿病诊断**:通过空腹血糖和餐后血糖综合判断
-2. **血糖控制评估**:观察不同时间点的血糖波动
-3. **治疗效果监测**:跟踪药物治疗对血糖的影响
-
-### 数据分析价值
-1. **血糖模式识别**:识别血糖控制模式(黎明现象、餐后高血糖等)
-2. **趋势分析**:观察长期血糖控制趋势
-3. **个性化治疗**:为医生提供精准治疗依据
-
-## 扩展性考虑
-
-### 未来扩展
-1. **更多时间点**:如凌晨2-3点血糖监测
-2. **连续血糖监测**:支持CGM设备数据接入
-3. **血糖目标设置**:根据患者情况设置个性化血糖目标
-4. **智能提醒**:根据历史数据智能提醒测量时间
-
-### 兼容性
-- 向后兼容:现有数据结构保持不变
-- 向前兼容:新功能不影响现有功能使用
-
-## 注意事项
-
-1. **测量时机**:严格按照定义的时间点进行测量
-2. **测量方法**:建议使用标准血糖仪,确保测量准确性
-3. **数据记录**:鼓励用户完整记录,便于医生分析
-4. **异常处理**:对异常血糖值进行预警提醒
-5. **隐私保护**:血糖数据属于敏感医疗数据,严格保护隐私
-
-## 参考标准
-
-- WHO糖尿病诊断标准
-- ADA血糖控制目标
-- 中国糖尿病防治指南
-- 国际糖尿病联盟(IDF)标准

+ 0 - 369
docs/DevDesign/HealthData/HealthDataAPIDocument.md

@@ -1,369 +0,0 @@
-# 健康数据模块API接口规范
-
-## 概述
-
-本文档详细定义了健康数据模块的API接口规范,包括4个子模块的完整接口定义。所有接口遵循RESTful设计理念,采用统一的请求/响应格式。
-
-## 公共规范
-
-### 请求格式
-- **Content-Type**: `application/json`
-- **认证方式**: Bearer Token (`Authorization: Bearer <token>`)
-- **参数校验**: 使用Bean Validation注解
-
-### 响应格式
-```json
-{
-    "code": "SUCCESS",
-    "message": "操作成功",
-    "data": {}
-}
-```
-
-### 分页响应格式
-```json
-{
-    "code": "SUCCESS",
-    "message": "查询成功",
-    "data": {
-        "records": [],
-        "current": 1,
-        "size": 10,
-        "total": 100
-    }
-}
-```
-
-### 错误响应格式
-```json
-{
-    "code": "PARAM_ERROR",
-    "message": "参数校验失败",
-    "data": null
-}
-```
-
-## 体格数据模块API
-
-### 1. 添加体格数据
-- **接口路径**: `POST /physical-data/add`
-- **功能描述**: 添加用户的体格数据(身高、体重)
-- **请求参数**:
-```json
-{
-    "height": 170.5,
-    "weight": 65.2,
-    "measureTime": "2024-01-15T10:30:00"
-}
-```
-- **参数说明**:
-  - `height`: 身高(cm),范围100-250,必填
-  - `weight`: 体重(kg),范围20-300,必填
-  - `measureTime`: 测量时间,必填
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "添加成功",
-    "data": null
-}
-```
-
-### 2. 查询体格数据列表
-- **接口路径**: `POST /physical-data/list`
-- **功能描述**: 分页查询用户的体格数据历史记录
-- **请求参数**:
-```json
-{
-    "pageNum": 1,
-    "pageSize": 10,
-    "startTime": "2024-01-01T00:00:00",
-    "endTime": "2024-01-31T23:59:59"
-}
-```
-- **参数说明**:
-  - `pageNum`: 页码,默认1
-  - `pageSize`: 每页大小,默认10,最大100
-  - `startTime`: 开始时间,可选
-  - `endTime`: 结束时间,可选
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "查询成功",
-    "data": {
-        "records": [
-            {
-                "id": 1,
-                "height": 170.5,
-                "weight": 65.2,
-                "bmi": 22.45,
-                "measureTime": "2024-01-15T10:30:00",
-                "createTime": "2024-01-15T10:35:00"
-            }
-        ],
-        "current": 1,
-        "size": 10,
-        "total": 1
-    }
-}
-```
-
-### 3. 计算BMI
-- **接口路径**: `GET /physical-data/bmi`
-- **功能描述**: 根据身高体重计算BMI值
-- **请求参数**: Query参数
-  - `height`: 身高(cm),范围100-250,必填
-  - `weight`: 体重(kg),范围20-300,必填
-- **请求示例**: `GET /physical-data/bmi?height=170.5&weight=65.2`
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "计算成功",
-    "data": 22.45
-}
-```
-
-## 血压数据模块API
-
-### 1. 添加血压数据
-- **接口路径**: `POST /blood-pressure-data/add`
-- **功能描述**: 添加用户的血压数据
-- **请求参数**:
-```json
-{
-    "systolicPressure": 120,
-    "diastolicPressure": 80,
-    "measureTime": "2024-01-15T10:30:00"
-}
-```
-- **参数说明**:
-  - `systolicPressure`: 收缩压(mmHg),范围60-250,必填
-  - `diastolicPressure`: 舒张压(mmHg),范围40-150,必填
-  - `measureTime`: 测量时间,必填
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "添加成功",
-    "data": null
-}
-```
-
-### 2. 查询血压数据列表
-- **接口路径**: `POST /blood-pressure-data/list`
-- **功能描述**: 分页查询用户的血压数据历史记录
-- **请求参数**:
-```json
-{
-    "pageNum": 1,
-    "pageSize": 10,
-    "startTime": "2024-01-01T00:00:00",
-    "endTime": "2024-01-31T23:59:59"
-}
-```
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "查询成功",
-    "data": {
-        "records": [
-            {
-                "id": 1,
-                "systolicPressure": 120,
-                "diastolicPressure": 80,
-                "measureTime": "2024-01-15T10:30:00",
-                "createTime": "2024-01-15T10:35:00"
-            }
-        ],
-        "current": 1,
-        "size": 10,
-        "total": 1
-    }
-}
-```
-
-## 血糖数据模块API
-
-### 1. 添加血糖数据
-- **接口路径**: `POST /blood-glucose-data/add`
-- **功能描述**: 添加用户的血糖数据
-- **请求参数**:
-```json
-{
-    "type": "FASTING",
-    "value": 5.2,
-    "measureTime": "2024-01-15T10:30:00"
-}
-```
-- **参数说明**:
-  - `type`: 血糖测量类型,枚举值(如`FASTING`、`AFTER_BREAKFAST`等),必填
-  - `value`: 血糖值(mmol/L),范围1.0-30.0,必填
-  - `measureTime`: 测量时间,必填
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "添加成功",
-    "data": null
-}
-```
-
-### 2. 查询血糖数据列表
-- **接口路径**: `POST /blood-glucose-data/list`
-- **功能描述**: 分页查询用户的血糖数据历史记录
-- **请求参数**:
-```json
-{
-    "pageNum": 1,
-    "pageSize": 10,
-    "startTime": "2024-01-01T00:00:00",
-    "endTime": "2024-01-31T23:59:59"
-}
-```
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "查询成功",
-    "data": {
-        "records": [
-            {
-                "id": 1,
-                "fastingBloodGlucose": 5.2,
-                "afterBreakfastBloodGlucose": 8.5,
-                "beforeLunchBloodGlucose": 6.1,
-                "afterLunchBloodGlucose": 9.2,
-                "beforeDinnerBloodGlucose": 5.8,
-                "afterDinnerBloodGlucose": 8.9,
-                "beforeBedBloodGlucose": 7.3,
-                "measureTime": "2024-01-15T10:30:00",
-                "createTime": "2024-01-15T10:35:00"
-            }
-        ],
-        "current": 1,
-        "size": 10,
-        "total": 1
-    }
-}
-```
-
-## 心率数据模块API
-
-### 1. 添加心率数据
-- **接口路径**: `POST /heart-rate-data/add`
-- **功能描述**: 添加用户的心率数据
-- **请求参数**:
-```json
-{
-    "heartRate": 75,
-    "measureTime": "2024-01-15T10:30:00"
-}
-```
-- **参数说明**:
-  - `heartRate`: 心率(次/分钟),范围30-200,必填
-  - `measureTime`: 测量时间,必填
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "添加成功",
-    "data": null
-}
-```
-
-### 2. 查询心率数据列表
-- **接口路径**: `POST /heart-rate-data/list`
-- **功能描述**: 分页查询用户的心率数据历史记录
-- **请求参数**:
-```json
-{
-    "pageNum": 1,
-    "pageSize": 10,
-    "startTime": "2024-01-01T00:00:00",
-    "endTime": "2024-01-31T23:59:59"
-}
-```
-- **响应示例**:
-```json
-{
-    "code": "SUCCESS",
-    "message": "查询成功",
-    "data": {
-        "records": [
-            {
-                "id": 1,
-                "heartRate": 75,
-                "measureTime": "2024-01-15T10:30:00",
-                "createTime": "2024-01-15T10:35:00"
-            }
-        ],
-        "current": 1,
-        "size": 10,
-        "total": 1
-    }
-}
-```
-
-## 错误码定义
-
-### 通用错误码
-- `SUCCESS`: 操作成功
-- `PARAM_ERROR`: 参数校验失败
-- `SYSTEM_ERROR`: 系统内部错误
-- `UNAUTHORIZED`: 未授权访问
-- `FORBIDDEN`: 权限不足
-
-### 业务错误码
-- `DATA_NOT_FOUND`: 数据不存在
-- `DATA_ALREADY_EXISTS`: 数据已存在
-- `INVALID_MEASURE_TIME`: 无效的测量时间
-- `INVALID_DATA_RANGE`: 数据超出有效范围
-
-## 接口调用示例
-
-### 添加体格数据
-```bash
-curl -X POST "http://localhost:8080/physical-data/add" \
-  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-  -H "Content-Type: application/json" \
-  -d '{
-    "height": 170.5,
-    "weight": 65.2,
-    "measureTime": "2024-01-15T10:30:00"
-  }'
-```
-
-### 查询体格数据
-```bash
-curl -X POST "http://localhost:8080/physical-data/list" \
-  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-  -H "Content-Type: application/json" \
-  -d '{
-    "pageNum": 1,
-    "pageSize": 10
-  }'
-```
-
-### 计算BMI
-```bash
-curl -X GET "http://localhost:8080/physical-data/bmi?height=170.5&weight=65.2" \
-  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
-```
-
-## 注意事项
-
-1. **数据单位**: 严格按照接口文档中定义的单位进行数据录入
-2. **时间格式**: 所有时间字段使用ISO 8601格式
-3. **分页参数**: 页码从1开始,每页大小不超过100
-4. **权限控制**: 所有接口都需要有效的用户认证
-5. **数据校验**: 前端应进行初步校验,后端会进行二次校验
-6. **并发控制**: 高频数据录入时注意避免重复提交
-
-## 版本信息
-
-- **API版本**: v1.0
-- **文档版本**: 1.0
-- **更新日期**: 2024-01-15

+ 0 - 980
docs/DevDesign/HealthData/HealthDataModuleDesign.md

@@ -1,980 +0,0 @@
-# 健康数据模块设计文档
-
-## 概述
-
-本设计文档针对慢病APP增加病人用户健康数据模块的需求进行详细设计。模块包含身高、体重、BMI(自动计算)、血压、血糖(空腹、早餐后、午餐前、午餐后、晚餐前、晚餐后、睡前)、心率等健康指标的记录和管理功能。
-
-**重要更新**:根据需求,每种类型的健康数据需要独立存储和独立的接口。因此,健康数据模块将被拆分为以下4个独立子模块:
-
-1. **体格数据模块**:身高、体重数据存储,BMI自动计算
-2. **血压数据模块**:收缩压、舒张压数据存储
-3. **血糖数据模块**:空腹血糖、早餐后血糖、午餐前血糖、午餐后血糖、晚餐前血糖、晚餐后血糖、睡前血糖数据存储
-4. **心率数据模块**:心率数据存储
-
-每个子模块独立设计,包含独立的数据库表、数据模型、接口和服务。
-
-## 需求分析
-
-### 功能需求
-1. **数据录入**:支持用户录入各项健康数据
-2. **数据查询**:支持查询历史健康数据,支持分页查询
-3. **BMI计算**:根据身高体重自动计算BMI,不存储计算结果
-4. **数据验证**:对输入数据进行合理性校验
-5. **权限控制**:基于用户角色控制数据访问权限
-
-### 数据项说明
-- **体格数据**:
-  - 身高:单位cm,范围100-250cm
-  - 体重:单位kg,范围20-300kg
-  - BMI:自动计算,身高体重/100^2,不存储
-- **血压数据**:
-  - 收缩压:单位mmHg,范围60-250
-  - 舒张压:单位mmHg,范围40-150
-- **血糖数据**:
-  - 空腹血糖:早餐前测量,单位mmol/L,范围1.0-30.0
-  - 早餐后血糖:早餐后2小时测量,单位mmol/L,范围1.0-30.0
-  - 午餐前血糖:午餐前测量,单位mmol/L,范围1.0-30.0
-  - 午餐后血糖:午餐后2小时测量,单位mmol/L,范围1.0-30.0
-  - 晚餐前血糖:晚餐前测量,单位mmol/L,范围1.0-30.0
-  - 晚餐后血糖:晚餐后2小时测量,单位mmol/L,范围1.0-30.0
-  - 睡前血糖:睡前测量,单位mmol/L,范围1.0-30.0
-- **心率数据**:
-  - 心率:单位次/分钟,范围30-200
-
-## 设计原则
-
-### 遵循规范
-- 严格遵循项目结构规范(02-项目结构规范.md)
-- 遵循API设计规范(03-API设计规范.md)
-- 遵循数据库规范(07-数据库规范.md)
-- 遵循安全规范(08-安全规范.md)
-
-### 设计原则
-1. **模块独立性**:每个健康数据类型独立存储和管理
-2. **数据完整性**:确保数据录入的准确性和完整性
-3. **性能优化**:合理设计索引,支持高效查询
-4. **扩展性**:预留扩展空间,支持未来增加更多健康指标
-5. **安全性**:基于角色权限控制数据访问
-6. **血糖分类**:按照医疗标准对血糖进行精细分类,便于医生分析病情
-
-### 血糖测量类型枚举
-```java
-// BloodGlucoseType.java
-public enum BloodGlucoseType {
-    FASTING("空腹", "早餐前测量"),
-    AFTER_BREAKFAST("早餐后", "早餐后2小时测量"),
-    BEFORE_LUNCH("午餐前", "午餐前测量"),
-    AFTER_LUNCH("午餐后", "午餐后2小时测量"),
-    BEFORE_DINNER("晚餐前", "晚餐前测量"),
-    AFTER_DINNER("晚餐后", "晚餐后2小时测量"),
-    BEFORE_BED("睡前", "睡前测量");
-
-    private final String name;
-    private final String description;
-
-    BloodGlucoseType(String name, String description) {
-        this.name = name;
-        this.description = description;
-    }
-
-    // getters
-}
-```
-
-## 模块架构
-
-### 总体架构
-```
-健康数据模块
-├── 体格数据子模块 (PhysicalData)
-│   ├── 数据库表:t_physical_data
-│   ├── PO:PhysicalData
-│   ├── VO:AddPhysicalDataRequest, PhysicalDataResponse等
-│   ├── Controller:PhysicalDataController
-│   ├── Service:PhysicalDataService
-│   └── Mapper:PhysicalDataMapper
-├── 血压数据子模块 (BloodPressureData)
-│   ├── 数据库表:t_blood_pressure_data
-│   ├── PO:BloodPressureData
-│   ├── VO:AddBloodPressureDataRequest, BloodPressureDataResponse等
-│   ├── Controller:BloodPressureDataController
-│   ├── Service:BloodPressureDataService
-│   └── Mapper:BloodPressureDataMapper
-├── 血糖数据子模块 (BloodGlucoseData)
-│   ├── 数据库表:t_blood_glucose_data
-│   ├── PO:BloodGlucoseData
-│   ├── VO:AddBloodGlucoseDataRequest, BloodGlucoseDataResponse等
-│   ├── Controller:BloodGlucoseDataController
-│   ├── Service:BloodGlucoseDataService
-│   └── Mapper:BloodGlucoseDataMapper
-└── 心率数据子模块 (HeartRateData)
-    ├── 数据库表:t_heart_rate_data
-    ├── PO:HeartRateData
-    ├── VO:AddHeartRateDataRequest, HeartRateDataResponse等
-    ├── Controller:HeartRateDataController
-    ├── Service:HeartRateDataService
-    └── Mapper:HeartRateDataMapper
-```
-
-### 公共组件
-- 统一的查询请求基类:`BaseQueryRequest`
-- 统一的分页响应基类:`BasePageResponse<T>`
-- 统一的业务异常处理
-- 统一的用户权限验证
-
-## 数据库设计
-
-### 体格数据表 (t_physical_data)
-```sql
-CREATE TABLE t_physical_data (
-    id BIGINT PRIMARY KEY COMMENT '主键ID',
-    user_id BIGINT NOT NULL COMMENT '用户ID',
-    height DECIMAL(5,2) COMMENT '身高(cm)',
-    weight DECIMAL(5,2) COMMENT '体重(kg)',
-    measure_time DATETIME NOT NULL COMMENT '测量时间',
-    create_user BIGINT COMMENT '创建者ID',
-    create_time DATETIME COMMENT '创建时间',
-    update_user BIGINT COMMENT '更新者ID',
-    update_time DATETIME COMMENT '更新时间',
-    version INT DEFAULT 0 COMMENT '乐观锁版本号'
-) COMMENT '体格数据表';
-
--- 索引设计
-CREATE INDEX idx_physical_user_measure_time ON t_physical_data(user_id, measure_time);
-CREATE INDEX idx_physical_user_id ON t_physical_data(user_id);
-```
-
-### 血压数据表 (t_blood_pressure_data)
-```sql
-CREATE TABLE t_blood_pressure_data (
-    id BIGINT PRIMARY KEY COMMENT '主键ID',
-    user_id BIGINT NOT NULL COMMENT '用户ID',
-    systolic_pressure INT COMMENT '收缩压(mmHg)',
-    diastolic_pressure INT COMMENT '舒张压(mmHg)',
-    measure_time DATETIME NOT NULL COMMENT '测量时间',
-    create_user BIGINT COMMENT '创建者ID',
-    create_time DATETIME COMMENT '创建时间',
-    update_user BIGINT COMMENT '更新者ID',
-    update_time DATETIME COMMENT '更新时间',
-    version INT DEFAULT 0 COMMENT '乐观锁版本号'
-) COMMENT '血压数据表';
-
--- 索引设计
-CREATE INDEX idx_bp_user_measure_time ON t_blood_pressure_data(user_id, measure_time);
-CREATE INDEX idx_bp_user_id ON t_blood_pressure_data(user_id);
-```
-
-### 血糖数据表 (t_blood_glucose_data)
-```sql
-CREATE TABLE t_blood_glucose_data (
-    id BIGINT PRIMARY KEY COMMENT '主键ID',
-    user_id BIGINT NOT NULL COMMENT '用户ID',
-    measure_time DATETIME NOT NULL COMMENT '测量时间',
-    type VARCHAR(50) NOT NULL COMMENT '血糖测量类型',
-    value DECIMAL(5, 2) NOT NULL COMMENT '血糖值',
-    version INT DEFAULT 0 COMMENT '乐观锁版本号'
-) COMMENT '血糖数据表';
-
--- 索引设计
-CREATE INDEX idx_bg_user_measure_time ON t_blood_glucose_data(user_id, measure_time);
-CREATE INDEX idx_bg_user_id ON t_blood_glucose_data(user_id);
-CREATE INDEX idx_bg_type ON t_blood_glucose_data(type);
-```
-
-### 心率数据表 (t_heart_rate_data)
-```sql
-CREATE TABLE t_heart_rate_data (
-    id BIGINT PRIMARY KEY COMMENT '主键ID',
-    user_id BIGINT NOT NULL COMMENT '用户ID',
-    heart_rate INT COMMENT '心率(次/分钟)',
-    measure_time DATETIME NOT NULL COMMENT '测量时间',
-    create_user BIGINT COMMENT '创建者ID',
-    create_time DATETIME COMMENT '创建时间',
-    update_user BIGINT COMMENT '更新者ID',
-    update_time DATETIME COMMENT '更新时间',
-    version INT DEFAULT 0 COMMENT '乐观锁版本号'
-) COMMENT '心率数据表';
-
--- 索引设计
-CREATE INDEX idx_hr_user_measure_time ON t_heart_rate_data(user_id, measure_time);
-CREATE INDEX idx_hr_user_id ON t_heart_rate_data(user_id);
-```
-
-### 字段说明
-- `id`:主键,使用雪花算法生成
-- `user_id`:关联用户ID
-- `measure_time`:数据测量时间
-- 各模块特有字段:
-  - 体格数据:`height`(身高), `weight`(体重)
-  - 血压数据:`systolic_pressure`(收缩压), `diastolic_pressure`(舒张压)
-  - 血糖数据:`type`(血糖测量类型), `value`(血糖值)
-  - 心率数据:`heart_rate`(心率)
-- 继承BaseEntity的公共字段
-
-## 数据模型设计
-
-### PO (持久化对象)
-
-#### 体格数据PO
-```java
-// PhysicalData.java
-@TableName("t_physical_data")
-public class PhysicalData extends BaseEntity {
-    @TableField("user_id")
-    private Long userId;
-
-    @TableField("height")
-    private BigDecimal height;
-
-    @TableField("weight")
-    private BigDecimal weight;
-
-    @TableField("measure_time")
-    private LocalDateTime measureTime;
-
-    // getters and setters
-}
-```
-
-#### 血压数据PO
-```java
-// BloodPressureData.java
-@TableName("t_blood_pressure_data")
-public class BloodPressureData extends BaseEntity {
-    @TableField("user_id")
-    private Long userId;
-
-    @TableField("systolic_pressure")
-    private Integer systolicPressure;
-
-    @TableField("diastolic_pressure")
-    private Integer diastolicPressure;
-
-    @TableField("measure_time")
-    private LocalDateTime measureTime;
-
-    // getters and setters
-}
-```
-
-#### 血糖数据PO
-```java
-// BloodGlucoseData.java
-@TableName("t_blood_glucose_data")
-public class BloodGlucoseData extends BaseEntity {
-    @TableField("user_id")
-    private Long userId;
-
-    @TableField("measure_time")
-    private LocalDateTime measureTime;
-
-    @TableField("type")
-    private String type;
-
-    @TableField("value")
-    private BigDecimal value;
-
-    // getters and setters
-}
-```
-
-#### 心率数据PO
-```java
-// HeartRateData.java
-@TableName("t_heart_rate_data")
-public class HeartRateData extends BaseEntity {
-    @TableField("user_id")
-    private Long userId;
-
-    @TableField("heart_rate")
-    private Integer heartRate;
-
-    @TableField("measure_time")
-    private LocalDateTime measureTime;
-
-    // getters and setters
-}
-```
-
-### VO (视图对象)
-
-#### 公共查询请求基类
-```java
-// BaseQueryRequest.java
-@Schema(description = "基础查询请求")
-public class BaseQueryRequest {
-    @Schema(description = "页码", minimum = "1", defaultValue = "1")
-    @Min(1)
-    private Integer pageNum = 1;
-
-    @Schema(description = "每页大小", minimum = "1", maximum = "100", defaultValue = "10")
-    @Min(1) @Max(100)
-    private Integer pageSize = 10;
-
-    @Schema(description = "开始时间")
-    private LocalDateTime startTime;
-
-    @Schema(description = "结束时间")
-    private LocalDateTime endTime;
-
-    // getters and setters
-}
-```
-
-#### 体格数据VO
-```java
-// AddPhysicalDataRequest.java
-@Schema(description = "添加体格数据请求")
-public class AddPhysicalDataRequest {
-    @Schema(description = "身高(cm)", minimum = "100", maximum = "250")
-    @DecimalMin("100") @DecimalMax("250")
-    private BigDecimal height;
-
-    @Schema(description = "体重(kg)", minimum = "20", maximum = "300")
-    @DecimalMin("20") @DecimalMax("300")
-    private BigDecimal weight;
-
-    @Schema(description = "测量时间")
-    @NotNull
-    private LocalDateTime measureTime;
-
-    // getters and setters
-}
-
-// PhysicalDataResponse.java
-@Schema(description = "体格数据响应")
-public class PhysicalDataResponse {
-    @Schema(description = "记录ID")
-    private Long id;
-
-    @Schema(description = "身高(cm)")
-    private BigDecimal height;
-
-    @Schema(description = "体重(kg)")
-    private BigDecimal weight;
-
-    @Schema(description = "BMI")
-    private BigDecimal bmi;
-
-    @Schema(description = "测量时间")
-    private LocalDateTime measureTime;
-
-    @Schema(description = "创建时间")
-    private LocalDateTime createTime;
-
-    // getters and setters
-}
-```
-
-#### 血压数据VO
-```java
-// AddBloodPressureDataRequest.java
-@Schema(description = "添加血压数据请求")
-public class AddBloodPressureDataRequest {
-    @Schema(description = "收缩压(mmHg)", minimum = "60", maximum = "250")
-    @Min(60) @Max(250)
-    private Integer systolicPressure;
-
-    @Schema(description = "舒张压(mmHg)", minimum = "40", maximum = "150")
-    @Min(40) @Max(150)
-    private Integer diastolicPressure;
-
-    @Schema(description = "测量时间")
-    @NotNull
-    private LocalDateTime measureTime;
-
-    // getters and setters
-}
-
-// BloodPressureDataResponse.java
-@Schema(description = "血压数据响应")
-public class BloodPressureDataResponse {
-    @Schema(description = "记录ID")
-    private Long id;
-
-    @Schema(description = "收缩压(mmHg)")
-    private Integer systolicPressure;
-
-    @Schema(description = "舒张压(mmHg)")
-    private Integer diastolicPressure;
-
-    @Schema(description = "测量时间")
-    private LocalDateTime measureTime;
-
-    @Schema(description = "创建时间")
-    private LocalDateTime createTime;
-
-    // getters and setters
-}
-```
-
-#### 血糖数据VO
-```java
-// AddBloodGlucoseDataRequest.java
-@Schema(description = "添加血糖数据请求")
-public class AddBloodGlucoseDataRequest {
-    @Schema(description = "测量时间")
-    @NotNull
-    private LocalDateTime measureTime;
-
-    @Schema(description = "血糖测量类型")
-    @NotNull
-    private String type;
-
-    @Schema(description = "血糖值", minimum = "1.0", maximum = "30.0")
-    @DecimalMin("1.0") @DecimalMax("30.0")
-    private BigDecimal value;
-
-    // getters and setters
-}
-
-// BloodGlucoseDataResponse.java
-@Schema(description = "血糖数据响应")
-public class BloodGlucoseDataResponse {
-    @Schema(description = "记录ID")
-    private Long id;
-
-    @Schema(description = "测量时间")
-    private LocalDateTime measureTime;
-
-    @Schema(description = "血糖测量类型")
-    private String type;
-
-    @Schema(description = "血糖值")
-    private BigDecimal value;
-
-    @Schema(description = "创建时间")
-    private LocalDateTime createTime;
-
-    // getters and setters
-}
-```
-
-#### 心率数据VO
-```java
-// AddHeartRateDataRequest.java
-@Schema(description = "添加心率数据请求")
-public class AddHeartRateDataRequest {
-    @Schema(description = "心率(次/分钟)", minimum = "30", maximum = "200")
-    @Min(30) @Max(200)
-    private Integer heartRate;
-
-    @Schema(description = "测量时间")
-    @NotNull
-    private LocalDateTime measureTime;
-
-    // getters and setters
-}
-
-// HeartRateDataResponse.java
-@Schema(description = "心率数据响应")
-public class HeartRateDataResponse {
-    @Schema(description = "记录ID")
-    private Long id;
-
-    @Schema(description = "心率(次/分钟)")
-    private Integer heartRate;
-
-    @Schema(description = "测量时间")
-    private LocalDateTime measureTime;
-
-    @Schema(description = "创建时间")
-    private LocalDateTime createTime;
-
-    // getters and setters
-}
-```
-
-## 接口设计
-
-### 体格数据模块接口
-
-#### Controller层
-```java
-@RestController
-@RequestMapping("/physical-data")
-@Tag(name = "体格数据管理", description = "病人体格数据相关接口")
-public class PhysicalDataController {
-
-    @Autowired
-    private PhysicalDataService physicalDataService;
-
-    @PostMapping("/add")
-    @Operation(summary = "添加体格数据")
-    public R<Void> addPhysicalData(@RequestBody @Valid AddPhysicalDataRequest request) {
-        physicalDataService.addPhysicalData(request);
-        return R.success(SuccessResultCode.SUCCESS, "添加成功", null);
-    }
-
-    @PostMapping("/list")
-    @Operation(summary = "查询体格数据列表")
-    public R<Page<PhysicalDataResponse>> listPhysicalData(@RequestBody @Valid BaseQueryRequest request) {
-        Page<PhysicalDataResponse> response = physicalDataService.listPhysicalData(request);
-        return R.success(SuccessResultCode.SUCCESS, "查询成功", response);
-    }
-
-    @GetMapping("/bmi")
-    @Operation(summary = "计算BMI")
-    public R<BigDecimal> calculateBMI(@RequestParam @DecimalMin("100") @DecimalMax("250") BigDecimal height,
-                                     @RequestParam @DecimalMin("20") @DecimalMax("300") BigDecimal weight) {
-        BigDecimal bmi = physicalDataService.calculateBMI(height, weight);
-        return R.success(SuccessResultCode.SUCCESS, "计算成功", bmi);
-    }
-}
-```
-
-#### Service层
-```java
-public interface PhysicalDataService {
-    void addPhysicalData(AddPhysicalDataRequest request);
-    Page<PhysicalDataResponse> listPhysicalData(BaseQueryRequest request);
-    BigDecimal calculateBMI(BigDecimal height, BigDecimal weight);
-}
-
-@Service
-public class PhysicalDataServiceImpl implements PhysicalDataService {
-
-    @Autowired
-    private PhysicalDataMapper physicalDataMapper;
-
-    @Override
-    public void addPhysicalData(AddPhysicalDataRequest request) {
-        Long userId = getCurrentUserId();
-
-        PhysicalData physicalData = new PhysicalData();
-        BeanUtils.copyProperties(request, physicalData);
-        physicalData.setUserId(userId);
-
-        physicalDataMapper.insert(physicalData);
-    }
-
-    @Override
-    public Page<PhysicalDataResponse> listPhysicalData(BaseQueryRequest request) {
-        Long userId = getCurrentUserId();
-
-        Page<PhysicalData> page = new Page<>(request.getPageNum(), request.getPageSize());
-        LambdaQueryWrapper<PhysicalData> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(PhysicalData::getUserId, userId)
-               .ge(request.getStartTime() != null, PhysicalData::getMeasureTime, request.getStartTime())
-               .le(request.getEndTime() != null, PhysicalData::getMeasureTime, request.getEndTime())
-               .orderByDesc(PhysicalData::getMeasureTime);
-
-        Page<PhysicalData> result = physicalDataMapper.selectPage(page, wrapper);
-
-        // 转换为响应对象,计算BMI
-        List<PhysicalDataResponse> responses = result.getRecords().stream()
-            .map(this::convertToResponse)
-            .collect(Collectors.toList());
-
-        Page<PhysicalDataResponse> responsePage = new Page<>();
-        responsePage.setRecords(responses);
-        responsePage.setCurrent(result.getCurrent());
-        responsePage.setSize(result.getSize());
-        responsePage.setTotal(result.getTotal());
-
-        return responsePage;
-    }
-
-    @Override
-    public BigDecimal calculateBMI(BigDecimal height, BigDecimal weight) {
-        if (height == null || weight == null || height.compareTo(BigDecimal.ZERO) <= 0) {
-            return BigDecimal.ZERO;
-        }
-        // BMI = 体重(kg) / [身高(m)]^2
-        BigDecimal heightInMeters = height.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
-        return weight.divide(heightInMeters.pow(2), 2, RoundingMode.HALF_UP);
-    }
-
-    private PhysicalDataResponse convertToResponse(PhysicalData physicalData) {
-        PhysicalDataResponse response = new PhysicalDataResponse();
-        BeanUtils.copyProperties(physicalData, response);
-        // 计算BMI
-        response.setBmi(calculateBMI(physicalData.getHeight(), physicalData.getWeight()));
-        return response;
-    }
-
-    private Long getCurrentUserId() {
-        // 从安全上下文中获取当前用户ID
-        return 1L; // 临时实现
-    }
-}
-```
-
-#### Mapper层
-```java
-@Mapper
-public interface PhysicalDataMapper extends BaseMapper<PhysicalData> {
-}
-```
-
-### 血压数据模块接口
-
-#### Controller层
-```java
-@RestController
-@RequestMapping("/blood-pressure-data")
-@Tag(name = "血压数据管理", description = "病人血压数据相关接口")
-public class BloodPressureDataController {
-
-    @Autowired
-    private BloodPressureDataService bloodPressureDataService;
-
-    @PostMapping("/add")
-    @Operation(summary = "添加血压数据")
-    public R<Void> addBloodPressureData(@RequestBody @Valid AddBloodPressureDataRequest request) {
-        bloodPressureDataService.addBloodPressureData(request);
-        return R.success(SuccessResultCode.SUCCESS, "添加成功", null);
-    }
-
-    @PostMapping("/list")
-    @Operation(summary = "查询血压数据列表")
-    public R<Page<BloodPressureDataResponse>> listBloodPressureData(@RequestBody @Valid BaseQueryRequest request) {
-        Page<BloodPressureDataResponse> response = bloodPressureDataService.listBloodPressureData(request);
-        return R.success(SuccessResultCode.SUCCESS, "查询成功", response);
-    }
-}
-```
-
-#### Service层
-```java
-public interface BloodPressureDataService {
-    void addBloodPressureData(AddBloodPressureDataRequest request);
-    Page<BloodPressureDataResponse> listBloodPressureData(BaseQueryRequest request);
-}
-
-@Service
-public class BloodPressureDataServiceImpl implements BloodPressureDataService {
-
-    @Autowired
-    private BloodPressureDataMapper bloodPressureDataMapper;
-
-    @Override
-    public void addBloodPressureData(AddBloodPressureDataRequest request) {
-        Long userId = getCurrentUserId();
-
-        BloodPressureData bloodPressureData = new BloodPressureData();
-        BeanUtils.copyProperties(request, bloodPressureData);
-        bloodPressureData.setUserId(userId);
-
-        bloodPressureDataMapper.insert(bloodPressureData);
-    }
-
-    @Override
-    public Page<BloodPressureDataResponse> listBloodPressureData(BaseQueryRequest request) {
-        Long userId = getCurrentUserId();
-
-        Page<BloodPressureData> page = new Page<>(request.getPageNum(), request.getPageSize());
-        LambdaQueryWrapper<BloodPressureData> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(BloodPressureData::getUserId, userId)
-               .ge(request.getStartTime() != null, BloodPressureData::getMeasureTime, request.getStartTime())
-               .le(request.getEndTime() != null, BloodPressureData::getMeasureTime, request.getEndTime())
-               .orderByDesc(BloodPressureData::getMeasureTime);
-
-        Page<BloodPressureData> result = bloodPressureDataMapper.selectPage(page, wrapper);
-
-        List<BloodPressureDataResponse> responses = result.getRecords().stream()
-            .map(record -> {
-                BloodPressureDataResponse response = new BloodPressureDataResponse();
-                BeanUtils.copyProperties(record, response);
-                return response;
-            })
-            .collect(Collectors.toList());
-
-        Page<BloodPressureDataResponse> responsePage = new Page<>();
-        responsePage.setRecords(responses);
-        responsePage.setCurrent(result.getCurrent());
-        responsePage.setSize(result.getSize());
-        responsePage.setTotal(result.getTotal());
-
-        return responsePage;
-    }
-
-    private Long getCurrentUserId() {
-        // 从安全上下文中获取当前用户ID
-        return 1L; // 临时实现
-    }
-}
-```
-
-#### Mapper层
-```java
-@Mapper
-public interface BloodPressureDataMapper extends BaseMapper<BloodPressureData> {
-}
-```
-
-### 血糖数据模块接口
-
-#### Controller层
-```java
-@RestController
-@RequestMapping("/blood-glucose-data")
-@Tag(name = "血糖数据管理", description = "病人血糖数据相关接口")
-public class BloodGlucoseDataController {
-
-    @Autowired
-    private BloodGlucoseDataService bloodGlucoseDataService;
-
-    @PostMapping("/add")
-    @Operation(summary = "添加血糖数据")
-    public R<Void> addBloodGlucoseData(@RequestBody @Valid AddBloodGlucoseDataRequest request) {
-        bloodGlucoseDataService.addBloodGlucoseData(request);
-        return R.success(SuccessResultCode.SUCCESS, "添加成功", null);
-    }
-
-    @PostMapping("/list")
-    @Operation(summary = "查询血糖数据列表")
-    public R<Page<BloodGlucoseDataResponse>> listBloodGlucoseData(@RequestBody @Valid BaseQueryRequest request) {
-        Page<BloodGlucoseDataResponse> response = bloodGlucoseDataService.listBloodGlucoseData(request);
-        return R.success(SuccessResultCode.SUCCESS, "查询成功", response);
-    }
-}
-```
-
-#### Service层
-```java
-public interface BloodGlucoseDataService {
-    void addBloodGlucoseData(AddBloodGlucoseDataRequest request);
-    Page<BloodGlucoseDataResponse> listBloodGlucoseData(BaseQueryRequest request);
-}
-
-@Service
-public class BloodGlucoseDataServiceImpl implements BloodGlucoseDataService {
-
-    @Autowired
-    private BloodGlucoseDataMapper bloodGlucoseDataMapper;
-
-    @Override
-    public void addBloodGlucoseData(AddBloodGlucoseDataRequest request) {
-        Long userId = getCurrentUserId();
-
-        BloodGlucoseData bloodGlucoseData = new BloodGlucoseData();
-        BeanUtils.copyProperties(request, bloodGlucoseData);
-        bloodGlucoseData.setUserId(userId);
-
-        bloodGlucoseDataMapper.insert(bloodGlucoseData);
-    }
-
-    @Override
-    public Page<BloodGlucoseDataResponse> listBloodGlucoseData(BaseQueryRequest request) {
-        Long userId = getCurrentUserId();
-
-        Page<BloodGlucoseData> page = new Page<>(request.getPageNum(), request.getPageSize());
-        LambdaQueryWrapper<BloodGlucoseData> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(BloodGlucoseData::getUserId, userId)
-               .ge(request.getStartTime() != null, BloodGlucoseData::getMeasureTime, request.getStartTime())
-               .le(request.getEndTime() != null, BloodGlucoseData::getMeasureTime, request.getEndTime())
-               .orderByDesc(BloodGlucoseData::getMeasureTime);
-
-        Page<BloodGlucoseData> result = bloodGlucoseDataMapper.selectPage(page, wrapper);
-
-        List<BloodGlucoseDataResponse> responses = result.getRecords().stream()
-            .map(record -> {
-                BloodGlucoseDataResponse response = new BloodGlucoseDataResponse();
-                BeanUtils.copyProperties(record, response);
-                return response;
-            })
-            .collect(Collectors.toList());
-
-        Page<BloodGlucoseDataResponse> responsePage = new Page<>();
-        responsePage.setRecords(responses);
-        responsePage.setCurrent(result.getCurrent());
-        responsePage.setSize(result.getSize());
-        responsePage.setTotal(result.getTotal());
-
-        return responsePage;
-    }
-
-    private Long getCurrentUserId() {
-        // 从安全上下文中获取当前用户ID
-        return 1L; // 临时实现
-    }
-}
-```
-
-#### Mapper层
-```java
-@Mapper
-public interface BloodGlucoseDataMapper extends BaseMapper<BloodGlucoseData> {
-}
-```
-
-### 心率数据模块接口
-
-#### Controller层
-```java
-@RestController
-@RequestMapping("/heart-rate-data")
-@Tag(name = "心率数据管理", description = "病人心率数据相关接口")
-public class HeartRateDataController {
-
-    @Autowired
-    private HeartRateDataService heartRateDataService;
-
-    @PostMapping("/add")
-    @Operation(summary = "添加心率数据")
-    public R<Void> addHeartRateData(@RequestBody @Valid AddHeartRateDataRequest request) {
-        heartRateDataService.addHeartRateData(request);
-        return R.success(SuccessResultCode.SUCCESS, "添加成功", null);
-    }
-
-    @PostMapping("/list")
-    @Operation(summary = "查询心率数据列表")
-    public R<Page<HeartRateDataResponse>> listHeartRateData(@RequestBody @Valid BaseQueryRequest request) {
-        Page<HeartRateDataResponse> response = heartRateDataService.listHeartRateData(request);
-        return R.success(SuccessResultCode.SUCCESS, "查询成功", response);
-    }
-}
-```
-
-#### Service层
-```java
-public interface HeartRateDataService {
-    void addHeartRateData(AddHeartRateDataRequest request);
-    Page<HeartRateDataResponse> listHeartRateData(BaseQueryRequest request);
-}
-
-@Service
-public class HeartRateDataServiceImpl implements HeartRateDataService {
-
-    @Autowired
-    private HeartRateDataMapper heartRateDataMapper;
-
-    @Override
-    public void addHeartRateData(AddHeartRateDataRequest request) {
-        Long userId = getCurrentUserId();
-
-        HeartRateData heartRateData = new HeartRateData();
-        BeanUtils.copyProperties(request, heartRateData);
-        heartRateData.setUserId(userId);
-
-        heartRateDataMapper.insert(heartRateData);
-    }
-
-    @Override
-    public Page<HeartRateDataResponse> listHeartRateData(BaseQueryRequest request) {
-        Long userId = getCurrentUserId();
-
-        Page<HeartRateData> page = new Page<>(request.getPageNum(), request.getPageSize());
-        LambdaQueryWrapper<HeartRateData> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(HeartRateData::getUserId, userId)
-               .ge(request.getStartTime() != null, HeartRateData::getMeasureTime, request.getStartTime())
-               .le(request.getEndTime() != null, HeartRateData::getMeasureTime, request.getEndTime())
-               .orderByDesc(HeartRateData::getMeasureTime);
-
-        Page<HeartRateData> result = heartRateDataMapper.selectPage(page, wrapper);
-
-        List<HeartRateDataResponse> responses = result.getRecords().stream()
-            .map(record -> {
-                HeartRateDataResponse response = new HeartRateDataResponse();
-                BeanUtils.copyProperties(record, response);
-                return response;
-            })
-            .collect(Collectors.toList());
-
-        Page<HeartRateDataResponse> responsePage = new Page<>();
-        responsePage.setRecords(responses);
-        responsePage.setCurrent(result.getCurrent());
-        responsePage.setSize(result.getSize());
-        responsePage.setTotal(result.getTotal());
-
-        return responsePage;
-    }
-
-    private Long getCurrentUserId() {
-        // 从安全上下文中获取当前用户ID
-        return 1L; // 临时实现
-    }
-}
-```
-
-#### Mapper层
-```java
-@Mapper
-public interface HeartRateDataMapper extends BaseMapper<HeartRateData> {
-}
-```
-
-## 安全考虑
-
-### 权限控制
-- 患者只能访问自己的健康数据
-- 医生可以访问指定患者的健康数据
-- 系统管理员可以访问所有数据
-
-### 数据验证
-- 使用Bean Validation进行输入校验
-- 业务逻辑层进行数据合理性校验(如血压高低压关系)
-
-## 性能优化
-
-### 索引设计
-- 用户ID + 测量时间复合索引,支持时间范围查询
-- 用户ID索引,支持用户数据隔离
-
-### 查询优化
-- 分页查询,避免一次性加载大量数据
-- 支持时间范围过滤,减少数据扫描量
-
-## 扩展性考虑
-
-### 未来扩展
-- 支持更多健康指标(如血脂、尿酸等)
-- 支持数据统计和趋势分析
-- 支持数据导出功能
-- 支持批量数据导入
-
-### 版本控制
-- API版本控制,为未来升级预留空间
-- 数据库表结构设计考虑向后兼容
-
-## 实施计划
-
-本设计文档为第一阶段输出,后续阶段将包括:
-1. **阶段2**:创建详细的API接口规范文档(包含所有4个子模块的完整API文档)
-2. **阶段3**:创建数据库表结构和迁移脚本文档
-3. **阶段4**:创建数据模型(PO/VO)详细设计文档
-4. **阶段5**:创建单元测试计划和集成测试用例
-5. **阶段6**:创建业务逻辑和异常处理设计文档
-6. **阶段7**:创建部署和运维文档
-
-每个阶段都会生成独立的中间文件,确保设计过程可审查和可追溯。
-
-### 实施顺序建议
-1. 优先实施体格数据模块(包含BMI计算功能)
-2. 其次实施血压数据模块
-3. 然后实施血糖数据模块
-4. 最后实施心率数据模块
-
-这样可以确保核心功能(BMI计算)优先实现,同时为其他模块提供参考模板。
-
-## 风险评估
-
-### 技术风险
-- 数据精度问题:使用BigDecimal确保数值计算精度
-- 并发问题:使用乐观锁防止并发更新冲突
-
-### 业务风险
-- 数据隐私:确保用户数据安全,遵循医疗数据保护规范
-- 数据准确性:通过校验和审核机制确保数据质量
-
-## 总结
-
-本设计遵循项目现有规范,提供了完整的健康数据模块设计方案。设计考虑了数据完整性、安全性、性能和扩展性,为慢病APP的健康数据管理提供了坚实的基础。
-
-**关键特性:**
-- **模块化设计**:将健康数据拆分为4个独立子模块,每个模块独立存储和管理
-- **数据隔离**:每种健康数据类型使用独立的数据库表,确保数据隔离和性能优化
-- **统一架构**:所有子模块遵循相同的架构模式,便于维护和扩展
-- **BMI计算**:体格数据模块提供BMI自动计算功能,不存储计算结果
-- **血糖精细分类**:血糖数据按7个标准医疗时间点分类,便于医生诊断分析
-- **权限控制**:基于用户角色确保数据访问安全
-- **分页查询**:支持时间范围过滤和分页查询,提高查询性能
-
-**设计优势:**
-1. **高内聚低耦合**:每个模块职责单一,易于维护
-2. **扩展性强**:新增健康数据类型只需按照模板添加新模块
-3. **性能优化**:独立表设计避免了大数据量查询时的性能问题
-4. **医疗专业性**:血糖数据按标准医疗时间点分类,便于医生诊断
-5. **数据一致性**:每种数据类型独立管理,确保数据一致性
-6. **接口清晰**:每个模块提供独立的API,便于前端集成

+ 0 - 156
docs/DevDesign/HealthData/ImplementationDifferences.md

@@ -1,156 +0,0 @@
-# 健康数据模块 — 实现与设计功能差异清单
-
-说明:本文件记录代码实现相对于设计稿(见同目录下的设计文档)在功能层面的差异。每项包括:差异描述、实际影响、建议修正、优先级,以及预留的“解决状态”字段(供后续对话中逐项标记)。
-
----
-
-## 使用说明
-- 状态字段:`[status]`,可取值 `not-started` / `in-progress` / `resolved`。
-- 负责人/备注:在项下方 `owner` 与 `notes` 字段中填写负责人的姓名与处理备注。
-- 当项被解决时,请把 `status` 改为 `resolved` 并在 `notes` 中写明修改文件或提交说明(例如:`修改了 X 文件,commit 123abc`)。
-
----
-
-## 概览
-总体结论:项目已实现四个子模块(体格/血压/血糖/心率)的核心 CRUD、PO/VO/Mapper/Service/Controller、分页与字段校验。但在权限/角色、接口命名与方法、血糖枚举与录入模式、异常/响应语义、数据库迁移等方面存在功能性差异或未完全实现的设计要求。
-
-下列条目按建议优先级排序(高 -> 低)。
-
----
-
-### Item A — 权限与多角色访问(高)
-- id: A
-- description: 设计稿要求患者只能访问自己的数据;医生可访问指定患者的数据;管理员可访问所有数据。当前实现仅基于 `currentUserId` 过滤,未实现医生/管理员的授权与跨患者访问策略。
-- impact: 医生/管理员无法按设计查看或代查患者数据,权限模型不完整,存在功能缺失。
-- recommendation: 
-  1. 在用户模型或 TokenService 中提供用户角色信息(patient/doctor/admin)。
-  2. 在需要支持医生访问的接口中加入 `patientId` 参数,并在 Service 层校验当前用户角色是否有访问该 patientId 的权限(如医生会诊名单、授权表等)。
-  3. 提供统一的权限工具(例如 `SecurityUtils.getCurrentUser()` 返回包含 id 与 role 的对象)。
-- priority: high
-- status: not-started
-- owner: 
-- notes: 
-
----
-
-### Item B — API 路径与请求方法不一致(中)
-- id: B
-- description: 设计文档定义了接口路径如 `/physical-data/*`, `/blood-glucose-data/*`, `/heart-rate-data/*` 等;实现中为 `/physical`, `/blood-glucose`, `/heart-rate` 等短路径。BMI 在文档为 GET `/physical-data/bmi`,实现为 POST `/physical/bmi`。
-- impact: 前端与文档将无法直接对接,GET/POST 差异会影响缓存/语义。
-- recommendation: 选取一种统一策略:
-  - 方案 1(推荐):让代码遵循设计文档的路径与方法(修改 Controller 的 RequestMapping 与方法);
-  - 方案 2:如果更倾向于保持当前实现,则把 API 文档更新为与代码一致。
-- priority: medium
-- status: not-started
-- owner: 
-- notes: 
-
----
-
-### Item C — 血糖枚举与录入模型差异(中)
-- id: C
-- description: 设计稿里 `BloodGlucoseType` 包含 integer code、unit、normalRange、显示顺序等元数据,并且设计示例支持一次提交多时间点(多个字段);实现中枚举使用 String code,且 API 以每条记录一个 type+value 的方式接收数据。
-- impact: 前端无法直接从后端获得参考范围/单位/显示顺序信息;若业务需要一次性提交多时间点数据(按天表单),当前接口不支持。
-- recommendation: 
-  - 如果按当前单条记录模型继续:扩展枚举 `BloodGlucoseType` 增加 `unit`、`normalRange`、`getOrderedTypes()` 等方法,并提供一个枚举元数据的 API 端点供前端获取显示信息;
-  - 如果需要支持批量提交:新增 batch API(例如 `POST /blood-glucose-data/batch`)和相应 VO,在服务端做批量插入与校验。
-- priority: medium
-- status: not-started
-- owner: 
-- notes: 
-
----
-
-### Item D — 返回/错误语义与异常处理不统一(中)
-- id: D
-- description: 设计文档期望返回格式使用语义化字符串 code(例如 `SUCCESS`, `PARAM_ERROR`),而代码中 `R` 主要使用数值(如 200、500)。Controller 中部分地方使用局部 try/catch 导致全局异常处理器不一致地被绕过。同时 `CustomException` 在代码中被修改为 `RuntimeException`。
-- impact: 前端/集成方可能无法根据文档预期解析 `code`。局部 try/catch 会导致错误响应格式不统一。
-- recommendation: 
-  - 统一响应格式(两选一):
-    - 让 `R` 返回设计稿中语义化 code(修改 R & CustomExceptionHandler);或
-    - 在文档中确认并改为 numeric-style code,然后统一文档与实现;
-  - 移除不必要的 Controller 层 try/catch(或仅保留用于捕获同步业务错误),让异常通过全局 `CustomExceptionHandler` 处理以保证统一格式。
-  - 审核并确认 `CustomException` 是否应为 checked 或 unchecked(团队约定)。
-- priority: medium
-- status: not-started
-- owner: 
-- notes: 
-
----
-
-### Item E — AuthInterceptor 与 SecurityUtils 的对齐(高/已实现)
-- id: E
-- description: 设计中拦截器会把用户 ID 放入 request attribute(`currentUserId`)。我已实现 `SecurityUtils.getCurrentUserId()` 并替换了分散实现,AuthInterceptor 代码确认了写入 `currentUserId`。
-- impact: 基础用户 ID 获取机制已统一,但仍需确认拦截器在所有部署环境中都启用并写入该 attribute;若拦截器改动需同步 SecurityUtils。
-- recommendation:
-  - 将属性 key `currentUserId` 作为常量(例如 `SecurityConstants.CURRENT_USER_ID`)并在拦截器与工具类中引用;
-  - 为 SecurityUtils 增加回退策略(如从 Authorization header 解 token)以增强健壮性。
-- priority: high
-- status: resolved
-- owner: (已实现)
-- notes: `SecurityUtils` 新增并已替换四处 service impl 与 WeChatController 的读取点;请确认是否需要常量化 key 或增加回退策略。
-
----
-
-### Item F — 数据库建表脚本与迁移(中)
-- id: F
-- description: 设计稿提供了 CREATE TABLE 语句,但仓库内未发现 Flyway/Liquibase 等自动迁移脚本。
-- impact: 部署时需要手动建表或外部脚本,降低自动化与可重复部署能力。
-- recommendation: 添加 Flyway 或 Liquibase 的迁移脚本(`db/migration`)并将建表 SQL 列入迁移历史;在 CI/CD 中执行迁移以保证环境一致。
-- priority: medium
-- status: not-started
-- owner: 
-- notes: 
-
----
-
-### Item G — 枚举元数据/显示顺序缺失(低)
-- id: G
-- description: 设计里建议提供 `getOrderedTypes()`、单位、参考范围等;实现的枚举未包含这些额外元数据。
-- impact: 前端无法自动获得显示顺序或参考范围,需要在多个地方硬编码,降低一致性。
-- recommendation: 扩展 `BloodGlucoseType` 枚举以包含 `unit`、`normalRange`、`getOrderedTypes()`,并暴露一个元数据 API(例如 `GET /meta/blood-glucose-types`)。
-- priority: low
-- status: not-started
-- owner: 
-- notes: 
-
----
-
-### Item H — 关键业务校验缺失(低-中)
-- id: H
-- description: 设计提到若干业务校验(如血压高低压关系、重复记录策略、异常预警等),但实现仅包含基础字段范围校验,缺少业务层面规则。
-- impact: 可能导致错误数据被录入(例如收缩压 < 舒张压未校验),或未对重复/异常进行预警/处理。
-- recommendation: 在 Service 层补充以下校验:
-  - 血压:收缩压 >= 舒张压;
-  - 重复提交:同一用户、同一类型、同一测量时间窗内的去重或提示策略;
-  - 异常值预警:当值超出临床阈值时触发告警或返回明确业务码。
-- priority: low-to-medium
-- status: not-started
-- owner: 
-- notes: 
-
----
-
-### Item I — 文档与代码不同步(低)
-- id: I
-- description: 多处代码与设计文档在路径、方法、响应格式上存在不一致(汇总见上)。
-- impact: 影响前后端协作和 API 测试;造成审查/维护成本。
-- recommendation: 决定以代码为准还是以文档为准并执行一次一致性同步(我可按选择自动生成更新的文档或批量修改 Controller 路径)。
-- priority: low
-- status: not-started
-- owner: 
-- notes: 
-
----
-
-## 后续流程建议
-1. 先解决高优先级项(A、E),确保权限/认证/用户上下文准确;
-2. 再统一异常/响应语义(C)与 API 路径(B);
-3. 然后补充枚举元数据/批量录入(G、C)与业务校验(H);
-4. 最后完善迁移脚本与文档(F、I)。
-
-如果你确认这个清单,我会把它放入版本库(已保存到本文件),并可以在你选定的条目上逐一开始实现 —— 请回复你想先解决的项(例如 `先做 A` 或 `先做 C 和 B`)。
-
----
-
-文件生成:`docs/DevDesign/HealthData/ImplementationDifferences.md`