Files
TERES_web_frontend/src/pages/knowledge/KnowledgeBaseList.tsx

263 lines
7.4 KiB
TypeScript
Raw Normal View History

import React, { useState, useCallback, useMemo } from 'react';
import {
Box,
Typography,
TextField,
Select,
MenuItem,
FormControl,
InputLabel,
Button,
InputAdornment,
Pagination,
Stack,
CircularProgress,
} from '@mui/material';
import {
Search as SearchIcon,
Add as AddIcon,
Refresh as RefreshIcon,
} from '@mui/icons-material';
import { useNavigate } from 'react-router-dom';
import { useKnowledgeList } from '@/hooks/knowledge_hooks';
import { useUserData } from '@/hooks/useUserData';
import KnowledgeGridView from '@/components/KnowledgeGridView';
import type { IKnowledge } from '@/interfaces/database/knowledge';
const KnowledgeBaseList: React.FC = () => {
const navigate = useNavigate();
// 搜索和筛选状态
const [searchTerm, setSearchTerm] = useState('');
const [teamFilter, setTeamFilter] = useState('all');
const pageSize = 12; // 每页显示12个知识库
// 获取用户数据(包含租户列表)
const { tenantList } = useUserData();
// 使用knowledge_hooks获取数据
const {
knowledgeBases,
total,
loading,
error,
currentPage,
setKeywords,
setCurrentPage,
refresh,
} = useKnowledgeList({
keywords: searchTerm,
page: 1,
page_size: pageSize,
});
// 处理搜索
const handleSearch = useCallback((value: string) => {
setSearchTerm(value);
setKeywords(value);
}, [setKeywords]);
// 处理团队筛选
const handleTeamFilterChange = useCallback((value: string) => {
setTeamFilter(value);
setCurrentPage(1); // 筛选时重置到第一页
}, [setCurrentPage]);
// 处理分页变化
const handlePageChange = useCallback((_: React.ChangeEvent<unknown>, page: number) => {
setCurrentPage(page);
}, [setCurrentPage]);
// 处理刷新
const handleRefresh = useCallback(() => {
refresh();
}, [refresh]);
// 处理创建知识库
const handleCreateKnowledge = useCallback(() => {
navigate('/knowledge/create');
}, [navigate]);
// 处理编辑知识库
const handleEditKnowledge = useCallback((kb: IKnowledge) => {
navigate(`/knowledge/${kb.id}/edit`);
}, [navigate]);
// 处理查看知识库详情
const handleViewKnowledge = useCallback((kb: IKnowledge) => {
navigate(`/knowledge/${kb.id}`);
}, [navigate]);
// 处理删除知识库
const handleDeleteKnowledge = useCallback((kb: IKnowledge) => {
// TODO: 实现删除逻辑
console.log('删除知识库:', kb.id);
}, []);
// 根据团队筛选过滤知识库
const filteredKnowledgeBases = useMemo(() => {
if (!knowledgeBases) return [];
if (teamFilter === 'all') {
return knowledgeBases;
}
// 根据租户ID筛选
if (teamFilter !== 'all') {
return knowledgeBases.filter(kb => {
// 如果选择的是特定租户ID则筛选该租户的知识库
if (teamFilter === 'me') {
// 假设'me'表示当前用户的知识库,这里可以根据实际业务逻辑调整
return kb.permission === 'me' || kb.tenant_id === tenantList?.[0].tenant_id;
}
// 如果是具体的租户ID
return kb.tenant_id === teamFilter;
});
}
return knowledgeBases;
}, [knowledgeBases, teamFilter, tenantList]);
// 计算总页数(基于筛选后的结果)
const totalPages = Math.ceil(filteredKnowledgeBases.length / pageSize);
// 获取当前页的数据
const currentPageData = useMemo(() => {
const startIndex = (currentPage - 1) * pageSize;
const endIndex = startIndex + pageSize;
return filteredKnowledgeBases.slice(startIndex, endIndex);
}, [filteredKnowledgeBases, currentPage, pageSize]);
// 构建团队筛选选项
const teamFilterOptions = useMemo(() => {
const options = [
{ value: 'all', label: '全部' },
];
// 添加租户选项
if (tenantList && tenantList.length > 0) {
tenantList.forEach(tenant => {
options.push({
value: tenant.tenant_id,
label: tenant.nickname || tenant.tenant_id,
});
});
}
return options;
}, [tenantList]);
return (
<Box sx={{ p: 3 }}>
{/* 页面标题 */}
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
<Typography variant="h4" fontWeight={600}>
</Typography>
<Button
variant="contained"
startIcon={<AddIcon />}
onClick={handleCreateKnowledge}
sx={{ borderRadius: 2 }}
>
</Button>
</Box>
{/* 搜索和筛选区域 */}
<Box sx={{ display: 'flex', gap: 2, mb: 3, alignItems: 'center' }}>
<TextField
placeholder="搜索知识库..."
value={searchTerm}
onChange={(e) => handleSearch(e.target.value)}
sx={{ flex: 1, maxWidth: 400 }}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
<FormControl sx={{ minWidth: 120 }}>
<InputLabel></InputLabel>
<Select
value={teamFilter}
label="团队筛选"
onChange={(e) => handleTeamFilterChange(e.target.value)}
>
{teamFilterOptions.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
<Button
variant="outlined"
startIcon={<RefreshIcon />}
onClick={handleRefresh}
disabled={loading}
>
</Button>
</Box>
{/* 错误提示 */}
{error && (
<Box sx={{ mb: 3, p: 2, bgcolor: 'error.light', borderRadius: 1 }}>
<Typography color="error">
: {error}
</Typography>
</Box>
)}
{/* 加载状态 */}
{loading && (
<Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
<CircularProgress />
</Box>
)}
{/* 知识库列表 */}
{!loading && (
<>
<KnowledgeGridView
knowledgeBases={currentPageData}
onEdit={handleEditKnowledge}
onDelete={handleDeleteKnowledge}
onView={handleViewKnowledge}
loading={loading}
searchTerm={searchTerm}
teamFilter={teamFilter}
onCreateKnowledge={handleCreateKnowledge}
/>
{/* 分页组件 */}
{totalPages > 1 && (
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 4 }}>
<Stack spacing={2}>
<Pagination
count={totalPages}
page={currentPage}
onChange={handlePageChange}
color="primary"
size="large"
showFirstButton
showLastButton
/>
<Typography variant="body2" color="text.secondary" textAlign="center">
{filteredKnowledgeBases.length} {currentPage} {totalPages}
</Typography>
</Stack>
</Box>
)}
</>
)}
</Box>
);
};
export default KnowledgeBaseList;