feat:完成dify知识库文档基础CRUD模块
This commit is contained in:
@@ -1,30 +1,18 @@
|
||||
import { Layout, theme, message } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import DatasetSidebar from './sidebar';
|
||||
import { message, Spin } from 'antd';
|
||||
import DocumentList from './document-list';
|
||||
import type { Dataset, Document } from '~/api/dify-dataset';
|
||||
import { fetchDatasets, fetchDocuments } from '~/api/dify-dataset';
|
||||
import '../../styles/components/dify-dataset-manager/index.css';
|
||||
|
||||
const { Content } = Layout;
|
||||
|
||||
/**
|
||||
* 知识库管理主组件
|
||||
* 简化版 - 假设只有一个知识库,直接显示文档列表
|
||||
*/
|
||||
export default function DatasetManager() {
|
||||
// 主题
|
||||
const {
|
||||
token: { colorBgContainer },
|
||||
} = theme.useToken();
|
||||
|
||||
// 侧边栏状态
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
|
||||
// 知识库状态
|
||||
const [datasets, setDatasets] = useState<Dataset[]>([]);
|
||||
const [currentDatasetId, setCurrentDatasetId] = useState<string>('');
|
||||
const [loadingDatasets, setLoadingDatasets] = useState(true);
|
||||
const [dataset, setDataset] = useState<Dataset | null>(null);
|
||||
const [loadingDataset, setLoadingDataset] = useState(true);
|
||||
|
||||
// 文档状态
|
||||
const [documents, setDocuments] = useState<Document[]>([]);
|
||||
@@ -38,29 +26,29 @@ export default function DatasetManager() {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
/**
|
||||
* 加载知识库列表
|
||||
* 加载知识库(获取第一个知识库)
|
||||
*/
|
||||
const loadDatasets = async () => {
|
||||
setLoadingDatasets(true);
|
||||
const loadDataset = async () => {
|
||||
setLoadingDataset(true);
|
||||
try {
|
||||
console.log('[DatasetManager] 加载知识库列表...');
|
||||
const response = await fetchDatasets(1, 100);
|
||||
console.log('[DatasetManager] 知识库列表响应:', response);
|
||||
console.log('[DatasetManager] 加载知识库...');
|
||||
const response = await fetchDatasets(1, 1);
|
||||
console.log('[DatasetManager] 知识库响应:', response);
|
||||
|
||||
if (response && response.data) {
|
||||
setDatasets(response.data);
|
||||
|
||||
// 如果有知识库,默认选中第一个
|
||||
if (response.data.length > 0 && !currentDatasetId) {
|
||||
setCurrentDatasetId(response.data[0].id);
|
||||
}
|
||||
if (response && response.data && response.data.length > 0) {
|
||||
const firstDataset = response.data[0];
|
||||
setDataset(firstDataset);
|
||||
// 立即加载文档
|
||||
await loadDocuments(firstDataset.id, 1);
|
||||
} else {
|
||||
setError('未找到知识库,请先在Dify中创建知识库');
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error('[DatasetManager] 加载知识库列表失败:', err);
|
||||
setError(err.message || '加载知识库列表失败');
|
||||
message.error('加载知识库列表失败');
|
||||
console.error('[DatasetManager] 加载知识库失败:', err);
|
||||
setError(err.message || '加载知识库失败');
|
||||
message.error('加载知识库失败');
|
||||
} finally {
|
||||
setLoadingDatasets(false);
|
||||
setLoadingDataset(false);
|
||||
setInited(true);
|
||||
}
|
||||
};
|
||||
@@ -90,21 +78,13 @@ export default function DatasetManager() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理知识库选择
|
||||
*/
|
||||
const handleDatasetSelect = (datasetId: string) => {
|
||||
if (datasetId !== currentDatasetId) {
|
||||
setCurrentDatasetId(datasetId);
|
||||
setDocumentPage(1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理文档页码变化
|
||||
*/
|
||||
const handlePageChange = (page: number) => {
|
||||
loadDocuments(currentDatasetId, page);
|
||||
if (dataset) {
|
||||
loadDocuments(dataset.id, page);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -115,13 +95,12 @@ export default function DatasetManager() {
|
||||
setDocumentTotal((prev) => prev - 1);
|
||||
|
||||
// 更新知识库的文档数量
|
||||
setDatasets((prev) =>
|
||||
prev.map((ds) =>
|
||||
ds.id === currentDatasetId
|
||||
? { ...ds, document_count: ds.document_count - 1 }
|
||||
: ds
|
||||
)
|
||||
);
|
||||
if (dataset) {
|
||||
setDataset({
|
||||
...dataset,
|
||||
document_count: dataset.document_count - 1
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -139,103 +118,62 @@ export default function DatasetManager() {
|
||||
* 刷新文档列表
|
||||
*/
|
||||
const handleRefresh = () => {
|
||||
loadDocuments(currentDatasetId, documentPage);
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理侧边栏切换
|
||||
*/
|
||||
const handleSidebarToggle = () => {
|
||||
setSidebarCollapsed(!sidebarCollapsed);
|
||||
if (dataset) {
|
||||
loadDocuments(dataset.id, documentPage);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化
|
||||
useEffect(() => {
|
||||
loadDatasets();
|
||||
loadDataset();
|
||||
}, []);
|
||||
|
||||
// 当选中的知识库变化时,加载文档列表
|
||||
useEffect(() => {
|
||||
if (currentDatasetId) {
|
||||
loadDocuments(currentDatasetId, 1);
|
||||
}
|
||||
}, [currentDatasetId]);
|
||||
|
||||
// 检查屏幕尺寸
|
||||
useEffect(() => {
|
||||
const checkScreenSize = () => {
|
||||
setIsMobile(window.innerWidth < 992);
|
||||
};
|
||||
|
||||
checkScreenSize();
|
||||
window.addEventListener('resize', checkScreenSize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', checkScreenSize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 获取当前选中的知识库
|
||||
const currentDataset = datasets.find((ds) => ds.id === currentDatasetId);
|
||||
|
||||
// 如果有错误,显示错误页面
|
||||
if (error && !inited) {
|
||||
// 加载中状态
|
||||
if (!inited || loadingDataset) {
|
||||
return (
|
||||
<div className="dataset-manager-container">
|
||||
<div className="dataset-empty">
|
||||
<h3>加载失败</h3>
|
||||
<p>{error}</p>
|
||||
<div className="dataset-manager-wrapper">
|
||||
<div className="dataset-manager-card">
|
||||
<div className="dataset-loading-state">
|
||||
<Spin size="large" />
|
||||
<span className="loading-text">正在加载知识库...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 错误状态
|
||||
if (error) {
|
||||
return (
|
||||
<div className="dataset-manager-wrapper">
|
||||
<div className="dataset-manager-card">
|
||||
<div className="dataset-error-state">
|
||||
<i className="ri-error-warning-line error-icon"></i>
|
||||
<h3>加载失败</h3>
|
||||
<p>{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout style={{ height: '100%', display: 'flex', flexDirection: 'row' }}>
|
||||
{/* 移动端遮罩层 */}
|
||||
{!sidebarCollapsed && isMobile && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black bg-opacity-50 z-[999]"
|
||||
onClick={handleSidebarToggle}
|
||||
<div className="dataset-manager-wrapper">
|
||||
<div className="dataset-manager-card">
|
||||
<DocumentList
|
||||
datasetId={dataset?.id || ''}
|
||||
datasetName={dataset?.name || ''}
|
||||
documents={documents}
|
||||
loading={loadingDocuments}
|
||||
total={documentTotal}
|
||||
page={documentPage}
|
||||
pageSize={documentPageSize}
|
||||
onPageChange={handlePageChange}
|
||||
onDocumentDeleted={handleDocumentDeleted}
|
||||
onDocumentStatusChanged={handleDocumentStatusChanged}
|
||||
onRefresh={handleRefresh}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 侧边栏 */}
|
||||
<DatasetSidebar
|
||||
collapsed={sidebarCollapsed}
|
||||
onToggle={handleSidebarToggle}
|
||||
datasets={datasets}
|
||||
currentDatasetId={currentDatasetId}
|
||||
onDatasetSelect={handleDatasetSelect}
|
||||
loading={loadingDatasets}
|
||||
/>
|
||||
|
||||
{/* 主内容区域 */}
|
||||
<Layout style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
|
||||
<Content
|
||||
style={{
|
||||
background: colorBgContainer,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
minHeight: 0,
|
||||
}}
|
||||
>
|
||||
<DocumentList
|
||||
datasetId={currentDatasetId}
|
||||
datasetName={currentDataset?.name || ''}
|
||||
documents={documents}
|
||||
loading={loadingDocuments}
|
||||
total={documentTotal}
|
||||
page={documentPage}
|
||||
pageSize={documentPageSize}
|
||||
onPageChange={handlePageChange}
|
||||
onDocumentDeleted={handleDocumentDeleted}
|
||||
onDocumentStatusChanged={handleDocumentStatusChanged}
|
||||
onRefresh={handleRefresh}
|
||||
/>
|
||||
</Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user