stash
This commit is contained in:
456
docs/API-AI-HEALTH-REPORT.md
Normal file
456
docs/API-AI-HEALTH-REPORT.md
Normal file
@@ -0,0 +1,456 @@
|
||||
# AI 健康报告接口文档
|
||||
|
||||
## 接口概述
|
||||
|
||||
生成用户的 AI 健康报告图片接口,基于用户的健康数据(体重、饮食、运动等)生成可视化的健康分析报告图片。
|
||||
|
||||
---
|
||||
|
||||
## 接口信息
|
||||
|
||||
- **接口名称**: 生成 AI 健康报告
|
||||
- **接口路径**: `/users/ai-report`
|
||||
- **请求方法**: `POST`
|
||||
- **认证方式**: JWT Token (Bearer Token)
|
||||
- **内容类型**: `application/json`
|
||||
|
||||
---
|
||||
|
||||
## 请求说明
|
||||
|
||||
### 请求头 (Headers)
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||||
| ------------- | ------ | ---- | ------------ | ------------------------------------------------ |
|
||||
| Authorization | string | 是 | JWT 访问令牌 | `Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...` |
|
||||
| Content-Type | string | 是 | 请求内容类型 | `application/json` |
|
||||
|
||||
### 请求体 (Body)
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||||
| ------ | ------ | ---- | ------------------------------------------------------------- | -------------- |
|
||||
| date | string | 否 | 指定生成报告的日期,格式 YYYY-MM-DD。不传则默认生成今天的报告 | `"2024-01-15"` |
|
||||
|
||||
### 请求示例
|
||||
|
||||
#### 示例 1: 生成今天的报告
|
||||
|
||||
```bash
|
||||
curl -X POST 'https://api.example.com/users/ai-report' \
|
||||
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{}'
|
||||
```
|
||||
|
||||
#### 示例 2: 生成指定日期的报告
|
||||
|
||||
```bash
|
||||
curl -X POST 'https://api.example.com/users/ai-report' \
|
||||
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"date": "2024-01-15"
|
||||
}'
|
||||
```
|
||||
|
||||
#### JavaScript/TypeScript 示例
|
||||
|
||||
```typescript
|
||||
// 使用 fetch
|
||||
async function generateHealthReport(date?: string) {
|
||||
const response = await fetch("https://api.example.com/users/ai-report", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(date ? { date } : {}),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
}
|
||||
|
||||
// 使用 axios
|
||||
import axios from "axios";
|
||||
|
||||
async function generateHealthReport(date?: string) {
|
||||
const response = await axios.post(
|
||||
"https://api.example.com/users/ai-report",
|
||||
date ? { date } : {},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return response.data;
|
||||
}
|
||||
```
|
||||
|
||||
#### Swift 示例
|
||||
|
||||
```swift
|
||||
func generateHealthReport(date: String? = nil, completion: @escaping (Result<HealthReportResponse, Error>) -> Void) {
|
||||
let url = URL(string: "https://api.example.com/users/ai-report")!
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
|
||||
var body: [String: Any] = [:]
|
||||
if let date = date {
|
||||
body["date"] = date
|
||||
}
|
||||
|
||||
if !body.isEmpty {
|
||||
request.httpBody = try? JSONSerialization.data(withJSONObject: body)
|
||||
}
|
||||
|
||||
URLSession.shared.dataTask(with: request) { data, response, error in
|
||||
if let error = error {
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
guard let data = data else {
|
||||
completion(.failure(NSError(domain: "", code: -1, userInfo: nil)))
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let result = try decoder.decode(HealthReportResponse.self, from: data)
|
||||
completion(.success(result))
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}.resume()
|
||||
}
|
||||
|
||||
// 响应模型
|
||||
struct HealthReportResponse: Codable {
|
||||
let code: Int
|
||||
let message: String
|
||||
let data: HealthReportData
|
||||
}
|
||||
|
||||
struct HealthReportData: Codable {
|
||||
let imageUrl: String
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 响应说明
|
||||
|
||||
### 响应格式
|
||||
|
||||
所有响应都遵循统一的响应格式:
|
||||
|
||||
```typescript
|
||||
{
|
||||
code: number; // 响应码: 0-成功, 1-失败
|
||||
message: string; // 响应消息
|
||||
data: {
|
||||
imageUrl: string; // 生成的报告图片 URL
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 成功响应
|
||||
|
||||
**HTTP 状态码**: `200 OK`
|
||||
|
||||
**响应体示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "AI健康报告生成成功",
|
||||
"data": {
|
||||
"imageUrl": "https://pilates-1234567890.cos.ap-guangzhou.myqcloud.com/health-reports/user-123/2024-01-15/report-xxxxx.png"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**字段说明**:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| ------------- | ------ | -------------------------------------------- |
|
||||
| code | number | 响应码,0 表示成功 |
|
||||
| message | string | 响应消息,成功时为 "AI健康报告生成成功" |
|
||||
| data.imageUrl | string | 生成的健康报告图片完整 URL,可直接访问和下载 |
|
||||
|
||||
### 失败响应
|
||||
|
||||
**HTTP 状态码**: `200 OK` (业务失败也返回 200,通过 code 字段判断)
|
||||
|
||||
**响应体示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 1,
|
||||
"message": "生成失败: 用户健康数据不足",
|
||||
"data": {
|
||||
"imageUrl": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**常见错误消息**:
|
||||
|
||||
| 错误消息 | 说明 | 解决方案 |
|
||||
| ----------------------------- | ------------------------------ | ---------------------------------------------- |
|
||||
| `生成失败: 用户健康数据不足` | 用户没有足够的健康数据生成报告 | 引导用户添加更多健康数据(体重、饮食、运动等) |
|
||||
| `生成失败: 日期格式不正确` | date 参数格式错误 | 确保日期格式为 YYYY-MM-DD |
|
||||
| `生成失败: 未找到用户信息` | 用户不存在或 Token 无效 | 检查认证 Token 是否有效 |
|
||||
| `生成失败: AI 服务暂时不可用` | AI 模型服务异常 | 稍后重试 |
|
||||
|
||||
### 认证失败响应
|
||||
|
||||
**HTTP 状态码**: `401 Unauthorized`
|
||||
|
||||
**响应体示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"statusCode": 401,
|
||||
"message": "Unauthorized"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 业务逻辑说明
|
||||
|
||||
### 报告内容
|
||||
|
||||
AI 健康报告会基于用户的以下数据生成:
|
||||
|
||||
1. **体重数据**: 当天或最近的体重记录
|
||||
2. **饮食数据**: 当天的饮食记录和营养摄入
|
||||
3. **运动数据**: 当天的运动记录和卡路里消耗
|
||||
4. **围度数据**: 身体各部位的围度测量数据
|
||||
5. **目标进度**: 用户设定的健康目标完成情况
|
||||
|
||||
### 报告生成逻辑
|
||||
|
||||
- 如果不传 `date` 参数,默认生成今天的报告
|
||||
- 如果指定日期没有数据,会返回数据不足的提示
|
||||
- 报告图片为 PNG 格式,尺寸适配移动端展示
|
||||
- 图片会存储在腾讯云 COS,有效期永久(或根据策略定期清理)
|
||||
|
||||
### 缓存策略
|
||||
|
||||
- 同一天同一用户的报告会缓存,重复请求会返回相同的图片 URL
|
||||
- 如果用户更新了当天的数据,可以重新生成覆盖旧报告
|
||||
|
||||
---
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 客户端错误处理示例
|
||||
|
||||
```typescript
|
||||
async function fetchHealthReport(date?: string) {
|
||||
try {
|
||||
const response = await fetch("https://api.example.com/users/ai-report", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(date ? { date } : {}),
|
||||
});
|
||||
|
||||
// 检查 HTTP 状态码
|
||||
if (response.status === 401) {
|
||||
// Token 失效,需要重新登录
|
||||
throw new Error("认证失败,请重新登录");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// 检查业务状态码
|
||||
if (result.code !== 0) {
|
||||
// 业务失败
|
||||
throw new Error(result.message);
|
||||
}
|
||||
|
||||
// 成功,返回图片 URL
|
||||
return result.data.imageUrl;
|
||||
} catch (error) {
|
||||
console.error("生成健康报告失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用示例
|
||||
try {
|
||||
const imageUrl = await fetchHealthReport();
|
||||
console.log("报告生成成功:", imageUrl);
|
||||
// 在 UI 中展示图片
|
||||
} catch (error) {
|
||||
// 向用户展示错误提示
|
||||
alert(error.message);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 使用建议
|
||||
|
||||
### 1. 前置检查
|
||||
|
||||
在调用接口前,建议先检查:
|
||||
|
||||
- 用户是否已登录(有有效的 JWT Token)
|
||||
- 用户是否有足够的健康数据(可通过其他接口查询)
|
||||
- 网络连接是否正常
|
||||
|
||||
### 2. 加载提示
|
||||
|
||||
由于报告生成需要调用 AI 服务,可能需要几秒钟时间,建议:
|
||||
|
||||
- 显示加载动画或进度提示
|
||||
- 设置合理的超时时间(建议 30-60 秒)
|
||||
- 提供取消操作的选项
|
||||
|
||||
### 3. 图片展示
|
||||
|
||||
获取到图片 URL 后:
|
||||
|
||||
- 可以直接在 Image 组件中使用该 URL
|
||||
- 支持下载保存到本地相册
|
||||
- 支持分享到社交媒体
|
||||
|
||||
### 4. 错误处理
|
||||
|
||||
- 网络错误:提示用户检查网络连接
|
||||
- 数据不足:引导用户添加健康数据
|
||||
- Token 过期:自动刷新 Token 或引导重新登录
|
||||
|
||||
---
|
||||
|
||||
## 完整示例
|
||||
|
||||
### React Native 完整示例
|
||||
|
||||
```typescript
|
||||
import React, { useState } from 'react';
|
||||
import { View, Image, Button, Text, ActivityIndicator } from 'react-native';
|
||||
import axios from 'axios';
|
||||
|
||||
const HealthReportScreen = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [imageUrl, setImageUrl] = useState<string | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const generateReport = async (date?: string) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await axios.post(
|
||||
'https://api.example.com/users/ai-report',
|
||||
date ? { date } : {},
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${accessToken}`,
|
||||
},
|
||||
timeout: 60000, // 60秒超时
|
||||
}
|
||||
);
|
||||
|
||||
if (response.data.code === 0) {
|
||||
setImageUrl(response.data.data.imageUrl);
|
||||
} else {
|
||||
setError(response.data.message);
|
||||
}
|
||||
} catch (err) {
|
||||
if (axios.isAxiosError(err)) {
|
||||
if (err.response?.status === 401) {
|
||||
setError('登录已过期,请重新登录');
|
||||
} else if (err.code === 'ECONNABORTED') {
|
||||
setError('请求超时,请检查网络连接');
|
||||
} else {
|
||||
setError(err.response?.data?.message || '生成报告失败');
|
||||
}
|
||||
} else {
|
||||
setError('未知错误');
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, padding: 20 }}>
|
||||
<Button
|
||||
title="生成今天的健康报告"
|
||||
onPressed={() => generateReport()}
|
||||
disabled={loading}
|
||||
/>
|
||||
|
||||
{loading && (
|
||||
<View style={{ marginTop: 20, alignItems: 'center' }}>
|
||||
<ActivityIndicator size="large" />
|
||||
<Text style={{ marginTop: 10 }}>正在生成报告...</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<Text style={{ color: 'red', marginTop: 20 }}>
|
||||
{error}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{imageUrl && (
|
||||
<Image
|
||||
source={{ uri: imageUrl }}
|
||||
style={{ width: '100%', height: 400, marginTop: 20 }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default HealthReportScreen;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **认证要求**: 必须携带有效的 JWT Token,否则返回 401
|
||||
2. **请求频率**: 建议不要频繁调用,同一用户同一天建议缓存结果
|
||||
3. **图片有效期**: 图片 URL 长期有效,可以缓存在客户端
|
||||
4. **数据依赖**: 需要用户有足够的健康数据才能生成有意义的报告
|
||||
5. **网络要求**: AI 报告生成需要调用外部服务,需要稳定的网络连接
|
||||
6. **超时设置**: 建议设置 30-60 秒的请求超时时间
|
||||
|
||||
---
|
||||
|
||||
## 相关接口
|
||||
|
||||
- [用户信息接口](./API-USER-INFO.md)
|
||||
- [体重记录接口](./API-WEIGHT-RECORDS.md)
|
||||
- [饮食记录接口](./API-DIET-RECORDS.md)
|
||||
- [运动记录接口](./API-WORKOUT-RECORDS.md)
|
||||
|
||||
---
|
||||
|
||||
## 更新日志
|
||||
|
||||
| 版本 | 日期 | 更新内容 |
|
||||
| ---- | ---------- | ------------------------------ |
|
||||
| v1.0 | 2024-01-15 | 初始版本,支持基础健康报告生成 |
|
||||
|
||||
---
|
||||
|
||||
## 技术支持
|
||||
|
||||
如有问题,请联系技术支持团队。
|
||||
Reference in New Issue
Block a user