mirror of
https://github.com/Funkoala14/knowledgebase_law.git
synced 2025-06-08 05:28:15 +08:00
184 lines
7.4 KiB
JavaScript
184 lines
7.4 KiB
JavaScript
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.list || { items: [], status: 'idle', error: null });
|
||
const operationStatus = useSelector((state) => state.chat.createSession?.status);
|
||
const operationError = useSelector((state) => state.chat.createSession?.error);
|
||
|
||
// 判断是否在知识库选择页面
|
||
const isNewChatView = !chatId;
|
||
|
||
// 获取聊天记录列表
|
||
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'}
|
||
isNewChatView={isNewChatView}
|
||
/>
|
||
</div>
|
||
|
||
{/* Main Content */}
|
||
<div
|
||
className='chat-main col-md-9 col-lg-10 p-0'
|
||
style={{ height: 'calc(100vh - 84px)', overflowY: 'auto' }}
|
||
>
|
||
{isNewChatView ? <NewChat /> : <ChatWindow chatId={chatId} knowledgeBaseId={knowledgeBaseId} />}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|