Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
7a56c0c
feat: Update site name to DataMate and refine text for AI data proces…
chenghh-9609 Oct 24, 2025
4717a9f
Merge branch 'main' of github.com:chenghh-9609/DataMate
chenghh-9609 Oct 28, 2025
d201ecd
feat: Refactor settings page and implement model access functionality
chenghh-9609 Oct 28, 2025
3189c7c
Merge branch 'ModelEngine-Group:main' into main
chenghh-9609 Oct 28, 2025
92d7189
feat: Implement Data Collection Page with Task Management and Executi…
chenghh-9609 Oct 28, 2025
db0fb4e
Merge branch 'ModelEngine-Group:main' into main
chenghh-9609 Oct 28, 2025
a646924
Merge branch 'main' of github.com:chenghh-9609/DataMate
chenghh-9609 Oct 28, 2025
4169399
feat: Update task creation API endpoint and enhance task creation for…
chenghh-9609 Oct 28, 2025
8733e53
Merge branch 'ModelEngine-Group:main' into main
chenghh-9609 Oct 28, 2025
9344786
Merge branch 'main' of github.com:chenghh-9609/DataMate
chenghh-9609 Oct 28, 2025
e1d4f77
Merge branch 'ModelEngine-Group:main' into main
chenghh-9609 Oct 29, 2025
17c78d9
Merge branch 'ModelEngine-Group:main' into main
chenghh-9609 Oct 30, 2025
7ff535b
Refactor file upload and operator management components
chenghh-9609 Oct 30, 2025
d69262b
Merge branch 'main' of github.com:chenghh-9609/DataMate
chenghh-9609 Oct 30, 2025
b615890
Refactor Knowledge Generation to Knowledge Base
chenghh-9609 Oct 30, 2025
fffa921
Merge branch 'ModelEngine-Group:main' into main
chenghh-9609 Oct 30, 2025
e9c2382
Merge branch 'main' of github.com:chenghh-9609/DataMate
chenghh-9609 Oct 30, 2025
cda7532
Merge branch 'ModelEngine-Group:main' into main
chenghh-9609 Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
582 changes: 582 additions & 0 deletions frontend/src/pages/KnowledgeBase/Create/KnowledgeBaseCreate.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -30,62 +30,20 @@ import {
Checkbox,
Dropdown,
} from "antd";
import { mockKnowledgeBases } from "@/mock/knowledgeBase";
import { useNavigate } from "react-router";
import DetailHeader from "@/components/DetailHeader";
import { SearchControls } from "@/components/SearchControls";
import DevelopmentInProgress from "@/components/DevelopmentInProgress";
import { KnowledgeBaseItem } from "../knowledge-base.model";

const KnowledgeBaseDetailPage: React.FC = () => {
return <DevelopmentInProgress />;
const navigate = useNavigate();
const knowledgeBase = mockKnowledgeBases[0];

const [knowledgeBase, setKnowledgeBase] = useState<KnowledgeBaseItem>(null);
const [files, setFiles] = useState([]);

// --- 新增的状态 ---
const [fileSearchQuery, setFileSearchQuery] = useState("");
const [fileTypeFilter, setFileTypeFilter] = useState<string | null>(null);
const [fileStatusFilter, setFileStatusFilter] = useState<string | null>(null);
const [fileSortOrder, setFileSortOrder] = useState<
"ascend" | "descend" | null
>(null);

// 获取所有类型和状态选项
const allFileTypes = Array.from(
new Set((knowledgeBase.files ?? []).map((f: KBFile) => f.type))
).filter(Boolean);

const allVectorizationStatuses = [
{ label: "全部", value: null },
{ label: "已完成", value: "completed" },
{ label: "处理中", value: "processing" },
{ label: "向量化中", value: "vectorizing" },
{ label: "导入中", value: "importing" },
{ label: "错误", value: "error" },
{ label: "已禁用", value: "disabled" },
];

useEffect(() => {
setFiles(knowledgeBase.files);
}, [knowledgeBase]);

const [showVectorizationDialog, setShowVectorizationDialog] = useState(false);
const [showEditFileDialog, setShowEditFileDialog] = useState<KBFile | null>(
null
);

// File table logic
const handleDeleteFile = (file: KBFile) => {};

const handleFileSelect = (file: KBFile) => {
setShowEditFileDialog(file);
};

const handleStartVectorization = (fileId?: string) => {
message.info(fileId ? `开始向量化文件 ${fileId}` : "批量向量化所有文件");
// 实际业务逻辑可在此实现
};

const handleDeleteKB = (kb: KnowledgeBase) => {};

Expand Down Expand Up @@ -182,7 +140,7 @@ const KnowledgeBaseDetailPage: React.FC = () => {
<Button
type="link"
onClick={() =>
navigate("/data/knowledge-generation/file-detail/" + file.id)
navigate("/data/knowledge-base/file-detail/" + file.id)
}
>
{file.name}
Expand Down Expand Up @@ -296,7 +254,7 @@ const KnowledgeBaseDetailPage: React.FC = () => {
<div className="mb-4">
<Breadcrumb>
<Breadcrumb.Item>
<a onClick={() => navigate("/data/knowledge-generation")}>知识库</a>
<a onClick={() => navigate("/data/knowledge-base")}>知识库</a>
</Breadcrumb.Item>
<Breadcrumb.Item>{knowledgeBase.name}</Breadcrumb.Item>
</Breadcrumb>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { mockChunks, mockQAPairs, sliceOperators } from "@/mock/knowledgeBase";
import type {
KnowledgeBase,
KBFile,
} from "@/pages/KnowledgeGeneration/knowledge-base.model";
} from "@/pages/KnowledgeBase/knowledge-base.model";
import { Link, useNavigate } from "react-router";
import DetailHeader from "@/components/DetailHeader";
import DevelopmentInProgress from "@/components/DevelopmentInProgress";
Expand Down Expand Up @@ -258,11 +258,11 @@ const KnowledgeBaseFileDetail: React.FC = () => {
<Breadcrumb
items={[
{
title: <Link to="/data/knowledge-generation">知识库</Link>,
title: <Link to="/data/knowledge-base">知识库</Link>,
},
{
title: (
<Link to="/data/knowledge-generation/detail/1">
<Link to="/data/knowledge-base/detail/1">
{selectedKB?.name}
</Link>
),
Expand Down
189 changes: 189 additions & 0 deletions frontend/src/pages/KnowledgeBase/Home/KnowledgeGeneration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { useState } from "react";
import { Card, Button, Table, Tooltip, message } from "antd";
import { DeleteOutlined, EditOutlined } from "@ant-design/icons";
import { SearchControls } from "@/components/SearchControls";
import { useNavigate } from "react-router";
import CardView from "@/components/CardView";
import {
deleteKnowledgeBaseByIdUsingDelete,
queryKnowledgeBasesUsingPost,
} from "../knowledge-base.api";
import useFetchData from "@/hooks/useFetchData";
import { KnowledgeBaseItem } from "../knowledge-base.model";
import CreateKnowledgeBase from "../components/CreateKnowledgeBase";
import { mapKnowledgeBase } from "../knowledge-base.const";

export default function KnowledgeGenerationPage() {
const navigate = useNavigate();
const [viewMode, setViewMode] = useState<"card" | "list">("card");
const [isEdit, setIsEdit] = useState(false);
const [currentKB, setCurrentKB] = useState<KnowledgeBaseItem | null>(null);
const {
loading,
tableData,
searchParams,
pagination,
fetchData,
setSearchParams,
handleFiltersChange,
} = useFetchData<KnowledgeBaseItem>(
queryKnowledgeBasesUsingPost,
mapKnowledgeBase
);

const handleDeleteKB = async (kb: KnowledgeBaseItem) => {
try {
await deleteKnowledgeBaseByIdUsingDelete(kb.id);
message.success("知识库删除成功");
fetchData();
} catch (error) {
message.error("知识库删除失败");
}
};

const operations = [
{
key: "edit",
label: "编辑",
icon: <EditOutlined />,
onClick: (item) => {
setIsEdit(true);
setCurrentKB(item);
},
},
{
key: "delete",
label: "删除",
danger: true,
icon: <DeleteOutlined />,
confirm: {
title: "确认删除",
description: "此操作不可撤销,是否继续?",
okText: "删除",
okType: "danger",
cancelText: "取消",
},
onClick: (item) => handleDeleteKB(item),
},
];

const columns = [
{
title: "知识库",
dataIndex: "name",
key: "name",
fixed: "left" as const,
width: 200,
ellipsis: true,
// render: (_: any, kb: KnowledgeBaseItem) => (
// <Button
// type="link"
// onClick={() => navigate(`/data/knowledge-base/detail/${kb.id}`)}
// >
// {kb.name}
// </Button>
// ),
},
{
title: "向量数据库",
dataIndex: "embeddingModel",
key: "embeddingModel",
width: 150,
ellipsis: true,
},
{
title: "大语言模型",
dataIndex: "chatModel",
key: "chatModel",
width: 150,
ellipsis: true,
},
{
title: "创建时间",
dataIndex: "createdAt",
key: "createdAt",
ellipsis: true,
width: 150,
},
{
title: "更新时间",
dataIndex: "updatedAt",
key: "updatedAt",
ellipsis: true,
width: 150,
},
{
title: "描述",
dataIndex: "description",
key: "description",
width: 120,
ellipsis: true,
},
{
title: "操作",
key: "actions",
fixed: "right" as const,
width: 150,
render: (_: any, kb: KnowledgeBaseItem) => (
<div className="flex items-center gap-2">
{operations.map((op) => (
<Tooltip key={op.key} title={op.label}>
<Button
type="text"
icon={op.icon}
danger={op.danger}
onClick={() => op.onClick(kb)}
/>
</Tooltip>
))}
</div>
),
},
];
// Main list view
return (
<div className="h-full flex flex-col gap-4">
<div className="flex items-center justify-between">
<h1 className="text-xl font-bold">知识生成</h1>
<CreateKnowledgeBase
isEdit={isEdit}
data={currentKB}
onUpdate={fetchData}
/>
</div>

<SearchControls
searchTerm={searchParams.keyword}
onSearchChange={(keyword) =>
setSearchParams({ ...searchParams, keyword })
}
searchPlaceholder="搜索知识库..."
filters={[]}
onFiltersChange={handleFiltersChange}
onClearFilters={() => setSearchParams({ ...searchParams, filter: {} })}
viewMode={viewMode}
onViewModeChange={setViewMode}
showViewToggle
onReload={fetchData}
/>
{viewMode === "card" ? (
<CardView
data={tableData}
operations={operations}
// onView={(item) => navigate(`/data/knowledge-base/detail/${item.id}`)}
pagination={pagination}
/>
) : (
<Card>
<Table
loading={loading}
scroll={{ x: "max-content", y: "calc(100vh - 20rem)" }}
columns={columns}
dataSource={tableData}
rowKey="id"
/>
</Card>
)}
</div>
);
}
66 changes: 66 additions & 0 deletions frontend/src/pages/KnowledgeBase/components/AddDataDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
export default function AddDataDialog() {
const [isOpen, setIsOpen] = useState(false);
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
const { message } = App.useApp();

const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
setSelectedFiles(Array.from(e.target.files));
}
};

const handleUpload = async () => {
if (selectedFiles.length === 0) {
message.error("请先选择文件");
return;
}

try {
const formData = new FormData();
selectedFiles.forEach((file) => {
formData.append("files", file);
});

await uploadDataFilesUsingPost(formData);
message.success("文件上传成功");
setIsOpen(false);
setSelectedFiles([]);
} catch (error) {
message.error("文件上传失败");
}
};

return (
<>
<Button type="primary" onClick={() => setIsOpen(true)}>
添加数据
</Button>
<Modal
title="添加数据文件"
open={isOpen}
onCancel={() => setIsOpen(false)}
onOk={handleUpload}
okText="上传"
>
<input
type="file"
multiple
onChange={handleFileChange}
accept=".txt,.pdf,.docx,.csv,.json"
/>
{selectedFiles.length > 0 && (
<div className="mt-4">
<h4>已选择的文件:</h4>
<ul>
{selectedFiles.map((file, index) => (
<li key={index}>
{file.name} - {(file.size / 1024).toFixed(2)} KB
</li>
))}
</ul>
</div>
)}
</Modal>
</>
);
}
Loading