214 lines
7.1 KiB
JavaScript
214 lines
7.1 KiB
JavaScript
/**
|
||
* 宠物助手相关API接口模块
|
||
* 对接后端宠物助手服务接口
|
||
*/
|
||
|
||
import BaseRequest from '../utils/request-helper.js'
|
||
import { LOADING_TEXTS } from '../config/constants.js'
|
||
|
||
// ==================== 宠物助手聊天接口 ====================
|
||
|
||
/**
|
||
* 向宠物助手提问(非流式)
|
||
* @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 = {}) => {
|
||
console.warn('sendMessage is deprecated, please use askPetAssistant instead')
|
||
return askPetAssistant(messageData, config)
|
||
}
|
||
|
||
/**
|
||
* 获取聊天历史(兼容旧版本)
|
||
* @deprecated 请使用 getAssistantHistory 替代
|
||
* @param {Object} params 查询参数
|
||
* @param {Object} config 自定义配置
|
||
* @returns {Promise}
|
||
*/
|
||
export const getChatHistory = (params = {}, 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 = {}) => {
|
||
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 }
|
||
}
|
||
|
||
/**
|
||
* 格式化聊天消息
|
||
* @description 将API返回的消息格式化为前端显示格式
|
||
* @param {Object} apiMessage API返回的消息对象
|
||
* @returns {Object} 格式化后的消息对象
|
||
*/
|
||
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
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 格式化消息时间
|
||
* @description 将时间戳或时间字符串格式化为显示格式
|
||
* @param {string|number|Date} timestamp 时间戳或时间对象
|
||
* @returns {string} 格式化后的时间字符串
|
||
*/
|
||
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
|
||
})
|
||
}
|
||
}
|