2025-04-16 09:51:27 +08:00
|
|
|
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
|
|
|
|
import { get, post, put, del, streamRequest } from '../../services/api';
|
|
|
|
|
import { showNotification } from '../notification.slice';
|
2025-04-18 08:38:06 +08:00
|
|
|
|
import { addMessage, updateMessage, setActiveChat } from './chat.slice';
|
2025-04-16 09:51:27 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取聊天列表
|
|
|
|
|
* @param {Object} params - 查询参数
|
|
|
|
|
* @param {number} params.page - 页码
|
|
|
|
|
* @param {number} params.page_size - 每页数量
|
|
|
|
|
*/
|
|
|
|
|
export const fetchChats = createAsyncThunk('chat/fetchChats', async (params = {}, { rejectWithValue }) => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await get('/chat-history/', { params });
|
|
|
|
|
|
|
|
|
|
// 处理返回格式
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
return {
|
|
|
|
|
results: response.data.results,
|
|
|
|
|
total: response.data.total,
|
|
|
|
|
page: response.data.page || 1,
|
|
|
|
|
page_size: response.data.page_size || 10,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { results: [], total: 0, page: 1, page_size: 10 };
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error fetching chats:', error);
|
|
|
|
|
return rejectWithValue(error.response?.data?.message || 'Failed to fetch chats');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 更新聊天
|
2025-04-18 08:38:06 +08:00
|
|
|
|
* 更新已经发送出去的聊天,获得新的回复,相当于编辑以往的聊天记录。暂时未使用
|
2025-04-16 09:51:27 +08:00
|
|
|
|
* @param {Object} params - 更新参数
|
|
|
|
|
* @param {string} params.id - 聊天ID
|
|
|
|
|
* @param {Object} params.data - 更新数据
|
|
|
|
|
*/
|
|
|
|
|
export const updateChat = createAsyncThunk('chat/updateChat', async ({ id, data }, { rejectWithValue }) => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await put(`/chat-history/${id}/`, data);
|
|
|
|
|
|
|
|
|
|
// 处理返回格式
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
return response.data.chat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data?.chat || {};
|
|
|
|
|
} catch (error) {
|
|
|
|
|
return rejectWithValue(error.response?.data?.message || 'Failed to update chat');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 删除聊天
|
|
|
|
|
* @param {string} conversationId - 聊天ID
|
|
|
|
|
*/
|
|
|
|
|
export const deleteChat = createAsyncThunk('chat/deleteChat', async (conversationId, { rejectWithValue }) => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await del(`/chat-history/delete_conversation?conversation_id=${conversationId}`);
|
|
|
|
|
|
|
|
|
|
// 处理返回格式
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
return conversationId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return conversationId;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error deleting chat:', error);
|
|
|
|
|
return rejectWithValue(error.response?.data?.message || '删除聊天失败');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取可用于聊天的知识库列表
|
|
|
|
|
*/
|
|
|
|
|
export const fetchAvailableDatasets = createAsyncThunk(
|
|
|
|
|
'chat/fetchAvailableDatasets',
|
|
|
|
|
async (_, { rejectWithValue }) => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await get('/chat-history/available_datasets/');
|
|
|
|
|
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
return response.data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rejectWithValue('获取可用知识库列表失败');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error fetching available datasets:', error);
|
|
|
|
|
return rejectWithValue(error.response?.data?.message || '获取可用知识库列表失败');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
2025-04-18 08:38:06 +08:00
|
|
|
|
* 创建/继续聊天
|
|
|
|
|
* 创建新会话,或者继续一个已有的会话,根据conversation_id来更新
|
2025-04-16 09:51:27 +08:00
|
|
|
|
* @param {Object} params - 聊天参数
|
|
|
|
|
* @param {string[]} params.dataset_id_list - 知识库ID列表
|
|
|
|
|
* @param {string} params.question - 用户问题
|
|
|
|
|
* @param {string} params.conversation_id - 会话ID,可选
|
|
|
|
|
*/
|
|
|
|
|
export const createChatRecord = createAsyncThunk(
|
|
|
|
|
'chat/createChatRecord',
|
|
|
|
|
async ({ question, conversation_id, dataset_id_list }, { dispatch, getState, rejectWithValue }) => {
|
|
|
|
|
try {
|
|
|
|
|
// 构建请求数据
|
|
|
|
|
const requestBody = {
|
|
|
|
|
question,
|
|
|
|
|
dataset_id_list,
|
|
|
|
|
conversation_id,
|
|
|
|
|
};
|
|
|
|
|
console.log('准备发送聊天请求:', requestBody);
|
|
|
|
|
|
|
|
|
|
// 先添加用户消息到聊天窗口
|
|
|
|
|
const userMessageId = Date.now().toString();
|
2025-04-18 08:38:06 +08:00
|
|
|
|
const userMessage = {
|
|
|
|
|
id: userMessageId,
|
|
|
|
|
role: 'user',
|
|
|
|
|
content: question,
|
|
|
|
|
created_at: new Date().toISOString(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 添加用户消息
|
2025-04-16 09:51:27 +08:00
|
|
|
|
dispatch(
|
|
|
|
|
addMessage({
|
2025-04-18 08:38:06 +08:00
|
|
|
|
conversationId: conversation_id,
|
|
|
|
|
message: userMessage,
|
2025-04-16 09:51:27 +08:00
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 添加临时的助手消息(流式传输期间显示)
|
|
|
|
|
const assistantMessageId = (Date.now() + 1).toString();
|
2025-04-18 08:38:06 +08:00
|
|
|
|
const assistantMessage = {
|
|
|
|
|
id: assistantMessageId,
|
|
|
|
|
role: 'assistant',
|
|
|
|
|
content: '',
|
|
|
|
|
created_at: new Date().toISOString(),
|
|
|
|
|
is_streaming: true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 添加助手消息
|
2025-04-16 09:51:27 +08:00
|
|
|
|
dispatch(
|
|
|
|
|
addMessage({
|
2025-04-18 08:38:06 +08:00
|
|
|
|
conversationId: conversation_id,
|
|
|
|
|
message: assistantMessage,
|
2025-04-16 09:51:27 +08:00
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let finalMessage = '';
|
|
|
|
|
let conversationId = conversation_id;
|
|
|
|
|
|
|
|
|
|
// 使用流式请求函数处理
|
|
|
|
|
const result = await streamRequest(
|
|
|
|
|
'/chat-history/',
|
|
|
|
|
requestBody,
|
|
|
|
|
// 处理每个数据块
|
|
|
|
|
(chunkText) => {
|
|
|
|
|
try {
|
|
|
|
|
const data = JSON.parse(chunkText);
|
|
|
|
|
console.log('收到聊天数据块:', data);
|
|
|
|
|
|
|
|
|
|
if (data.code === 200) {
|
|
|
|
|
// 保存会话ID (无论消息类型,只要找到会话ID就保存)
|
|
|
|
|
if (data.data && data.data.conversation_id && !conversationId) {
|
|
|
|
|
conversationId = data.data.conversation_id;
|
|
|
|
|
console.log('获取到会话ID:', conversationId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理各种可能的消息类型
|
|
|
|
|
const messageType = data.message;
|
|
|
|
|
|
|
|
|
|
// 处理部分内容更新
|
|
|
|
|
if ((messageType === 'partial' || messageType === '部分') && data.data) {
|
|
|
|
|
// 累加内容
|
|
|
|
|
if (data.data.content !== undefined) {
|
|
|
|
|
finalMessage += data.data.content;
|
|
|
|
|
console.log('累加内容:', finalMessage);
|
|
|
|
|
|
2025-04-18 08:38:06 +08:00
|
|
|
|
// 获取服务器消息ID (如果存在)
|
|
|
|
|
const serverMessageId = data.data.id;
|
|
|
|
|
|
2025-04-16 09:51:27 +08:00
|
|
|
|
// 更新消息内容
|
|
|
|
|
dispatch(
|
|
|
|
|
updateMessage({
|
2025-04-18 08:38:06 +08:00
|
|
|
|
conversationId: conversationId,
|
|
|
|
|
messageId: assistantMessageId,
|
|
|
|
|
serverMessageId: serverMessageId,
|
|
|
|
|
updates: { content: finalMessage },
|
2025-04-16 09:51:27 +08:00
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理结束标志
|
|
|
|
|
if (data.data.is_end) {
|
|
|
|
|
console.log('检测到消息结束标志');
|
2025-04-18 08:38:06 +08:00
|
|
|
|
|
|
|
|
|
// 获取服务器消息ID (如果存在)
|
|
|
|
|
const serverMessageId = data.data.id;
|
|
|
|
|
|
2025-04-16 09:51:27 +08:00
|
|
|
|
dispatch(
|
|
|
|
|
updateMessage({
|
2025-04-18 08:38:06 +08:00
|
|
|
|
conversationId: conversationId,
|
|
|
|
|
messageId: assistantMessageId,
|
|
|
|
|
serverMessageId: serverMessageId,
|
|
|
|
|
updates: { is_streaming: false },
|
2025-04-16 09:51:27 +08:00
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 处理开始流式传输的消息
|
|
|
|
|
else if (messageType === '开始流式传输' || messageType === 'start_streaming') {
|
|
|
|
|
console.log('开始流式传输,会话ID:', data.data?.conversation_id);
|
|
|
|
|
}
|
|
|
|
|
// 处理完成消息
|
|
|
|
|
else if (
|
|
|
|
|
messageType === 'completed' ||
|
|
|
|
|
messageType === '完成' ||
|
|
|
|
|
messageType === 'end_streaming' ||
|
|
|
|
|
messageType === '结束流式传输'
|
|
|
|
|
) {
|
|
|
|
|
console.log('收到完成消息');
|
2025-04-18 08:38:06 +08:00
|
|
|
|
// 获取服务器消息ID (如果存在)
|
|
|
|
|
const serverMessageId = data.data?.id;
|
|
|
|
|
|
2025-04-16 09:51:27 +08:00
|
|
|
|
dispatch(
|
|
|
|
|
updateMessage({
|
2025-04-18 08:38:06 +08:00
|
|
|
|
conversationId: conversationId,
|
|
|
|
|
messageId: assistantMessageId,
|
|
|
|
|
serverMessageId: serverMessageId,
|
|
|
|
|
updates: { is_streaming: false },
|
2025-04-16 09:51:27 +08:00
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
// 其他类型的消息
|
|
|
|
|
else {
|
|
|
|
|
console.log('收到其他类型消息:', messageType);
|
|
|
|
|
// 如果有content字段,也尝试更新
|
|
|
|
|
if (data.data && data.data.content !== undefined) {
|
|
|
|
|
finalMessage += data.data.content;
|
2025-04-18 08:38:06 +08:00
|
|
|
|
// 获取服务器消息ID (如果存在)
|
|
|
|
|
const serverMessageId = data.data.id;
|
|
|
|
|
|
2025-04-16 09:51:27 +08:00
|
|
|
|
dispatch(
|
|
|
|
|
updateMessage({
|
2025-04-18 08:38:06 +08:00
|
|
|
|
conversationId: conversationId,
|
|
|
|
|
messageId: assistantMessageId,
|
|
|
|
|
serverMessageId: serverMessageId,
|
|
|
|
|
updates: { content: finalMessage },
|
2025-04-16 09:51:27 +08:00
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.warn('收到非成功状态码:', data.code, data.message);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('解析或处理JSON失败:', error, '原始数据:', chunkText);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 处理错误
|
|
|
|
|
(error) => {
|
|
|
|
|
console.error('流式请求错误:', error);
|
|
|
|
|
dispatch(
|
|
|
|
|
updateMessage({
|
2025-04-18 08:38:06 +08:00
|
|
|
|
conversationId: conversationId,
|
|
|
|
|
messageId: assistantMessageId,
|
|
|
|
|
updates: {
|
|
|
|
|
content: `错误: ${error.message || '请求失败'}`,
|
|
|
|
|
is_streaming: false,
|
|
|
|
|
},
|
2025-04-16 09:51:27 +08:00
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 确保流式传输结束后标记消息已完成
|
|
|
|
|
dispatch(
|
|
|
|
|
updateMessage({
|
2025-04-18 08:38:06 +08:00
|
|
|
|
conversationId: conversationId,
|
|
|
|
|
messageId: assistantMessageId,
|
|
|
|
|
updates: { is_streaming: false },
|
2025-04-16 09:51:27 +08:00
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 返回会话信息
|
|
|
|
|
const chatInfo = {
|
|
|
|
|
conversation_id: conversationId || result.conversation_id,
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 如果聊天创建成功,添加到历史列表,并设置为当前激活聊天
|
|
|
|
|
if (chatInfo.conversation_id) {
|
|
|
|
|
// 获取知识库信息
|
|
|
|
|
const state = getState();
|
|
|
|
|
const availableDatasets = state.chat.availableDatasets.items || [];
|
2025-04-18 08:38:06 +08:00
|
|
|
|
const existingChats = state.chat.chats.items || [];
|
2025-04-16 09:51:27 +08:00
|
|
|
|
|
|
|
|
|
// 检查是否已存在此会话ID的记录
|
|
|
|
|
const existingChat = existingChats.find((chat) => chat.conversation_id === chatInfo.conversation_id);
|
|
|
|
|
|
|
|
|
|
// 只有在不存在相同会话ID的记录时才创建新的记录
|
|
|
|
|
if (!existingChat) {
|
|
|
|
|
console.log('创建新的聊天sidebar记录:', chatInfo.conversation_id);
|
|
|
|
|
|
|
|
|
|
// 创建一个新的聊天记录对象添加到历史列表
|
|
|
|
|
const newChatEntry = {
|
|
|
|
|
conversation_id: chatInfo.conversation_id,
|
|
|
|
|
datasets: dataset_id_list.map((id) => {
|
|
|
|
|
// 尝试查找知识库名称
|
|
|
|
|
const formattedId = id.includes('-')
|
|
|
|
|
? id
|
|
|
|
|
: id.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5');
|
|
|
|
|
const dataset = availableDatasets.find((ds) => ds.id === formattedId);
|
|
|
|
|
return {
|
|
|
|
|
id: formattedId,
|
|
|
|
|
name: dataset?.name || '新知识库对话',
|
|
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
create_time: new Date().toISOString(),
|
|
|
|
|
last_message: question,
|
|
|
|
|
message_count: 2, // 用户问题和助手回复
|
2025-04-18 08:38:06 +08:00
|
|
|
|
messages: [userMessage, assistantMessage], // 添加消息到聊天记录
|
2025-04-16 09:51:27 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 更新当前聊天
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'chat/fetchChats/fulfilled',
|
|
|
|
|
payload: {
|
|
|
|
|
results: [newChatEntry],
|
|
|
|
|
total: 1,
|
|
|
|
|
append: true, // 标记为追加,而不是替换
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.log('聊天sidebar记录已存在,不再创建:', chatInfo.conversation_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置为当前聊天
|
2025-04-18 08:38:06 +08:00
|
|
|
|
dispatch(setActiveChat(chatInfo.conversation_id));
|
2025-04-16 09:51:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return chatInfo;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('创建聊天记录失败:', error);
|
|
|
|
|
|
|
|
|
|
// 显示错误通知
|
|
|
|
|
dispatch(
|
|
|
|
|
showNotification({
|
|
|
|
|
message: `发送失败: ${error.message || '未知错误'}`,
|
|
|
|
|
type: 'danger',
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return rejectWithValue(error.message || '创建聊天记录失败');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取会话详情
|
|
|
|
|
* @param {string} conversationId - 会话ID
|
|
|
|
|
*/
|
|
|
|
|
export const fetchConversationDetail = createAsyncThunk(
|
|
|
|
|
'chat/fetchConversationDetail',
|
|
|
|
|
async (conversationId, { rejectWithValue, dispatch, getState }) => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await get('/chat-history/conversation_detail', {
|
|
|
|
|
params: { conversation_id: conversationId },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
return response.data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rejectWithValue('获取会话详情失败');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// 明确检查是否是404错误
|
|
|
|
|
const is404Error = error.response && error.response.status === 404;
|
|
|
|
|
|
|
|
|
|
if (is404Error) {
|
|
|
|
|
console.log('会话未找到,可能是新创建的会话:', conversationId);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.error('Error fetching conversation detail:', error);
|
|
|
|
|
return rejectWithValue(error.response?.data?.message || '获取会话详情失败');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
2025-04-18 08:38:06 +08:00
|
|
|
|
* 创建新会话(仅获取会话ID,相当于一个会话凭证,不发送消息)
|
2025-04-16 09:51:27 +08:00
|
|
|
|
* @param {Object} params - 参数
|
|
|
|
|
* @param {string[]} params.dataset_id_list - 知识库ID列表
|
|
|
|
|
*/
|
|
|
|
|
export const createConversation = createAsyncThunk(
|
|
|
|
|
'chat/createConversation',
|
|
|
|
|
async ({ dataset_id_list }, { dispatch, getState, rejectWithValue }) => {
|
|
|
|
|
try {
|
|
|
|
|
console.log('创建新会话,知识库ID列表:', dataset_id_list);
|
|
|
|
|
const params = {
|
|
|
|
|
dataset_id_list: dataset_id_list,
|
|
|
|
|
};
|
|
|
|
|
const response = await post('/chat-history/create_conversation/', params);
|
|
|
|
|
|
|
|
|
|
if (response && response.code === 200) {
|
|
|
|
|
const conversationData = response.data;
|
|
|
|
|
console.log('会话创建成功:', conversationData);
|
|
|
|
|
|
|
|
|
|
// 获取知识库信息
|
|
|
|
|
const state = getState();
|
|
|
|
|
const availableDatasets = state.chat.availableDatasets.items || [];
|
|
|
|
|
|
|
|
|
|
// 创建一个新的聊天记录对象添加到历史列表
|
|
|
|
|
const newChatEntry = {
|
|
|
|
|
conversation_id: conversationData.conversation_id,
|
|
|
|
|
datasets: dataset_id_list.map((id) => {
|
|
|
|
|
// 尝试查找知识库名称
|
|
|
|
|
const formattedId = id.includes('-')
|
|
|
|
|
? id
|
|
|
|
|
: id.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5');
|
|
|
|
|
const dataset = availableDatasets.find((ds) => ds.id === formattedId);
|
|
|
|
|
return {
|
|
|
|
|
id: formattedId,
|
|
|
|
|
name: dataset?.name || '新知识库对话',
|
|
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
create_time: new Date().toISOString(),
|
|
|
|
|
last_message: '',
|
|
|
|
|
message_count: 0,
|
2025-04-18 08:38:06 +08:00
|
|
|
|
messages: [], // 初始化空消息数组
|
2025-04-16 09:51:27 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 更新聊天历史列表
|
|
|
|
|
dispatch({
|
|
|
|
|
type: 'chat/fetchChats/fulfilled',
|
|
|
|
|
payload: {
|
|
|
|
|
results: [newChatEntry],
|
|
|
|
|
total: 1,
|
|
|
|
|
append: true, // 标记为追加,而不是替换
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 设置为当前聊天
|
2025-04-18 08:38:06 +08:00
|
|
|
|
dispatch(setActiveChat(conversationData.conversation_id));
|
2025-04-16 09:51:27 +08:00
|
|
|
|
|
|
|
|
|
return conversationData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rejectWithValue('创建会话失败');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('创建会话失败:', error);
|
|
|
|
|
|
|
|
|
|
// 显示错误通知
|
|
|
|
|
dispatch(
|
|
|
|
|
showNotification({
|
|
|
|
|
message: `创建会话失败: ${error.message || '未知错误'}`,
|
|
|
|
|
type: 'danger',
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return rejectWithValue(error.message || '创建会话失败');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|