knowledgebase_law/src/pages/Chat/Chat.jsx

184 lines
7.4 KiB
React
Raw Normal View History

2025-04-11 23:47:09 +08:00
import React, { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { fetchChats, deleteChat, createChatRecord, createConversation } from '../../store/chat/chat.thunks';
import { showNotification } from '../../store/notification.slice';
import ChatSidebar from './ChatSidebar';
import NewChat from './NewChat';
import ChatWindow from './ChatWindow';
export default function Chat() {
const { knowledgeBaseId, chatId } = useParams();
const navigate = useNavigate();
const dispatch = useDispatch();
// 从 Redux store 获取聊天记录列表
const {
items: chatHistory,
status,
error,
} = useSelector((state) => state.chat.history || { items: [], status: 'idle', error: null });
const operationStatus = useSelector((state) => state.chat.createSession?.status);
const operationError = useSelector((state) => state.chat.createSession?.error);
2025-04-13 01:32:20 +08:00
// 判断是否在知识库选择页面
const isNewChatView = !chatId;
2025-04-11 23:47:09 +08:00
// 获取聊天记录列表
useEffect(() => {
dispatch(fetchChats({ page: 1, page_size: 20 }));
}, [dispatch]);
// 监听操作状态,显示通知
useEffect(() => {
if (operationStatus === 'succeeded') {
dispatch(
showNotification({
message: '操作成功',
type: 'success',
})
);
} else if (operationStatus === 'failed' && operationError) {
dispatch(
showNotification({
message: `操作失败: ${operationError}`,
type: 'danger',
})
);
}
}, [operationStatus, operationError, dispatch]);
// If we have a knowledgeBaseId but no chatId, check if we have an existing chat or create a new one
useEffect(() => {
// 只有当 knowledgeBaseId 存在但 chatId 不存在,且聊天历史已加载完成时才执行
if (knowledgeBaseId && !chatId && status === 'succeeded' && !status.includes('loading')) {
console.log('Chat.jsx: 检查是否需要创建聊天...');
// 处理可能的多个知识库ID (以逗号分隔)
const knowledgeBaseIds = knowledgeBaseId.split(',').map((id) => id.trim());
console.log('Chat.jsx: 处理知识库ID列表:', knowledgeBaseIds);
// 检查是否存在包含所有选中知识库的聊天记录
const existingChat = chatHistory.find((chat) => {
// 没有datasets属性或不是数组跳过
if (!chat.datasets || !Array.isArray(chat.datasets)) {
return false;
}
// 获取当前聊天记录中的知识库ID列表
const chatDatasetIds = chat.datasets.map((ds) => ds.id);
// 检查所有选中的知识库是否都包含在这个聊天中
// 并且聊天中的知识库数量要和选中的相同(完全匹配)
return (
knowledgeBaseIds.length === chatDatasetIds.length &&
knowledgeBaseIds.every((id) => chatDatasetIds.includes(id))
);
});
console.log('Chat.jsx: existingChat', existingChat);
if (existingChat) {
console.log(
`Chat.jsx: 找到现有聊天记录,导航到 /chat/${knowledgeBaseId}/${existingChat.conversation_id}`
);
// 找到现有聊天记录,导航到该聊天页面
navigate(`/chat/${knowledgeBaseId}/${existingChat.conversation_id}`);
} else {
console.log('Chat.jsx: 创建新聊天...');
// 创建新聊天 - 使用新的API创建会话
dispatch(
createConversation({
dataset_id_list: knowledgeBaseIds,
})
)
.unwrap()
.then((response) => {
// 创建成功使用返回的conversation_id导航
if (response && response.conversation_id) {
console.log(
`Chat.jsx: 创建成功,导航到 /chat/${knowledgeBaseId}/${response.conversation_id}`
);
navigate(`/chat/${knowledgeBaseId}/${response.conversation_id}`);
} else {
// 错误处理
console.error('Chat.jsx: 创建失败未能获取会话ID');
dispatch(
showNotification({
message: '创建聊天失败未能获取会话ID',
type: 'danger',
})
);
}
})
.catch((error) => {
console.error('Chat.jsx: 创建失败', error);
dispatch(
showNotification({
message: `创建聊天失败: ${error}`,
type: 'danger',
})
);
});
}
}
}, [knowledgeBaseId, chatId, chatHistory, status, navigate, dispatch]);
const handleDeleteChat = (id) => {
// 调用 Redux action 删除聊天
dispatch(deleteChat(id))
.unwrap()
.then(() => {
// 删除成功后显示通知
dispatch(
showNotification({
message: '聊天记录已删除',
type: 'success',
})
);
// If the deleted chat is the current one, navigate to the chat list
if (chatId === id) {
navigate('/chat');
}
})
.catch((error) => {
// 删除失败显示错误通知
dispatch(
showNotification({
message: `删除失败: ${error}`,
type: 'danger',
})
);
});
};
return (
<div className='chat-container container-fluid'>
<div className='row h-100'>
{/* Sidebar */}
<div
className='col-md-3 col-lg-2 p-0 border-end'
style={{ height: 'calc(100vh - 84px)', overflowY: 'auto' }}
>
<ChatSidebar
chatHistory={chatHistory}
onDeleteChat={handleDeleteChat}
isLoading={status === 'loading'}
hasError={status === 'failed'}
2025-04-13 01:32:20 +08:00
isNewChatView={isNewChatView}
2025-04-11 23:47:09 +08:00
/>
</div>
{/* Main Content */}
<div
className='chat-main col-md-9 col-lg-10 p-0'
style={{ height: 'calc(100vh - 84px)', overflowY: 'auto' }}
>
2025-04-13 01:32:20 +08:00
{isNewChatView ? <NewChat /> : <ChatWindow chatId={chatId} knowledgeBaseId={knowledgeBaseId} />}
2025-04-11 23:47:09 +08:00
</div>
</div>
</div>
);
}