# 药物管理 API 文档 - 客户端版本 ## 基础信息 **Base URL**: `https://your-domain.com/api` **认证方式**: Bearer Token (JWT) **Content-Type**: `application/json` ## 认证说明 所有接口都需要在 HTTP Header 中携带 JWT Token: ```http Authorization: Bearer ``` ## 数据类型定义 ### MedicationForm(药物剂型) ```typescript enum MedicationForm { CAPSULE = "capsule", // 胶囊 PILL = "pill", // 药片 INJECTION = "injection", // 注射 SPRAY = "spray", // 喷雾 DROP = "drop", // 滴剂 SYRUP = "syrup", // 糖浆 OTHER = "other", // 其他 } ``` ### RepeatPattern(重复模式) ```typescript enum RepeatPattern { DAILY = "daily", // 每日(目前仅支持每日模式) } ``` ### MedicationStatus(服药状态) ```typescript enum MedicationStatus { UPCOMING = "upcoming", // 待服用 TAKEN = "taken", // 已服用 MISSED = "missed", // 已错过 SKIPPED = "skipped", // 已跳过 } ``` ### Medication(药物信息) ```typescript interface Medication { id: string; // 药物唯一标识 userId: string; // 用户ID name: string; // 药物名称 photoUrl?: string; // 药物照片URL(可选) form: MedicationForm; // 药物剂型 dosageValue: number; // 剂量数值(如 1、0.5) dosageUnit: string; // 剂量单位(片、粒、毫升等) timesPerDay: number; // 每日服用次数 medicationTimes: string[]; // 服药时间列表,格式:["08:00", "12:00", "18:00"] repeatPattern: RepeatPattern; // 重复模式 startDate: string; // 开始日期,ISO 8601 格式 endDate?: string; // 结束日期(可选),ISO 8601 格式 note?: string; // 备注信息(可选) isActive: boolean; // 是否激活 deleted: boolean; // 是否已删除 createdAt: string; // 创建时间,ISO 8601 格式 updatedAt: string; // 更新时间,ISO 8601 格式 } ``` ### MedicationRecord(服药记录) ```typescript interface MedicationRecord { id: string; // 记录唯一标识 medicationId: string; // 关联的药物ID userId: string; // 用户ID scheduledTime: string; // 计划服药时间,ISO 8601 格式 actualTime?: string; // 实际服药时间(可选),ISO 8601 格式 status: MedicationStatus; // 服药状态 note?: string; // 备注(可选) deleted: boolean; // 是否已删除 createdAt: string; // 创建时间,ISO 8601 格式 updatedAt: string; // 更新时间,ISO 8601 格式 medication?: Medication; // 关联的药物信息(可选,用于联表查询) } ``` ### DailyMedicationStats(每日统计) ```typescript interface DailyMedicationStats { date: string; // 日期,格式:YYYY-MM-DD totalScheduled: number; // 计划服药总次数 taken: number; // 已服用次数 missed: number; // 已错过次数 upcoming: number; // 待服用次数 completionRate: number; // 完成率(百分比,0-100,保留两位小数) } ``` ### 统一响应格式 ```typescript interface ApiResponse { code: number; // 状态码:200成功,其他为错误 message: string; // 响应消息 data: T | null; // 响应数据 } ``` --- ## 药物管理接口 ### 1. 获取药物列表 获取当前用户的药物列表。 **接口**: `GET /medications` **请求参数**: | 参数 | 类型 | 必填 | 说明 | | -------- | ------- | ---- | ---------------------------------- | | isActive | boolean | 否 | 是否只获取激活的药物,默认获取全部 | | page | number | 否 | 页码,默认 1 | | pageSize | number | 否 | 每页数量,默认 20 | **请求示例**: ```http GET /medications?isActive=true&page=1&pageSize=20 Authorization: Bearer ``` **响应示例**: ```json { "code": 200, "message": "查询成功", "data": [ { "id": "med_001", "userId": "user_123", "name": "阿司匹林", "photoUrl": "https://cdn.example.com/medications/aspirin.jpg", "form": "pill", "dosageValue": 1, "dosageUnit": "片", "timesPerDay": 2, "medicationTimes": ["08:00", "20:00"], "repeatPattern": "daily", "startDate": "2025-01-01T00:00:00.000Z", "endDate": null, "note": "饭后服用", "isActive": true, "deleted": false, "createdAt": "2025-01-01T00:00:00.000Z", "updatedAt": "2025-01-01T00:00:00.000Z" } ] } ``` --- ### 2. 获取单个药物详情 获取指定药物的详细信息。 **接口**: `GET /medications/{id}` **路径参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | id | string | 是 | 药物ID | **请求示例**: ```http GET /medications/med_001 Authorization: Bearer ``` **响应**: 同"获取药物列表"中的单个药物对象 --- ### 3. 创建药物 创建新的药物信息。 **接口**: `POST /medications` **请求体**: ```json { "name": "阿司匹林", "photoUrl": "https://cdn.example.com/medications/aspirin.jpg", "form": "pill", "dosageValue": 1, "dosageUnit": "片", "timesPerDay": 2, "medicationTimes": ["08:00", "20:00"], "repeatPattern": "daily", "startDate": "2025-01-01T00:00:00.000Z", "endDate": null, "note": "饭后服用" } ``` **字段说明**: | 字段 | 类型 | 必填 | 说明 | | --------------- | -------------- | ---- | ---------------------------------------------------- | | name | string | 是 | 药物名称,最大100字符 | | photoUrl | string | 否 | 药物照片URL | | form | MedicationForm | 是 | 药物剂型 | | dosageValue | number | 是 | 剂量数值,必须大于0 | | dosageUnit | string | 是 | 剂量单位,最大20字符 | | timesPerDay | number | 是 | 每日服用次数,1-10次 | | medicationTimes | string[] | 是 | 服药时间列表,格式:"HH:mm",数量必须等于timesPerDay | | repeatPattern | RepeatPattern | 是 | 重复模式,目前仅支持"daily" | | startDate | string | 是 | 开始日期,ISO 8601格式 | | endDate | string | 否 | 结束日期,ISO 8601格式 | | note | string | 否 | 备注信息 | **响应示例**: ```json { "code": 200, "message": "创建成功", "data": { "id": "med_001", "userId": "user_123", "name": "阿司匹林", "photoUrl": "https://cdn.example.com/medications/aspirin.jpg", "form": "pill", "dosageValue": 1, "dosageUnit": "片", "timesPerDay": 2, "medicationTimes": ["08:00", "20:00"], "repeatPattern": "daily", "startDate": "2025-01-01T00:00:00.000Z", "endDate": null, "note": "饭后服用", "isActive": true, "deleted": false, "createdAt": "2025-01-01T00:00:00.000Z", "updatedAt": "2025-01-01T00:00:00.000Z" } } ``` --- ### 4. 更新药物信息 更新指定药物的信息。 **接口**: `PUT /medications/{id}` **路径参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | id | string | 是 | 药物ID | **请求体**: 与创建药物相同,所有字段均为可选 **请求示例**: ```json { "dosageValue": 2, "timesPerDay": 3, "medicationTimes": ["08:00", "14:00", "20:00"], "note": "饭后服用,加量" } ``` **响应**: 同"创建药物"响应 --- ### 5. 删除药物 删除指定药物(软删除)。 **接口**: `DELETE /medications/{id}` **路径参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | id | string | 是 | 药物ID | **请求示例**: ```http DELETE /medications/med_001 Authorization: Bearer ``` **响应示例**: ```json { "code": 200, "message": "删除成功", "data": null } ``` --- ### 6. 停用药物 停用指定药物(将 isActive 设为 false)。 **接口**: `POST /medications/{id}/deactivate` **路径参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | id | string | 是 | 药物ID | **请求示例**: ```http POST /medications/med_001/deactivate Authorization: Bearer ``` **响应示例**: ```json { "code": 200, "message": "停用成功", "data": { "id": "med_001", "isActive": false, "updatedAt": "2025-01-15T00:00:00.000Z" } } ``` --- ## 服药记录接口 ### 1. 获取服药记录 查询服药记录,支持多种筛选条件。 **接口**: `GET /medication-records` **请求参数**: | 参数 | 类型 | 必填 | 说明 | | ------------ | ---------------- | ---- | -------------------------------------- | | date | string | 否 | 指定日期(YYYY-MM-DD),不填则返回所有 | | startDate | string | 否 | 开始日期(YYYY-MM-DD) | | endDate | string | 否 | 结束日期(YYYY-MM-DD) | | medicationId | string | 否 | 指定药物ID | | status | MedicationStatus | 否 | 状态筛选 | **重要说明**: - 首次查询某天的记录时,后端会自动生成该天的服药记录(惰性生成) - 建议使用 `date` 参数查询特定日期,效率更高 **请求示例**: ```http GET /medication-records?date=2025-01-15&status=upcoming Authorization: Bearer ``` **响应示例**: ```json { "code": 200, "message": "查询成功", "data": [ { "id": "record_001", "medicationId": "med_001", "userId": "user_123", "scheduledTime": "2025-01-15T08:00:00.000Z", "actualTime": null, "status": "upcoming", "note": null, "deleted": false, "createdAt": "2025-01-15T00:00:00.000Z", "updatedAt": "2025-01-15T00:00:00.000Z", "medication": { "id": "med_001", "name": "阿司匹林", "form": "pill", "dosageValue": 1, "dosageUnit": "片" } } ] } ``` --- ### 2. 获取今日服药记录 快捷获取今天的所有服药记录。 **接口**: `GET /medication-records/today` **请求示例**: ```http GET /medication-records/today Authorization: Bearer ``` **响应**: 同"获取服药记录"响应 --- ### 3. 获取服药记录详情 获取指定服药记录的详细信息。 **接口**: `GET /medication-records/{id}` **路径参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | id | string | 是 | 记录ID | **请求示例**: ```http GET /medication-records/record_001 Authorization: Bearer ``` **响应**: 同"获取服药记录"中的单个记录对象 --- ### 4. 标记为已服用 将服药记录标记为已服用。 **接口**: `POST /medication-records/{id}/take` **路径参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | id | string | 是 | 记录ID | **请求体**: ```json { "actualTime": "2025-01-15T08:10:00.000Z" } ``` **字段说明**: | 字段 | 类型 | 必填 | 说明 | | ---------- | ------ | ---- | ---------------------------------------------- | | actualTime | string | 否 | 实际服药时间,ISO 8601格式,不填则使用当前时间 | **响应示例**: ```json { "code": 200, "message": "已记录服药", "data": { "id": "record_001", "medicationId": "med_001", "userId": "user_123", "scheduledTime": "2025-01-15T08:00:00.000Z", "actualTime": "2025-01-15T08:10:00.000Z", "status": "taken", "note": null, "deleted": false, "createdAt": "2025-01-15T00:00:00.000Z", "updatedAt": "2025-01-15T08:10:00.000Z" } } ``` --- ### 5. 跳过服药 跳过本次服药,不计入已错过。 **接口**: `POST /medication-records/{id}/skip` **路径参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | id | string | 是 | 记录ID | **请求体**: ```json { "note": "今天身体不适,暂时跳过" } ``` **字段说明**: | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------------ | | note | string | 否 | 跳过原因备注 | **响应示例**: ```json { "code": 200, "message": "已跳过服药", "data": { "id": "record_001", "medicationId": "med_001", "userId": "user_123", "scheduledTime": "2025-01-15T08:00:00.000Z", "actualTime": null, "status": "skipped", "note": "今天身体不适,暂时跳过", "deleted": false, "createdAt": "2025-01-15T00:00:00.000Z", "updatedAt": "2025-01-15T08:15:00.000Z" } } ``` --- ### 6. 更新服药记录 更新服药记录的状态和信息。 **接口**: `PUT /medication-records/{id}` **路径参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | id | string | 是 | 记录ID | **请求体**: ```json { "status": "taken", "actualTime": "2025-01-15T08:15:00.000Z", "note": "延迟服用" } ``` **字段说明**: 所有字段均为可选 | 字段 | 类型 | 必填 | 说明 | | ---------- | ---------------- | ---- | -------------------------- | | status | MedicationStatus | 否 | 服药状态 | | actualTime | string | 否 | 实际服药时间,ISO 8601格式 | | note | string | 否 | 备注信息 | **响应**: 同"标记为已服用"响应 --- ## 统计接口 ### 1. 获取每日统计 获取指定日期的服药统计数据。 **接口**: `GET /medication-stats/daily` **请求参数**: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ---------------------- | | date | string | 是 | 日期,格式:YYYY-MM-DD | **请求示例**: ```http GET /medication-stats/daily?date=2025-01-15 Authorization: Bearer ``` **响应示例**: ```json { "code": 200, "message": "查询成功", "data": { "date": "2025-01-15", "totalScheduled": 6, "taken": 4, "missed": 1, "upcoming": 1, "completionRate": 66.67 } } ``` --- ### 2. 获取日期范围统计 获取指定日期范围内每天的统计数据。 **接口**: `GET /medication-stats/range` **请求参数**: | 参数 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | -------------------------- | | startDate | string | 是 | 开始日期,格式:YYYY-MM-DD | | endDate | string | 是 | 结束日期,格式:YYYY-MM-DD | **请求示例**: ```http GET /medication-stats/range?startDate=2025-01-01&endDate=2025-01-15 Authorization: Bearer ``` **响应示例**: ```json { "code": 200, "message": "查询成功", "data": [ { "date": "2025-01-15", "totalScheduled": 6, "taken": 4, "missed": 1, "upcoming": 1, "completionRate": 66.67 }, { "date": "2025-01-14", "totalScheduled": 6, "taken": 6, "missed": 0, "upcoming": 0, "completionRate": 100.0 } ] } ``` --- ### 3. 获取总体统计 获取用户的总体服药统计概览。 **接口**: `GET /medication-stats/overall` **请求示例**: ```http GET /medication-stats/overall Authorization: Bearer ``` **响应示例**: ```json { "code": 200, "message": "查询成功", "data": { "totalMedications": 5, "totalRecords": 120, "completionRate": 85.5, "streak": 7 } } ``` **字段说明**: | 字段 | 类型 | 说明 | | ---------------- | ------ | ---------------------------------- | | totalMedications | number | 药物总数 | | totalRecords | number | 服药记录总数 | | completionRate | number | 总体完成率(百分比,保留两位小数) | | streak | number | 连续完成天数 | --- ## 错误码说明 | 错误码 | 说明 | | ------ | ------------------------- | | 200 | 操作成功 | | 400 | 请求参数错误 | | 401 | 未授权,Token无效或已过期 | | 403 | 权限不足,无法访问该资源 | | 404 | 资源不存在 | | 409 | 资源冲突(如重复创建) | | 500 | 服务器内部错误 | **错误响应格式**: ```json { "code": 400, "message": "请求参数错误:药物名称不能为空", "data": null } ``` --- ## 业务逻辑说明 ### 1. 服药记录的惰性生成 - 服药记录不会在创建药物时预先生成 - 当首次查询某天的记录时,后端会自动生成该天的所有服药记录 - 生成规则:根据药物的 `timesPerDay` 和 `medicationTimes` 生成对应数量的记录 **示例**: - 如果药物设置为每天2次,服药时间为 08:00 和 20:00 - 首次查询 2025-01-15 的记录时,会自动生成该天 08:00 和 20:00 两条记录 ### 2. 状态自动更新 - 后端每30分钟运行一次定时任务 - 自动将已过期的 `upcoming` 状态更新为 `missed` - 客户端无需手动更新状态 **示例**: - 08:00 的服药记录,到了 08:30 还未标记为已服用 - 定时任务会自动将其状态改为 `missed` ### 3. 推送提醒 - 后端每5分钟检查一次即将到来的服药时间(15-20分钟后) - 自动发送推送通知提醒用户服药 - 客户端需要正确配置推送通知权限 ### 4. 时区处理 - **重要**:所有时间字段使用 UTC 时间存储和传输 - 客户端需要: 1. 发送请求时:将本地时间转换为 UTC 2. 接收响应时:将 UTC 时间转换为本地时间显示 **示例代码(JavaScript)**: ```javascript // 本地时间转 UTC const localTime = new Date("2025-01-15 08:00"); const utcTime = localTime.toISOString(); // "2025-01-15T00:00:00.000Z" (假设时区为UTC+8) // UTC 转本地时间 const utcTime = "2025-01-15T00:00:00.000Z"; const localTime = new Date(utcTime); console.log(localTime.toLocaleString()); // "2025-01-15 08:00:00" (UTC+8) ``` --- ## 最佳实践建议 ### 1. 获取今日服药记录 推荐使用专用接口而非通用查询: ```http ✅ 推荐 GET /medication-records/today ❌ 不推荐 GET /medication-records?date=2025-01-15 ``` ### 2. 批量操作 如果需要更新多个记录,建议单独调用每个接口,后端暂不支持批量操作。 ### 3. 错误处理 建议在客户端统一处理 API 错误: ```javascript async function callApi(url, options) { try { const response = await fetch(url, options); const data = await response.json(); if (data.code !== 200) { // 显示错误提示 showError(data.message); return null; } return data.data; } catch (error) { // 网络错误 showError("网络连接失败,请稍后重试"); return null; } } ``` ### 4. 数据缓存 建议在客户端缓存以下数据以提升性能: - 药物列表(有变更时刷新) - 今日服药记录(实时更新) - 统计数据(按天缓存) ### 5. 定时刷新 建议定时刷新今日服药记录以获取最新状态: ```javascript // 每5分钟刷新一次今日记录 setInterval( async () => { const records = await getTodayRecords(); updateUI(records); }, 5 * 60 * 1000 ); ``` --- ## 完整使用流程示例 ### 1. 创建药物并查看今日记录 ```javascript // Step 1: 创建药物 const medication = await createMedication({ name: "阿司匹林", form: "pill", dosageValue: 1, dosageUnit: "片", timesPerDay: 2, medicationTimes: ["08:00", "20:00"], repeatPattern: "daily", startDate: new Date().toISOString(), note: "饭后服用", }); // Step 2: 获取今日服药记录(会自动生成) const todayRecords = await getTodayRecords(); // Step 3: 显示记录列表 showRecordsList(todayRecords); ``` ### 2. 标记服用并查看统计 ```javascript // Step 1: 标记为已服用 await takeMedication(recordId, { actualTime: new Date().toISOString(), }); // Step 2: 刷新今日记录 const todayRecords = await getTodayRecords(); // Step 3: 获取今日统计 const todayStats = await getDailyStats(formatDate(new Date())); // Step 4: 显示完成率 showCompletionRate(todayStats.completionRate); ``` ### 3. 查看历史统计 ```javascript // 获取最近7天的统计 const startDate = formatDate(daysAgo(7)); const endDate = formatDate(new Date()); const rangeStats = await getRangeStats(startDate, endDate); // 绘制趋势图表 drawChart(rangeStats); ``` --- ## 技术支持 如有疑问或需要帮助,请联系: - **技术文档**: 本文档 - **API 基础URL**: https://your-domain.com/api - **更新日期**: 2025-01-15 - **文档版本**: v1.0 --- ## 更新日志 ### v1.0 (2025-01-15) - 初始版本发布 - 完整的药物管理功能 - 服药记录追踪 - 统计分析功能 - 自动状态更新 - 推送提醒支持