# 保质期提醒小程序 - API 文档 ## 基础信息 **Base URL**: `/api/expiry` **认证方式**: JWT Token(通过公共登录接口获取,参见 `docs/common/auth.md`) **请求头**: ``` Authorization: Bearer Content-Type: application/json ``` --- ## 1. 物品管理 ### 1.1 获取物品列表 **接口**: `GET /api/expiry/items` **Query 参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | status | string | ❌ | 状态筛选:all/expiring/expired/normal/used | | category | string | ❌ | 分类筛选:all/food/medicine/cosmetic/other | | sort | string | ❌ | 排序方式:expiry_date/created_at,默认 expiry_date | | page | int | ❌ | 页码,默认 1 | | page_size | int | ❌ | 每页数量,默认 20,最大 100 | **响应示例**: ```json { "code": 0, "message": "success", "data": { "items": [ { "id": 1, "name": "牛奶", "category": "food", "production_date": "2026-02-01", "expiry_date": "2026-03-10", "shelf_life_days": 37, "quantity": 2, "location": "冰箱", "remark": "", "status": "normal", "days_left": 6, "created_at": "2026-03-01T10:00:00Z", "updated_at": "2026-03-01T10:00:00Z" } ], "total": 15, "page": 1, "page_size": 20 } } ``` **状态说明**: - `normal`: 正常(距离过期 > 7天) - `expiring`: 即将过期(0-7天) - `expired`: 已过期(< 0天) - `used`: 已使用 - `discarded`: 已丢弃 **days_left 计算**: - 正数:距离过期还有 N 天 - 0:今天过期 - 负数:已过期 N 天 --- ### 1.2 获取首页汇总 **接口**: `GET /api/expiry/summary` **响应示例**: ```json { "code": 0, "message": "success", "data": { "total_items": 15, "expiring_soon": 3, "expired": 2, "normal": 10, "used": 0, "discarded": 0 } } ``` **字段说明**: - `total_items`: 当前有效物品总数(不含已使用/已丢弃) - `expiring_soon`: 7天内即将过期的数量 - `expired`: 已过期的数量 - `normal`: 正常状态的数量 - `used`: 已使用的数量 - `discarded`: 已丢弃的数量 --- ### 1.3 添加物品 **接口**: `POST /api/expiry/items` **请求体**: ```json { "name": "牛奶", "category": "food", "production_date": "2026-02-01", "expiry_date": "2026-03-10", "shelf_life_days": 37, "quantity": 2, "location": "冰箱", "remark": "伊利纯牛奶" } ``` **字段说明**: | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | name | string | ✅ | 物品名称,最长 100 字符 | | category | string | ✅ | 分类:food/medicine/cosmetic/other | | production_date | string | ❌ | 生产日期,格式 YYYY-MM-DD | | expiry_date | string | ✅ | 过期日期,格式 YYYY-MM-DD | | shelf_life_days | int | ❌ | 保质期天数 | | quantity | int | ❌ | 数量,默认 1 | | location | string | ❌ | 存放位置,最长 50 字符 | | remark | string | ❌ | 备注,最长 255 字符 | **业务逻辑**: 1. 如果提供 `production_date` 和 `shelf_life_days`,后端会自动计算 `expiry_date`(如果未提供) 2. `expiry_date` 必填,或者 `production_date` + `shelf_life_days` 组合必填 3. 初始状态为 `normal`,后端根据 `expiry_date` 自动计算 `days_left` **响应示例**: ```json { "code": 0, "message": "添加成功", "data": { "id": 1, "name": "牛奶", "category": "food", "production_date": "2026-02-01", "expiry_date": "2026-03-10", "shelf_life_days": 37, "quantity": 2, "location": "冰箱", "remark": "伊利纯牛奶", "status": "normal", "days_left": 6, "created_at": "2026-03-04T10:00:00Z", "updated_at": "2026-03-04T10:00:00Z" } } ``` --- ### 1.4 更新物品 **接口**: `PUT /api/expiry/items/:id` **路径参数**: - `id`: 物品 ID **请求体**: 同添加物品 **响应示例**: ```json { "code": 0, "message": "更新成功", "data": { "id": 1, "name": "牛奶(已开封)", ... } } ``` --- ### 1.5 删除物品 **接口**: `DELETE /api/expiry/items/:id` **路径参数**: - `id`: 物品 ID **响应示例**: ```json { "code": 0, "message": "删除成功" } ``` **说明**: 使用软删除,数据不会真正删除 --- ### 1.6 标记物品状态 **接口**: `POST /api/expiry/items/:id/status` **路径参数**: - `id`: 物品 ID **请求体**: ```json { "status": "used" } ``` **status 可选值**: - `used`: 已使用 - `discarded`: 已丢弃 **响应示例**: ```json { "code": 0, "message": "标记成功", "data": { "id": 1, "status": "used", "updated_at": "2026-03-04T10:00:00Z" } } ``` --- ## 2. 用户设置 ### 2.1 获取用户设置 **接口**: `GET /api/expiry/settings` **响应示例**: ```json { "code": 0, "message": "success", "data": { "remind_days": [7, 3, 1] } } ``` **说明**: 如果用户未设置,返回默认值 `[7, 3, 1]` --- ### 2.2 更新用户设置 **接口**: `POST /api/expiry/settings` **请求体**: ```json { "remind_days": [10, 5, 2, 1] } ``` **字段说明**: - `remind_days`: 提醒天数数组,最多 5 个值,每个值范围 1-30 **响应示例**: ```json { "code": 0, "message": "更新成功", "data": { "remind_days": [10, 5, 2, 1] } } ``` --- ## 3. 错误码 | code | message | 说明 | |------|---------|------| | 0 | success | 成功 | | 400 | 参数错误 | 请求参数不合法 | | 401 | 未授权 | Token 无效或过期 | | 404 | 资源不存在 | 物品不存在 | | 500 | 服务器错误 | 内部错误 | **错误响应示例**: ```json { "code": 400, "message": "物品名称不能为空" } ``` --- ## 4. 前端集成示例 ### 4.1 获取首页数据 ```javascript // 并行请求 Promise.all([ wx.request({ url: '/api/expiry/summary' }), wx.request({ url: '/api/expiry/items?status=expiring&page_size=10' }) ]).then(([summary, items]) => { // 渲染首页 }); ``` ### 4.2 添加物品 ```javascript wx.request({ url: '/api/expiry/items', method: 'POST', data: { name: '牛奶', category: 'food', expiry_date: '2026-03-10', quantity: 2, location: '冰箱' }, success: (res) => { if (res.data.code === 0) { wx.showToast({ title: '添加成功' }); // 刷新列表 } } }); ``` ### 4.3 标记已使用 ```javascript wx.request({ url: `/api/expiry/items/${itemId}/status`, method: 'POST', data: { status: 'used' }, success: (res) => { if (res.data.code === 0) { wx.showToast({ title: '已标记' }); // 刷新列表 } } }); ``` --- ## 5. 性能建议 ### 5.1 缓存策略 - **summary**: 进入首页时刷新,缓存 5 分钟 - **items 列表**: 下拉刷新时更新,支持分页加载 - **settings**: 登录后缓存,修改时更新 ### 5.2 请求优化 - 首页使用并行请求 `summary` + `items` - 列表滚动到底部时自动加载下一页 - 使用防抖避免频繁请求 --- ## 6. 数据库索引建议 ```sql -- 用户 + 过期日期(最常用查询) CREATE INDEX idx_user_expiry ON expiry_items(user_id, expiry_date); -- 用户 + 分类 CREATE INDEX idx_user_category ON expiry_items(user_id, category); -- 用户 + 状态 CREATE INDEX idx_user_status ON expiry_items(user_id, status); -- 软删除 CREATE INDEX idx_deleted_at ON expiry_items(deleted_at); ```