This commit is contained in:
2025-09-10 17:27:39 +08:00
parent 6ab8f89770
commit e78a7b95a1
5 changed files with 1051 additions and 147 deletions
+177 -29
View File
@@ -1,65 +1,213 @@
/**
* AI助手相关API接口模块
* 宠物助手相关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 BaseRequest.post('/ai/chat', messageData, 'AUTHENTICATED_UPDATE', LOADING_TEXTS.AI_THINKING, 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 BaseRequest.get('/ai/knowledge', params, 'SILENT_REQUEST', config)
}
/**
* 获取聊天历史
* 获取聊天历史(兼容旧版本)
* @deprecated 请使用 getAssistantHistory 替代
* @param {Object} params 查询参数
* @param {Object} config 自定义配置
* @returns {Promise}
*/
export const getChatHistory = (params = {}, config = {}) => {
return BaseRequest.get('/ai/chat/history', params, 'AUTHENTICATED_QUERY', 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 BaseRequest.delete('/ai/chat/history', {}, 'AUTHENTICATED_DELETE', '正在清除历史记录...', 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 BaseRequest.post('/ai/suggestion', petData, 'AUTHENTICATED_UPDATE', '正在分析宠物状况...', 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 BaseRequest.upload('/ai/speech-to-text', audioData, LOADING_TEXTS.SPEECH_RECOGNITION, 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
})
}
}