Compare commits
4
Commits
c191002cc6
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcc93fad2a | ||
|
|
cb710b47df | ||
|
|
e78a7b95a1 | ||
|
|
6ab8f89770 |
@@ -42,6 +42,8 @@
|
||||
// 检查本地是否有有效token
|
||||
const token = uni.getStorageSync('token')
|
||||
if (token) {
|
||||
// 已有token,直接跳过WebSocket初始化
|
||||
console.log('已有token,跳过WebSocket初始化')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -74,7 +76,7 @@
|
||||
|
||||
if (result && result.token) {
|
||||
// 用户已授权过手机号,保存登录信息
|
||||
this.saveLoginData(result)
|
||||
await this.saveLoginData(result)
|
||||
} else {
|
||||
// 用户未授权手机号,保存微信登录code供后续使用
|
||||
this.saveWxCode(loginRes.code)
|
||||
@@ -87,7 +89,7 @@
|
||||
},
|
||||
|
||||
// 保存登录数据
|
||||
saveLoginData(result) {
|
||||
async saveLoginData(result) {
|
||||
uni.setStorageSync('token', result.token)
|
||||
if (result.refreshToken) {
|
||||
uni.setStorageSync('refreshToken', result.refreshToken)
|
||||
@@ -102,6 +104,9 @@
|
||||
? 'profile_completed'
|
||||
: 'phone_authed'
|
||||
uni.setStorageSync('loginStep', loginStep)
|
||||
|
||||
// 跳过WebSocket初始化
|
||||
console.log('登录成功,跳过WebSocket初始化')
|
||||
},
|
||||
|
||||
// 保存微信code
|
||||
@@ -109,6 +114,11 @@
|
||||
uni.setStorageSync('wxLoginCode', code)
|
||||
uni.setStorageSync('loginDate', new Date().toISOString())
|
||||
uni.setStorageSync('loginStep', 'wx_logged')
|
||||
},
|
||||
|
||||
// WebSocket功能已移除,保留方法避免调用错误
|
||||
async initWebSocketConnection(token) {
|
||||
console.log('WebSocket功能已移除,使用HTTP API替代')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-105
@@ -1,5 +1,9 @@
|
||||
// 领养专区相关API接口
|
||||
// 注意:所有接口的鉴权配置已在 http/config/config.js 中统一管理
|
||||
/**
|
||||
* 领养专区相关API接口模块
|
||||
*/
|
||||
|
||||
import BaseRequest from '../utils/request-helper.js'
|
||||
import { LOADING_TEXTS } from '../config/constants.js'
|
||||
|
||||
/**
|
||||
* 获取待领养宠物列表
|
||||
@@ -8,15 +12,7 @@
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getAdoptionPets = (params = {}, config = {}) => {
|
||||
return uni.$u.http.get('/adoption/pets', {
|
||||
params,
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get('/adoption/pets', params, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,15 +22,7 @@ export const getAdoptionPets = (params = {}, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const searchPets = (searchParams, config = {}) => {
|
||||
return uni.$u.http.get('/adoption/pets/search', {
|
||||
params: searchParams,
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get('/adoption/pets/search', searchParams, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,14 +32,7 @@ export const searchPets = (searchParams, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const filterPets = (filterParams, config = {}) => {
|
||||
return uni.$u.http.post('/adoption/pets/filter', filterParams, {
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.post('/adoption/pets/filter', filterParams, 'PUBLIC_REQUEST', null, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,14 +42,7 @@ export const filterPets = (filterParams, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getAdoptionPetDetail = (petId, config = {}) => {
|
||||
return uni.$u.http.get(`/adoption/pets/${petId}`, {
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get(`/adoption/pets/${petId}`, {}, 'PUBLIC_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,15 +52,7 @@ export const getAdoptionPetDetail = (petId, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const applyAdoption = (adoptionData, config = {}) => {
|
||||
return uni.$u.http.post('/adoption/apply', adoptionData, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在提交申请...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.post('/adoption/apply', adoptionData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.SUBMIT_APPLICATION, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,15 +62,7 @@ export const applyAdoption = (adoptionData, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getMyAdoptionApplications = (params = {}, config = {}) => {
|
||||
return uni.$u.http.get('/adoption/my-applications', {
|
||||
params,
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get('/adoption/my-applications', params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,15 +72,7 @@ export const getMyAdoptionApplications = (params = {}, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const cancelAdoptionApplication = (applicationId, config = {}) => {
|
||||
return uni.$u.http.delete(`/adoption/applications/${applicationId}`, {}, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在取消申请...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.delete(`/adoption/applications/${applicationId}`, {}, 'AUTHENTICATED_DELETE', LOADING_TEXTS.CANCEL_APPLICATION, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,15 +82,7 @@ export const cancelAdoptionApplication = (applicationId, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getAdoptionOrganizations = (params = {}, config = {}) => {
|
||||
return uni.$u.http.get('/adoption/organizations', {
|
||||
params,
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get('/adoption/organizations', params, 'PUBLIC_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,14 +92,7 @@ export const getAdoptionOrganizations = (params = {}, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getOrganizationDetail = (orgId, config = {}) => {
|
||||
return uni.$u.http.get(`/adoption/organizations/${orgId}`, {
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get(`/adoption/organizations/${orgId}`, {}, 'PUBLIC_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,14 +102,7 @@ export const getOrganizationDetail = (orgId, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const favoritePet = (petId, config = {}) => {
|
||||
return uni.$u.http.post(`/adoption/pets/${petId}/favorite`, {}, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.post(`/adoption/pets/${petId}/favorite`, {}, 'AUTHENTICATED_UPDATE', null, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,14 +112,7 @@ export const favoritePet = (petId, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const unfavoritePet = (petId, config = {}) => {
|
||||
return uni.$u.http.delete(`/adoption/pets/${petId}/favorite`, {}, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.delete(`/adoption/pets/${petId}/favorite`, {}, 'AUTHENTICATED_DELETE', null, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,13 +122,5 @@ export const unfavoritePet = (petId, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getFavoritePets = (params = {}, config = {}) => {
|
||||
return uni.$u.http.get('/adoption/favorites', {
|
||||
params,
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get('/adoption/favorites', params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
|
||||
+181
-80
@@ -1,112 +1,213 @@
|
||||
// AI助手相关API接口
|
||||
// 注意:所有接口的鉴权配置已在 http/config/config.js 中统一管理
|
||||
/**
|
||||
* 宠物助手相关API接口模块
|
||||
* 对接后端宠物助手服务接口
|
||||
*/
|
||||
|
||||
import BaseRequest from '../utils/request-helper.js'
|
||||
import { LOADING_TEXTS } from '../config/constants.js'
|
||||
|
||||
// ==================== 宠物助手聊天接口 ====================
|
||||
|
||||
/**
|
||||
* 发送消息给AI助手
|
||||
* 向宠物助手提问(非流式)
|
||||
* @description 发送消息给宠物助手,获取专业的宠物护理建议
|
||||
* @param {Object} messageData 消息数据对象
|
||||
* @param {string} messageData.message 用户消息内容,必填,1-2000字符
|
||||
* @param {string} [messageData.sessionId] 会话ID,可选,UUID格式
|
||||
* @param {boolean} [messageData.stream=false] 是否流式响应
|
||||
* @param {number} [messageData.temperature=0.7] 温度参数,控制随机性,范围0-2
|
||||
* @param {number} [messageData.maxTokens=1000] 最大生成token数,范围1-4000
|
||||
* @param {string} [messageData.model] 模型名称,可选
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回聊天响应对象
|
||||
* @example
|
||||
* // 基本用法
|
||||
* const response = await askPetAssistant({
|
||||
* message: '我的狗狗不吃饭怎么办?'
|
||||
* })
|
||||
*
|
||||
* // 指定会话和参数
|
||||
* const response = await askPetAssistant({
|
||||
* message: '还有其他建议吗?',
|
||||
* sessionId: 'uuid-session-id',
|
||||
* temperature: 0.8,
|
||||
* maxTokens: 1500
|
||||
* })
|
||||
*/
|
||||
export const askPetAssistant = (messageData, config = {}) => {
|
||||
return BaseRequest.post('/pet/user/assistant/ask', messageData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.AI_THINKING, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 向宠物助手流式提问
|
||||
* @description 发送消息给宠物助手,获取流式响应(实时显示回复过程)
|
||||
* @param {Object} messageData 消息数据对象
|
||||
* @param {string} messageData.message 用户消息内容
|
||||
* @param {string} [messageData.sessionId] 会话ID,可选
|
||||
* @param {number} [messageData.temperature=0.7] 温度参数
|
||||
* @param {number} [messageData.maxTokens=1000] 最大token数
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回流式响应对象
|
||||
* @example
|
||||
* const response = await streamAskPetAssistant({
|
||||
* message: '我的猫咪呕吐是什么原因?',
|
||||
* sessionId: 'uuid-session-id'
|
||||
* })
|
||||
*/
|
||||
export const streamAskPetAssistant = (messageData, config = {}) => {
|
||||
// 强制设置为流式响应
|
||||
const streamData = { ...messageData, stream: true }
|
||||
return BaseRequest.post('/pet/user/assistant/stream-ask', streamData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.AI_THINKING, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宠物助手对话历史
|
||||
* @description 获取用户与宠物助手的对话历史记录(单一会话)
|
||||
* @param {Object} [params={}] 查询参数
|
||||
* @param {number} [params.page=1] 页码,默认第1页
|
||||
* @param {number} [params.pageSize=20] 每页数量,默认20条
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回历史记录列表
|
||||
* @example
|
||||
* // 获取历史记录
|
||||
* const history = await getAssistantHistory({
|
||||
* page: 1,
|
||||
* pageSize: 50
|
||||
* })
|
||||
*/
|
||||
export const getAssistantHistory = (params = {}, config = {}) => {
|
||||
return BaseRequest.get('/pet/user/assistant/history', params, 'AUTHENTICATED_QUERY', config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空宠物助手对话历史
|
||||
* @description 清空用户与宠物助手的对话历史记录
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回操作结果
|
||||
* @example
|
||||
* // 清空历史记录
|
||||
* await clearAssistantHistory()
|
||||
*/
|
||||
export const clearAssistantHistory = (config = {}) => {
|
||||
return BaseRequest.delete('/pet/user/assistant/clear-history', {}, 'AUTHENTICATED_DELETE', '正在清除历史记录...', config)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==================== 兼容性接口(保持向后兼容) ====================
|
||||
|
||||
/**
|
||||
* 发送消息给AI助手(兼容旧版本)
|
||||
* @deprecated 请使用 askPetAssistant 替代
|
||||
* @param {Object} messageData 消息数据
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const sendMessage = (messageData, config = {}) => {
|
||||
return uni.$u.http.post('/ai/chat', messageData, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: 'AI正在思考中...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
console.warn('sendMessage is deprecated, please use askPetAssistant instead')
|
||||
return askPetAssistant(messageData, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AI知识库
|
||||
* @param {Object} params 查询参数
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getKnowledgeBase = (params = {}, config = {}) => {
|
||||
return uni.$u.http.get('/ai/knowledge', {
|
||||
params,
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天历史
|
||||
* 获取聊天历史(兼容旧版本)
|
||||
* @deprecated 请使用 getAssistantHistory 替代
|
||||
* @param {Object} params 查询参数
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getChatHistory = (params = {}, config = {}) => {
|
||||
return uni.$u.http.get('/ai/chat/history', {
|
||||
params,
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
console.warn('getChatHistory is deprecated, please use getAssistantHistory instead')
|
||||
return getAssistantHistory(params, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除聊天历史
|
||||
* 清除聊天历史(兼容旧版本)
|
||||
* @deprecated 请使用 clearAssistantHistory 替代
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const clearChatHistory = (config = {}) => {
|
||||
return uni.$u.http.delete('/ai/chat/history', {}, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在清除历史记录...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
console.warn('clearChatHistory is deprecated, please use clearAssistantHistory instead')
|
||||
return clearAssistantHistory({}, config)
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 验证消息内容
|
||||
* @description 验证用户输入的消息是否符合要求
|
||||
* @param {string} message 消息内容
|
||||
* @returns {Object} 验证结果 { valid: boolean, error?: string }
|
||||
*/
|
||||
export const validateMessage = (message) => {
|
||||
if (!message || typeof message !== 'string') {
|
||||
return { valid: false, error: '消息内容不能为空' }
|
||||
}
|
||||
|
||||
const trimmedMessage = message.trim()
|
||||
if (trimmedMessage.length === 0) {
|
||||
return { valid: false, error: '消息内容不能为空' }
|
||||
}
|
||||
|
||||
if (trimmedMessage.length > 2000) {
|
||||
return { valid: false, error: '消息内容不能超过2000个字符' }
|
||||
}
|
||||
|
||||
return { valid: true }
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AI建议
|
||||
* @param {Object} petData 宠物数据
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise}
|
||||
* 格式化聊天消息
|
||||
* @description 将API返回的消息格式化为前端显示格式
|
||||
* @param {Object} apiMessage API返回的消息对象
|
||||
* @returns {Object} 格式化后的消息对象
|
||||
*/
|
||||
export const getAISuggestion = (petData, config = {}) => {
|
||||
return uni.$u.http.post('/ai/suggestion', petData, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在分析宠物状况...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
export const formatChatMessage = (apiMessage) => {
|
||||
return {
|
||||
id: apiMessage.id,
|
||||
type: apiMessage.role === 'user' ? 'user' : 'ai',
|
||||
content: apiMessage.messageContent || apiMessage.message || '',
|
||||
time: formatMessageTime(apiMessage.createdAt || apiMessage.created_at),
|
||||
sessionId: apiMessage.sessionId,
|
||||
isSensitive: apiMessage.isSensitive || false,
|
||||
tokenCount: apiMessage.tokenCount || 0,
|
||||
responseTime: apiMessage.responseTime || 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音转文字
|
||||
* @param {Object} audioData 音频数据
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise}
|
||||
* 格式化消息时间
|
||||
* @description 将时间戳或时间字符串格式化为显示格式
|
||||
* @param {string|number|Date} timestamp 时间戳或时间对象
|
||||
* @returns {string} 格式化后的时间字符串
|
||||
*/
|
||||
export const speechToText = (audioData, config = {}) => {
|
||||
return uni.$u.http.upload('/ai/speech-to-text', {
|
||||
filePath: audioData.filePath,
|
||||
name: 'audio',
|
||||
formData: audioData.formData || {},
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在识别语音...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
export const formatMessageTime = (timestamp) => {
|
||||
if (!timestamp) return ''
|
||||
|
||||
const date = new Date(timestamp)
|
||||
const now = new Date()
|
||||
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
||||
const messageDate = new Date(date.getFullYear(), date.getMonth(), date.getDate())
|
||||
|
||||
const timeStr = date.toLocaleTimeString('zh-CN', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false
|
||||
})
|
||||
|
||||
if (messageDate.getTime() === today.getTime()) {
|
||||
return timeStr
|
||||
} else if (messageDate.getTime() === today.getTime() - 24 * 60 * 60 * 1000) {
|
||||
return `昨天 ${timeStr}`
|
||||
} else {
|
||||
return date.toLocaleDateString('zh-CN', {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+39
-371
@@ -1,483 +1,151 @@
|
||||
/**
|
||||
* 用户认证相关API接口模块
|
||||
*
|
||||
* @fileoverview 提供用户登录、注册、认证、短信验证等相关的API接口
|
||||
* @author 系统开发团队
|
||||
* @version 2.0.0
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @description
|
||||
* 本模块包含以下功能分组:
|
||||
* - 用户登录相关API:普通登录、微信登录、手机号登录
|
||||
* - 用户注册相关API:用户注册、密码重置
|
||||
* - 会话管理相关API:登出、token刷新
|
||||
* - 短信验证相关API:发送验证码、验证码校验
|
||||
*
|
||||
* @example
|
||||
* // 基本用法示例
|
||||
* import { userLogin, wxPhoneLogin } from '@/http/api/auth.js'
|
||||
*
|
||||
* // 用户登录
|
||||
* const result = await userLogin({ username: 'user', password: 'pass' })
|
||||
*
|
||||
* // 微信手机号登录
|
||||
* const result = await wxPhoneLogin({ code, encryptedData, iv })
|
||||
*
|
||||
* @example
|
||||
* // 使用配置常量
|
||||
* import { AUTH_CONFIG, AUTH_UTILS } from '@/http/api/auth.js'
|
||||
*
|
||||
* // 使用工具函数创建自定义请求
|
||||
* const customRequest = AUTH_UTILS.executeAuthRequest('/custom/auth')
|
||||
* 提供用户登录、注册、认证、短信验证等相关的API接口
|
||||
*/
|
||||
|
||||
// ==================== 类型定义 ====================
|
||||
|
||||
/**
|
||||
* @typedef {Object} LoginData 登录数据对象
|
||||
* @property {string} username 用户名
|
||||
* @property {string} password 密码
|
||||
* @property {boolean} [rememberMe] 是否记住登录状态
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} WxLoginData 微信登录数据对象
|
||||
* @property {string} code 微信登录凭证
|
||||
* @property {string} [encryptedData] 加密数据
|
||||
* @property {string} [iv] 初始向量
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PhoneAuthData 手机号授权数据对象
|
||||
* @property {string} code 微信登录凭证
|
||||
* @property {string} encryptedData 加密的手机号数据
|
||||
* @property {string} iv 初始向量
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} AuthResult 认证结果对象
|
||||
* @property {string} token 访问令牌
|
||||
* @property {string} refreshToken 刷新令牌
|
||||
* @property {Object} userInfo 用户基本信息
|
||||
* @property {number} expiresIn 令牌过期时间(秒)
|
||||
*/
|
||||
|
||||
// ==================== 配置常量 ====================
|
||||
|
||||
/**
|
||||
* 认证API的默认配置模板
|
||||
*/
|
||||
const AUTH_CONFIG_TEMPLATES = {
|
||||
// 无需认证的登录请求
|
||||
PUBLIC_AUTH: {
|
||||
auth: false,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的会话管理请求
|
||||
AUTHENTICATED_SESSION: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 静默的token刷新请求
|
||||
SILENT_REFRESH: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
toast: false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证相关的loading文本配置
|
||||
*/
|
||||
const AUTH_LOADING_TEXTS = {
|
||||
LOGIN: '正在登录...',
|
||||
WX_LOGIN: '正在登录...',
|
||||
PHONE_VERIFY: '正在验证手机号...',
|
||||
REGISTER: '正在注册...',
|
||||
LOGOUT: '正在退出...',
|
||||
SEND_SMS: '正在发送验证码...',
|
||||
VERIFY_SMS: '正在验证...',
|
||||
RESET_PASSWORD: '正在重置密码...'
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
/**
|
||||
* 创建认证请求的标准化配置
|
||||
* @param {string} template 配置模板名称
|
||||
* @param {Object} customConfig 自定义配置
|
||||
* @param {string} loadingText 自定义loading文本
|
||||
* @returns {Object} 标准化的请求配置
|
||||
*/
|
||||
const createAuthConfig = (template, customConfig = {}, loadingText = null) => {
|
||||
const baseConfig = AUTH_CONFIG_TEMPLATES[template] || {}
|
||||
|
||||
const config = {
|
||||
custom: {
|
||||
...baseConfig,
|
||||
...(loadingText && { loadingText }),
|
||||
...customConfig.custom
|
||||
},
|
||||
...customConfig
|
||||
}
|
||||
|
||||
// 移除custom属性中的undefined值
|
||||
Object.keys(config.custom).forEach(key => {
|
||||
if (config.custom[key] === undefined) {
|
||||
delete config.custom[key]
|
||||
}
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行认证相关的POST请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executeAuthRequest = (url, data = {}, template = 'PUBLIC_AUTH', loadingText = null, config = {}) => {
|
||||
const requestConfig = createAuthConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.post(url, data, requestConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行认证请求(支持不同HTTP方法)
|
||||
* @param {string} method HTTP方法
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executeAuthRequestWithMethod = (method, url, data = {}, template = 'PUBLIC_AUTH', loadingText = null, config = {}) => {
|
||||
const requestConfig = createAuthConfig(template, config, loadingText)
|
||||
|
||||
switch (method.toUpperCase()) {
|
||||
case 'GET':
|
||||
return uni.$u.http.get(url, requestConfig)
|
||||
case 'POST':
|
||||
return uni.$u.http.post(url, data, requestConfig)
|
||||
case 'PUT':
|
||||
return uni.$u.http.put(url, data, requestConfig)
|
||||
case 'DELETE':
|
||||
return uni.$u.http.delete(url, requestConfig)
|
||||
default:
|
||||
return uni.$u.http.post(url, data, requestConfig)
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== API方法 ====================
|
||||
import BaseRequest from '../utils/request-helper.js'
|
||||
import { LOADING_TEXTS } from '../config/constants.js'
|
||||
|
||||
// ==================== 用户登录相关API ====================
|
||||
|
||||
/**
|
||||
* 用户账号密码登录
|
||||
* @description 使用用户名和密码进行登录认证
|
||||
* @param {LoginData} loginData 登录数据对象
|
||||
* @param {Object} loginData 登录数据对象
|
||||
* @param {string} loginData.username 用户名或邮箱
|
||||
* @param {string} loginData.password 用户密码
|
||||
* @param {boolean} [loginData.rememberMe=false] 是否记住登录状态
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<AuthResult>} 返回认证结果,包含token和用户信息
|
||||
* @example
|
||||
* // 基本登录
|
||||
* const result = await userLogin({
|
||||
* username: 'user@example.com',
|
||||
* password: 'password123'
|
||||
* })
|
||||
*
|
||||
* // 记住登录状态
|
||||
* const result = await userLogin({
|
||||
* username: 'user@example.com',
|
||||
* password: 'password123',
|
||||
* rememberMe: true
|
||||
* })
|
||||
* @param {boolean} [loginData.rememberMe] 是否记住登录状态
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @returns {Promise} 返回认证结果,包含token和用户信息
|
||||
*/
|
||||
export const userLogin = (loginData, config = {}) => {
|
||||
return executeAuthRequest('/auth/login', loginData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.LOGIN, config)
|
||||
return BaseRequest.post('/auth/login', loginData, 'PUBLIC_REQUEST', LOADING_TEXTS.LOGIN, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信授权登录
|
||||
* @description 使用微信授权码进行登录认证
|
||||
* @param {WxLoginData} wxData 微信登录数据对象
|
||||
* @param {Object} wxData 微信登录数据对象
|
||||
* @param {string} wxData.code 微信登录凭证code
|
||||
* @param {string} [wxData.encryptedData] 加密的用户数据
|
||||
* @param {string} [wxData.iv] 初始向量
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<AuthResult>} 返回认证结果,包含token和用户信息
|
||||
* @example
|
||||
* // 基本微信登录
|
||||
* const result = await wxLogin({ code: 'wx_code_123' })
|
||||
*
|
||||
* // 包含用户信息的微信登录
|
||||
* const result = await wxLogin({
|
||||
* code: 'wx_code_123',
|
||||
* encryptedData: 'encrypted_user_data',
|
||||
* iv: 'initial_vector'
|
||||
* })
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @returns {Promise} 返回认证结果,包含token和用户信息
|
||||
*/
|
||||
export const wxLogin = (wxData, config = {}) => {
|
||||
return executeAuthRequest('/wechat/user/mini/login', wxData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.WX_LOGIN, config)
|
||||
return BaseRequest.post('/wechat/user/mini/login', wxData, 'PUBLIC_REQUEST', LOADING_TEXTS.LOGIN, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信手机号登录
|
||||
* @description 通过微信手机号授权进行登录,获取用户token和信息
|
||||
* @param {PhoneLoginData} phoneData 手机号登录数据对象
|
||||
* @param {Object} phoneData 手机号登录数据对象
|
||||
* @param {string} phoneData.code 微信登录code
|
||||
* @param {string} phoneData.encryptedData 加密的手机号数据
|
||||
* @param {string} phoneData.iv 初始向量
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回登录结果,包含token和用户信息
|
||||
* @example
|
||||
* // 微信手机号登录
|
||||
* const result = await wxPhoneLogin({
|
||||
* code: 'wx_login_code',
|
||||
* encryptedData: 'encrypted_phone_data',
|
||||
* iv: 'initial_vector'
|
||||
* })
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @returns {Promise} 返回登录结果,包含token和用户信息
|
||||
*/
|
||||
export const wxPhoneLogin = (phoneData, config = {}) => {
|
||||
return executeAuthRequest('/wechat/user/mini/phone-login', phoneData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.PHONE_LOGIN, config)
|
||||
return BaseRequest.post('/wechat/user/mini/phone-login', phoneData, 'PUBLIC_REQUEST', LOADING_TEXTS.LOGIN, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户手机号
|
||||
* @description 通过微信手机号授权更新已登录用户的手机号,需要用户已登录
|
||||
* @param {PhoneAuthData} phoneData 手机号授权数据对象
|
||||
* @param {Object} phoneData 手机号授权数据对象
|
||||
* @param {string} phoneData.encryptedData 加密的手机号数据
|
||||
* @param {string} phoneData.iv 初始向量
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<string>} 返回解密后的手机号
|
||||
* @example
|
||||
* // 更新用户手机号
|
||||
* const phoneNumber = await updatePhoneNumber({
|
||||
* encryptedData: 'encrypted_phone_data',
|
||||
* iv: 'initial_vector'
|
||||
* })
|
||||
*
|
||||
* @since 2.0.0 重构为手机号更新功能
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @returns {Promise} 返回解密后的手机号
|
||||
*/
|
||||
export const updatePhoneNumber = (phoneData, config = {}) => {
|
||||
return executeAuthRequest('/user/wechat/mini/phone-update', phoneData, 'AUTHENTICATED_SESSION', AUTH_LOADING_TEXTS.PHONE_VERIFY, config)
|
||||
return BaseRequest.post('/user/wechat/mini/phone-update', phoneData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.PHONE_VERIFY, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
* @description 获取当前登录用户的详细信息
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回用户信息
|
||||
* @example
|
||||
* // 获取用户信息
|
||||
* const userInfo = await getUserInfo()
|
||||
*
|
||||
* @since 2.0.0 微信小程序用户信息接口
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @returns {Promise} 返回用户信息
|
||||
*/
|
||||
export const getUserInfo = (config = {}) => {
|
||||
return executeAuthRequestWithMethod('GET', '/user/wechat/mini/userinfo', {}, 'AUTHENTICATED_SESSION', '获取用户信息中...', config)
|
||||
return BaseRequest.get('/user/wechat/mini/userinfo', {}, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息
|
||||
* @description 更新当前登录用户的信息
|
||||
* @param {Object} userData 用户数据对象
|
||||
* @param {string} [userData.nickname] 用户昵称
|
||||
* @param {string} [userData.avatar] 用户头像URL
|
||||
* @param {number} [userData.gender] 性别:0-未知,1-男,2-女
|
||||
* @param {string} [userData.city] 城市
|
||||
* @param {string} [userData.province] 省份
|
||||
* @param {string} [userData.country] 国家
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回更新结果
|
||||
* @example
|
||||
* // 更新用户昵称
|
||||
* const result = await updateUserInfo({
|
||||
* nickname: '新昵称'
|
||||
* })
|
||||
*
|
||||
* @since 2.0.0 微信小程序用户信息更新接口
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @returns {Promise} 返回更新结果
|
||||
*/
|
||||
export const updateUserInfo = (userData, config = {}) => {
|
||||
return executeAuthRequestWithMethod('PUT', '/user/wechat/mini/userinfo', userData, 'AUTHENTICATED_SESSION', '更新用户信息中...', config)
|
||||
return BaseRequest.put('/user/wechat/mini/userinfo', userData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.UPDATING_USER_INFO, config)
|
||||
}
|
||||
|
||||
// ==================== 用户注册相关API ====================
|
||||
|
||||
/**
|
||||
* 用户账号注册
|
||||
* @description 创建新的用户账号
|
||||
* @param {Object} registerData 注册数据对象
|
||||
* @param {string} registerData.username 用户名
|
||||
* @param {string} registerData.password 密码
|
||||
* @param {string} registerData.email 邮箱地址
|
||||
* @param {string} [registerData.phoneNumber] 手机号码
|
||||
* @param {string} [registerData.inviteCode] 邀请码
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<AuthResult>} 返回注册结果,包含token和用户信息
|
||||
* @example
|
||||
* // 基本注册
|
||||
* const result = await userRegister({
|
||||
* username: 'newuser',
|
||||
* password: 'password123',
|
||||
* email: 'user@example.com'
|
||||
* })
|
||||
*
|
||||
* // 包含手机号的注册
|
||||
* const result = await userRegister({
|
||||
* username: 'newuser',
|
||||
* password: 'password123',
|
||||
* email: 'user@example.com',
|
||||
* phoneNumber: '13800138000'
|
||||
* })
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @returns {Promise} 返回注册结果,包含token和用户信息
|
||||
*/
|
||||
export const userRegister = (registerData, config = {}) => {
|
||||
return executeAuthRequest('/auth/register', registerData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.REGISTER, config)
|
||||
return BaseRequest.post('/auth/register', registerData, 'PUBLIC_REQUEST', LOADING_TEXTS.REGISTER, config)
|
||||
}
|
||||
|
||||
// ==================== 会话管理相关API ====================
|
||||
|
||||
/**
|
||||
* 用户登出
|
||||
* @description 退出当前用户登录状态,清除服务端会话
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回登出结果
|
||||
* @example
|
||||
* // 基本登出
|
||||
* await userLogout()
|
||||
*
|
||||
* // 静默登出(不显示loading)
|
||||
* await userLogout({
|
||||
* custom: { loading: false }
|
||||
* })
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @returns {Promise} 返回登出结果
|
||||
*/
|
||||
export const userLogout = (config = {}) => {
|
||||
return executeAuthRequest('/auth/logout', {}, 'AUTHENTICATED_SESSION', AUTH_LOADING_TEXTS.LOGOUT, config)
|
||||
return BaseRequest.post('/auth/logout', {}, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.LOGOUT, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新访问令牌
|
||||
* @description 使用刷新令牌获取新的访问令牌,通常在token过期时自动调用
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @param {Object} [config] 自定义请求配置
|
||||
* @param {string} [config.refreshToken] 自定义刷新令牌,不传则从本地存储获取
|
||||
* @returns {Promise<Object>} 返回新的token信息
|
||||
* @example
|
||||
* // 自动刷新token
|
||||
* const newTokens = await refreshToken()
|
||||
*
|
||||
* // 使用自定义刷新令牌
|
||||
* const newTokens = await refreshToken({
|
||||
* refreshToken: 'custom_refresh_token'
|
||||
* })
|
||||
* @returns {Promise} 返回新的token信息
|
||||
*/
|
||||
export const refreshToken = (config = {}) => {
|
||||
const refreshTokenValue = config.refreshToken || uni.getStorageSync('refreshToken')
|
||||
const requestConfig = createAuthConfig('SILENT_REFRESH', config)
|
||||
|
||||
return uni.$u.http.post('/auth/refresh', { refreshToken: refreshTokenValue }, requestConfig)
|
||||
return BaseRequest.post('/auth/refresh', { refreshToken: refreshTokenValue }, 'SILENT_REQUEST', null, config)
|
||||
}
|
||||
|
||||
// ==================== 短信验证相关API ====================
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
* @description 向指定手机号发送短信验证码,用于注册、登录或密码重置
|
||||
* @param {Object} phoneData 手机号数据对象
|
||||
* @param {string} phoneData.phoneNumber 手机号码
|
||||
* @param {string} phoneData.type 验证码类型:'register' | 'login' | 'reset' | 'bind'
|
||||
* @param {string} [phoneData.captcha] 图形验证码(防刷机制)
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回发送结果,包含验证码ID和过期时间
|
||||
* @example
|
||||
* // 注册时发送验证码
|
||||
* const result = await sendSmsCode({
|
||||
* phoneNumber: '13800138000',
|
||||
* type: 'register'
|
||||
* })
|
||||
*
|
||||
* // 密码重置时发送验证码
|
||||
* const result = await sendSmsCode({
|
||||
* phoneNumber: '13800138000',
|
||||
* type: 'reset',
|
||||
* captcha: 'abc123'
|
||||
* })
|
||||
* @returns {Promise<Object>} 返回发送结果
|
||||
*/
|
||||
export const sendSmsCode = (phoneData, config = {}) => {
|
||||
return executeAuthRequest('/sms/send', phoneData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.SEND_SMS, config)
|
||||
return BaseRequest.post('/sms/send', phoneData, 'PUBLIC_REQUEST', LOADING_TEXTS.SEND_SMS, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证短信验证码
|
||||
* @description 验证用户输入的短信验证码是否正确
|
||||
* @param {Object} verifyData 验证数据对象
|
||||
* @param {string} verifyData.phoneNumber 手机号码
|
||||
* @param {string} verifyData.code 验证码
|
||||
* @param {string} verifyData.codeId 验证码ID(发送时返回)
|
||||
* @param {string} verifyData.type 验证码类型
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回验证结果
|
||||
* @example
|
||||
* // 验证注册验证码
|
||||
* const result = await verifySmsCode({
|
||||
* phoneNumber: '13800138000',
|
||||
* code: '123456',
|
||||
* codeId: 'sms_id_123',
|
||||
* type: 'register'
|
||||
* })
|
||||
*/
|
||||
export const verifySmsCode = (verifyData, config = {}) => {
|
||||
return executeAuthRequest('/sms/verify', verifyData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.VERIFY_SMS, config)
|
||||
return BaseRequest.post('/sms/verify', verifyData, 'PUBLIC_REQUEST', LOADING_TEXTS.VERIFY_SMS, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置用户密码
|
||||
* @description 通过短信验证码重置用户密码
|
||||
* @param {Object} resetData 重置密码数据对象
|
||||
* @param {string} resetData.phoneNumber 手机号码
|
||||
* @param {string} resetData.code 短信验证码
|
||||
* @param {string} resetData.codeId 验证码ID
|
||||
* @param {string} resetData.newPassword 新密码
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回重置结果
|
||||
* @example
|
||||
* // 重置密码
|
||||
* const result = await resetPassword({
|
||||
* phoneNumber: '13800138000',
|
||||
* code: '123456',
|
||||
* codeId: 'sms_id_123',
|
||||
* newPassword: 'newPassword123'
|
||||
* })
|
||||
*/
|
||||
export const resetPassword = (resetData, config = {}) => {
|
||||
return executeAuthRequest('/auth/reset-password', resetData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.RESET_PASSWORD, config)
|
||||
}
|
||||
|
||||
// ==================== 导出配置常量(供外部使用) ====================
|
||||
|
||||
/**
|
||||
* 导出认证配置常量,供其他模块使用
|
||||
*/
|
||||
export const AUTH_CONFIG = {
|
||||
AUTH_CONFIG_TEMPLATES,
|
||||
AUTH_LOADING_TEXTS
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出认证工具函数,供其他模块使用
|
||||
*/
|
||||
export const AUTH_UTILS = {
|
||||
createAuthConfig,
|
||||
executeAuthRequest,
|
||||
executeAuthRequestWithMethod
|
||||
return BaseRequest.post('/auth/reset-password', resetData, 'PUBLIC_REQUEST', LOADING_TEXTS.RESET_PASSWORD, config)
|
||||
}
|
||||
|
||||
+33
-313
@@ -1,149 +1,12 @@
|
||||
/**
|
||||
* 通用API接口模块
|
||||
*
|
||||
* @fileoverview 提供文件上传、系统配置、地区数据等通用功能的API接口
|
||||
* @author 系统开发团队
|
||||
* @version 2.0.0
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @description
|
||||
* 本模块包含以下功能分组:
|
||||
* - 文件上传相关API:图片上传、文件上传、批量上传
|
||||
* - 云存储相关API:七牛云、阿里云OSS配置获取
|
||||
* - 系统信息相关API:系统配置、版本信息、更新检查
|
||||
* - 基础数据相关API:地区数据、反馈提交
|
||||
*
|
||||
* @example
|
||||
* // 基本用法示例
|
||||
* import { uploadImage, getSystemConfig } from '@/http/api/common.js'
|
||||
*
|
||||
* // 上传图片
|
||||
* const result = await uploadImage({ filePath: 'path/to/image.jpg' })
|
||||
*
|
||||
* // 获取系统配置
|
||||
* const config = await getSystemConfig()
|
||||
* 提供文件上传、系统配置、地区数据等通用功能的API接口
|
||||
*/
|
||||
|
||||
// ==================== 类型定义 ====================
|
||||
import BaseRequest from '../utils/request-helper.js'
|
||||
import { LOADING_TEXTS } from '../config/constants.js'
|
||||
|
||||
/**
|
||||
* @typedef {Object} UploadData 上传数据对象
|
||||
* @property {string} filePath 文件路径
|
||||
* @property {string} [name] 文件字段名,默认'file'
|
||||
* @property {Object} [formData] 额外的表单数据
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} UploadResult 上传结果对象
|
||||
* @property {string} url 文件访问URL
|
||||
* @property {string} key 文件存储键名
|
||||
* @property {number} size 文件大小
|
||||
* @property {string} type 文件类型
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SystemConfig 系统配置对象
|
||||
* @property {Object} upload 上传配置
|
||||
* @property {Object} app 应用配置
|
||||
* @property {Object} features 功能开关配置
|
||||
*/
|
||||
|
||||
// ==================== 配置常量 ====================
|
||||
|
||||
/**
|
||||
* 通用API的默认配置模板
|
||||
*/
|
||||
const COMMON_CONFIG_TEMPLATES = {
|
||||
// 需要认证的上传请求
|
||||
AUTHENTICATED_UPLOAD: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 公开的下载请求
|
||||
PUBLIC_DOWNLOAD: {
|
||||
auth: false,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 静默的配置获取请求
|
||||
SILENT_CONFIG: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
toast: false
|
||||
},
|
||||
|
||||
// 需要认证的提交请求
|
||||
AUTHENTICATED_SUBMIT: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用操作的loading文本配置
|
||||
*/
|
||||
const COMMON_LOADING_TEXTS = {
|
||||
UPLOAD_IMAGE: '正在上传图片...',
|
||||
UPLOAD_FILE: '正在上传文件...',
|
||||
UPLOAD_IMAGES: '正在批量上传...',
|
||||
DOWNLOAD_FILE: '正在下载文件...',
|
||||
CHECK_UPDATE: '正在检查更新...',
|
||||
SUBMIT_FEEDBACK: '正在提交反馈...'
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
/**
|
||||
* 创建通用请求的标准化配置
|
||||
* @param {string} template 配置模板名称
|
||||
* @param {Object} customConfig 自定义配置
|
||||
* @param {string} loadingText 自定义loading文本
|
||||
* @returns {Object} 标准化的请求配置
|
||||
*/
|
||||
const createCommonConfig = (template, customConfig = {}, loadingText = null) => {
|
||||
const baseConfig = COMMON_CONFIG_TEMPLATES[template] || {}
|
||||
|
||||
const config = {
|
||||
custom: {
|
||||
...baseConfig,
|
||||
...(loadingText && { loadingText }),
|
||||
...customConfig.custom
|
||||
},
|
||||
...customConfig
|
||||
}
|
||||
|
||||
// 移除custom属性中的undefined值
|
||||
Object.keys(config.custom).forEach(key => {
|
||||
if (config.custom[key] === undefined) {
|
||||
delete config.custom[key]
|
||||
}
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行上传请求的通用方法
|
||||
* @param {string} url 上传URL
|
||||
* @param {Object} uploadData 上传数据
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executeUploadRequest = (url, uploadData, loadingText, config = {}) => {
|
||||
const requestConfig = createCommonConfig('AUTHENTICATED_UPLOAD', config, loadingText)
|
||||
|
||||
return uni.$u.http.upload(url, {
|
||||
filePath: uploadData.filePath,
|
||||
name: uploadData.name || 'file',
|
||||
formData: uploadData.formData || {},
|
||||
...requestConfig
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== API方法 ====================
|
||||
|
||||
@@ -151,51 +14,19 @@ const executeUploadRequest = (url, uploadData, loadingText, config = {}) => {
|
||||
|
||||
/**
|
||||
* 上传单张图片
|
||||
* @description 上传图片文件到服务器,支持多种图片格式
|
||||
* @param {UploadData} imageData 图片上传数据对象
|
||||
* @param {string} imageData.filePath 图片文件路径
|
||||
* @param {string} [imageData.name='file'] 上传字段名
|
||||
* @param {Object} [imageData.formData={}] 额外的表单数据
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<UploadResult>} 返回上传结果,包含图片URL等信息
|
||||
* @example
|
||||
* // 基本图片上传
|
||||
* const result = await uploadImage({
|
||||
* filePath: 'path/to/image.jpg'
|
||||
* })
|
||||
*
|
||||
* // 带额外数据的图片上传
|
||||
* const result = await uploadImage({
|
||||
* filePath: 'path/to/image.jpg',
|
||||
* name: 'avatar',
|
||||
* formData: { category: 'profile' }
|
||||
* })
|
||||
* @param {Object} imageData 图片上传数据对象
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回上传结果
|
||||
*/
|
||||
export const uploadImage = (imageData, config = {}) => {
|
||||
return executeUploadRequest('/upload/image', imageData, COMMON_LOADING_TEXTS.UPLOAD_IMAGE, config)
|
||||
return BaseRequest.upload('/upload/image', imageData, LOADING_TEXTS.UPLOAD_IMAGE, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量上传多张图片
|
||||
* @description 同时上传多张图片,支持并发上传提升效率
|
||||
* @param {UploadData[]} imageList 图片列表数组
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @param {boolean} [config.showProgress=true] 是否显示整体进度
|
||||
* @param {number} [config.maxConcurrent=3] 最大并发上传数量
|
||||
* @returns {Promise<UploadResult[]>} 返回所有图片的上传结果数组
|
||||
* @example
|
||||
* // 批量上传图片
|
||||
* const results = await uploadImages([
|
||||
* { filePath: 'path/to/image1.jpg' },
|
||||
* { filePath: 'path/to/image2.jpg' },
|
||||
* { filePath: 'path/to/image3.jpg' }
|
||||
* ])
|
||||
*
|
||||
* // 自定义并发数量
|
||||
* const results = await uploadImages(imageList, {
|
||||
* maxConcurrent: 5,
|
||||
* custom: { loadingText: '正在批量上传图片...' }
|
||||
* })
|
||||
* @param {Array} imageList 图片列表数组
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回所有图片的上传结果数组
|
||||
*/
|
||||
export const uploadImages = async (imageList, config = {}) => {
|
||||
const { maxConcurrent = 3, showProgress = true } = config
|
||||
@@ -236,140 +67,56 @@ export const uploadImages = async (imageList, config = {}) => {
|
||||
|
||||
/**
|
||||
* 上传通用文件
|
||||
* @description 上传各种类型的文件到服务器
|
||||
* @param {UploadData} fileData 文件上传数据对象
|
||||
* @param {string} fileData.filePath 文件路径
|
||||
* @param {string} [fileData.name='file'] 上传字段名
|
||||
* @param {Object} [fileData.formData={}] 额外的表单数据
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<UploadResult>} 返回上传结果,包含文件URL等信息
|
||||
* @example
|
||||
* // 上传文档文件
|
||||
* const result = await uploadFile({
|
||||
* filePath: 'path/to/document.pdf',
|
||||
* formData: { type: 'document' }
|
||||
* })
|
||||
* @param {Object} fileData 文件上传数据对象
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回上传结果
|
||||
*/
|
||||
export const uploadFile = (fileData, config = {}) => {
|
||||
return executeUploadRequest('/upload/file', fileData, COMMON_LOADING_TEXTS.UPLOAD_FILE, config)
|
||||
return BaseRequest.upload('/upload/file', fileData, LOADING_TEXTS.UPLOAD_FILE, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件到本地
|
||||
* @description 从服务器下载文件到本地存储
|
||||
* @param {string} url 文件下载URL
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @param {string} [config.savePath] 保存路径,不指定则使用默认路径
|
||||
* @returns {Promise<Object>} 返回下载结果,包含本地文件路径
|
||||
* @example
|
||||
* // 基本文件下载
|
||||
* const result = await downloadFile('https://example.com/file.pdf')
|
||||
*
|
||||
* // 指定保存路径
|
||||
* const result = await downloadFile('https://example.com/file.pdf', {
|
||||
* savePath: 'downloads/myfile.pdf'
|
||||
* })
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回下载结果
|
||||
*/
|
||||
export const downloadFile = (url, config = {}) => {
|
||||
const requestConfig = createCommonConfig('PUBLIC_DOWNLOAD', config, COMMON_LOADING_TEXTS.DOWNLOAD_FILE)
|
||||
|
||||
return uni.$u.http.download(url, {
|
||||
...(config.savePath && { savePath: config.savePath }),
|
||||
...requestConfig
|
||||
})
|
||||
return BaseRequest.download(url, config.savePath, LOADING_TEXTS.DOWNLOAD_FILE, config)
|
||||
}
|
||||
|
||||
// ==================== 云存储相关API ====================
|
||||
|
||||
/**
|
||||
* 获取七牛云上传凭证
|
||||
* @description 获取七牛云直传所需的上传token
|
||||
* @param {Object} [params={}] 请求参数
|
||||
* @param {string} [params.bucket] 存储桶名称
|
||||
* @param {string} [params.prefix] 文件前缀
|
||||
* @param {number} [params.expires] 过期时间(秒)
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回七牛云上传配置信息
|
||||
* @example
|
||||
* // 获取默认配置
|
||||
* const qiniuConfig = await getQiniuToken()
|
||||
*
|
||||
* // 获取指定桶的配置
|
||||
* const qiniuConfig = await getQiniuToken({
|
||||
* bucket: 'my-bucket',
|
||||
* prefix: 'images/',
|
||||
* expires: 3600
|
||||
* })
|
||||
* @param {Object} params 请求参数
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回七牛云上传配置信息
|
||||
*/
|
||||
export const getQiniuToken = (params = {}, config = {}) => {
|
||||
const requestConfig = createCommonConfig('SILENT_CONFIG', config)
|
||||
|
||||
return uni.$u.http.get('/upload/qiniu-token', {
|
||||
...(Object.keys(params).length > 0 && { params }),
|
||||
...requestConfig
|
||||
})
|
||||
return BaseRequest.get('/upload/qiniu-token', params, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取阿里云OSS上传签名
|
||||
* @description 获取阿里云OSS直传所需的签名信息
|
||||
* @param {Object} [params={}] 请求参数
|
||||
* @param {string} [params.bucket] 存储桶名称
|
||||
* @param {string} [params.prefix] 文件前缀
|
||||
* @param {number} [params.expires] 过期时间(秒)
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回OSS上传配置信息
|
||||
* @example
|
||||
* // 获取默认OSS配置
|
||||
* const ossConfig = await getOSSSignature()
|
||||
*
|
||||
* // 获取指定配置
|
||||
* const ossConfig = await getOSSSignature({
|
||||
* bucket: 'my-oss-bucket',
|
||||
* prefix: 'uploads/',
|
||||
* expires: 1800
|
||||
* })
|
||||
* @param {Object} params 请求参数
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回OSS上传配置信息
|
||||
*/
|
||||
export const getOSSSignature = (params = {}, config = {}) => {
|
||||
const requestConfig = createCommonConfig('SILENT_CONFIG', config)
|
||||
|
||||
return uni.$u.http.get('/upload/oss-signature', {
|
||||
...(Object.keys(params).length > 0 && { params }),
|
||||
...requestConfig
|
||||
})
|
||||
return BaseRequest.get('/upload/oss-signature', params, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
// ==================== 系统信息相关API ====================
|
||||
|
||||
/**
|
||||
* 获取系统配置信息
|
||||
* @description 获取应用的系统配置,包括功能开关、上传配置等
|
||||
* @param {Object} [params={}] 查询参数
|
||||
* @param {string[]} [params.keys] 指定获取的配置键名数组
|
||||
* @param {string} [params.category] 配置分类:'app' | 'upload' | 'features'
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<SystemConfig>} 返回系统配置对象
|
||||
* @example
|
||||
* // 获取所有配置
|
||||
* const systemConfig = await getSystemConfig()
|
||||
*
|
||||
* // 获取指定分类的配置
|
||||
* const uploadConfig = await getSystemConfig({
|
||||
* category: 'upload'
|
||||
* })
|
||||
*
|
||||
* // 获取指定键的配置
|
||||
* const specificConfig = await getSystemConfig({
|
||||
* keys: ['maxFileSize', 'allowedTypes']
|
||||
* })
|
||||
* @param {Object} params 查询参数
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回系统配置对象
|
||||
*/
|
||||
export const getSystemConfig = (params = {}, config = {}) => {
|
||||
const requestConfig = createCommonConfig('SILENT_CONFIG', config)
|
||||
|
||||
return uni.$u.http.get('/system/config', {
|
||||
...(Object.keys(params).length > 0 && { params }),
|
||||
...requestConfig
|
||||
})
|
||||
return BaseRequest.get('/system/config', params, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,9 +136,7 @@ export const getSystemConfig = (params = {}, config = {}) => {
|
||||
* // }
|
||||
*/
|
||||
export const getVersionInfo = (config = {}) => {
|
||||
const requestConfig = createCommonConfig('SILENT_CONFIG', config)
|
||||
|
||||
return uni.$u.http.get('/system/version', requestConfig)
|
||||
return BaseRequest.get('/system/version', {}, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -418,9 +163,7 @@ export const getVersionInfo = (config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const checkUpdate = (versionData, config = {}) => {
|
||||
const requestConfig = createCommonConfig('PUBLIC_DOWNLOAD', config, COMMON_LOADING_TEXTS.CHECK_UPDATE)
|
||||
|
||||
return uni.$u.http.post('/system/check-update', versionData, requestConfig)
|
||||
return BaseRequest.post('/system/check-update', versionData, 'PUBLIC_REQUEST', LOADING_TEXTS.CHECK_UPDATE, config)
|
||||
}
|
||||
|
||||
// 短信验证码相关API已移至 http/api/auth.js 文件中
|
||||
@@ -450,12 +193,7 @@ export const checkUpdate = (versionData, config = {}) => {
|
||||
* const allRegions = await getRegionData({ level: 'all' })
|
||||
*/
|
||||
export const getRegionData = (params = {}, config = {}) => {
|
||||
const requestConfig = createCommonConfig('SILENT_CONFIG', config)
|
||||
|
||||
return uni.$u.http.get('/common/regions', {
|
||||
...(Object.keys(params).length > 0 && { params }),
|
||||
...requestConfig
|
||||
})
|
||||
return BaseRequest.get('/common/regions', params, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -488,25 +226,7 @@ export const getRegionData = (params = {}, config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const submitFeedback = (feedbackData, config = {}) => {
|
||||
const requestConfig = createCommonConfig('AUTHENTICATED_SUBMIT', config, COMMON_LOADING_TEXTS.SUBMIT_FEEDBACK)
|
||||
|
||||
return uni.$u.http.post('/feedback', feedbackData, requestConfig)
|
||||
return BaseRequest.post('/feedback', feedbackData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.SUBMIT_FEEDBACK, config)
|
||||
}
|
||||
|
||||
// ==================== 导出配置常量(供外部使用) ====================
|
||||
|
||||
/**
|
||||
* 导出通用配置常量,供其他模块使用
|
||||
*/
|
||||
export const COMMON_CONFIG = {
|
||||
COMMON_CONFIG_TEMPLATES,
|
||||
COMMON_LOADING_TEXTS
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出通用工具函数,供其他模块使用
|
||||
*/
|
||||
export const COMMON_UTILS = {
|
||||
createCommonConfig,
|
||||
executeUploadRequest
|
||||
}
|
||||
|
||||
+22
-384
@@ -1,199 +1,9 @@
|
||||
/**
|
||||
* 宠物管理相关API接口模块
|
||||
*
|
||||
* @fileoverview 提供宠物信息管理、记录管理、健康档案等相关的API接口
|
||||
* @author 系统开发团队
|
||||
* @version 2.0.0
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @description
|
||||
* 本模块包含以下功能分组:
|
||||
* - 宠物基础信息管理:增删改查宠物信息
|
||||
* - 宠物记录管理:日常记录、健康记录、成长记录
|
||||
* - 宠物健康档案:疫苗记录、体检记录、用药记录
|
||||
* - 宠物统计分析:成长数据、健康趋势分析
|
||||
*
|
||||
* @example
|
||||
* // 基本用法示例
|
||||
* import { getPetsList, addPet, getPetRecords } from '@/http/api/pets.js'
|
||||
*
|
||||
* // 获取宠物列表
|
||||
* const pets = await getPetsList()
|
||||
*
|
||||
* // 添加新宠物
|
||||
* await addPet({ name: '小白', breed: '金毛', age: 2 })
|
||||
*
|
||||
* // 获取宠物记录
|
||||
* const records = await getPetRecords(petId)
|
||||
*/
|
||||
|
||||
// ==================== 类型定义 ====================
|
||||
|
||||
/**
|
||||
* @typedef {Object} PetInfo 宠物信息对象
|
||||
* @property {string} id 宠物ID
|
||||
* @property {string} name 宠物名称
|
||||
* @property {string} breed 品种
|
||||
* @property {string} type 类型:'dog' | 'cat' | 'bird' | 'rabbit' | 'other'
|
||||
* @property {string} gender 性别:'male' | 'female'
|
||||
* @property {number} age 年龄(月)
|
||||
* @property {number} weight 体重(kg)
|
||||
* @property {string} avatarUrl 头像URL
|
||||
* @property {string} description 描述
|
||||
* @property {string} createTime 创建时间
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PetRecord 宠物记录对象
|
||||
* @property {string} id 记录ID
|
||||
* @property {string} petId 宠物ID
|
||||
* @property {string} type 记录类型:'feeding' | 'health' | 'exercise' | 'grooming' | 'other'
|
||||
* @property {string} title 记录标题
|
||||
* @property {string} content 记录内容
|
||||
* @property {string[]} images 相关图片
|
||||
* @property {string} recordTime 记录时间
|
||||
*/
|
||||
|
||||
// ==================== 配置常量 ====================
|
||||
|
||||
/**
|
||||
* 宠物API的默认配置模板
|
||||
*/
|
||||
const PETS_CONFIG_TEMPLATES = {
|
||||
// 需要认证的查询请求(无loading)
|
||||
AUTHENTICATED_QUERY: {
|
||||
auth: true,
|
||||
loading: false,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的查询请求(有loading)
|
||||
AUTHENTICATED_QUERY_WITH_LOADING: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的更新请求
|
||||
AUTHENTICATED_UPDATE: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的删除请求
|
||||
AUTHENTICATED_DELETE: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 宠物相关的loading文本配置
|
||||
*/
|
||||
const PETS_LOADING_TEXTS = {
|
||||
ADD_PET: '正在添加宠物...',
|
||||
UPDATE_PET: '正在更新宠物信息...',
|
||||
DELETE_PET: '正在删除宠物...',
|
||||
ADD_RECORD: '正在添加记录...',
|
||||
UPDATE_RECORD: '正在更新记录...',
|
||||
DELETE_RECORD: '正在删除记录...',
|
||||
LOADING_DATA: '正在加载...'
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
/**
|
||||
* 创建宠物请求的标准化配置
|
||||
* @param {string} template 配置模板名称
|
||||
* @param {Object} customConfig 自定义配置
|
||||
* @param {string} loadingText 自定义loading文本
|
||||
* @returns {Object} 标准化的请求配置
|
||||
*/
|
||||
const createPetsConfig = (template, customConfig = {}, loadingText = null) => {
|
||||
const baseConfig = PETS_CONFIG_TEMPLATES[template] || {}
|
||||
|
||||
const config = {
|
||||
custom: {
|
||||
...baseConfig,
|
||||
...(loadingText && { loadingText }),
|
||||
...customConfig.custom
|
||||
},
|
||||
...customConfig
|
||||
}
|
||||
|
||||
// 移除custom属性中的undefined值
|
||||
Object.keys(config.custom).forEach(key => {
|
||||
if (config.custom[key] === undefined) {
|
||||
delete config.custom[key]
|
||||
}
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行宠物相关的GET请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} params 查询参数
|
||||
* @param {string} template 配置模板
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executePetsGetRequest = (url, params = {}, template = 'AUTHENTICATED_QUERY', config = {}) => {
|
||||
const requestConfig = createPetsConfig(template, config)
|
||||
|
||||
return uni.$u.http.get(url, {
|
||||
...(Object.keys(params).length > 0 && { params }),
|
||||
...requestConfig
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行宠物相关的POST请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executePetsPostRequest = (url, data = {}, template = 'AUTHENTICATED_UPDATE', loadingText = null, config = {}) => {
|
||||
const requestConfig = createPetsConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.post(url, data, requestConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行宠物相关的PUT请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executePetsPutRequest = (url, data = {}, template = 'AUTHENTICATED_UPDATE', loadingText = null, config = {}) => {
|
||||
const requestConfig = createPetsConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.put(url, data, requestConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行宠物相关的DELETE请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executePetsDeleteRequest = (url, data = {}, template = 'AUTHENTICATED_DELETE', loadingText = null, config = {}) => {
|
||||
const requestConfig = createPetsConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.delete(url, data, requestConfig)
|
||||
}
|
||||
import BaseRequest from '../utils/request-helper.js'
|
||||
import { LOADING_TEXTS } from '../config/constants.js'
|
||||
|
||||
// ==================== API方法 ====================
|
||||
|
||||
@@ -201,199 +11,71 @@ const executePetsDeleteRequest = (url, data = {}, template = 'AUTHENTICATED_DELE
|
||||
|
||||
/**
|
||||
* 获取用户宠物列表
|
||||
* @description 获取当前用户的所有宠物信息列表,支持分页和筛选
|
||||
* @param {Object} [params={}] 查询参数
|
||||
* @param {number} [params.page=1] 页码
|
||||
* @param {number} [params.pageSize=20] 每页数量
|
||||
* @param {string} [params.type] 宠物类型筛选:'dog' | 'cat' | 'bird' | 'rabbit' | 'other'
|
||||
* @param {string} [params.breed] 品种筛选
|
||||
* @param {string} [params.keyword] 关键词搜索(名称、品种)
|
||||
* @param {string} [params.sortBy] 排序字段:'createTime' | 'name' | 'age'
|
||||
* @param {string} [params.sortOrder] 排序方向:'asc' | 'desc'
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回宠物列表和分页信息
|
||||
* @example
|
||||
* // 获取所有宠物
|
||||
* const pets = await getPetsList()
|
||||
*
|
||||
* // 分页获取狗狗列表
|
||||
* const dogs = await getPetsList({
|
||||
* type: 'dog',
|
||||
* page: 1,
|
||||
* pageSize: 10
|
||||
* })
|
||||
*
|
||||
* // 搜索宠物
|
||||
* const searchResults = await getPetsList({
|
||||
* keyword: '小白',
|
||||
* sortBy: 'createTime',
|
||||
* sortOrder: 'desc'
|
||||
* })
|
||||
*/
|
||||
export const getPetsList = (params = {}, config = {}) => {
|
||||
return executePetsGetRequest('/pets', params, 'AUTHENTICATED_QUERY', config)
|
||||
return BaseRequest.get('/pets', params, 'AUTHENTICATED_QUERY', config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宠物详细信息
|
||||
* @description 根据宠物ID获取详细的宠物信息
|
||||
* @param {string|number} petId 宠物ID
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @param {boolean} [config.includeRecords=false] 是否包含最近记录
|
||||
* @param {boolean} [config.includeHealth=false] 是否包含健康档案
|
||||
* @returns {Promise<PetInfo>} 返回宠物详细信息
|
||||
* @example
|
||||
* // 获取基本信息
|
||||
* const pet = await getPetDetail(123)
|
||||
*
|
||||
* // 获取包含记录的详细信息
|
||||
* const petWithRecords = await getPetDetail(123, {
|
||||
* includeRecords: true,
|
||||
* includeHealth: true
|
||||
* })
|
||||
* @returns {Promise} 返回宠物详细信息
|
||||
*/
|
||||
export const getPetDetail = (petId, config = {}) => {
|
||||
const params = {}
|
||||
if (config.includeRecords) params.includeRecords = true
|
||||
if (config.includeHealth) params.includeHealth = true
|
||||
|
||||
return executePetsGetRequest(`/pets/${petId}`, params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
return BaseRequest.get(`/pets/${petId}`, params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加新宠物
|
||||
* @description 为当前用户添加一只新宠物
|
||||
* @param {Object} petData 宠物信息数据
|
||||
* @param {string} petData.name 宠物名称(必填)
|
||||
* @param {string} petData.breed 品种(必填)
|
||||
* @param {string} petData.type 类型:'dog' | 'cat' | 'bird' | 'rabbit' | 'other'
|
||||
* @param {string} petData.gender 性别:'male' | 'female'
|
||||
* @param {number} [petData.age] 年龄(月)
|
||||
* @param {number} [petData.weight] 体重(kg)
|
||||
* @param {string} [petData.avatarUrl] 头像URL
|
||||
* @param {string} [petData.description] 描述
|
||||
* @param {string} [petData.birthDate] 出生日期
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<PetInfo>} 返回新添加的宠物信息
|
||||
* @example
|
||||
* // 添加基本宠物信息
|
||||
* const newPet = await addPet({
|
||||
* name: '小白',
|
||||
* breed: '金毛',
|
||||
* type: 'dog',
|
||||
* gender: 'male',
|
||||
* age: 24,
|
||||
* weight: 25.5
|
||||
* })
|
||||
*
|
||||
* // 添加完整宠物信息
|
||||
* const newPet = await addPet({
|
||||
* name: '小花',
|
||||
* breed: '英短',
|
||||
* type: 'cat',
|
||||
* gender: 'female',
|
||||
* age: 12,
|
||||
* weight: 4.2,
|
||||
* avatarUrl: 'https://example.com/cat.jpg',
|
||||
* description: '很可爱的小猫咪',
|
||||
* birthDate: '2023-01-15'
|
||||
* })
|
||||
* @returns {Promise} 返回新添加的宠物信息
|
||||
*/
|
||||
export const addPet = (petData, config = {}) => {
|
||||
return executePetsPostRequest('/pets', petData, 'AUTHENTICATED_UPDATE', PETS_LOADING_TEXTS.ADD_PET, config)
|
||||
return BaseRequest.post('/pets', petData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.ADD_PET, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新宠物信息
|
||||
* @description 更新指定宠物的信息,支持部分字段更新
|
||||
* @param {string|number} petId 宠物ID
|
||||
* @param {Object} petData 要更新的宠物数据
|
||||
* @param {string} [petData.name] 宠物名称
|
||||
* @param {string} [petData.breed] 品种
|
||||
* @param {string} [petData.type] 类型
|
||||
* @param {string} [petData.gender] 性别
|
||||
* @param {number} [petData.age] 年龄(月)
|
||||
* @param {number} [petData.weight] 体重(kg)
|
||||
* @param {string} [petData.avatarUrl] 头像URL
|
||||
* @param {string} [petData.description] 描述
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<PetInfo>} 返回更新后的宠物信息
|
||||
* @example
|
||||
* // 更新宠物体重
|
||||
* const updatedPet = await updatePet(123, {
|
||||
* weight: 26.0
|
||||
* })
|
||||
*
|
||||
* // 更新多个字段
|
||||
* const updatedPet = await updatePet(123, {
|
||||
* name: '小白白',
|
||||
* age: 25,
|
||||
* description: '更新后的描述'
|
||||
* })
|
||||
* @returns {Promise} 返回更新后的宠物信息
|
||||
*/
|
||||
export const updatePet = (petId, petData, config = {}) => {
|
||||
return executePetsPutRequest(`/pets/${petId}`, petData, 'AUTHENTICATED_UPDATE', PETS_LOADING_TEXTS.UPDATE_PET, config)
|
||||
return BaseRequest.put(`/pets/${petId}`, petData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.UPDATE_PET, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除宠物
|
||||
* @description 永久删除指定的宠物及其所有相关记录,此操作不可逆
|
||||
* @param {string|number} petId 宠物ID
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @param {boolean} [config.force=false] 是否强制删除(忽略关联数据检查)
|
||||
* @returns {Promise<Object>} 返回删除结果
|
||||
* @example
|
||||
* // 普通删除
|
||||
* await deletePet(123)
|
||||
*
|
||||
* // 强制删除(忽略关联数据)
|
||||
* await deletePet(123, { force: true })
|
||||
*
|
||||
* @warning 此操作将永久删除宠物及其所有记录,请谨慎使用
|
||||
*/
|
||||
export const deletePet = (petId, config = {}) => {
|
||||
const data = config.force ? { force: true } : {}
|
||||
return executePetsDeleteRequest(`/pets/${petId}`, data, 'AUTHENTICATED_DELETE', PETS_LOADING_TEXTS.DELETE_PET, config)
|
||||
return BaseRequest.delete(`/pets/${petId}`, data, 'AUTHENTICATED_DELETE', LOADING_TEXTS.DELETE_PET, config)
|
||||
}
|
||||
|
||||
// ==================== 宠物记录管理API ====================
|
||||
|
||||
/**
|
||||
* 获取宠物记录列表
|
||||
* @description 获取指定宠物的所有记录,支持分页和筛选
|
||||
* @param {string|number} petId 宠物ID
|
||||
* @param {Object} [params={}] 查询参数
|
||||
* @param {number} [params.page=1] 页码
|
||||
* @param {number} [params.pageSize=20] 每页数量
|
||||
* @param {string} [params.type] 记录类型筛选:'feeding' | 'health' | 'exercise' | 'grooming' | 'other'
|
||||
* @param {string} [params.startDate] 开始日期
|
||||
* @param {string} [params.endDate] 结束日期
|
||||
* @param {string} [params.keyword] 关键词搜索
|
||||
* @param {string} [params.sortBy] 排序字段:'recordTime' | 'createTime'
|
||||
* @param {string} [params.sortOrder] 排序方向:'asc' | 'desc'
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回记录列表和分页信息
|
||||
* @example
|
||||
* // 获取所有记录
|
||||
* const records = await getPetRecords(123)
|
||||
*
|
||||
* // 获取指定类型的记录
|
||||
* const healthRecords = await getPetRecords(123, {
|
||||
* type: 'health',
|
||||
* page: 1,
|
||||
* pageSize: 10
|
||||
* })
|
||||
*
|
||||
* // 按日期范围查询
|
||||
* const recentRecords = await getPetRecords(123, {
|
||||
* startDate: '2024-01-01',
|
||||
* endDate: '2024-01-31',
|
||||
* sortBy: 'recordTime',
|
||||
* sortOrder: 'desc'
|
||||
* })
|
||||
*/
|
||||
export const getPetRecords = (petId, params = {}, config = {}) => {
|
||||
return executePetsGetRequest(`/pets/${petId}/records`, params, 'AUTHENTICATED_QUERY', config)
|
||||
return BaseRequest.get(`/pets/${petId}/records`, params, 'AUTHENTICATED_QUERY', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,7 +113,7 @@ export const getPetRecords = (petId, params = {}, config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const addPetRecord = (petId, recordData, config = {}) => {
|
||||
return executePetsPostRequest(`/pets/${petId}/records`, recordData, 'AUTHENTICATED_UPDATE', PETS_LOADING_TEXTS.ADD_RECORD, config)
|
||||
return BaseRequest.post(`/pets/${petId}/records`, recordData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.ADD_RECORD, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,7 +137,7 @@ export const addPetRecord = (petId, recordData, config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const updatePetRecord = (petId, recordId, recordData, config = {}) => {
|
||||
return executePetsPutRequest(`/pets/${petId}/records/${recordId}`, recordData, 'AUTHENTICATED_UPDATE', PETS_LOADING_TEXTS.UPDATE_RECORD, config)
|
||||
return BaseRequest.put(`/pets/${petId}/records/${recordId}`, recordData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.UPDATE_RECORD, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -470,73 +152,29 @@ export const updatePetRecord = (petId, recordId, recordData, config = {}) => {
|
||||
* await deletePetRecord(123, 456)
|
||||
*/
|
||||
export const deletePetRecord = (petId, recordId, config = {}) => {
|
||||
return executePetsDeleteRequest(`/pets/${petId}/records/${recordId}`, {}, 'AUTHENTICATED_DELETE', PETS_LOADING_TEXTS.DELETE_RECORD, config)
|
||||
return BaseRequest.delete(`/pets/${petId}/records/${recordId}`, {}, 'AUTHENTICATED_DELETE', LOADING_TEXTS.DELETE_RECORD, config)
|
||||
}
|
||||
|
||||
// ==================== 宠物健康档案API ====================
|
||||
|
||||
/**
|
||||
* 获取宠物健康数据
|
||||
* @description 获取宠物的健康档案数据,包括疫苗记录、体检记录等
|
||||
* @param {string|number} petId 宠物ID
|
||||
* @param {Object} [params={}] 查询参数
|
||||
* @param {string} [params.type] 健康数据类型:'vaccine' | 'checkup' | 'medication' | 'all'
|
||||
* @param {string} [params.startDate] 开始日期
|
||||
* @param {string} [params.endDate] 结束日期
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object>} 返回健康数据
|
||||
* @example
|
||||
* // 获取所有健康数据
|
||||
* const healthData = await getPetHealthData(123)
|
||||
*
|
||||
* // 获取疫苗记录
|
||||
* const vaccineData = await getPetHealthData(123, {
|
||||
* type: 'vaccine'
|
||||
* })
|
||||
* @param {Object} params 查询参数
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回健康数据
|
||||
*/
|
||||
export const getPetHealthData = (petId, params = {}, config = {}) => {
|
||||
return executePetsGetRequest(`/pets/${petId}/health`, params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
return BaseRequest.get(`/pets/${petId}/health`, params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宠物成长时间线
|
||||
* @description 获取宠物的成长时间线,包括重要事件和里程碑
|
||||
* @param {string|number} petId 宠物ID
|
||||
* @param {Object} [params={}] 查询参数
|
||||
* @param {number} [params.limit] 限制返回数量
|
||||
* @param {string} [params.type] 事件类型筛选
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<Object[]>} 返回时间线事件数组
|
||||
* @example
|
||||
* // 获取完整时间线
|
||||
* const timeline = await getPetTimeline(123)
|
||||
*
|
||||
* // 获取最近10个事件
|
||||
* const recentEvents = await getPetTimeline(123, {
|
||||
* limit: 10
|
||||
* })
|
||||
* @param {Object} params 查询参数
|
||||
* @param {Object} config 自定义请求配置
|
||||
* @returns {Promise} 返回时间线事件数组
|
||||
*/
|
||||
export const getPetTimeline = (petId, params = {}, config = {}) => {
|
||||
return executePetsGetRequest(`/pets/${petId}/timeline`, params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
|
||||
// ==================== 导出配置常量(供外部使用) ====================
|
||||
|
||||
/**
|
||||
* 导出宠物配置常量,供其他模块使用
|
||||
*/
|
||||
export const PETS_CONFIG = {
|
||||
PETS_CONFIG_TEMPLATES,
|
||||
PETS_LOADING_TEXTS
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出宠物工具函数,供其他模块使用
|
||||
*/
|
||||
export const PETS_UTILS = {
|
||||
createPetsConfig,
|
||||
executePetsGetRequest,
|
||||
executePetsPostRequest,
|
||||
executePetsPutRequest,
|
||||
executePetsDeleteRequest
|
||||
return BaseRequest.get(`/pets/${petId}/timeline`, params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
+14
-232
@@ -1,209 +1,10 @@
|
||||
/**
|
||||
* 个人中心相关API接口模块
|
||||
*
|
||||
* @fileoverview 提供用户信息管理、资料完善、偏好设置等相关的API接口
|
||||
* @author 系统开发团队
|
||||
* @version 2.0.0
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @description
|
||||
* 本模块包含以下功能分组:
|
||||
* - 用户信息相关API:获取、更新用户基本信息
|
||||
* - 用户统计相关API:获取各项统计数据
|
||||
* - 账户管理相关API:账户注销等敏感操作
|
||||
* - 用户资料完善相关API:新用户资料完善
|
||||
* - 头像上传相关API:头像图片上传和更新
|
||||
* - 用户偏好设置相关API:个性化设置管理
|
||||
* - 用户活动记录相关API:操作记录查询
|
||||
*
|
||||
* @example
|
||||
* // 基本用法示例
|
||||
* import { getUserInfo, updateUserInfo } from '@/http/api/profile.js'
|
||||
*
|
||||
* // 获取用户信息
|
||||
* const userInfo = await getUserInfo()
|
||||
*
|
||||
* // 更新用户信息
|
||||
* await updateUserInfo({ nickName: '新昵称' })
|
||||
*
|
||||
* @example
|
||||
* // 使用配置常量
|
||||
* import { PROFILE_CONFIG, PROFILE_UTILS } from '@/http/api/profile.js'
|
||||
*
|
||||
* // 使用工具函数创建自定义请求
|
||||
* const customRequest = PROFILE_UTILS.executeGetRequest('/custom/endpoint')
|
||||
* 提供用户信息管理、资料完善、偏好设置等相关的API接口
|
||||
*/
|
||||
|
||||
// ==================== 类型定义 ====================
|
||||
|
||||
/**
|
||||
* @typedef {Object} UserInfo 用户信息对象
|
||||
* @property {string} id 用户ID
|
||||
* @property {string} nickName 用户昵称
|
||||
* @property {string} avatarUrl 头像URL
|
||||
* @property {string} gender 性别:'男' | '女' | '保密'
|
||||
* @property {string} birthday 生日,格式:YYYY-MM-DD
|
||||
* @property {string} region 所在地区
|
||||
* @property {string} bio 个人简介
|
||||
* @property {string} createTime 创建时间
|
||||
* @property {string} updateTime 更新时间
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} UserStats 用户统计数据对象
|
||||
* @property {number} petCount 宠物数量
|
||||
* @property {number} recordCount 记录数量
|
||||
* @property {number} reminderCount 提醒数量
|
||||
* @property {number} familyMemberCount 家庭成员数量
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} RequestConfig 请求配置对象
|
||||
* @property {Object} custom 自定义配置
|
||||
* @property {boolean} custom.auth 是否需要认证
|
||||
* @property {boolean} custom.loading 是否显示loading
|
||||
* @property {string} custom.loadingText loading文本
|
||||
* @property {boolean} custom.toast 是否显示错误提示
|
||||
*/
|
||||
|
||||
// ==================== 配置常量 ====================
|
||||
|
||||
/**
|
||||
* API请求的默认配置模板
|
||||
*/
|
||||
const DEFAULT_CONFIG_TEMPLATES = {
|
||||
// 需要认证的查询请求(无loading)
|
||||
AUTHENTICATED_QUERY: {
|
||||
auth: true,
|
||||
loading: false,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的查询请求(有loading)
|
||||
AUTHENTICATED_QUERY_WITH_LOADING: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的更新请求
|
||||
AUTHENTICATED_UPDATE: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的删除请求
|
||||
AUTHENTICATED_DELETE: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 常用的loading文本配置
|
||||
*/
|
||||
const LOADING_TEXTS = {
|
||||
UPDATING_USER_INFO: '正在更新用户信息...',
|
||||
SAVING_PROFILE: '正在保存...',
|
||||
DELETING_ACCOUNT: '正在注销账户...',
|
||||
UPLOADING_AVATAR: '正在上传头像...',
|
||||
LOADING_DATA: '正在加载...'
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
/**
|
||||
* 创建标准化的API请求配置
|
||||
* @param {string} template 配置模板名称
|
||||
* @param {Object} customConfig 自定义配置
|
||||
* @param {string} loadingText 自定义loading文本
|
||||
* @returns {Object} 标准化的请求配置
|
||||
*/
|
||||
const createRequestConfig = (template, customConfig = {}, loadingText = null) => {
|
||||
const baseConfig = DEFAULT_CONFIG_TEMPLATES[template] || {}
|
||||
|
||||
const config = {
|
||||
custom: {
|
||||
...baseConfig,
|
||||
...(loadingText && { loadingText }),
|
||||
...customConfig.custom
|
||||
},
|
||||
...customConfig
|
||||
}
|
||||
|
||||
// 移除custom属性中的undefined值
|
||||
Object.keys(config.custom).forEach(key => {
|
||||
if (config.custom[key] === undefined) {
|
||||
delete config.custom[key]
|
||||
}
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行GET请求的通用方法
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} params 查询参数
|
||||
* @param {string} template 配置模板
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executeGetRequest = (url, params = {}, template = 'AUTHENTICATED_QUERY', config = {}) => {
|
||||
const requestConfig = createRequestConfig(template, config)
|
||||
|
||||
return uni.$u.http.get(url, {
|
||||
...(Object.keys(params).length > 0 && { params }),
|
||||
...requestConfig
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行POST请求的通用方法
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executePostRequest = (url, data = {}, template = 'AUTHENTICATED_UPDATE', loadingText = null, config = {}) => {
|
||||
const requestConfig = createRequestConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.post(url, data, requestConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行PUT请求的通用方法
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executePutRequest = (url, data = {}, template = 'AUTHENTICATED_UPDATE', loadingText = null, config = {}) => {
|
||||
const requestConfig = createRequestConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.put(url, data, requestConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行DELETE请求的通用方法
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
const executeDeleteRequest = (url, data = {}, template = 'AUTHENTICATED_DELETE', loadingText = null, config = {}) => {
|
||||
const requestConfig = createRequestConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.delete(url, data, requestConfig)
|
||||
}
|
||||
import BaseRequest from '../utils/request-helper.js'
|
||||
import { LOADING_TEXTS } from '../config/constants.js'
|
||||
|
||||
// ==================== API方法 ====================
|
||||
|
||||
@@ -227,7 +28,7 @@ const executeDeleteRequest = (url, data = {}, template = 'AUTHENTICATED_DELETE',
|
||||
* })
|
||||
*/
|
||||
export const getUserInfo = (config = {}) => {
|
||||
return executeGetRequest('/user/info', {}, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
return BaseRequest.get('/user/info', {}, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,7 +49,7 @@ export const getUserInfo = (config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const getWxUserInfo = (config = {}) => {
|
||||
return executeGetRequest('/user/wechat/mini/userinfo', {}, 'AUTHENTICATED_QUERY', config)
|
||||
return BaseRequest.get('/user/wechat/mini/userinfo', {}, 'AUTHENTICATED_QUERY', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,7 +71,7 @@ export const getWxUserInfo = (config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const updateUserInfo = (userInfo, config = {}) => {
|
||||
return executePutRequest('/user/info', userInfo, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.UPDATING_USER_INFO, config)
|
||||
return BaseRequest.put('/user/info', userInfo, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.UPDATING_USER_INFO, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,7 +92,7 @@ export const updateUserInfo = (userInfo, config = {}) => {
|
||||
* const pets = await getUserPets({ page: 1, pageSize: 10 })
|
||||
*/
|
||||
export const getUserPets = (params = {}, config = {}) => {
|
||||
return executeGetRequest('/user/pets', params, 'AUTHENTICATED_QUERY', config)
|
||||
return BaseRequest.get('/user/pets', params, 'AUTHENTICATED_QUERY', config)
|
||||
}
|
||||
|
||||
// ==================== 用户统计相关API ====================
|
||||
@@ -314,7 +115,7 @@ export const getUserPets = (params = {}, config = {}) => {
|
||||
* // }
|
||||
*/
|
||||
export const getUserStats = (config = {}) => {
|
||||
return executeGetRequest('/user/stats', {}, 'AUTHENTICATED_QUERY', config)
|
||||
return BaseRequest.get('/user/stats', {}, 'AUTHENTICATED_QUERY', config)
|
||||
}
|
||||
|
||||
// ==================== 账户管理相关API ====================
|
||||
@@ -333,7 +134,7 @@ export const getUserStats = (config = {}) => {
|
||||
* @warning 此操作将永久删除所有用户数据,请谨慎使用
|
||||
*/
|
||||
export const deleteAccount = (config = {}) => {
|
||||
return executeDeleteRequest('/user/account', {}, 'AUTHENTICATED_DELETE', LOADING_TEXTS.DELETING_ACCOUNT, config)
|
||||
return BaseRequest.delete('/user/account', {}, 'AUTHENTICATED_DELETE', LOADING_TEXTS.DELETING_ACCOUNT, config)
|
||||
}
|
||||
|
||||
// ==================== 用户资料完善相关API ====================
|
||||
@@ -369,7 +170,7 @@ export const deleteAccount = (config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const completeUserProfile = (profileData, config = {}) => {
|
||||
return executePostRequest('/user/profile/complete', profileData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.SAVING_PROFILE, config)
|
||||
return BaseRequest.post('/user/profile/complete', profileData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.SAVING_PROFILE, config)
|
||||
}
|
||||
|
||||
// ==================== 头像上传相关API ====================
|
||||
@@ -387,7 +188,7 @@ export const completeUserProfile = (profileData, config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const uploadAvatar = (avatarData, config = {}) => {
|
||||
return executePostRequest('/user/avatar', avatarData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.UPLOADING_AVATAR, config)
|
||||
return BaseRequest.post('/user/avatar', avatarData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.UPLOADING_AVATAR, config)
|
||||
}
|
||||
|
||||
// ==================== 用户偏好设置相关API ====================
|
||||
@@ -401,7 +202,7 @@ export const uploadAvatar = (avatarData, config = {}) => {
|
||||
* const preferences = await getUserPreferences()
|
||||
*/
|
||||
export const getUserPreferences = (config = {}) => {
|
||||
return executeGetRequest('/user/preferences', {}, 'AUTHENTICATED_QUERY', config)
|
||||
return BaseRequest.get('/user/preferences', {}, 'AUTHENTICATED_QUERY', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -420,7 +221,7 @@ export const getUserPreferences = (config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const updateUserPreferences = (preferences, config = {}) => {
|
||||
return executePutRequest('/user/preferences', preferences, 'AUTHENTICATED_UPDATE', '正在保存设置...', config)
|
||||
return BaseRequest.put('/user/preferences', preferences, 'AUTHENTICATED_UPDATE', '正在保存设置...', config)
|
||||
}
|
||||
|
||||
// ==================== 用户活动记录相关API ====================
|
||||
@@ -444,26 +245,7 @@ export const updateUserPreferences = (preferences, config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const getUserActivities = (params = {}, config = {}) => {
|
||||
return executeGetRequest('/user/activities', params, 'AUTHENTICATED_QUERY', config)
|
||||
return BaseRequest.get('/user/activities', params, 'AUTHENTICATED_QUERY', config)
|
||||
}
|
||||
|
||||
// ==================== 导出配置常量(供外部使用) ====================
|
||||
|
||||
/**
|
||||
* 导出配置常量,供其他模块使用
|
||||
*/
|
||||
export const PROFILE_CONFIG = {
|
||||
DEFAULT_CONFIG_TEMPLATES,
|
||||
LOADING_TEXTS
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出工具函数,供其他模块使用
|
||||
*/
|
||||
export const PROFILE_UTILS = {
|
||||
createRequestConfig,
|
||||
executeGetRequest,
|
||||
executePostRequest,
|
||||
executePutRequest,
|
||||
executeDeleteRequest
|
||||
}
|
||||
|
||||
+17
-97
@@ -1,4 +1,9 @@
|
||||
// 评价相关API接口
|
||||
/**
|
||||
* 评价相关API接口模块
|
||||
*/
|
||||
|
||||
import BaseRequest from '../utils/request-helper.js'
|
||||
import { LOADING_TEXTS } from '../config/constants.js'
|
||||
|
||||
/**
|
||||
* 获取评价列表
|
||||
@@ -7,15 +12,7 @@
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getReviews = (params = {}, config = {}) => {
|
||||
return uni.$u.http.get('/reviews', {
|
||||
params,
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get('/reviews', params, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,15 +24,7 @@ export const getReviews = (params = {}, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getTargetReviews = (targetType, targetId, params = {}, config = {}) => {
|
||||
return uni.$u.http.get(`/reviews/${targetType}/${targetId}`, {
|
||||
params,
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get(`/reviews/${targetType}/${targetId}`, params, 'SILENT_REQUEST', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,15 +34,7 @@ export const getTargetReviews = (targetType, targetId, params = {}, config = {})
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const addReview = (reviewData, config = {}) => {
|
||||
return uni.$u.http.post('/reviews', reviewData, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在提交评价...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.post('/reviews', reviewData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.SUBMIT_REVIEW, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,15 +45,7 @@ export const addReview = (reviewData, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const updateReview = (reviewId, reviewData, config = {}) => {
|
||||
return uni.$u.http.put(`/reviews/${reviewId}`, reviewData, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在更新评价...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.put(`/reviews/${reviewId}`, reviewData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.UPDATE_REVIEW, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,15 +55,7 @@ export const updateReview = (reviewId, reviewData, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const deleteReview = (reviewId, config = {}) => {
|
||||
return uni.$u.http.delete(`/reviews/${reviewId}`, {}, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在删除评价...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.delete(`/reviews/${reviewId}`, {}, 'AUTHENTICATED_DELETE', LOADING_TEXTS.DELETE_REVIEW, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,15 +65,7 @@ export const deleteReview = (reviewId, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getMyReviews = (params = {}, config = {}) => {
|
||||
return uni.$u.http.get('/reviews/my', {
|
||||
params,
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get('/reviews/my', params, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,14 +75,7 @@ export const getMyReviews = (params = {}, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const likeReview = (reviewId, config = {}) => {
|
||||
return uni.$u.http.post(`/reviews/${reviewId}/like`, {}, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.post(`/reviews/${reviewId}/like`, {}, 'AUTHENTICATED_QUERY', null, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,14 +85,7 @@ export const likeReview = (reviewId, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const unlikeReview = (reviewId, config = {}) => {
|
||||
return uni.$u.http.delete(`/reviews/${reviewId}/like`, {}, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: false,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.delete(`/reviews/${reviewId}/like`, {}, 'AUTHENTICATED_QUERY', null, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,15 +96,7 @@ export const unlikeReview = (reviewId, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const reportReview = (reviewId, reportData, config = {}) => {
|
||||
return uni.$u.http.post(`/reviews/${reviewId}/report`, reportData, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在提交举报...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.post(`/reviews/${reviewId}/report`, reportData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.SUBMIT_REPORT, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,15 +107,7 @@ export const reportReview = (reviewId, reportData, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const replyReview = (reviewId, replyData, config = {}) => {
|
||||
return uni.$u.http.post(`/reviews/${reviewId}/reply`, replyData, {
|
||||
custom: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
loadingText: '正在回复评价...',
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.post(`/reviews/${reviewId}/reply`, replyData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.REPLY_REVIEW, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,12 +118,5 @@ export const replyReview = (reviewId, replyData, config = {}) => {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const getReviewStats = (targetType, targetId, config = {}) => {
|
||||
return uni.$u.http.get(`/reviews/${targetType}/${targetId}/stats`, {
|
||||
custom: {
|
||||
auth: false,
|
||||
loading: true,
|
||||
...config.custom
|
||||
},
|
||||
...config
|
||||
})
|
||||
return BaseRequest.get(`/reviews/${targetType}/${targetId}/stats`, {}, 'PUBLIC_REQUEST', config)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* HTTP模块统一配置常量文件
|
||||
* 统一管理所有配置模板、Loading文本常量和其他共享常量
|
||||
*/
|
||||
|
||||
// ==================== 配置模板 ====================
|
||||
|
||||
/**
|
||||
* 统一的请求配置模板
|
||||
* 合并了REQUEST_CONFIG_TEMPLATES、COMMON_CONFIG_TEMPLATES、DEFAULT_CONFIG_TEMPLATES
|
||||
*/
|
||||
export const CONFIG_TEMPLATES = {
|
||||
// 需要认证的查询请求(无loading)
|
||||
AUTHENTICATED_QUERY: {
|
||||
auth: true,
|
||||
loading: false,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的查询请求(有loading)
|
||||
AUTHENTICATED_QUERY_WITH_LOADING: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的更新请求
|
||||
AUTHENTICATED_UPDATE: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的删除请求
|
||||
AUTHENTICATED_DELETE: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 无需认证的公开请求
|
||||
PUBLIC_REQUEST: {
|
||||
auth: false,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 静默请求(无loading和toast)
|
||||
SILENT_REQUEST: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
toast: false
|
||||
},
|
||||
|
||||
// 需要认证的上传请求
|
||||
AUTHENTICATED_UPLOAD: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 需要认证的提交请求
|
||||
AUTHENTICATED_SUBMIT: {
|
||||
auth: true,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 公开的下载请求
|
||||
PUBLIC_DOWNLOAD: {
|
||||
auth: false,
|
||||
loading: true,
|
||||
toast: true
|
||||
},
|
||||
|
||||
// 静默的配置获取请求
|
||||
SILENT_CONFIG: {
|
||||
auth: false,
|
||||
loading: false,
|
||||
toast: false
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Loading文本常量 ====================
|
||||
|
||||
/**
|
||||
* 统一的Loading文本配置
|
||||
* 合并了所有模块中的LOADING_TEXTS常量
|
||||
*/
|
||||
export const LOADING_TEXTS = {
|
||||
// 通用操作
|
||||
LOADING: '正在加载...',
|
||||
SAVING: '正在保存...',
|
||||
DELETING: '正在删除...',
|
||||
UPDATING: '正在更新...',
|
||||
SUBMITTING: '正在提交...',
|
||||
UPLOADING: '正在上传...',
|
||||
|
||||
// 认证相关
|
||||
LOGIN: '正在登录...',
|
||||
LOGOUT: '正在退出...',
|
||||
REGISTER: '正在注册...',
|
||||
PHONE_VERIFY: '正在验证手机号...',
|
||||
SEND_SMS: '正在发送验证码...',
|
||||
VERIFY_SMS: '正在验证...',
|
||||
RESET_PASSWORD: '正在重置密码...',
|
||||
|
||||
// 用户相关
|
||||
UPDATING_USER_INFO: '正在更新用户信息...',
|
||||
UPLOADING_AVATAR: '正在上传头像...',
|
||||
SAVING_PROFILE: '正在保存...',
|
||||
DELETING_ACCOUNT: '正在注销账户...',
|
||||
LOADING_DATA: '正在加载...',
|
||||
|
||||
// 宠物相关
|
||||
ADD_PET: '正在添加宠物...',
|
||||
UPDATE_PET: '正在更新宠物信息...',
|
||||
DELETE_PET: '正在删除宠物...',
|
||||
ADD_RECORD: '正在添加记录...',
|
||||
UPDATE_RECORD: '正在更新记录...',
|
||||
DELETE_RECORD: '正在删除记录...',
|
||||
|
||||
// 文件相关
|
||||
UPLOAD_IMAGE: '正在上传图片...',
|
||||
UPLOAD_FILE: '正在上传文件...',
|
||||
UPLOAD_IMAGES: '正在批量上传...',
|
||||
DOWNLOAD_FILE: '正在下载文件...',
|
||||
|
||||
// AI助手相关
|
||||
AI_THINKING: 'AI正在思考中...',
|
||||
SPEECH_RECOGNITION: '正在识别语音...',
|
||||
|
||||
// 领养相关
|
||||
SUBMIT_APPLICATION: '正在提交申请...',
|
||||
CANCEL_APPLICATION: '正在取消申请...',
|
||||
|
||||
// 评价相关
|
||||
SUBMIT_REVIEW: '正在提交评价...',
|
||||
UPDATE_REVIEW: '正在更新评价...',
|
||||
DELETE_REVIEW: '正在删除评价...',
|
||||
SUBMIT_REPORT: '正在提交举报...',
|
||||
REPLY_REVIEW: '正在回复评价...',
|
||||
|
||||
// 其他
|
||||
SUBMIT_FEEDBACK: '正在提交反馈...',
|
||||
CHECK_UPDATE: '正在检查更新...'
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
/**
|
||||
* 创建标准化的请求配置
|
||||
* @param {string} template 配置模板名称
|
||||
* @param {Object} customConfig 自定义配置
|
||||
* @param {string} loadingText 自定义loading文本
|
||||
* @returns {Object} 标准化的请求配置
|
||||
*/
|
||||
export const createRequestConfig = (template, customConfig = {}, loadingText = null) => {
|
||||
const baseConfig = CONFIG_TEMPLATES[template] || {}
|
||||
|
||||
const config = {
|
||||
custom: {
|
||||
...baseConfig,
|
||||
...(loadingText && { loadingText }),
|
||||
...customConfig.custom
|
||||
},
|
||||
...customConfig
|
||||
}
|
||||
|
||||
// 移除custom属性中的undefined值
|
||||
Object.keys(config.custom).forEach(key => {
|
||||
if (config.custom[key] === undefined) {
|
||||
delete config.custom[key]
|
||||
}
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
+2
-101
@@ -1,111 +1,12 @@
|
||||
// HTTP请求配置和拦截器
|
||||
// 基于uView-next的luch-request库实现
|
||||
|
||||
import { HTTP_CONFIG, checkApiAuth, AUTH_REQUIRED_APIS } from './config.js'
|
||||
import { HTTP_CONFIG, checkApiAuth, checkAuthRequiredApi } from './config.js'
|
||||
import { clearAuthData, isUserLoggedIn, handleAuthRequired, tryAutoLogin } from '../utils/auth-helper.js'
|
||||
|
||||
/**
|
||||
* 清理认证数据
|
||||
*/
|
||||
function clearAuthData() {
|
||||
console.log('HTTP拦截器: 清理认证数据被调用')
|
||||
console.trace('调用堆栈:')
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
|
||||
uni.removeStorageSync('loginStep')
|
||||
uni.removeStorageSync('wxLoginCode')
|
||||
uni.removeStorageSync('wxUserInfo')
|
||||
uni.removeStorageSync('loginDate')
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查接口是否需要强制登录
|
||||
* @param {String} url 接口URL
|
||||
* @returns {Boolean} 是否需要强制登录
|
||||
*/
|
||||
function checkAuthRequiredApi(url) {
|
||||
// 移除查询参数,只保留路径
|
||||
const path = url.split('?')[0]
|
||||
|
||||
// 检查是否在需要强制登录的列表中
|
||||
for (const authApi of AUTH_REQUIRED_APIS) {
|
||||
// 支持通配符匹配
|
||||
if (authApi.includes('*')) {
|
||||
const regex = new RegExp('^' + authApi.replace(/\*/g, '.*') + '$')
|
||||
if (regex.test(path)) {
|
||||
return true
|
||||
}
|
||||
} else if (path === authApi || path.startsWith(authApi + '/')) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否已完成登录
|
||||
* @returns {Boolean} 是否已完成登录
|
||||
*/
|
||||
function isUserLoggedIn() {
|
||||
const token = uni.getStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
const loginStep = uni.getStorageSync('loginStep')
|
||||
|
||||
// 检查是否有有效的token和完成的登录流程
|
||||
return !!(token && (loginStep === 'profile_completed' || loginStep === 'phone_authed'))
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试自动登录
|
||||
* @returns {Promise<Boolean>} 是否登录成功
|
||||
*/
|
||||
async function tryAutoLogin() {
|
||||
try {
|
||||
return await autoLogin()
|
||||
} catch (error) {
|
||||
console.error('自动登录失败:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理需要鉴权的情况
|
||||
*/
|
||||
function handleAuthRequired() {
|
||||
const loginStep = uni.getStorageSync('loginStep')
|
||||
|
||||
// 根据当前登录状态决定跳转页面
|
||||
let targetPage = '/pages/login/login'
|
||||
let toastMessage = '请先登录'
|
||||
|
||||
switch (loginStep) {
|
||||
case 'wx_logged':
|
||||
targetPage = '/pages/auth/phone-auth'
|
||||
toastMessage = '请完成手机号授权'
|
||||
break
|
||||
case 'phone_authed':
|
||||
case 'phone_skipped':
|
||||
targetPage = '/pages/profile/user-info?mode=setup'
|
||||
toastMessage = '请完善个人信息'
|
||||
break
|
||||
default:
|
||||
targetPage = '/pages/login/login'
|
||||
toastMessage = '请先登录'
|
||||
}
|
||||
|
||||
// 显示提示并跳转
|
||||
uni.showToast({
|
||||
title: toastMessage,
|
||||
icon: 'none',
|
||||
duration: 1500
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({ url: targetPage }).catch(() => {
|
||||
uni.reLaunch({ url: targetPage })
|
||||
})
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化HTTP配置
|
||||
|
||||
+50
-28
@@ -1,4 +1,7 @@
|
||||
// HTTP模块统一导出文件
|
||||
/**
|
||||
* HTTP模块统一导出文件
|
||||
* 提供完整的API接口、配置管理、工具函数和认证功能
|
||||
*/
|
||||
|
||||
// 导入所有API模块
|
||||
import * as petsApi from './api/pets.js'
|
||||
@@ -7,52 +10,71 @@ import * as adoptionApi from './api/adoption.js'
|
||||
import * as profileApi from './api/profile.js'
|
||||
import * as reviewApi from './api/review.js'
|
||||
import * as commonApi from './api/common.js'
|
||||
import * as authApi from './api/auth.js'
|
||||
|
||||
// 导入配置
|
||||
// ==================== 配置导出 ====================
|
||||
export { HTTP_CONFIG, NO_AUTH_APIS, addNoAuthApis, setEnvironment } from './config/config.js'
|
||||
|
||||
// 导入工具
|
||||
// ==================== 工具函数导出 ====================
|
||||
export { validateRequired, validateId, validatePagination, validateFileUpload } from './utils/validator.js'
|
||||
|
||||
// 统一导出所有API
|
||||
// ==================== 认证工具导出 ====================
|
||||
export {
|
||||
isUserLoggedIn,
|
||||
validateToken,
|
||||
checkLoginStatus,
|
||||
clearAuthData,
|
||||
clearTempLoginData,
|
||||
navigateToLogin,
|
||||
handleAuthRequired,
|
||||
tryAutoLogin
|
||||
} from './utils/auth-helper.js'
|
||||
|
||||
// ==================== API模块导出 ====================
|
||||
export {
|
||||
petsApi,
|
||||
assistantApi,
|
||||
adoptionApi,
|
||||
profileApi,
|
||||
reviewApi,
|
||||
commonApi
|
||||
commonApi,
|
||||
authApi
|
||||
}
|
||||
|
||||
// 也可以按模块导出,便于按需引入
|
||||
// ==================== 默认导出 ====================
|
||||
export default {
|
||||
// API模块
|
||||
pets: petsApi,
|
||||
assistant: assistantApi,
|
||||
adoption: adoptionApi,
|
||||
profile: profileApi,
|
||||
review: reviewApi,
|
||||
common: commonApi
|
||||
common: commonApi,
|
||||
auth: authApi,
|
||||
|
||||
// 配置
|
||||
config: {
|
||||
HTTP_CONFIG,
|
||||
NO_AUTH_APIS,
|
||||
addNoAuthApis,
|
||||
setEnvironment
|
||||
},
|
||||
|
||||
// 工具函数
|
||||
utils: {
|
||||
validateRequired,
|
||||
validateId,
|
||||
validatePagination,
|
||||
validateFileUpload,
|
||||
isUserLoggedIn,
|
||||
validateToken,
|
||||
checkLoginStatus,
|
||||
clearAuthData,
|
||||
clearTempLoginData,
|
||||
navigateToLogin,
|
||||
handleAuthRequired,
|
||||
tryAutoLogin
|
||||
}
|
||||
}
|
||||
|
||||
// 使用示例:
|
||||
// 方式1:按模块导入API
|
||||
// import { petsApi, assistantApi } from '@/http/index.js'
|
||||
// petsApi.getPetsList()
|
||||
// assistantApi.sendMessage()
|
||||
|
||||
// 方式2:导入所有API
|
||||
// import api from '@/http/index.js'
|
||||
// api.pets.getPetsList()
|
||||
// api.assistant.sendMessage()
|
||||
|
||||
// 方式3:解构导入特定接口
|
||||
// import { petsApi } from '@/http/index.js'
|
||||
// const { getPetsList, addPet } = petsApi
|
||||
|
||||
// 方式4:配置不需要鉴权的接口
|
||||
// import { addNoAuthApis } from '@/http/index.js'
|
||||
// addNoAuthApis(['/custom/api1', '/custom/api2'])
|
||||
|
||||
// 方式5:切换环境
|
||||
// import { setEnvironment } from '@/http/index.js'
|
||||
// setEnvironment('production') // 切换到生产环境
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* 统一认证工具模块
|
||||
* 整合所有认证检查、登录状态管理等功能
|
||||
*/
|
||||
|
||||
import { HTTP_CONFIG } from '../config/config.js'
|
||||
|
||||
// ==================== 认证状态检查 ====================
|
||||
|
||||
/**
|
||||
* 检查用户是否已完成登录
|
||||
* @returns {Boolean} 是否已完成登录
|
||||
*/
|
||||
export function isUserLoggedIn() {
|
||||
const token = uni.getStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
const loginStep = uni.getStorageSync('loginStep')
|
||||
|
||||
// 检查是否有有效的token和完成的登录流程
|
||||
return !!(token && (loginStep === 'profile_completed' || loginStep === 'phone_authed'))
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并验证token有效性
|
||||
* @returns {Promise<boolean>} token是否有效
|
||||
*/
|
||||
export async function validateToken() {
|
||||
const token = uni.getStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
if (!token) {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用一个简单的API来验证token
|
||||
const { getUserInfo } = await import('../api/profile.js')
|
||||
await getUserInfo({
|
||||
custom: {
|
||||
loading: false,
|
||||
toast: false
|
||||
}
|
||||
})
|
||||
return true
|
||||
} catch (error) {
|
||||
console.log('Token验证失败:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查登录状态并处理
|
||||
* @returns {boolean} 是否已登录
|
||||
*/
|
||||
export function checkLoginStatus() {
|
||||
if (!isUserLoggedIn()) {
|
||||
console.log('用户未登录,跳转到登录页')
|
||||
navigateToLogin()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ==================== 认证数据管理 ====================
|
||||
|
||||
/**
|
||||
* 清理认证数据
|
||||
*/
|
||||
export function clearAuthData() {
|
||||
console.log('清理认证数据被调用')
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
|
||||
uni.removeStorageSync('loginStep')
|
||||
uni.removeStorageSync('wxLoginCode')
|
||||
uni.removeStorageSync('wxUserInfo')
|
||||
uni.removeStorageSync('loginDate')
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理登录流程中的临时数据
|
||||
*/
|
||||
export function clearTempLoginData() {
|
||||
// 清理临时数据,保留重要的用户信息
|
||||
uni.removeStorageSync('wxLoginCode')
|
||||
console.log('清理临时登录数据')
|
||||
}
|
||||
|
||||
// ==================== 登录流程处理 ====================
|
||||
|
||||
/**
|
||||
* 跳转到登录页面
|
||||
*/
|
||||
export function navigateToLogin() {
|
||||
uni.reLaunch({
|
||||
url: HTTP_CONFIG.loginPage
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理需要鉴权的情况
|
||||
*/
|
||||
export function handleAuthRequired() {
|
||||
const loginStep = uni.getStorageSync('loginStep')
|
||||
|
||||
// 根据当前登录状态决定跳转页面
|
||||
let targetPage = '/pages/login/login'
|
||||
let toastMessage = '请先登录'
|
||||
|
||||
switch (loginStep) {
|
||||
case 'wx_logged':
|
||||
targetPage = '/pages/auth/phone-auth'
|
||||
toastMessage = '请完成手机号授权'
|
||||
break
|
||||
case 'phone_authed':
|
||||
case 'phone_skipped':
|
||||
targetPage = '/pages/profile/user-info?mode=setup'
|
||||
toastMessage = '请完善个人信息'
|
||||
break
|
||||
default:
|
||||
targetPage = '/pages/login/login'
|
||||
toastMessage = '请先登录'
|
||||
}
|
||||
|
||||
// 显示提示并跳转
|
||||
uni.showToast({
|
||||
title: toastMessage,
|
||||
icon: 'none',
|
||||
duration: 1500
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({ url: targetPage }).catch(() => {
|
||||
uni.reLaunch({ url: targetPage })
|
||||
})
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试自动登录
|
||||
* @returns {Promise<Boolean>} 是否登录成功
|
||||
*/
|
||||
export async function tryAutoLogin() {
|
||||
try {
|
||||
// 这里需要导入实际的自动登录函数
|
||||
const { autoLogin } = await import('../../utils/loginState.js')
|
||||
return await autoLogin()
|
||||
} catch (error) {
|
||||
console.error('自动登录失败:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* HTTP请求统一工具类
|
||||
* 基于BaseRequest类提供标准化的请求配置和执行方法
|
||||
*/
|
||||
|
||||
import { CONFIG_TEMPLATES, LOADING_TEXTS, createRequestConfig } from '../config/constants.js'
|
||||
|
||||
// ==================== BaseRequest工具类 ====================
|
||||
|
||||
/**
|
||||
* 统一的HTTP请求工具类
|
||||
* 提供标准化的请求方法,基于uni.$u.http实现
|
||||
*/
|
||||
class BaseRequest {
|
||||
/**
|
||||
* 执行GET请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} params 查询参数
|
||||
* @param {string} template 配置模板
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
static get(url, params = {}, template = 'AUTHENTICATED_QUERY', config = {}) {
|
||||
const requestConfig = createRequestConfig(template, config)
|
||||
|
||||
return uni.$u.http.get(url, {
|
||||
...(Object.keys(params).length > 0 && { params }),
|
||||
...requestConfig
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行POST请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
static post(url, data = {}, template = 'AUTHENTICATED_UPDATE', loadingText = null, config = {}) {
|
||||
const requestConfig = createRequestConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.post(url, data, requestConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行PUT请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
static put(url, data = {}, template = 'AUTHENTICATED_UPDATE', loadingText = null, config = {}) {
|
||||
const requestConfig = createRequestConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.put(url, data, requestConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行DELETE请求
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} data 请求数据
|
||||
* @param {string} template 配置模板
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
static delete(url, data = {}, template = 'AUTHENTICATED_DELETE', loadingText = null, config = {}) {
|
||||
const requestConfig = createRequestConfig(template, config, loadingText)
|
||||
|
||||
return uni.$u.http.delete(url, data, requestConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行上传请求
|
||||
* @param {string} url 上传URL
|
||||
* @param {Object} uploadData 上传数据
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
static upload(url, uploadData, loadingText, config = {}) {
|
||||
const requestConfig = createRequestConfig('AUTHENTICATED_UPLOAD', config, loadingText)
|
||||
|
||||
return uni.$u.http.upload(url, {
|
||||
filePath: uploadData.filePath,
|
||||
name: uploadData.name || 'file',
|
||||
formData: uploadData.formData || {},
|
||||
...requestConfig
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行下载请求
|
||||
* @param {string} url 下载URL
|
||||
* @param {string} loadingText loading文本
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
static download(url, loadingText, config = {}) {
|
||||
const requestConfig = createRequestConfig('PUBLIC_DOWNLOAD', config, loadingText)
|
||||
|
||||
return uni.$u.http.download(url, {
|
||||
...(config.savePath && { savePath: config.savePath }),
|
||||
...requestConfig
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量上传多个文件
|
||||
* @param {Array} fileList 文件列表数组
|
||||
* @param {string} url 上传URL
|
||||
* @param {Object} config 自定义配置
|
||||
* @returns {Promise} 请求Promise
|
||||
*/
|
||||
static async batchUpload(fileList, url, config = {}) {
|
||||
const { maxConcurrent = 3, showProgress = true } = config
|
||||
|
||||
// 显示整体进度loading
|
||||
if (showProgress) {
|
||||
uni.showLoading({
|
||||
title: config.custom?.loadingText || LOADING_TEXTS.UPLOAD_IMAGES
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
// 分批并发上传
|
||||
const results = []
|
||||
for (let i = 0; i < fileList.length; i += maxConcurrent) {
|
||||
const batch = fileList.slice(i, i + maxConcurrent)
|
||||
const batchPromises = batch.map(fileData => {
|
||||
return BaseRequest.upload(url, fileData, null, {
|
||||
...config,
|
||||
custom: {
|
||||
loading: false, // 批量上传时不显示单个loading
|
||||
...config.custom
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const batchResults = await Promise.all(batchPromises)
|
||||
results.push(...batchResults)
|
||||
}
|
||||
|
||||
return results
|
||||
} finally {
|
||||
if (showProgress) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 导出 ====================
|
||||
|
||||
// 默认导出BaseRequest类
|
||||
export default BaseRequest
|
||||
|
||||
// 向后兼容的命名导出
|
||||
export const executeGetRequest = BaseRequest.get
|
||||
export const executePostRequest = BaseRequest.post
|
||||
export const executePutRequest = BaseRequest.put
|
||||
export const executeDeleteRequest = BaseRequest.delete
|
||||
export const executeUploadRequest = BaseRequest.upload
|
||||
export const executeDownloadRequest = BaseRequest.download
|
||||
export const executeBatchUploadRequest = BaseRequest.batchUpload
|
||||
|
||||
// 导出配置相关(从constants.js重新导出)
|
||||
export { CONFIG_TEMPLATES, LOADING_TEXTS, createRequestConfig }
|
||||
+313
-117
@@ -15,8 +15,13 @@
|
||||
<view class="status-dot"></view>
|
||||
<text class="status-text">在线</text>
|
||||
</view>
|
||||
<view class="knowledge-icon" @click="openKnowledge">
|
||||
<text class="icon-text">📚</text>
|
||||
<view class="action-buttons">
|
||||
<view class="action-btn" @click="clearHistory" title="清空历史">
|
||||
<text class="icon-text">🗑️</text>
|
||||
</view>
|
||||
<view class="action-btn" @click="openKnowledge" title="知识库">
|
||||
<text class="icon-text">📚</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -114,6 +119,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
askPetAssistant,
|
||||
streamAskPetAssistant,
|
||||
getAssistantHistory,
|
||||
clearAssistantHistory,
|
||||
validateMessage,
|
||||
formatChatMessage,
|
||||
formatMessageTime
|
||||
} from '@/http/api/assistant.js'
|
||||
// WebSocket功能已移除,使用HTTP API替代
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -121,82 +137,46 @@ export default {
|
||||
scrollTop: 0,
|
||||
isThinking: false,
|
||||
userAvatar: '/static/user-avatar.png',
|
||||
messageList: [
|
||||
{
|
||||
type: 'ai',
|
||||
content: '您好!我是您的宠物AI助手🐾\n\n我可以为您解答关于宠物饲养、健康、训练、营养等方面的问题。\n\n**我能帮你做什么:**\n- 🍖 **饮食建议**:营养搭配、食物选择\n- 🏥 **健康咨询**:症状分析、预防措施 \n- 🎾 **训练指导**:行为纠正、技能训练\n- 💡 **日常护理**:清洁、美容、环境\n\n有什么想了解的吗?',
|
||||
time: this.getCurrentTime()
|
||||
}
|
||||
],
|
||||
quickQuestions: [
|
||||
{ id: 1, text: '猫咪不吃饭怎么办?' },
|
||||
{ id: 2, text: '狗狗需要多久洗一次澡?' },
|
||||
{ id: 3, text: '宠物疫苗接种时间' },
|
||||
{ id: 4, text: '如何训练宠物定点上厕所?' },
|
||||
{ id: 5, text: '宠物发烧的症状' },
|
||||
{ id: 6, text: '幼猫喂养注意事项' }
|
||||
],
|
||||
// 知识库数据
|
||||
knowledgeBase: {
|
||||
'喂食': {
|
||||
keywords: ['喂食', '吃饭', '食物', '饮食', '营养'],
|
||||
responses: [
|
||||
'定时定量喂食很重要,成年猫每天2-3次,幼猫3-4次。',
|
||||
'选择优质的宠物食品,避免给宠物吃人类食物。',
|
||||
'确保宠物随时有清洁的饮用水。'
|
||||
]
|
||||
},
|
||||
'健康': {
|
||||
keywords: ['健康', '生病', '症状', '发烧', '呕吐', '腹泻'],
|
||||
responses: [
|
||||
'定期体检很重要,建议每年至少一次。',
|
||||
'注意观察宠物的食欲、精神状态和排便情况。',
|
||||
'如果出现异常症状,请及时就医。'
|
||||
]
|
||||
},
|
||||
'疫苗': {
|
||||
keywords: ['疫苗', '接种', '免疫', '预防'],
|
||||
responses: [
|
||||
'幼猫幼犬8-12周开始接种疫苗。',
|
||||
'成年宠物每年需要加强免疫。',
|
||||
'常见疫苗包括三联疫苗和狂犬疫苗。'
|
||||
]
|
||||
},
|
||||
'训练': {
|
||||
keywords: ['训练', '教育', '行为', '定点', '上厕所'],
|
||||
responses: [
|
||||
'训练需要耐心和一致性。',
|
||||
'使用正向强化,奖励好行为。',
|
||||
'避免体罚,这会让宠物产生恐惧。'
|
||||
]
|
||||
},
|
||||
'洗澡': {
|
||||
keywords: ['洗澡', '清洁', '卫生'],
|
||||
responses: [
|
||||
'狗狗一般1-2周洗一次澡,猫咪通常不需要经常洗澡。',
|
||||
'使用宠物专用洗浴用品。',
|
||||
'洗澡后要及时吹干,避免感冒。'
|
||||
]
|
||||
}
|
||||
}
|
||||
messageList: []
|
||||
}
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
// 加载历史记录
|
||||
this.loadChatHistory()
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 页面显示时滚动到底部
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom()
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
getCurrentTime() {
|
||||
const now = new Date()
|
||||
return `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`
|
||||
},
|
||||
|
||||
askQuestion(question) {
|
||||
this.inputMessage = question
|
||||
this.sendMessage()
|
||||
},
|
||||
|
||||
sendMessage() {
|
||||
|
||||
async sendMessage() {
|
||||
if (!this.inputMessage.trim() || this.isThinking) return
|
||||
|
||||
// 验证消息内容
|
||||
const validation = validateMessage(this.inputMessage)
|
||||
if (!validation.valid) {
|
||||
uni.showToast({
|
||||
title: validation.error,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 保存用户输入内容
|
||||
const userInput = this.inputMessage
|
||||
const userInput = this.inputMessage.trim()
|
||||
|
||||
// 添加用户消息
|
||||
const userMessage = {
|
||||
@@ -212,6 +192,9 @@ export default {
|
||||
// 开始AI思考
|
||||
this.isThinking = true
|
||||
|
||||
// 用于存储当前AI消息的引用
|
||||
let currentAiMessage = null
|
||||
|
||||
// 确保DOM更新后再滚动到思考状态
|
||||
this.$nextTick(() => {
|
||||
this.forceScrollToBottom()
|
||||
@@ -224,46 +207,255 @@ export default {
|
||||
}, 500)
|
||||
})
|
||||
|
||||
// 模拟AI回复
|
||||
setTimeout(() => {
|
||||
const aiMessage = {
|
||||
type: 'ai',
|
||||
content: this.getAIResponse(userInput),
|
||||
time: this.getCurrentTime()
|
||||
}
|
||||
this.messageList.push(aiMessage)
|
||||
this.isThinking = false
|
||||
|
||||
// AI回复完成后强制滚动到底部
|
||||
this.$nextTick(() => {
|
||||
this.forceScrollToBottom()
|
||||
// 延迟再次滚动,确保消息完全显示
|
||||
setTimeout(() => {
|
||||
this.forceScrollToBottom()
|
||||
}, 100)
|
||||
try {
|
||||
// 使用HTTP API流式响应
|
||||
const response = await this.handleStreamResponse({
|
||||
message: userInput,
|
||||
temperature: 0.7,
|
||||
maxTokens: 1000
|
||||
}, (aiMessage) => {
|
||||
// 保存AI消息引用,用于fallback时更新
|
||||
currentAiMessage = aiMessage
|
||||
})
|
||||
}, 1500 + Math.random() * 1000) // 1.5-2.5秒随机延迟
|
||||
|
||||
// 检查是否包含敏感词
|
||||
if (response && response.data && response.data.isSensitive) {
|
||||
uni.showToast({
|
||||
title: '消息包含敏感内容',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
|
||||
// 结束思考状态
|
||||
this.isThinking = false
|
||||
} catch (error) {
|
||||
console.error('SSE流式请求失败,尝试普通请求:', error)
|
||||
|
||||
// 降级处理:使用普通API
|
||||
try {
|
||||
const fallbackResponse = await askPetAssistant({
|
||||
message: userInput,
|
||||
temperature: 0.7,
|
||||
maxTokens: 1000
|
||||
})
|
||||
|
||||
if (fallbackResponse && fallbackResponse.data) {
|
||||
// 更新已存在的AI消息,而不是创建新的
|
||||
if (currentAiMessage) {
|
||||
currentAiMessage.content = fallbackResponse.data.message || fallbackResponse.data.content || '抱歉,我现在无法回答您的问题。'
|
||||
currentAiMessage.isSensitive = fallbackResponse.data.isSensitive || false
|
||||
currentAiMessage.tokenCount = fallbackResponse.data.tokenCount || 0
|
||||
currentAiMessage.responseTime = fallbackResponse.data.responseTime || 0
|
||||
} else {
|
||||
// 如果没有AI消息引用,创建新的(兜底逻辑)
|
||||
const aiMessage = {
|
||||
type: 'ai',
|
||||
content: fallbackResponse.data.message || fallbackResponse.data.content || '抱歉,我现在无法回答您的问题。',
|
||||
time: this.getCurrentTime(),
|
||||
isSensitive: fallbackResponse.data.isSensitive || false,
|
||||
tokenCount: fallbackResponse.data.tokenCount || 0,
|
||||
responseTime: fallbackResponse.data.responseTime || 0
|
||||
}
|
||||
this.messageList.push(aiMessage)
|
||||
}
|
||||
|
||||
// 检查敏感词
|
||||
if (fallbackResponse.data.isSensitive) {
|
||||
uni.showToast({
|
||||
title: '消息包含敏感内容',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
|
||||
this.forceScrollToBottom()
|
||||
} else {
|
||||
this.handleApiError('API响应格式异常', currentAiMessage)
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
console.error('普通请求也失败:', fallbackError)
|
||||
this.handleApiError(fallbackError.message || '网络请求失败', currentAiMessage)
|
||||
}
|
||||
} finally {
|
||||
// 确保思考状态结束(防止异常情况)
|
||||
this.isThinking = false
|
||||
}
|
||||
},
|
||||
|
||||
getAIResponse(question) {
|
||||
// 智能匹配知识库
|
||||
for (let category in this.knowledgeBase) {
|
||||
const { keywords, responses } = this.knowledgeBase[category]
|
||||
if (keywords.some(keyword => question.includes(keyword))) {
|
||||
const randomResponse = responses[Math.floor(Math.random() * responses.length)]
|
||||
return `${randomResponse}\n\n💡 如果您需要更详细的建议,建议咨询专业的宠物医生。`
|
||||
/**
|
||||
* 处理API错误
|
||||
* @param {string} errorMessage 错误信息
|
||||
* @param {Object} existingAiMessage 已存在的AI消息对象(可选)
|
||||
*/
|
||||
handleApiError(errorMessage, existingAiMessage = null) {
|
||||
const errorContent = `抱歉,我遇到了一些问题:${errorMessage}\n\n请稍后再试,或者检查网络连接。`
|
||||
|
||||
if (existingAiMessage) {
|
||||
// 更新已存在的AI消息
|
||||
existingAiMessage.content = errorContent
|
||||
existingAiMessage.isError = true
|
||||
} else {
|
||||
// 创建新的错误消息(兜底逻辑)
|
||||
const errorMessage_display = {
|
||||
type: 'ai',
|
||||
content: errorContent,
|
||||
time: this.getCurrentTime(),
|
||||
isError: true
|
||||
}
|
||||
this.messageList.push(errorMessage_display)
|
||||
}
|
||||
|
||||
// 默认回复
|
||||
const defaultResponses = [
|
||||
'这是一个很好的问题!建议您咨询专业的宠物医生获得更准确的建议。',
|
||||
'每只宠物的情况都不同,建议根据具体情况来处理。您可以查看我们的知识库了解更多信息。',
|
||||
'感谢您的提问!这个问题比较复杂,建议您带宠物去专业的宠物医院检查。',
|
||||
'我理解您的担心。建议您记录宠物的具体症状,然后咨询专业医生。'
|
||||
]
|
||||
this.forceScrollToBottom()
|
||||
},
|
||||
|
||||
return defaultResponses[Math.floor(Math.random() * defaultResponses.length)]
|
||||
/**
|
||||
* 加载聊天历史记录
|
||||
*/
|
||||
async loadChatHistory() {
|
||||
console.log('开始加载聊天历史记录...')
|
||||
try {
|
||||
const response = await getAssistantHistory({
|
||||
page: 1,
|
||||
pageSize: 20
|
||||
})
|
||||
|
||||
console.log('历史记录API响应:', response)
|
||||
|
||||
if (response && Array.isArray(response) && response.length > 0) {
|
||||
// 格式化并设置历史消息
|
||||
const historyMessages = response.map(msg => formatChatMessage(msg))
|
||||
console.log('格式化后的历史消息:', historyMessages)
|
||||
this.messageList = historyMessages
|
||||
|
||||
// 滚动到底部
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom()
|
||||
})
|
||||
|
||||
console.log('历史记录加载成功,共', historyMessages.length, '条消息')
|
||||
} else {
|
||||
// 没有历史记录,保持空列表
|
||||
console.log('没有历史记录或数据格式异常:', response)
|
||||
this.messageList = []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载历史记录失败:', error)
|
||||
|
||||
// 显示用户友好的错误提示
|
||||
uni.showToast({
|
||||
title: '加载历史记录失败',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
|
||||
// 保持空列表
|
||||
this.messageList = []
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 清空聊天历史
|
||||
*/
|
||||
async clearHistory() {
|
||||
try {
|
||||
const result = await uni.showModal({
|
||||
title: '确认清空',
|
||||
content: '确定要清空聊天记录吗?此操作不可恢复。',
|
||||
confirmText: '清空',
|
||||
cancelText: '取消'
|
||||
})
|
||||
|
||||
if (!result.confirm) return
|
||||
|
||||
uni.showLoading({
|
||||
title: '正在清空...'
|
||||
})
|
||||
|
||||
await clearAssistantHistory()
|
||||
|
||||
// 清空消息列表
|
||||
this.messageList = []
|
||||
|
||||
uni.showToast({
|
||||
title: '历史记录已清空',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('清空历史记录失败:', error)
|
||||
uni.showToast({
|
||||
title: '清空失败',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 处理HTTP流式响应
|
||||
* @param {Object} messageData 消息数据
|
||||
* @param {Function} onAiMessageCreated 创建AI消息后的回调函数
|
||||
* @returns {Promise} 返回流式响应处理结果
|
||||
*/
|
||||
async handleStreamResponse(messageData, onAiMessageCreated) {
|
||||
// 创建AI消息对象
|
||||
const aiMessage = {
|
||||
type: 'ai',
|
||||
content: '',
|
||||
time: this.getCurrentTime(),
|
||||
isSensitive: false,
|
||||
tokenCount: 0,
|
||||
responseTime: 0
|
||||
}
|
||||
|
||||
// 添加到消息列表
|
||||
this.messageList.push(aiMessage)
|
||||
|
||||
// 通知调用者AI消息已创建
|
||||
if (onAiMessageCreated) {
|
||||
onAiMessageCreated(aiMessage)
|
||||
}
|
||||
|
||||
// 使用HTTP API处理流式响应
|
||||
return streamAskPetAssistant(messageData)
|
||||
.then(result => {
|
||||
console.log('HTTP流式响应完成:', result)
|
||||
// 更新消息内容
|
||||
aiMessage.content = result.message || result.content || ''
|
||||
// 更新消息的元数据
|
||||
if (result.isSensitive !== undefined) {
|
||||
aiMessage.isSensitive = result.isSensitive
|
||||
}
|
||||
if (result.tokenCount !== undefined) {
|
||||
aiMessage.tokenCount = result.tokenCount
|
||||
}
|
||||
if (result.responseTime !== undefined) {
|
||||
aiMessage.responseTime = result.responseTime
|
||||
}
|
||||
// 强制触发视图更新
|
||||
this.$forceUpdate()
|
||||
return result
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('HTTP流式响应失败:', error)
|
||||
// 显示错误提示
|
||||
uni.showToast({
|
||||
title: '消息发送失败',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
})
|
||||
// 更新消息状态为错误
|
||||
aiMessage.content = '抱歉,消息发送失败,请重试。'
|
||||
aiMessage.isError = true
|
||||
// 强制触发视图更新
|
||||
this.$forceUpdate()
|
||||
throw error
|
||||
})
|
||||
},
|
||||
|
||||
scrollToBottom() {
|
||||
@@ -302,19 +494,11 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
startVoiceInput() {
|
||||
uni.showToast({
|
||||
title: '语音功能开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
|
||||
openKnowledge() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/assistant/knowledge'
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -398,18 +582,30 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.knowledge-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 30rpx;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
gap: 16rpx;
|
||||
|
||||
.icon-text {
|
||||
font-size: 28rpx;
|
||||
.action-btn {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 28rpx;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-23
@@ -155,38 +155,21 @@ export const saveProfileData = (profileData) => {
|
||||
|
||||
/**
|
||||
* 清理登录流程中的临时数据
|
||||
* @deprecated 使用 http/utils/auth-helper.js 中的 clearTempLoginData 替代
|
||||
*/
|
||||
export const clearTempLoginData = () => {
|
||||
// 清理临时数据,保留重要的用户信息
|
||||
uni.removeStorageSync(STORAGE_KEYS.WX_LOGIN_CODE)
|
||||
|
||||
console.log('清理临时登录数据')
|
||||
const { clearTempLoginData } = require('../http/utils/auth-helper.js')
|
||||
clearTempLoginData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并验证token有效性
|
||||
* @returns {Promise<boolean>} token是否有效
|
||||
* @deprecated 使用 http/utils/auth-helper.js 中的 validateToken 替代
|
||||
*/
|
||||
export const validateToken = async () => {
|
||||
const token = uni.getStorageSync(STORAGE_KEYS.TOKEN)
|
||||
if (!token) {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用一个简单的API来验证token
|
||||
const { getUserInfo } = await import('@/http/api/profile.js')
|
||||
await getUserInfo({
|
||||
custom: {
|
||||
loading: false,
|
||||
toast: false
|
||||
}
|
||||
})
|
||||
return true
|
||||
} catch (error) {
|
||||
console.log('Token验证失败:', error)
|
||||
return false
|
||||
}
|
||||
const { validateToken } = await import('../http/utils/auth-helper.js')
|
||||
return await validateToken()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
-17
@@ -188,38 +188,30 @@ export class WechatAuth {
|
||||
|
||||
/**
|
||||
* 清除所有登录信息
|
||||
* @deprecated 使用 http/utils/auth-helper.js 中的 clearAuthData 替代
|
||||
*/
|
||||
static clearLoginInfo() {
|
||||
try {
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
|
||||
console.log('登录信息清除成功')
|
||||
} catch (error) {
|
||||
console.error('清除登录信息失败:', error)
|
||||
}
|
||||
const { clearAuthData } = require('../http/utils/auth-helper.js')
|
||||
clearAuthData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到登录页面
|
||||
* @deprecated 使用 http/utils/auth-helper.js 中的 navigateToLogin 替代
|
||||
*/
|
||||
static navigateToLogin() {
|
||||
uni.reLaunch({
|
||||
url: HTTP_CONFIG.loginPage
|
||||
})
|
||||
const { navigateToLogin } = require('../http/utils/auth-helper.js')
|
||||
navigateToLogin()
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查登录状态并处理
|
||||
* @returns {boolean} 是否已登录
|
||||
* @deprecated 使用 http/utils/auth-helper.js 中的 checkLoginStatus 替代
|
||||
*/
|
||||
static checkLoginStatus() {
|
||||
if (!this.isLoggedIn()) {
|
||||
console.log('用户未登录,跳转到登录页')
|
||||
this.navigateToLogin()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
const { checkLoginStatus } = require('../http/utils/auth-helper.js')
|
||||
return checkLoginStatus()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user