# 01-API 服务对接 ## 目标 将前端原型从模拟数据切换到真实后端 API。 --- ## 前置要求 - APP/Web 原型开发完成 - 后端 API 服务运行中 --- ## 对接步骤概览 ### 1. 配置 API 基础地址 **APP (React Native):** 创建 `app/src/config/api.ts`: ```typescript // 开发环境配置 export const API_BASE_URL = __DEV__ ? 'http://localhost:8080/api' : 'https://api.yourservice.com/api'; export const TIMEOUT = 30000; ``` **Web (Vue):** 创建 `web/src/config/api.ts`: ```typescript export const API_BASE_URL = import.meta.env.DEV ? 'http://localhost:8080/api' : 'https://api.yourservice.com/api'; ``` --- ### 2. 创建 HTTP 请求封装 **APP (React Native):** 创建 `app/src/api/client.ts`: ```typescript import AsyncStorage from '@react-native-async-storage/async-storage'; import { API_BASE_URL, TIMEOUT } from '../config/api'; interface RequestOptions { method?: 'GET' | 'POST' | 'PUT' | 'DELETE'; body?: any; headers?: Record; } export async function apiRequest( endpoint: string, options: RequestOptions = {} ): Promise { const token = await AsyncStorage.getItem('token'); const headers: Record = { 'Content-Type': 'application/json', ...options.headers, }; if (token) { headers['Authorization'] = `Bearer ${token}`; } const response = await fetch(`${API_BASE_URL}${endpoint}`, { method: options.method || 'GET', headers, body: options.body ? JSON.stringify(options.body) : undefined, }); const data = await response.json(); if (data.code !== 0) { throw new Error(data.message || '请求失败'); } return data.data; } ``` **Web (Vue):** 创建 `web/src/api/client.ts`: ```typescript import axios from 'axios'; import { ElMessage } from 'element-plus'; import { API_BASE_URL } from '../config/api'; import { useAuthStore } from '../stores/auth'; import router from '../router'; const client = axios.create({ baseURL: API_BASE_URL, timeout: 30000, }); // 请求拦截器 client.interceptors.request.use(config => { const authStore = useAuthStore(); if (authStore.token) { config.headers.Authorization = `Bearer ${authStore.token}`; } return config; }); // 响应拦截器 client.interceptors.response.use( response => { const { code, message, data } = response.data; if (code !== 0) { ElMessage.error(message || '请求失败'); return Promise.reject(new Error(message)); } return data; }, error => { if (error.response?.status === 401) { const authStore = useAuthStore(); authStore.logout(); router.push('/login'); } ElMessage.error(error.message || '网络错误'); return Promise.reject(error); } ); export default client; ``` --- ### 3. 创建 API 模块 创建各模块 API 文件: **认证 API (`api/auth.ts`):** ```typescript import client from './client'; export const authApi = { login: (phone: string, password: string) => client.post('/auth/login', { phone, password }), register: (phone: string, password: string, nickname?: string) => client.post('/auth/register', { phone, password, nickname }), }; ``` **体质 API (`api/constitution.ts`):** ```typescript import client from './client'; export const constitutionApi = { getQuestions: () => client.get('/constitution/questions'), submit: (answers: { question_id: number; score: number }[]) => client.post('/constitution/submit', { answers }), getResult: () => client.get('/constitution/result'), getHistory: () => client.get('/constitution/history'), }; ``` **对话 API (`api/conversation.ts`):** ```typescript import client from './client'; export const conversationApi = { getList: () => client.get('/conversations'), create: (title?: string) => client.post('/conversations', { title }), getDetail: (id: string) => client.get(`/conversations/${id}`), delete: (id: string) => client.delete(`/conversations/${id}`), sendMessage: (id: string, content: string) => client.post(`/conversations/${id}/messages`, { content }), }; ``` **用户 API (`api/user.ts`):** ```typescript import client from './client'; export const userApi = { getProfile: () => client.get('/user/profile'), updateProfile: (data: { nickname?: string; avatar?: string }) => client.put('/user/profile', data), getHealthProfile: () => client.get('/user/health-profile'), }; ``` **产品 API (`api/product.ts`):** ```typescript import client from './client'; export const productApi = { getList: (category?: string) => client.get('/products', { params: { category } }), getDetail: (id: number) => client.get(`/products/${id}`), getRecommend: () => client.get('/products/recommend'), search: (keyword: string) => client.get('/products/search', { params: { keyword } }), }; ``` --- ### 4. 修改 Store 使用真实 API **示例:修改认证 Store:** ```typescript // stores/auth.ts (修改前 - 使用模拟数据) function login(userData: User) { user.value = userData; token.value = 'mock-token-' + userData.id; } // stores/auth.ts (修改后 - 使用真实 API) import { authApi } from '@/api/auth'; async function login(phone: string, password: string) { const result = await authApi.login(phone, password); user.value = { id: result.user_id, nickname: result.nickname, phone, surveyCompleted: result.survey_completed, }; token.value = result.token; localStorage.setItem('token', result.token); } ``` --- ### 5. 对接清单 | 功能模块 | 模拟数据 | 真实 API | 说明 | |---------|---------|---------|------| | 用户登录 | `mockLogin()` | `POST /auth/login` | 验证码改密码登录 | | 用户注册 | - | `POST /auth/register` | 新增功能 | | 体质问卷 | `constitutionQuestions` | `GET /constitution/questions` | - | | 体质提交 | `calculateConstitution()` | `POST /constitution/submit` | 后端计算 | | 体质结果 | `useConstitutionStore` | `GET /constitution/result` | - | | 对话列表 | `useChatStore` | `GET /conversations` | - | | 发送消息 | `mockAIReply()` | `POST /conversations/:id/messages` | AI 真实回复 | | 产品推荐 | `mockProducts` | `GET /products/recommend` | - | | 用户信息 | `useAuthStore` | `GET /user/profile` | - | | 健康档案 | `mockProfile` | `GET /user/health-profile` | - | --- ## 验收标准 - [ ] 登录接口对接成功 - [ ] 体质问卷从后端获取 - [ ] 体质结果由后端计算 - [ ] AI 对话调用真实接口 - [ ] Token 认证正常工作 - [ ] 错误处理正常 --- ## 预计耗时 60-90 分钟 --- ## 下一步 完成后进入 `05-前后端对接/02-联调测试.md`