feat: unify scope settings and catalog table interactions
Deploy production / deploy (push) Successful in 54s

This commit is contained in:
yuxuanhui
2026-09-12 12:11:53 +08:00
parent 9dee2de039
commit 8981c24fda
29 changed files with 2521 additions and 796 deletions
+193 -119
View File
@@ -1,3 +1,16 @@
import {
CatalogTableToolbar,
CatalogIconAction,
useCatalogColumns,
} from "../components/CatalogTableToolbar";
import {
IconRefresh,
IconDownload,
IconAIFilledLevel3,
IconEyeOpened,
IconPlus,
} from "@douyinfe/semi-icons";
import type { ColumnProps } from "@douyinfe/semi-ui-19/lib/es/table/interface";
import { WorkspaceTable as Table } from "../components/WorkspaceTable";
import { useEffect, useState } from "react";
import {
@@ -76,6 +89,19 @@ export function DatasetPage({
[q, setQ] = useState(""),
[category, setCategory] = useState(""),
[subcategory, setSubcategory] = useState("");
const [filterDraft, setFilterDraft] = useState({
q: "",
category: "",
subcategory: "",
});
const columnSettings = useCatalogColumns("catalog-dataset-columns", [
{ key: "dataset", label: "数据集", required: true },
{ key: "category", label: "分类" },
{ key: "field_count", label: "字段数" },
{ key: "value_score", label: "价值评分" },
{ key: "status", label: "同步状态" },
{ key: "actions", label: "操作", required: true },
]);
const [sort, setSort] = useState("name"),
[direction, setDirection] = useState("asc"),
[page, setPage] = useState(1),
@@ -223,6 +249,65 @@ export function DatasetPage({
setNoteVersion(n.version);
Toast.success("备注已保存");
}
const columns: ColumnProps<Entry>[] = [
{
title: "数据集",
width: 280,
render: (_, r) => (
<Button
theme="borderless"
title={r.name || r.id}
onClick={() => void work(() => view(r))}
>
{r.name || r.id}
</Button>
),
},
{ title: "分类", dataIndex: "category", render: displayValue },
{
title: "字段数",
render: (_, r) => r.complete_count ?? displayValue(r.field_count),
},
{ title: "价值评分", dataIndex: "value_score", render: displayValue },
{
title: "同步状态",
render: (_, r) => (
<Tag color={r.collection_version ? "green" : "grey"}>
{r.collection_version ? "已同步字段" : "待同步字段"}
</Tag>
),
},
{
title: "操作",
width: 140,
render: (_, r) => (
<div className="workspace-cell-actions">
<CatalogIconAction
label="查看"
icon={<IconEyeOpened aria-hidden="true" />}
disabled={busy}
onClick={() => void work(() => view(r))}
/>
<CatalogIconAction
label="同步"
icon={<IconDownload aria-hidden="true" />}
disabled={busy}
onClick={() => void work(() => sync(r.id))}
/>
<CatalogIconAction
label="使用"
icon={<IconPlus aria-hidden="true" />}
disabled={busy || !r.collection_version}
title={!r.collection_version ? "请先同步全部字段" : "使用"}
onClick={() => void work(() => use(r))}
/>
</div>
),
},
];
const visibleColumns = columns.filter((_, index) =>
columnSettings.visible.includes(columnSettings.choices[index].key),
);
return (
<section className="preparation-page">
<ScopeControls
@@ -243,69 +328,113 @@ export function DatasetPage({
}
/>
)}
<div className="preparation-tools">
<Input
aria-label="搜索数据集"
placeholder="搜索数据集名称或 ID"
value={q}
onChange={(v) => {
setQ(v);
setPage(1);
}}
/>
<ResearchSelect
label="分类"
placeholder="全部分类"
showClear
value={category || undefined}
optionList={Object.keys(data.categories).map((v) => ({
value: v,
label: v,
}))}
onChange={(v) => {
setCategory(String(v ?? ""));
setSubcategory("");
setPage(1);
}}
/>
<ResearchSelect
label="子分类"
placeholder="全部子分类"
showClear
value={subcategory || undefined}
optionList={(data.categories[category] ?? []).map((v) => ({
value: v,
label: v,
}))}
onChange={(v) => {
setSubcategory(String(v ?? ""));
setPage(1);
}}
/>
<ResearchSelect
label="数据集排序"
value={sort}
optionList={[
<CatalogTableToolbar
label="数据目录"
active={active && !suspended && !detail}
filterCount={[q, category, subcategory].filter(Boolean).length}
columns={columnSettings}
filters={
<div className="catalog-filter-grid">
<label className="catalog-filter-wide">
搜索
<Input
aria-label="搜索数据集"
placeholder="搜索数据集名称或 ID"
value={filterDraft.q}
onChange={(q) => setFilterDraft({ ...filterDraft, q })}
showClear
/>
</label>
<label>
分类
<ResearchSelect
label="分类"
placeholder="全部分类"
showClear
value={filterDraft.category || undefined}
optionList={Object.keys(data.categories).map((v) => ({
value: v,
label: v,
}))}
onChange={(v) =>
setFilterDraft({
...filterDraft,
category: String(v ?? ""),
subcategory: "",
})
}
/>
</label>
<label>
子分类
<ResearchSelect
label="子分类"
placeholder="全部子分类"
showClear
value={filterDraft.subcategory || undefined}
optionList={(data.categories[filterDraft.category] ?? []).map(
(v) => ({ value: v, label: v }),
)}
onChange={(v) =>
setFilterDraft({
...filterDraft,
subcategory: String(v ?? ""),
})
}
/>
</label>
</div>
}
onApply={() => {
setQ(filterDraft.q);
setCategory(filterDraft.category);
setSubcategory(filterDraft.subcategory);
setPage(1);
}}
onReset={() => {
setFilterDraft({ q: "", category: "", subcategory: "" });
setQ("");
setCategory("");
setSubcategory("");
setPage(1);
}}
sort={{
value: sort,
direction,
options: [
{ value: "name", label: "名称" },
{ value: "field_count", label: "字段数" },
{ value: "value_score", label: "价值评分" },
]}
onChange={(v) => {
setSort(String(v));
],
onChange: (value, dir) => {
setSort(value);
setDirection(dir);
setPage(1);
}}
/>
<Button
onClick={() => setDirection((v) => (v === "asc" ? "desc" : "asc"))}
>
{direction === "asc" ? "升序" : "降序"}
</Button>
<Button disabled={busy} onClick={() => void work(() => sync())}>
同步目录
</Button>
<Button onClick={() => setRev((v) => v + 1)}>刷新</Button>
<Button onClick={onChat}>AI 助手</Button>
</div>
},
}}
actions={
<>
<CatalogIconAction
label="刷新"
icon={<IconRefresh aria-hidden="true" />}
onClick={() => setRev((v) => v + 1)}
/>
<CatalogIconAction
label="AI 助手"
icon={<IconAIFilledLevel3 aria-hidden="true" />}
onClick={onChat}
/>
<Button
theme="solid"
icon={<IconDownload aria-hidden="true" />}
disabled={busy}
onClick={() => void work(() => sync())}
>
同步目录
</Button>
</>
}
/>
<Table<Entry>
fill
rowKey="id"
@@ -313,66 +442,11 @@ export function DatasetPage({
dataSource={data.items}
pagination={false}
loading={loading}
scroll={{ x: 1180, y: "100%" }}
columns={[
{
title: "数据集",
width: 280,
render: (_, r) => (
<Button
theme="borderless"
title={r.name || r.id}
onClick={() => void work(() => view(r))}
>
{r.name || r.id}
</Button>
),
},
{ title: "分类", dataIndex: "category", render: displayValue },
{
title: "字段数",
render: (_, r) => r.complete_count ?? displayValue(r.field_count),
},
{ title: "价值评分", dataIndex: "value_score", render: displayValue },
{
title: "同步状态",
render: (_, r) => (
<Tag color={r.collection_version ? "green" : "grey"}>
{r.collection_version ? "已同步字段" : "待同步字段"}
</Tag>
),
},
{
title: "操作",
width: 240,
render: (_, r) => (
<div className="workspace-cell-actions">
<Button
theme="borderless"
disabled={busy}
onClick={() => void work(() => view(r))}
>
查看
</Button>
<Button
theme="borderless"
disabled={busy}
onClick={() => void work(() => sync(r.id))}
>
同步
</Button>
<Button
theme="borderless"
disabled={busy || !r.collection_version}
title={!r.collection_version ? "请先同步全部字段" : undefined}
onClick={() => void work(() => use(r))}
>
使用
</Button>
</div>
),
},
]}
scroll={{
x: visibleColumns.reduce((sum, c) => sum + Number(c.width ?? 140), 0),
y: "100%",
}}
columns={visibleColumns}
/>
<div className="table-pagination workspace-table-footer">
<span>