feat: 统一研究模块表格布局与详情交互
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user