import React, { useState, useEffect, useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { showNotification } from '../../store/notification.slice'; import { fetchKnowledgeBases, searchKnowledgeBases, createKnowledgeBase, deleteKnowledgeBase, requestKnowledgeBaseAccess, } from '../../store/knowledgeBase/knowledgeBase.thunks'; import { clearSearchResults } from '../../store/knowledgeBase/knowledgeBase.slice'; import SvgIcon from '../../components/SvgIcon'; import AccessRequestModal from '../../components/AccessRequestModal'; import CreateKnowledgeBaseModal from '../../components/CreateKnowledgeBaseModal'; import Pagination from '../../components/Pagination'; import SearchBar from '../../components/SearchBar'; import ApiModeSwitch from '../../components/ApiModeSwitch'; // 导入拆分的组件 import KnowledgeBaseList from './components/KnowledgeBaseList'; export default function KnowledgeBase() { const dispatch = useDispatch(); const navigate = useNavigate(); const [showCreateModal, setShowCreateModal] = useState(false); const [showAccessRequestModal, setShowAccessRequestModal] = useState(false); const [formErrors, setFormErrors] = useState({}); const [accessRequestKnowledgeBase, setAccessRequestKnowledgeBase] = useState({ id: '', title: '', }); const [isSubmittingRequest, setIsSubmittingRequest] = useState(false); const [createdKnowledgeBaseId, setCreatedKnowledgeBaseId] = useState(null); // 获取当前用户信息 const currentUser = useSelector((state) => state.auth.user); const [newKnowledgeBase, setNewKnowledgeBase] = useState({ name: '', desc: '', type: 'private', // 默认为私有知识库 department: currentUser?.department || '', group: currentUser?.group || '', }); // Search state const [searchKeyword, setSearchKeyword] = useState(''); const [isSearchDropdownOpen, setIsSearchDropdownOpen] = useState(false); // Pagination state const [pagination, setPagination] = useState({ page: 1, page_size: 10, }); // Get knowledge bases from Redux store // 更新为新的Redux状态结构 const knowledgeBases = useSelector((state) => state.knowledgeBase.knowledgeBases); const loading = useSelector((state) => state.knowledgeBase.loading); const paginationData = useSelector((state) => state.knowledgeBase.pagination); const error = useSelector((state) => state.knowledgeBase.error); const operationStatus = useSelector((state) => state.knowledgeBase.editStatus); const operationError = useSelector((state) => state.knowledgeBase.error); // 从Redux获取搜索结果和加载状态 const searchResults = useSelector((state) => state.knowledgeBase.searchResults); const searchLoading = useSelector((state) => state.knowledgeBase.searchLoading); // Fetch knowledge bases when component mounts or pagination changes useEffect(() => { // 无论是否在搜索,都正常获取知识库列表 dispatch(fetchKnowledgeBases(pagination)); }, [dispatch, pagination.page, pagination.page_size]); // Show loading state while fetching data const isLoading = loading; // Show error notification if fetch fails useEffect(() => { if (!isLoading && error) { dispatch( showNotification({ message: `获取知识库列表失败: ${error.message || error}`, type: 'danger', }) ); } }, [isLoading, error, dispatch]); // Show notification for operation status useEffect(() => { if (operationStatus === 'successful') { // 操作成功通知由具体函数处理,这里只刷新列表 // Refresh the list after successful operation dispatch(fetchKnowledgeBases(pagination)); } else if (operationStatus === 'failed' && operationError) { dispatch( showNotification({ message: `操作失败: ${operationError.message || operationError}`, type: 'danger', }) ); } }, [operationStatus, operationError, dispatch, pagination]); // Handle search input change const handleSearchInputChange = (e) => { const value = e.target.value; console.log('搜索框输入值:', value); setSearchKeyword(value); // 如果搜索框清空,关闭下拉框 if (!value.trim()) { dispatch(clearSearchResults()); setIsSearchDropdownOpen(false); } }; // Handle search submit - 只影响下拉框,不影响主列表 const handleSearch = (e) => { e.preventDefault(); if (searchKeyword.trim()) { // 只设置下拉框搜索状态,不设置全局isSearching状态 dispatch( searchKnowledgeBases({ keyword: searchKeyword, page: 1, page_size: 5, // 下拉框只显示少量结果 }) ); setIsSearchDropdownOpen(true); } else { // 清空搜索及关闭下拉框 handleClearSearch(); } }; // Handle clear search const handleClearSearch = () => { setSearchKeyword(''); // 不影响主列表显示,只关闭下拉框 setIsSearchDropdownOpen(false); dispatch(clearSearchResults()); }; // Handle pagination change const handlePageChange = (newPage) => { setPagination((prev) => ({ ...prev, page: newPage, })); }; // Handle page size change const handlePageSizeChange = (newPageSize) => { setPagination({ page: 1, // Reset to first page when changing page size page_size: newPageSize, }); }; const handleInputChange = (e) => { const { name, value } = e.target; const isAdmin = currentUser?.role === 'admin'; const isLeader = currentUser?.role === 'leader'; // 根据用户角色允许修改部门和组别字段 if (name === 'department' || name === 'group') { // 仅管理员可以修改部门 if (name === 'department' && !isAdmin) { return; } // 仅管理员和组长可以修改组别 if (name === 'group' && !isAdmin && !isLeader) { return; } // 更新字段值 setNewKnowledgeBase((prev) => ({ ...prev, [name]: value, })); // 如果更新部门,重置组别 if (name === 'department') { setNewKnowledgeBase((prev) => ({ ...prev, group: '', // 部门变更时重置组别 })); } return; } // 检查用户是否有权限选择指定的知识库类型 if (name === 'type') { const role = currentUser?.role; let allowed = false; // 根据角色判断可以选择的知识库类型 if (role === 'admin') { // 管理员可以选择任何类型 allowed = ['admin', 'leader', 'member', 'private', 'secret'].includes(value); } else if (role === 'leader') { // 组长只能选择 member 和 private allowed = ['admin', 'member', 'private'].includes(value); } else { // 普通成员只能选择 private allowed = ['admin', 'private'].includes(value); } if (!allowed) { dispatch( showNotification({ message: '您没有权限创建此类型的知识库', type: 'warning', }) ); return; } } setNewKnowledgeBase((prev) => ({ ...prev, [name]: value, })); // Clear error when user types if (formErrors[name]) { setFormErrors((prev) => ({ ...prev, [name]: '', })); } }; const validateCreateForm = () => { const errors = {}; const isAdmin = currentUser?.role === 'admin'; const isLeader = currentUser?.role === 'leader'; // 只有member类型知识库需要选择组别,私有知识库不需要 const needSelectGroup = newKnowledgeBase.type === 'member'; // 私有知识库不需要选择部门和组别 const isPrivate = newKnowledgeBase.type === 'private'; if (!newKnowledgeBase.name.trim()) { errors.name = '请输入知识库名称'; } if (!newKnowledgeBase.desc.trim()) { errors.desc = '请输入知识库描述'; } if (!newKnowledgeBase.type) { errors.type = '请选择知识库类型'; } // 对于member级别的知识库,检查是否选择了部门和组别 if (needSelectGroup && !isPrivate) { // 管理员必须选择部门 if (isAdmin && !newKnowledgeBase.department) { errors.department = '创建member级别知识库时必须选择部门'; } // 所有用户创建member级别知识库时必须选择组别 if (!newKnowledgeBase.group) { errors.group = '创建member级别知识库时必须选择组别'; } } setFormErrors(errors); return Object.keys(errors).length === 0; }; const handleCreateKnowledgeBase = async () => { // Validate form if (!validateCreateForm()) { return; } try { // 私有知识库不需要部门和组别信息 const isPrivate = newKnowledgeBase.type === 'private'; // Dispatch create knowledge base action const resultAction = await dispatch( createKnowledgeBase({ name: newKnowledgeBase.name, desc: newKnowledgeBase.desc, description: newKnowledgeBase.desc, type: newKnowledgeBase.type, department: !isPrivate ? newKnowledgeBase.department : '', group: !isPrivate ? newKnowledgeBase.group : '', }) ); console.log('创建知识库返回数据:', resultAction); // Check if the action was successful if (createKnowledgeBase.fulfilled.match(resultAction)) { console.log('创建成功,payload:', resultAction.payload); const { knowledge_base } = resultAction.payload; const { id } = knowledge_base; // Get ID from payload and navigate if (id) { console.log('新知识库ID:', id); // 显示成功通知 dispatch( showNotification({ message: '知识库创建成功', type: 'success', }) ); // 直接导航到新创建的知识库详情页 navigate(`/knowledge-base/${id}`); } else { console.error('无法获取新知识库ID:', resultAction.payload); dispatch( showNotification({ message: '创建成功,但无法获取知识库ID', type: 'warning', }) ); } } else { console.error('创建知识库失败:', resultAction.error); dispatch( showNotification({ message: `创建知识库失败: ${resultAction.error?.message || '未知错误'}`, type: 'danger', }) ); } } catch (error) { console.error('创建知识库出错:', error); dispatch( showNotification({ message: `创建知识库出错: ${error.message || '未知错误'}`, type: 'danger', }) ); } // Reset form and close modal setNewKnowledgeBase({ name: '', desc: '', type: 'private', department: '', group: '' }); setFormErrors({}); setShowCreateModal(false); }; // Handle card click to navigate to knowledge base detail const handleCardClick = (id, permissions) => { // 检查用户是否有读取权限 if (!permissions || permissions.can_read === false) { dispatch( showNotification({ message: '您没有访问此知识库的权限,请先申请权限', type: 'warning', }) ); return; } // 有权限则跳转到详情页 navigate(`/knowledge-base/${id}/datasets`); }; const handleRequestAccess = (id, title) => { setAccessRequestKnowledgeBase({ id, title, }); setShowAccessRequestModal(true); }; const handleSubmitAccessRequest = async (requestData) => { setIsSubmittingRequest(true); try { // 使用权限服务发送请求 - 通过dispatch调用thunk await dispatch(requestKnowledgeBaseAccess(requestData)).unwrap(); // Close modal after success setShowAccessRequestModal(false); } catch (error) { dispatch( showNotification({ message: `权限申请失败: ${error.response?.data?.message || '请稍后重试'}`, type: 'danger', }) ); } finally { setIsSubmittingRequest(false); } }; const handleDelete = (e, id) => { e.preventDefault(); e.stopPropagation(); // Dispatch delete knowledge base action dispatch(deleteKnowledgeBase(id)) .unwrap() .then(() => { dispatch( showNotification({ message: '知识库已删除', type: 'success', }) ); // 不需要重新获取知识库列表,Redux store 已经在 reducer 中更新 }) .catch((error) => { dispatch( showNotification({ message: `删除失败: ${error || '未知错误'}`, type: 'danger', }) ); }); }; // Calculate total pages const totalPages = Math.ceil(paginationData.total / pagination.page_size); // 打开创建知识库弹窗 const handleOpenCreateModal = () => { const isAdmin = currentUser?.role === 'admin'; const isLeader = currentUser?.role === 'leader'; // 默认知识库类型设为公共知识库 let defaultType = 'admin'; // 初始部门和组别 let department = currentUser?.department || ''; let group = currentUser?.group || ''; setNewKnowledgeBase({ name: '', desc: '', type: defaultType, department: department, group: group, }); setFormErrors({}); setShowCreateModal(true); }; // 处理点击搜索结果 const handleSearchResultClick = (id, permissions) => { if (permissions?.can_read) { navigate(`/knowledge-base/${id}/datasets`); } }; return (