summaryrefslogtreecommitdiff
path: root/frontend/src/components/DatasetCard.svelte
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-18 15:49:44 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-18 15:49:44 +0800
commita7aab01f051487327e5ce52b6a8905208c546e8c (patch)
tree630a624523bc15d1a9f59ab20693385eaf55befb /frontend/src/components/DatasetCard.svelte
parent375584174fb7191a57c5423fea45924ad6d812d5 (diff)
downloadstrategy-lab-a7aab01f051487327e5ce52b6a8905208c546e8c.tar.gz
[变更性质] feat(frontend)
[新增功能] 12 页面组件全量 shadcn:Card/Button/Table/Tabs/Select/Alert;375 底部 Tab Bar 改用 Tabs 组件实现 [实现方案] 页面级手写 class 全部移除(.btn/.banner/table.data/.badge/.tabs/.metric-row/.m-tile/.hint 等改为 shadcn + tailwind 工具类);Modal/DatasetWizard/DatasetCard/DiffView/CodeEditor/Status/Layout 同步 [影响范围] src/pages/*.svelte、src/components/*.svelte
Diffstat (limited to 'frontend/src/components/DatasetCard.svelte')
-rw-r--r--frontend/src/components/DatasetCard.svelte60
1 files changed, 24 insertions, 36 deletions
diff --git a/frontend/src/components/DatasetCard.svelte b/frontend/src/components/DatasetCard.svelte
index 69083fb..266c9a4 100644
--- a/frontend/src/components/DatasetCard.svelte
+++ b/frontend/src/components/DatasetCard.svelte
@@ -119,50 +119,49 @@
<Card.Root>
{#if ds}
- <div class="spread">
+ <div class="flex flex-wrap justify-between items-center gap-2">
<div class="min-w-0">
- <strong>{ds.name ?? '未命名数据集'}</strong>
- {#if ds.manifest_hash}<span class="hint mono">manifest {ds.manifest_hash.slice(0, 10)}…</span>{/if}
+ <strong class="font-semibold">{ds.name ?? '未命名数据集'}</strong>
+ {#if ds.manifest_hash}<span class="text-sm text-muted-foreground ml-2 font-mono">manifest {ds.manifest_hash.slice(0, 10)}…</span>{/if}
{#if ds.cache_hit}<Badge variant="secondary">缓存命中 · 复用现有物化对象</Badge>{/if}
</div>
- <Badge variant={ds.status === 'ready' ? 'secondary' : ds.status === 'failed' ? 'destructive' : 'outline'}
- class={ds.status === 'ready' ? 'badge ok' : ds.status === 'failed' ? 'badge danger' : 'badge warn'}>
+ <Badge variant={ds.status === 'ready' ? 'secondary' : ds.status === 'failed' ? 'destructive' : 'outline'}>
{datasetStatusLabel[ds.status]}
</Badge>
</div>
- <div class="table-wrap">
+ <div class="overflow-x-auto min-w-0">
<Table.Root>
<Table.Body>
<Table.Row>
- <Table.Cell class="k">请求标的</Table.Cell>
+ <Table.Cell class="whitespace-nowrap text-muted-foreground font-medium w-24">请求标的</Table.Cell>
<Table.Cell>{(ds.request.instruments ?? []).map(instrumentLabel).join(';')}</Table.Cell>
</Table.Row>
<Table.Row>
- <Table.Cell class="k">范围</Table.Cell>
+ <Table.Cell class="whitespace-nowrap text-muted-foreground font-medium w-24">范围</Table.Cell>
<Table.Cell>{ds.request.start_date} ~ {ds.request.end_date} · {ds.request.frequency} · {adjustmentLabel[ds.request.adjustment] ?? ds.request.adjustment}</Table.Cell>
</Table.Row>
<Table.Row>
- <Table.Cell class="k">字段</Table.Cell>
+ <Table.Cell class="whitespace-nowrap text-muted-foreground font-medium w-24">字段</Table.Cell>
<Table.Cell>{(ds.request.fields ?? []).join(', ')}</Table.Cell>
</Table.Row>
<Table.Row>
- <Table.Cell class="k">创建时间</Table.Cell>
+ <Table.Cell class="whitespace-nowrap text-muted-foreground font-medium w-24">创建时间</Table.Cell>
<Table.Cell>{fmtDate(ds.created_at)}</Table.Cell>
</Table.Row>
</Table.Body>
</Table.Root>
</div>
{#if ds.status === 'failed'}
- <Alert variant="destructive" class="bg-[var(--danger-soft)] border-[#f2c7c7]"><span aria-hidden="true">✕</span><span>{ds.error ?? '数据获取失败'}</span></Alert>
- <div class="retry-row">
- <Button variant="outline" size="sm"
+ <Alert variant="destructive"><span aria-hidden="true">✕</span><span>{ds.error ?? '数据获取失败'}</span></Alert>
+ <div class="flex flex-wrap items-center gap-2 min-w-0 mt-1">
+ <Button variant="outline" size="sm" class="w-fit"
disabled={recreateBusy || recreatedId !== null}
onclick={() => void recreateFromRequest()}
>
{recreateBusy ? '重新获取中…' : '使用相同请求重新获取'}
</Button>
{#if recreatedId}
- <span class="hint">
+ <span class="text-sm text-muted-foreground break-all">
已用原请求创建新数据集(编号 {recreatedId.slice(0, 8)}…),新数据集出现在下方列表并自动跟踪进度;本条失败记录原样保留。
</span>
{/if}
@@ -176,22 +175,22 @@
</Button>
</div>
{#if showPreview}
- <div class="preview-box">
+ <div class="mt-2 flex flex-col gap-2">
<Status busy={previewBusy} busyText="加载预览…" error={previewError} empty={null} />
{#if preview}
{@const cov = summarizeCoverage(preview.coverage ?? [])}
{#if cov.warnings.length > 0}
- <Alert variant="default" class="bg-[var(--warn-soft)] border-[#f0ddb4]"><span aria-hidden="true">⚠</span><div>
- <div class="cov-caption">覆盖差异(共有区间 {cov.common.start ?? '—'} ~ {cov.common.end ?? '—'}):</div>
- <ul class="cov-list">
+ <Alert variant="default"><span aria-hidden="true">⚠</span><div>
+ <div class="font-semibold">覆盖差异(共有区间 {cov.common.start ?? '—'} ~ {cov.common.end ?? '—'}):</div>
+ <ul class="list-disc pl-5 mt-1">
{#each cov.warnings as w, i (i)}<li>{w}</li>{/each}
</ul>
</div></Alert>
{/if}
{#if (preview.coverage ?? []).some((c) => (c.warnings ?? []).length > 0)}
- <Alert variant="default" class="bg-[var(--warn-soft)] border-[#f0ddb4]" role="alert"><span aria-hidden="true">⚠</span><div>
- <div class="cov-caption">来源与口径说明:</div>
- <ul class="cov-list">
+ <Alert variant="default" role="alert"><span aria-hidden="true">⚠</span><div>
+ <div class="font-semibold">来源与口径说明:</div>
+ <ul class="list-disc pl-5 mt-1">
{#each preview.coverage.filter((c) => (c.warnings ?? []).length > 0) as c (c.instrument)}
<li>{c.instrument}:{(c.warnings ?? []).join(';')}</li>
{/each}
@@ -199,12 +198,12 @@
</div></Alert>
{/if}
{#if cov.common.start && cov.warnings.length === 0}
- <Alert variant="default" class="bg-[var(--brand-soft)] border-[#bfe9db]">
+ <Alert variant="default">
<span aria-hidden="true">✓</span>
<span>覆盖平稳:共有可用区间 {cov.common.start} ~ {cov.common.end}。可以直接用于回测。</span>
</Alert>
{/if}
- <div class="scrollx">
+ <div class="overflow-x-auto min-w-0">
<Table.Root>
<Table.Header>
<Table.Row>
@@ -214,14 +213,14 @@
<Table.Body>
{#each preview.rows as row, i (i)}
<Table.Row>
- {#each preview.columns as c (c)}<Table.Cell class="num">{row[c]}</Table.Cell>{/each}
+ {#each preview.columns as c (c)}<Table.Cell class="tabular-nums">{row[c]}</Table.Cell>{/each}
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</div>
{#if preview.truncated}
- <p class="hint">预览仅展示部分行</p>
+ <p class="text-sm text-muted-foreground">预览仅展示部分行</p>
{/if}
{/if}
</div>
@@ -231,14 +230,3 @@
<Status busy={busy} error={error} busyText="载入数据集…" empty={null} />
{/if}
</Card.Root>
-
-<style>
- .table-wrap :global(td:first-child) { width: 92px; min-width: 92px; color: var(--text-2); font-weight: 500; }
- .mono { font-family: var(--mono); margin-left: 0.5rem; }
- .preview-box { margin-top: 0.5rem; display: grid; gap: 0.5rem; }
- .scrollx { display: block; overflow-x: auto; min-width: 0; }
- .cov-caption { font-weight: 600; }
- .cov-list { margin: 0.2rem 0 0 1.1rem; padding: 0; }
- .retry-row { margin-top: 0.4rem; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; min-width: 0; }
- .retry-row .hint { min-width: 0; overflow-wrap: anywhere; }
-</style>