397 lines
7.3 KiB
Markdown
397 lines
7.3 KiB
Markdown
# 保质期提醒小程序 - API 文档
|
||
|
||
## 基础信息
|
||
|
||
**Base URL**: `/api/expiry`
|
||
|
||
**认证方式**: JWT Token(通过公共登录接口获取,参见 `docs/common/auth.md`)
|
||
|
||
**请求头**:
|
||
```
|
||
Authorization: Bearer <token>
|
||
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);
|
||
```
|