feat: 统一研究模块表格布局与详情交互

This commit is contained in:
yuxuanhui
2026-09-09 09:29:30 +08:00
parent f6c2dcead8
commit 20645d6d17
19 changed files with 1693 additions and 1243 deletions
+98 -90
View File
@@ -1,3 +1,4 @@
import { ResearchList, ResearchDetail } from "./ResearchList";
import { ResearchSelect } from "./ResearchSelect";
import { useEffect, useState } from "react";
import {
@@ -61,94 +62,65 @@ export function OperatorsPage({ active }: { active: boolean }) {
if (active) void task(load);
}, [active, query, category, favorite, offset]);
return (
<div className="research-workspace">
<header className="research-page-heading">
<div>
<h2>算子库</h2>
<p>
平台定义只读,本地收藏和研究备注独立保存。同步时间:
{formatTime(result.fetched_at)}
</p>
</div>
<Button
theme="solid"
loading={busy}
onClick={() =>
void task(async () => {
await post("/catalog/operators/refresh");
await load();
})
}
>
同步算子目录
</Button>
</header>
{error && <Banner type="danger" description={error} />}
<div className="research-toolbar">
<Input
aria-label="搜索算子"
placeholder="名称、参数或描述"
value={query}
onChange={(value) => {
setQuery(value);
setOffset(0);
}}
/>
<ResearchSelect
label="算子分类"
value={category}
optionList={[
{ value: "", label: "全部分类" },
...result.categories.map((value) => ({ value, label: value })),
]}
onChange={(value) => {
setCategory(value as string);
setOffset(0);
}}
/>
<Checkbox
checked={favorite}
onChange={(event) => {
setFavorite(!!event.target.checked);
setOffset(0);
}}
>
只看收藏
</Checkbox>
</div>
<div className="research-operator-layout">
<section className="research-card">
<table className="research-table">
<thead>
<tr>
<th>算子</th>
<th>分类</th>
<th>定义</th>
</tr>
</thead>
<tbody>
{result.items.map((item) => (
<tr key={item.name}>
<td>
<Button
theme="borderless"
onClick={() => setSelected(item)}
>
{item.local.favorite ? "已收藏 · " : ""}
{item.name}
</Button>
</td>
<td>{item.category}</td>
<td>
<code>{item.definition}</code>
</td>
</tr>
))}
</tbody>
</table>
{!result.items.length && (
<p>暂无算子。连接平台并同步目录,或调整筛选条件。</p>
)}
<div className="research-workspace research-list-page">
{error && !selected && <Banner type="danger" description={error} />}
<ResearchList
resetKey={JSON.stringify([query, category, favorite, offset])}
label="算子库"
filters={
<div className="research-toolbar">
<Input
aria-label="搜索算子"
placeholder="名称、参数或描述"
value={query}
onChange={(value) => {
setQuery(value);
setOffset(0);
}}
/>
<ResearchSelect
label="算子分类"
value={category}
optionList={[
{ value: "", label: "全部分类" },
...result.categories.map((value) => ({ value, label: value })),
]}
onChange={(value) => {
setCategory(value as string);
setOffset(0);
}}
/>
<Checkbox
checked={favorite}
onChange={(event) => {
setFavorite(!!event.target.checked);
setOffset(0);
}}
>
只看收藏
</Checkbox>
</div>
}
actions={
<>
<Button
theme="solid"
loading={busy}
onClick={() =>
void task(async () => {
await post("/catalog/operators/refresh");
await load();
})
}
>
同步算子目录
</Button>
<span className="muted">
同步时间:{formatTime(result.fetched_at)}
</span>
</>
}
pagination={
<div className="research-toolbar">
<span>共 {result.total} 个</span>
<Button
@@ -164,7 +136,43 @@ export function OperatorsPage({ active }: { active: boolean }) {
下一页
</Button>
</div>
</section>
}
>
<table className="research-table">
<thead>
<tr>
<th>算子</th>
<th>分类</th>
<th>定义</th>
</tr>
</thead>
<tbody>
{result.items.map((item) => (
<tr key={item.name}>
<td>
<Button theme="borderless" onClick={() => setSelected(item)}>
{item.local.favorite ? "已收藏 · " : ""}
{item.name}
</Button>
</td>
<td>{item.category}</td>
<td>
<code>{item.definition}</code>
</td>
</tr>
))}
</tbody>
</table>
{!result.items.length && (
<p>暂无算子。连接平台并同步目录,或调整筛选条件。</p>
)}
</ResearchList>
<ResearchDetail
title={selected?.name || "算子详情"}
visible={active && !!selected}
onClose={() => setSelected(null)}
>
{error && <Banner type="danger" description={error} />}
{selected && (
<section className="research-card">
<h3>{selected.name}</h3>
@@ -225,7 +233,7 @@ export function OperatorsPage({ active }: { active: boolean }) {
</div>
</section>
)}
</div>
</ResearchDetail>
</div>
);
}