Files
plates-server/docs/water-records-api.md

473 lines
11 KiB
Markdown
Raw Permalink 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 客户端接入说明
## 概述
喝水记录 API 提供了完整的喝水记录管理功能,包括记录创建、查询、更新、删除,以及喝水目标设置和统计查询等功能。
## 基础信息
- **Base URL**: `https://your-api-domain.com/api`
- **认证方式**: JWT Bearer Token
- **Content-Type**: `application/json`
## 认证
所有 API 请求都需要在请求头中包含有效的 JWT Token
```http
Authorization: Bearer <your-jwt-token>
```
## API 接口列表
### 1. 创建喝水记录
**接口地址**: `POST /water-records`
**描述**: 创建一条新的喝水记录
**请求参数**:
```json
{
"amount": 250, // 必填喝水量毫升范围1-5000
"recordedAt": "2023-12-01T10:00:00.000Z", // 可选,记录时间,默认为当前时间
"source": "Manual", // 可选记录来源Manual(手动) | Auto(自动)
"note": "早晨第一杯水" // 可选备注最大100字符
}
```
**响应示例**:
```json
{
"success": true,
"message": "操作成功",
"data": {
"id": 1,
"amount": 250,
"recordedAt": "2023-12-01T10:00:00.000Z",
"note": "早晨第一杯水",
"createdAt": "2023-12-01T10:00:00.000Z",
"updatedAt": "2023-12-01T10:00:00.000Z"
}
}
```
**客户端示例代码**:
```javascript
// JavaScript/TypeScript
const createWaterRecord = async (recordData) => {
const response = await fetch('/api/water-records', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(recordData)
});
return response.json();
};
// 使用示例
const result = await createWaterRecord({
amount: 250,
note: "早晨第一杯水"
});
```
### 2. 获取喝水记录列表
**接口地址**: `GET /water-records`
**描述**: 获取用户的喝水记录列表,支持分页和日期筛选
**查询参数**:
- `startDate` (可选): 开始日期格式YYYY-MM-DD
- `endDate` (可选): 结束日期格式YYYY-MM-DD
- `page` (可选): 页码默认1
- `limit` (可选): 每页数量默认20最大100
**请求示例**:
```
GET /water-records?startDate=2023-12-01&endDate=2023-12-31&page=1&limit=20
```
**响应示例**:
```json
{
"success": true,
"message": "操作成功",
"data": {
"records": [
{
"id": 1,
"amount": 250,
"recordedAt": "2023-12-01T10:00:00.000Z",
"note": "早晨第一杯水",
"createdAt": "2023-12-01T10:00:00.000Z",
"updatedAt": "2023-12-01T10:00:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 100,
"totalPages": 5
}
}
}
```
**客户端示例代码**:
```javascript
const getWaterRecords = async (params = {}) => {
const queryString = new URLSearchParams(params).toString();
const response = await fetch(`/api/water-records?${queryString}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.json();
};
// 使用示例
const records = await getWaterRecords({
startDate: '2023-12-01',
endDate: '2023-12-31',
page: 1,
limit: 20
});
```
### 3. 更新喝水记录
**接口地址**: `PUT /water-records/:id`
**描述**: 更新指定的喝水记录
**路径参数**:
- `id`: 记录ID
**请求参数** (所有字段都是可选的):
```json
{
"amount": 300, // 可选,喝水量(毫升)
"recordedAt": "2023-12-01T11:00:00.000Z", // 可选,记录时间
"source": "Manual", // 可选,记录来源
"note": "修改后的备注" // 可选,备注
}
```
**响应示例**:
```json
{
"success": true,
"message": "操作成功",
"data": {
"id": 1,
"amount": 300,
"recordedAt": "2023-12-01T11:00:00.000Z",
"note": "修改后的备注",
"createdAt": "2023-12-01T10:00:00.000Z",
"updatedAt": "2023-12-01T11:30:00.000Z"
}
}
```
**客户端示例代码**:
```javascript
const updateWaterRecord = async (recordId, updateData) => {
const response = await fetch(`/api/water-records/${recordId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(updateData)
});
return response.json();
};
```
### 4. 删除喝水记录
**接口地址**: `DELETE /water-records/:id`
**描述**: 删除指定的喝水记录
**路径参数**:
- `id`: 记录ID
**响应**: HTTP 204 No Content (成功删除)
**客户端示例代码**:
```javascript
const deleteWaterRecord = async (recordId) => {
const response = await fetch(`/api/water-records/${recordId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.status === 204;
};
```
### 5. 更新每日喝水目标
**接口地址**: `PUT /water-records/goal/daily`
**描述**: 设置或更新用户的每日喝水目标
**请求参数**:
```json
{
"dailyWaterGoal": 2000 // 必填每日喝水目标毫升范围500-10000
}
```
**响应示例**:
```json
{
"success": true,
"message": "操作成功",
"data": {
"dailyWaterGoal": 2000,
"updatedAt": "2023-12-01T12:00:00.000Z"
}
}
```
**客户端示例代码**:
```javascript
const updateWaterGoal = async (goalAmount) => {
const response = await fetch('/api/water-records/goal/daily', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ dailyWaterGoal: goalAmount })
});
return response.json();
};
```
### 6. 获取指定日期的喝水统计
**接口地址**: `GET /water-records/stats`
**描述**: 获取指定日期的喝水统计信息,包括总量、完成率等
**查询参数**:
- `date` (可选): 查询日期格式YYYY-MM-DD不传则默认为今天
**请求示例**:
```
GET /water-records/stats?date=2023-12-01
```
**响应示例**:
```json
{
"success": true,
"message": "操作成功",
"data": {
"date": "2023-12-01",
"totalAmount": 1500, // 当日总喝水量(毫升)
"dailyGoal": 2000, // 每日目标(毫升)
"completionRate": 75.0, // 完成率(百分比)
"recordCount": 6, // 记录次数
"records": [ // 当日所有记录
{
"id": 1,
"amount": 250,
"recordedAt": "2023-12-01T08:00:00.000Z",
"note": "早晨第一杯水"
},
{
"id": 2,
"amount": 300,
"recordedAt": "2023-12-01T10:30:00.000Z",
"note": null
}
]
}
}
```
**客户端示例代码**:
```javascript
const getWaterStats = async (date) => {
const params = date ? `?date=${date}` : '';
const response = await fetch(`/api/water-records/stats${params}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.json();
};
// 使用示例
const todayStats = await getWaterStats(); // 获取今天的统计
const specificDateStats = await getWaterStats('2023-12-01'); // 获取指定日期的统计
```
## 错误处理
### 常见错误码
- `400 Bad Request`: 请求参数错误
- `401 Unauthorized`: 未授权Token无效或过期
- `404 Not Found`: 资源不存在
- `422 Unprocessable Entity`: 数据验证失败
- `500 Internal Server Error`: 服务器内部错误
### 错误响应格式
```json
{
"success": false,
"message": "错误描述",
"error": {
"code": "ERROR_CODE",
"details": "详细错误信息"
}
}
```
### 客户端错误处理示例
```javascript
const handleApiCall = async (apiFunction) => {
try {
const result = await apiFunction();
if (result.success) {
return result.data;
} else {
throw new Error(result.message);
}
} catch (error) {
console.error('API调用失败:', error.message);
// 根据错误类型进行相应处理
if (error.status === 401) {
// Token过期重新登录
redirectToLogin();
}
throw error;
}
};
```
## 数据类型说明
### WaterRecordSource 枚举
```typescript
enum WaterRecordSource {
Manual = 'Manual', // 手动记录
Auto = 'Auto' // 自动记录
}
```
### 日期格式
- 所有日期时间字段使用 ISO 8601 格式:`YYYY-MM-DDTHH:mm:ss.sssZ`
- 查询参数中的日期使用简化格式:`YYYY-MM-DD`
## 最佳实践
1. **错误处理**: 始终检查响应的 `success` 字段,并妥善处理错误情况
2. **Token管理**: 实现Token自动刷新机制避免因Token过期导致的请求失败
3. **数据验证**: 在发送请求前进行客户端数据验证,提升用户体验
4. **缓存策略**: 对于统计数据等相对稳定的信息,可以实现适当的缓存策略
5. **分页处理**: 处理列表数据时,注意分页信息,避免一次性加载过多数据
## 完整的客户端封装示例
```javascript
class WaterRecordsAPI {
constructor(baseURL, token) {
this.baseURL = baseURL;
this.token = token;
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`,
...options.headers
},
...options
};
const response = await fetch(url, config);
const data = await response.json();
if (!data.success) {
throw new Error(data.message);
}
return data.data;
}
// 创建喝水记录
async createRecord(recordData) {
return this.request('/water-records', {
method: 'POST',
body: JSON.stringify(recordData)
});
}
// 获取记录列表
async getRecords(params = {}) {
const queryString = new URLSearchParams(params).toString();
return this.request(`/water-records?${queryString}`);
}
// 更新记录
async updateRecord(recordId, updateData) {
return this.request(`/water-records/${recordId}`, {
method: 'PUT',
body: JSON.stringify(updateData)
});
}
// 删除记录
async deleteRecord(recordId) {
await this.request(`/water-records/${recordId}`, {
method: 'DELETE'
});
return true;
}
// 更新喝水目标
async updateGoal(goalAmount) {
return this.request('/water-records/goal/daily', {
method: 'PUT',
body: JSON.stringify({ dailyWaterGoal: goalAmount })
});
}
// 获取统计数据
async getStats(date) {
const params = date ? `?date=${date}` : '';
return this.request(`/water-records/stats${params}`);
}
}
// 使用示例
const api = new WaterRecordsAPI('https://your-api-domain.com/api', 'your-jwt-token');
// 创建记录
const newRecord = await api.createRecord({
amount: 250,
note: '早晨第一杯水'
});
// 获取今日统计
const todayStats = await api.getStats();
```
这个API封装提供了完整的喝水记录管理功能可以直接在客户端项目中使用。