feat:交接
This commit is contained in:
452
src/utils/api.js
452
src/utils/api.js
@@ -1,8 +1,55 @@
|
||||
// API服务文件
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
// 文本清理函数 - 只保留文字和标点符号
|
||||
export const cleanText = (text) => {
|
||||
if (!text || typeof text !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// 去除所有HTML标签
|
||||
let cleaned = text.replace(/<[^>]*>/g, '');
|
||||
|
||||
// 去除Markdown格式标记
|
||||
cleaned = cleaned
|
||||
// 去除粗体标记 **text** 或 __text__
|
||||
.replace(/\*\*([^*]+)\*\*/g, '$1')
|
||||
.replace(/__([^_]+)__/g, '$1')
|
||||
// 去除斜体标记 *text* 或 _text_
|
||||
.replace(/\*([^*]+)\*/g, '$1')
|
||||
.replace(/_([^_]+)_/g, '$1')
|
||||
// 去除删除线标记 ~~text~~
|
||||
.replace(/~~([^~]+)~~/g, '$1')
|
||||
// 去除代码标记 `code`
|
||||
.replace(/`([^`]+)`/g, '$1')
|
||||
// 去除链接标记 [text](url)
|
||||
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||
// 去除图片标记 
|
||||
.replace(/!\[([^\]]*)\]\([^)]+\)/g, '$1')
|
||||
// 去除标题标记 # ## ###
|
||||
.replace(/^#{1,6}\s*/gm, '')
|
||||
// 去除列表标记 - * +
|
||||
.replace(/^[\s]*[-*+]\s*/gm, '')
|
||||
// 去除引用标记 >
|
||||
.replace(/^>\s*/gm, '')
|
||||
// 去除水平线标记 --- 或 ***
|
||||
.replace(/^[-*]{3,}$/gm, '');
|
||||
|
||||
// 去除多余的空白字符和换行
|
||||
cleaned = cleaned
|
||||
// 将多个连续空格和换行替换为单个空格
|
||||
.replace(/\s+/g, ' ')
|
||||
// 去除行首行尾空格
|
||||
.trim();
|
||||
|
||||
// 去除特殊字符(保留中文、英文、数字、标点符号)
|
||||
cleaned = cleaned.replace(/[^\u4e00-\u9fa5a-zA-Z0-9\s\.,;:!?()()【】""''""''、,。!?;:]/g, '');
|
||||
|
||||
return cleaned;
|
||||
};
|
||||
|
||||
// 基础配置
|
||||
const BASE_URL = 'http://8.145.52.111:8091'; // 根据后端地址调整
|
||||
const BASE_URL = 'http://localhost:8091'; // 根据后端地址调整
|
||||
|
||||
// 检查用户登录状态
|
||||
const checkLoginStatus = () => {
|
||||
@@ -43,7 +90,7 @@ const request = (options) => {
|
||||
method: options.method || 'GET',
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': loginStatus.token || '',
|
||||
'Authorization': loginStatus.token ? (loginStatus.token.startsWith('Bearer ') ? loginStatus.token : 'Bearer ' + loginStatus.token) : '',
|
||||
...options.header
|
||||
},
|
||||
data: options.data || {},
|
||||
@@ -98,15 +145,20 @@ export const chatAPI = {
|
||||
}
|
||||
|
||||
try {
|
||||
const requestData = {
|
||||
message: params.message,
|
||||
useFunctionCall: false,
|
||||
modelId: params.modelId || null, // 支持传入modelId,默认为null使用后端默认
|
||||
templateId: params.templateId || params.characterId, // 支持templateId参数
|
||||
sessionId: params.sessionId || null // 支持sessionId参数
|
||||
};
|
||||
|
||||
console.log('发送AI聊天请求,参数:', requestData);
|
||||
|
||||
const response = await request({
|
||||
url: '/api/chat/sync',
|
||||
method: 'POST',
|
||||
data: {
|
||||
message: params.message,
|
||||
useFunctionCall: false,
|
||||
modelId: null, // 使用默认模型
|
||||
templateId: params.characterId // 使用角色模板ID
|
||||
}
|
||||
data: requestData
|
||||
});
|
||||
|
||||
console.log('API原始响应:', response);
|
||||
@@ -120,8 +172,13 @@ export const chatAPI = {
|
||||
}
|
||||
// 如果响应是对象,尝试提取AI回复
|
||||
else if (typeof response === 'object' && response !== null) {
|
||||
// 优先处理嵌套结构:res.data.data.response
|
||||
if (response.data && response.data.data && response.data.data.response) {
|
||||
// 优先处理根级别的response字段(根据实际后端响应结构)
|
||||
if (response.response && typeof response.response === 'string') {
|
||||
processedResponse = response.response;
|
||||
console.log('从根级别字段 response 提取回复:', processedResponse);
|
||||
}
|
||||
// 备用:处理嵌套结构:res.data.data.response
|
||||
else if (response.data && response.data.data && response.data.data.response) {
|
||||
processedResponse = response.data.data.response;
|
||||
console.log('从嵌套结构 data.data.response 提取回复:', processedResponse);
|
||||
}
|
||||
@@ -131,6 +188,17 @@ export const chatAPI = {
|
||||
console.log('从字段 data.response 提取回复:', processedResponse);
|
||||
}
|
||||
// 检查是否为状态消息
|
||||
else if (response.message) {
|
||||
if (response.message === '对话成功') {
|
||||
// 后端返回成功消息,使用默认回复
|
||||
processedResponse = '我收到了你的消息,很高兴和你聊天!';
|
||||
console.log('检测到对话成功状态,使用默认回复');
|
||||
} else {
|
||||
// 如果后端返回了错误信息,抛出错误
|
||||
throw new Error(response.message);
|
||||
}
|
||||
}
|
||||
// 检查data中的message字段
|
||||
else if (response.data && response.data.message) {
|
||||
if (response.data.message === '对话成功') {
|
||||
// 后端返回成功消息,使用默认回复
|
||||
@@ -172,9 +240,14 @@ export const chatAPI = {
|
||||
console.log('未找到有效回复,使用默认回复');
|
||||
}
|
||||
|
||||
// 清理文本,只保留文字和标点符号
|
||||
const cleanedResponse = cleanText(processedResponse);
|
||||
console.log('原始回复:', processedResponse);
|
||||
console.log('清理后回复:', cleanedResponse);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: processedResponse,
|
||||
data: cleanedResponse,
|
||||
originalResponse: response
|
||||
};
|
||||
} catch (error) {
|
||||
@@ -369,7 +442,7 @@ export const voiceAPI = {
|
||||
}
|
||||
},
|
||||
|
||||
// 3. 语音对话 - 完整语音交互流程
|
||||
// 3. 语音对话 - 完整语音交互流程(前端发送aac格式,后端转换为wav处理)
|
||||
voiceChat: async (filePath, options = {}) => {
|
||||
try {
|
||||
const loginStatus = checkLoginStatus();
|
||||
@@ -384,6 +457,7 @@ export const voiceAPI = {
|
||||
}
|
||||
|
||||
console.log('开始语音对话,文件路径:', filePath);
|
||||
console.log('注意:前端发送aac格式音频,后端需要转换为wav格式进行处理');
|
||||
|
||||
// 构建认证头
|
||||
let authHeader = '';
|
||||
@@ -411,13 +485,55 @@ export const voiceAPI = {
|
||||
const data = JSON.parse(res.data);
|
||||
console.log('语音对话响应数据:', data);
|
||||
|
||||
if (data.code === 200 && data.data) {
|
||||
if (data.code === 200) {
|
||||
// 根据后端实际返回结构提取字段
|
||||
let aiResponse = null;
|
||||
let userText = null;
|
||||
let audioUrl = null;
|
||||
|
||||
// 从 data.llmResult.response 提取AI回复
|
||||
if (data.data && data.data.llmResult && data.data.llmResult.response) {
|
||||
aiResponse = data.data.llmResult.response;
|
||||
}
|
||||
|
||||
// 从 data.sttResult.text 提取用户文本(语音转文字)
|
||||
if (data.data && data.data.sttResult && data.data.sttResult.text) {
|
||||
userText = data.data.sttResult.text;
|
||||
}
|
||||
|
||||
// 从 data.ttsResult.audioPath 提取音频路径
|
||||
if (data.data && data.data.ttsResult && data.data.ttsResult.audioPath) {
|
||||
audioUrl = data.data.ttsResult.audioPath;
|
||||
}
|
||||
|
||||
// 备用字段提取(保持向后兼容)
|
||||
if (!aiResponse) {
|
||||
if (data.response && typeof data.response === 'string') {
|
||||
aiResponse = data.response;
|
||||
} else if (data.data && data.data.response) {
|
||||
aiResponse = data.data.response;
|
||||
}
|
||||
}
|
||||
|
||||
if (!userText) {
|
||||
userText = data.userText || data.data?.userText || data.data?.text || data.data?.user_text || data.data?.recognizedText || data.data?.transcription;
|
||||
}
|
||||
|
||||
if (!audioUrl) {
|
||||
audioUrl = data.audioPath || data.audioUrl || data.data?.audioUrl || data.data?.url || data.data?.audio_url || data.data?.speechUrl || data.data?.ttsUrl || data.data?.audioPath;
|
||||
}
|
||||
|
||||
// 清理AI回复文本
|
||||
const cleanedAiResponse = cleanText(aiResponse);
|
||||
console.log('原始AI回复:', aiResponse);
|
||||
console.log('清理后AI回复:', cleanedAiResponse);
|
||||
|
||||
resolve({
|
||||
success: true,
|
||||
data: {
|
||||
userText: data.data.userText || data.data.text,
|
||||
aiResponse: data.data.aiResponse || data.data.response,
|
||||
audioUrl: data.data.audioUrl || data.data.url
|
||||
userText: userText,
|
||||
aiResponse: cleanedAiResponse,
|
||||
audioUrl: audioUrl
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -452,7 +568,7 @@ export const voiceAPI = {
|
||||
}
|
||||
},
|
||||
|
||||
// 4. 音频文件上传语音对话
|
||||
// 4. 音频文件上传语音对话(前端发送aac格式,后端转换为wav处理)
|
||||
uploadVoiceChat: async (filePath, options = {}) => {
|
||||
try {
|
||||
const loginStatus = checkLoginStatus();
|
||||
@@ -467,6 +583,7 @@ export const voiceAPI = {
|
||||
}
|
||||
|
||||
console.log('开始上传音频文件语音对话,文件路径:', filePath);
|
||||
console.log('注意:前端发送aac格式音频,后端需要转换为wav格式进行处理');
|
||||
|
||||
// 构建认证头
|
||||
let authHeader = '';
|
||||
@@ -494,13 +611,55 @@ export const voiceAPI = {
|
||||
const data = JSON.parse(res.data);
|
||||
console.log('上传音频文件语音对话响应数据:', data);
|
||||
|
||||
if (data.code === 200 && data.data) {
|
||||
if (data.code === 200) {
|
||||
// 根据后端实际返回结构提取字段
|
||||
let aiResponse = null;
|
||||
let userText = null;
|
||||
let audioUrl = null;
|
||||
|
||||
// 从 data.llmResult.response 提取AI回复
|
||||
if (data.data && data.data.llmResult && data.data.llmResult.response) {
|
||||
aiResponse = data.data.llmResult.response;
|
||||
}
|
||||
|
||||
// 从 data.sttResult.text 提取用户文本(语音转文字)
|
||||
if (data.data && data.data.sttResult && data.data.sttResult.text) {
|
||||
userText = data.data.sttResult.text;
|
||||
}
|
||||
|
||||
// 从 data.ttsResult.audioPath 提取音频路径
|
||||
if (data.data && data.data.ttsResult && data.data.ttsResult.audioPath) {
|
||||
audioUrl = data.data.ttsResult.audioPath;
|
||||
}
|
||||
|
||||
// 备用字段提取(保持向后兼容)
|
||||
if (!aiResponse) {
|
||||
if (data.response && typeof data.response === 'string') {
|
||||
aiResponse = data.response;
|
||||
} else if (data.data && data.data.response) {
|
||||
aiResponse = data.data.response;
|
||||
}
|
||||
}
|
||||
|
||||
if (!userText) {
|
||||
userText = data.userText || data.data?.userText || data.data?.text || data.data?.user_text || data.data?.recognizedText || data.data?.transcription;
|
||||
}
|
||||
|
||||
if (!audioUrl) {
|
||||
audioUrl = data.audioPath || data.audioUrl || data.data?.audioUrl || data.data?.url || data.data?.audio_url || data.data?.speechUrl || data.data?.ttsUrl || data.data?.audioPath;
|
||||
}
|
||||
|
||||
// 清理AI回复文本
|
||||
const cleanedAiResponse = cleanText(aiResponse);
|
||||
console.log('原始AI回复:', aiResponse);
|
||||
console.log('清理后AI回复:', cleanedAiResponse);
|
||||
|
||||
resolve({
|
||||
success: true,
|
||||
data: {
|
||||
userText: data.data.userText || data.data.text,
|
||||
aiResponse: data.data.aiResponse || data.data.response,
|
||||
audioUrl: data.data.audioUrl || data.data.url
|
||||
userText: userText,
|
||||
aiResponse: cleanedAiResponse,
|
||||
audioUrl: audioUrl
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -550,5 +709,256 @@ export const voiceAPI = {
|
||||
}
|
||||
};
|
||||
|
||||
// 充值相关API
|
||||
export const rechargeAPI = {
|
||||
// 获取用户余额
|
||||
getUserBalance: async () => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/api/recharge/balance',
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取用户余额失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 创建充值订单
|
||||
createRechargeOrder: async (orderData) => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/api/recharge/create-order',
|
||||
method: 'POST',
|
||||
data: {
|
||||
amount: orderData.amount,
|
||||
paymentMethod: orderData.paymentMethod || 'wechat',
|
||||
bonusAmount: 0 // 已取消赠送服务
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('创建充值订单失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 查询订单状态
|
||||
getOrderStatus: async (orderId) => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: `/api/recharge/order-status/${orderId}`,
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('查询订单状态失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 获取充值记录
|
||||
getRechargeHistory: async (params = {}) => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/api/recharge/history',
|
||||
method: 'GET',
|
||||
data: {
|
||||
page: params.page || 1,
|
||||
pageSize: params.pageSize || 10,
|
||||
startDate: params.startDate,
|
||||
endDate: params.endDate
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取充值记录失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 角色相关API
|
||||
export const roleAPI = {
|
||||
// 获取角色列表
|
||||
getRoles: async () => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/api/role/query',
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取角色列表失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 获取角色详情
|
||||
getRoleById: async (roleId) => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: `/api/role/query?roleId=${roleId}`,
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取角色详情失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 配置相关API
|
||||
export const configAPI = {
|
||||
// 获取所有配置
|
||||
getAllConfigs: async () => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/app/config/query',
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取所有配置失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 获取LLM模型配置
|
||||
getModels: async () => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/app/config/models',
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取LLM模型配置失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 获取STT配置
|
||||
getSTTConfigs: async () => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/app/config/stt',
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取STT配置失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 获取模板配置
|
||||
getTemplates: async () => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/app/config/templates',
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取模板配置失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 获取TTS配置
|
||||
getTTSConfigs: async () => {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/app/config/tts',
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取TTS配置失败:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 导出默认请求方法
|
||||
export default request;
|
||||
|
||||
Reference in New Issue
Block a user