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
+48 -45
View File
@@ -514,45 +514,6 @@ export function AlphaPage({
</span>
</span>
</div>
<SavedViews
filters={{ ...filters, submission, sort, direction, limit: pageSize }}
columns={visibleColumns}
onRestore={(view) => {
const {
submission: savedSubmission,
sort: savedSort,
direction: savedDirection,
limit,
offset: _offset,
...rest
} = view.filters;
const values = Object.fromEntries(
Object.entries(rest)
.filter(([, v]) => v !== null && v !== undefined)
.map(([k, v]) => [k, String(v)]),
);
setFilters(values);
setDraft(values);
setPage(1);
setSelected([]);
if (
savedSubmission === "SUBMITTED" ||
savedSubmission === "UNSUBMITTED"
)
setSubmission(savedSubmission);
setSort(String(savedSort || "date_created"));
setDirection(String(savedDirection || "desc"));
if (typeof limit === "number") setPageSize(limit);
const next = [
...new Set([
"name",
...view.columns.filter((c) => c in columnLabels),
]),
];
setVisibleColumns(next);
localStorage.setItem("alpha-columns", JSON.stringify(next));
}}
/>
<form
className="filter-panel"
onSubmit={(e) => {
@@ -592,12 +553,6 @@ export function AlphaPage({
optionList={stateOptions}
onChange={(v) => updateDraft("research_state", v)}
/>
<Button htmlType="submit" theme="solid">
查询
</Button>
<Button type="tertiary" theme="borderless" onClick={clearFilters}>
重置
</Button>
</div>
<details className="advanced-filters">
<summary>
@@ -724,7 +679,55 @@ export function AlphaPage({
数值筛选使用平台原始值,例如 Turnover 0.15 表示 15%。
</p>
</details>
<div className="inline-actions filter-actions">
<Button htmlType="submit" theme="solid">
查询
</Button>
<Button type="tertiary" theme="borderless" onClick={clearFilters}>
重置
</Button>
</div>
</form>
<SavedViews
filters={{ ...filters, submission, sort, direction, limit: pageSize }}
columns={visibleColumns}
onRestore={(view) => {
const {
submission: savedSubmission,
sort: savedSort,
direction: savedDirection,
limit,
offset: _offset,
...rest
} = view.filters;
const values = Object.fromEntries(
Object.entries(rest)
.filter(([, v]) => v !== null && v !== undefined)
.map(([k, v]) => [k, String(v)]),
);
setFilters(values);
setDraft(values);
setPage(1);
setSelected([]);
if (
savedSubmission === "SUBMITTED" ||
savedSubmission === "UNSUBMITTED"
)
setSubmission(savedSubmission);
setSort(String(savedSort || "date_created"));
setDirection(String(savedDirection || "desc"));
if (typeof limit === "number") setPageSize(limit);
const next = [
...new Set([
"name",
...view.columns.filter((c) => c in columnLabels),
]),
];
setVisibleColumns(next);
localStorage.setItem("alpha-columns", JSON.stringify(next));
}}
/>
<div className="table-toolbar">
<div>
<strong>
+36 -40
View File
@@ -981,24 +981,6 @@ export function DatasetPage({
)
}
/>
<Button
loading={busy}
disabled={!scopeValid}
onClick={() => void sync()}
>
同步目录
</Button>
<Button
onClick={() => {
remember();
setHistoryOpen(true);
}}
>
已保存输入 ({drafts.length})
</Button>
<span className="muted">
{formatTime(data.synced_at, account?.timezone)}
</span>
</div>
{scopeError && (
<Banner
@@ -1041,9 +1023,27 @@ export function DatasetPage({
optionList={options(data.categories[browse.category] ?? [])}
onChange={(v) => editBrowse({ subcategory: String(v ?? "") })}
/>
<Button onClick={() => setBrowse(initialBrowse)}>重置筛选</Button>
</div>
<div className="catalog-tools">
<Button
loading={busy}
disabled={!scopeValid}
onClick={() => void sync()}
>
同步目录
</Button>
<Button
onClick={() => {
remember();
setHistoryOpen(true);
}}
>
已保存输入 ({drafts.length})
</Button>
<span className="muted">
{formatTime(data.synced_at, account?.timezone)}
</span>
<Button onClick={() => setBrowse(initialBrowse)}>重置筛选</Button>
<span aria-live="polite">{summary}</span>
{restoreAction}
{inputAction}
@@ -1075,24 +1075,11 @@ export function DatasetPage({
{...panelProps}
className="catalog-sheet catalog-fields"
visible={fieldsOpen && !suspended && active}
width={viewport < 900 ? viewport : viewport * 0.75}
width="60%"
mask={top === "fields"}
>
<div className="catalog-layer" ref={fieldsRef}>
{fieldError && <Banner type="danger" description={fieldError} />}
<div className="catalog-tools">
<Button onClick={onChat}>AI 助手</Button>
<Button aria-label="关闭字段列表" onClick={close}>
关闭
</Button>
<span>{summary}</span>
{restoreAction}
{inputAction}
<Button loading={busy} onClick={() => void sync(selected?.id)}>
刷新字段
</Button>
{jobStatus}
</div>
<div className="catalog-tools">
<span>
{scope.region} · {scope.universe} · Delay {scope.delay}
@@ -1130,9 +1117,22 @@ export function DatasetPage({
editBrowse({ coverage_min: String(v ?? "") }, true)
}
/>
</div>
<div className="catalog-tools">
<Button onClick={() => setFieldBrowse(initialBrowse)}>
重置筛选
</Button>
<Button onClick={onChat}>AI 助手</Button>
<Button aria-label="关闭字段列表" onClick={close}>
关闭
</Button>
<span>{summary}</span>
{restoreAction}
{inputAction}
<Button loading={busy} onClick={() => void sync(selected?.id)}>
刷新字段
</Button>
{jobStatus}
</div>
<Table<Entry>
className="alpha-table catalog-table"
@@ -1161,11 +1161,7 @@ export function DatasetPage({
zIndex={1101}
className="catalog-sheet catalog-detail"
visible={!!detail && !suspended && active}
width={
detail?.field && viewport >= 900
? viewport * 0.3
: Math.min(560, viewport)
}
width="60%"
>
<div className="catalog-layer" ref={detailRef}>
<div className="catalog-tools">
@@ -1288,7 +1284,7 @@ export function DatasetPage({
zIndex={1102}
className="catalog-sheet"
visible={inputOpen && !suspended && active}
width={Math.min(560, viewport)}
width="60%"
>
<div className="catalog-layer" ref={inputRef}>
<div className="catalog-tools">
@@ -1349,7 +1345,7 @@ export function DatasetPage({
zIndex={1103}
className="catalog-sheet"
visible={historyOpen && !suspended && active}
width={Math.min(560, viewport)}
width="60%"
>
<div className="catalog-layer" ref={historyRef}>
<div className="catalog-tools">