feat: unify scope settings and catalog table interactions
Deploy production / deploy (push) Successful in 54s
Deploy production / deploy (push) Successful in 54s
This commit is contained in:
+193
-119
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user