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