# API 文档 ## 目录 - [基础配置](#基础配置) - [请求封装](#请求封装) - [用户相关接口](#用户相关接口) - [职位相关接口](#职位相关接口) - [面试相关接口](#面试相关接口) - [文件上传接口](#文件上传接口) - [错误处理](#错误处理) ## 基础配置 ### API 基础地址 - **生产环境**: `https://backend.qicai321.com` - **测试环境**: `http://192.168.66.187:8083` ### 请求配置 - **请求超时**: 60000ms (60秒) - **认证方式**: Bearer Token + CSRF Token - **数据格式**: JSON ### 请求头 所有请求会自动添加以下请求头: ```javascript { 'Authorization': 'Bearer {token}', 'X-CSRF-Token': '{csrfToken}', 'Content-Type': 'application/json' } ``` ## 请求封装 ### HTTP 方法 项目使用封装的 `http` 对象提供以下方法: ```javascript import http from '@/utils/request.js'; // GET 请求 http.get(url, data, options) // POST 请求 http.post(url, data, options) // PUT 请求 http.put(url, data, options) // DELETE 请求 http.delete(url, data, options) // 文件上传 http.upload(url, filePath, name, formData, options) ``` ### 请求拦截器 自动添加的功能: 1. **Token 认证**: 自动从存储中获取 token 并添加到请求头 2. **CSRF 保护**: 自动添加 CSRF token 3. **URL 处理**: 自动拼接基础 URL 4. **错误处理**: 统一的错误处理和提示 ### 响应拦截器 自动处理的功能: 1. **状态码检查**: HTTP 状态码检查 2. **业务状态**: 检查业务返回码 (code/status) 3. **数据提取**: 自动提取 response.data.data 4. **错误映射**: 统一的错误码映射 ## 用户相关接口 ### 微信登录 ```javascript import { wxLogin } from '@/api/user.js'; // 请求参数 const params = { code: '微信登录code', userInfo: { nickname: '用户昵称', avatarUrl: '头像URL', gender: 0, // 性别 province: '省份', city: '城市', country: '国家', tenant_id: 1 }, signature: '签名', rawData: '原始数据', encryptedData: '加密数据', iv: '初始向量', _csrf: 'CSRF token' }; // 调用 const result = await wxLogin(params); ``` **接口地址**: `POST /wechat/wechatLogin` **返回数据**: ```javascript { status: 2000, code: 0, data: { token: 'jwt_token', userInfo: { openid: 'openid', nickname: '昵称', avatarUrl: '头像', tenant_id: 1 } } } ``` ### 获取用户信息 ```javascript import { getUserInfo } from '@/api/user.js'; // 获取当前用户信息 const userInfo = await getUserInfo(); // 获取指定用户信息 const otherUserInfo = await getUserInfo(userId, openid); ``` **接口地址**: `GET /wechat/getUserDetail` 或 `GET /api/wechat/get_user_info` ### 获取用户手机号 ```javascript import { getUserPhoneNumber } from '@/api/user.js'; const params = { code: '微信授权code', encryptedData: '加密数据', iv: '初始向量' }; const phoneInfo = await getUserPhoneNumber(params); ``` **接口地址**: `POST /wechat/getUserPhoneNumber` ### 更新用户信息 ```javascript import { updateUserInfo } from '@/api/user.js'; const userData = { nickname: '新昵称', phone: '手机号', // ...其他用户信息 }; await updateUserInfo(userData); ``` **接口地址**: `PUT /api/user/update` ### 上传头像 ```javascript import { uploadAvatar } from '@/api/user.js'; const filePath = '/path/to/image.jpg'; const result = await uploadAvatar(filePath); ``` **接口地址**: `POST /api/upload/avatar` ### 退出登录 ```javascript import { logout } from '@/api/user.js'; await logout(); ``` **接口地址**: `POST /wechat/wechatLogout` ### 填写用户信息 ```javascript import { fillUserInfo } from '@/api/user.js'; const userInfo = { name: '姓名', phone: '手机号', email: '邮箱', // ...其他信息 }; await fillUserInfo(userInfo); ``` **接口地址**: `POST /api/wechat/save_user_info` ## 职位相关接口 ### 获取职位列表 ```javascript import { getJobList } from '@/api/user.js'; const params = { page: 1, limit: 50, searchTerms: '关键词', status: '状态', tenant_id: 1 }; const jobList = await getJobList(params); ``` **接口地址**: `GET /api/system/job/list` **请求参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | page | Number | 否 | 页码,默认1 | | limit | Number | 否 | 每页数量,默认50 | | searchTerms | String | 否 | 搜索关键词 | | status | String | 否 | 职位状态 | | tenant_id | Number | 否 | 租户ID | ### 申请职位 ```javascript import { applyJob } from '@/api/user.js'; const params = { job_id: 123, user_id: 456, resume_id: 789 }; await applyJob(params); ``` **接口地址**: `POST /api/job/apply` ### 获取职位申请详情 ```javascript import { getApplicationDetail } from '@/api/user.js'; const params = { id: 123, application_id: 456 }; const detail = await getApplicationDetail(params); ``` **接口地址**: `GET /api/job/application_detail` **请求参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | id | Number | 是 | 用户ID | | tenant_id | Number | 是 | 租户ID | | application_id | Number | 是 | 申请ID | ## 面试相关接口 ### 获取面试列表 ```javascript import { getInterviewList } from '@/api/user.js'; const params = { user_id: 123, job_id: 456 }; const interviewList = await getInterviewList(params); ``` **接口地址**: `GET /job/questions` ### 获取面试详情 ```javascript import { getInterviewDetail } from '@/api/user.js'; const params = { interview_id: 123 }; const detail = await getInterviewDetail(params); ``` **接口地址**: `GET /interview_question/detail` ### 提交面试答案 ```javascript import { submitAnswer } from '@/api/user.js'; const params = { question_id: 123, answer: '答案内容', video_url: '视频URL', audio_url: '音频URL' }; await submitAnswer(params); ``` **接口地址**: `POST /api/job/submit_answer` ### 获取问题数据 ```javascript import { getQuestions } from '@/api/user.js'; const params = { job_id: 123, tenant_id: 1 }; const questions = await getQuestions(params); ``` **接口地址**: `GET /api/wechat/choice_questions/` **请求参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | job_id | Number | 是 | 职位ID | | tenant_id | Number | 是 | 租户ID | ### 语音面试互动 ```javascript // 直接调用 uni.request const res = await uni.request({ url: `${apiBaseUrl}/api/voice_interview_interaction/`, method: 'POST', data: { tenant_id: 1, question_id: 123, position_config_id: 456, application_id: 789 } }); ``` **接口地址**: `POST /api/voice_interview_interaction/` ## 文件上传接口 ### 上传照片 ```javascript import { uploadPhoto } from '@/api/user.js'; const params = { file: '文件路径', type: 'photo', user_id: 123 }; const result = await uploadPhoto(params); ``` **接口地址**: `POST /api/upload/` **上传文件示例**: ```javascript import http from '@/utils/request.js'; const result = await http.upload( '/api/upload/', filePath, 'file', // 文件字段名 { type: 'photo', tenant_id: 1 } ); ``` ## 错误处理 ### 错误码说明 | HTTP 状态码 | 业务码 | 说明 | 处理方式 | |------------|--------|------|---------| | 200 | 2000 | 请求成功 | 正常处理 | | 400 | - | 请求参数错误 | 检查请求参数 | | 401 | - | 未登录或token过期 | 跳转登录页面 | | 403 | - | 无权限 | 提示用户 | | 500 | - | 服务器错误 | 提示用户稍后重试 | | 400 | 999 | 业务错误(如职位已截止) | 显示错误信息 | ### 错误处理示例 ```javascript import http from '@/utils/request.js'; try { const result = await http.post('/api/example', data); // 处理成功结果 } catch (error) { // 错误已在拦截器中处理并提示用户 // 这里可以做额外的处理 if (error.status === 401) { // 跳转到登录页面 uni.reLaunch({ url: '/pages/login/login' }); } } ``` ### 特殊错误码 999 当返回 `status: 999` 或 `code: 999` 时,表示业务逻辑错误(如职位申请已截止),不会自动提示,需要手动处理: ```javascript try { await applyJob(params); } catch (error) { if (error.status === 999) { uni.showToast({ title: error.message || '申请已截止', icon: 'none' }); } } ``` ## 使用示例 ### 方式一:使用 API 模块 ```javascript // 在页面中导入 import { wxLogin, getUserInfo } from '@/api/user.js'; // 使用 export default { methods: { async handleLogin() { try { const result = await wxLogin(params); // 处理登录结果 } catch (error) { // 错误处理 } } } } ``` ### 方式二:使用 API 服务 ```javascript import apiService from '@/services/ApiService.js'; // 获取用户API const userApi = apiService.get('user'); const result = await userApi.getUserInfo(); // 或使用简写 const userApi = apiService.user; const result = await userApi.getUserInfo(); ``` ### 方式三:使用 Composition API ```javascript import { useUserApi } from '@/composables/useUserApi.js'; export default { setup() { const { login, loading, error } = useUserApi(); const handleLogin = async () => { try { const result = await login(code, userInfo); return result; } catch (err) { console.error('Login failed:', error.value); } }; return { handleLogin, loading, error }; } } ``` ### 方式四:直接使用 uni.request ```javascript import { apiBaseUrl } from '@/common/config.js'; const res = await uni.request({ url: `${apiBaseUrl}/api/wechat/user/get_full_info`, method: 'GET', data: { tenant_id: 1, openid: 'openid' } }); ``` ## 注意事项 ### Token 管理 - Token 存储在本地存储中: `uni.getStorageSync('token')` - 建议在 app.onLaunch 时检查 token 有效性 - Token 过期后需要重新登录 ### CSRF Token - CSRF Token 存储在: `uni.getStorageSync('csrfToken')` - 自动添加到请求头: `X-CSRF-Token` - 建议在首次加载时获取 CSRF token ### 请求超时 - 默认超时时间: 60秒 - 长请求可能需要调整超时时间 - 使用 `options.timeout` 参数自定义超时时间 ### 并发请求 - 多个请求并发时可使用 `Promise.all()` - 注意避免重复请求(使用防抖/节流) - 某些接口有防重入保护(如面试互动接口) ### 测试环境切换 修改 `common/config.js` 中的 `apiBaseUrl`: ```javascript // 生产环境 export const apiBaseUrl = 'https://backend.qicai321.com'; // 测试环境 export const apiBaseUrl = 'http://192.168.66.187:8083'; ``` ## API 列表汇总 ### 用户相关 - 微信登录: `POST /wechat/wechatLogin` - 获取用户信息: `GET /wechat/getUserDetail` - 获取手机号: `POST /wechat/getUserPhoneNumber` - 更新用户信息: `PUT /api/user/update` - 上传头像: `POST /api/upload/avatar` - 退出登录: `POST /wechat/wechatLogout` - 填写用户信息: `POST /api/wechat/save_user_info` ### 职位相关 - 获取职位列表: `GET /api/system/job/list` - 申请职位: `POST /api/job/apply` - 获取申请详情: `GET /api/job/application_detail` ### 面试相关 - 获取面试列表: `GET /job/questions` - 获取面试详情: `GET /interview_question/detail` - 提交答案: `POST /api/job/submit_answer` - 获取问题: `GET /api/wechat/choice_questions/` - 面试互动: `POST /api/voice_interview_interaction/` ### 文件相关 - 上传文件: `POST /api/upload/` ### 公共相关 - 用户协议: `GET /api/public/agreements/terms_of_service/` ## 更新日志 - **v1.0.0** (2024): 初始版本 - 基础API封装 - 用户、职位、面试相关接口 - 统一的错误处理 - CSRF 防护机制