summaryrefslogtreecommitdiff
path: root/frontend/src/pages/RunsPage.svelte
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-18 12:03:32 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-18 12:03:32 +0800
commit61f5c545953bb4ee20b123bf9671ac35d7f1f3c1 (patch)
tree9ede3483db5f7e0d81189f2d29514892b8f77867 /frontend/src/pages/RunsPage.svelte
parent1f16a357213611a6d7f84e506064fc0d9c6317c6 (diff)
downloadstrategy-lab-61f5c545953bb4ee20b123bf9671ac35d7f1f3c1.tar.gz
[变更性质] feat(frontend)
[新增功能] round3 页面组件全量迁移 shadcn-svelte(12 页面 + Modal/DatasetWizard/DatasetCard/Status) [实现方案] .btn→Button、.banner→Alert、table.data→Table.Root、.badge→Badge、.tabs→Tabs.Root、.metric-card/form.card→Card.Root;ProjectStrategyTab div 配对修复 [影响范围] src/pages/*.svelte、src/components/*.svelte
Diffstat (limited to 'frontend/src/pages/RunsPage.svelte')
-rw-r--r--frontend/src/pages/RunsPage.svelte104
1 files changed, 54 insertions, 50 deletions
diff --git a/frontend/src/pages/RunsPage.svelte b/frontend/src/pages/RunsPage.svelte
index ad72b5d..911da2a 100644
--- a/frontend/src/pages/RunsPage.svelte
+++ b/frontend/src/pages/RunsPage.svelte
@@ -7,6 +7,10 @@
import { extractStatusMessage } from '../lib/state';
import { fmtDateTime, runStatusLabel, runStatusBadge, fmtPct, fmtNum, formatMoney } from '../lib/format';
import { capitalReporting } from '../lib/capitalMetrics';
+ import { Alert } from '$lib/components/ui/alert';
+ import { Badge } from '$lib/components/ui/badge';
+ import * as Card from '$lib/components/ui/card';
+ import * as Table from '$lib/components/ui/table';
import type { Run } from '../lib/types';
let runs: Run[] = $state([]);
@@ -107,25 +111,25 @@ import { capitalReporting } from '../lib/capitalMetrics';
{/if}
{#if !busy && !error && runs.length > 0}
- <div class="card" style="padding:0.4rem 0.6rem">
- <table class="data">
- <thead>
- <tr>
- <th></th>
- <th>时间</th>
- <th>状态</th>
- <th>项目</th>
- <th>数据集</th>
- <th>资金/佣金/滑点</th>
- <th>收益</th>
- <th>最大回撤</th>
- <th>操作</th>
- </tr>
- </thead>
- <tbody>
+ <Card.Root size="sm" class="px-3 py-2 [&>*:[data-slot=card-content]]:p-0">
+ <Table.Root>
+ <Table.Header>
+ <Table.Row>
+ <Table.Head></Table.Head>
+ <Table.Head>时间</Table.Head>
+ <Table.Head>状态</Table.Head>
+ <Table.Head>项目</Table.Head>
+ <Table.Head>数据集</Table.Head>
+ <Table.Head>资金/佣金/滑点</Table.Head>
+ <Table.Head>收益</Table.Head>
+ <Table.Head>最大回撤</Table.Head>
+ <Table.Head>操作</Table.Head>
+ </Table.Row>
+ </Table.Header>
+ <Table.Body>
{#each runs as r (r.id)}
- <tr>
- <td>
+ <Table.Row>
+ <Table.Cell>
<input
type="checkbox"
checked={chosenIds.includes(r.id)}
@@ -133,53 +137,53 @@ import { capitalReporting } from '../lib/capitalMetrics';
aria-label={`选择 Run ${r.id.slice(0, 8)} 参与`}
disabled={r.status !== 'succeeded' && chosenIds.length >= 4 && !chosenIds.includes(r.id)}
/>
- </td>
- <td>{fmtDateTime(r.created_at)}</td>
- <td><span class="badge {runStatusBadge[r.status]}">{runStatusLabel[r.status]}</span></td>
- <td class="num">{r.project_id?.slice(0, 8)}…</td>
- <td class="num">{r.dataset_id?.slice(0, 8)}…</td>
- <td>{formatMoney(r.config?.capital)} · {fmtPct(r.config?.commission, 4)} / {fmtPct(r.config?.slippage, 4)}</td>
- <td>{r.result ? fmtPct(r.result.metrics.total_return) : '—'}</td>
- <td>{r.result ? fmtPct(r.result.metrics.max_drawdown) : '—'}</td>
- <td>
+ </Table.Cell>
+ <Table.Cell>{fmtDateTime(r.created_at)}</Table.Cell>
+ <Table.Cell><Badge variant={runStatusBadge[r.status] === 'ok' ? 'secondary' : runStatusBadge[r.status] === 'warn' ? 'outline' : 'destructive'}>{runStatusLabel[r.status]}</Badge></Table.Cell>
+ <Table.Cell class="num">{r.project_id?.slice(0, 8)}…</Table.Cell>
+ <Table.Cell class="num">{r.dataset_id?.slice(0, 8)}…</Table.Cell>
+ <Table.Cell>{formatMoney(r.config?.capital)} · {fmtPct(r.config?.commission, 4)} / {fmtPct(r.config?.slippage, 4)}</Table.Cell>
+ <Table.Cell>{r.result ? fmtPct(r.result.metrics.total_return) : '—'}</Table.Cell>
+ <Table.Cell>{r.result ? fmtPct(r.result.metrics.max_drawdown) : '—'}</Table.Cell>
+ <Table.Cell>
<Button size="sm" variant="outline" href={`#/projects/${r.project_id}/results?run=${r.id}`}>查看</Button>
- </td>
- </tr>
+ </Table.Cell>
+ </Table.Row>
{/each}
- </tbody>
- </table>
+ </Table.Body>
+ </Table.Root>
<p class="hint" style="padding:0.4rem 0.6rem">最多同时选中 4 个已完成的回测用于比较。</p>
- </div>
+ </Card.Root>
{#if selected.length > 0}
- <div class="card stack">
+ <Card.Root size="sm" class="stack">
<h2>条件差异</h2>
- <table class="data">
- <thead>
- <tr>
- <th>维度</th>
- {#each selected as r (r.id)}<th>Run {r.id.slice(0, 6)}</th>{/each}
- </tr>
- </thead>
- <tbody>
+ <Table.Root>
+ <Table.Header>
+ <Table.Row>
+ <Table.Head>维度</Table.Head>
+ {#each selected as r (r.id)}<Table.Head>Run {r.id.slice(0, 6)}.</Table.Head>{/each}
+ </Table.Row>
+ </Table.Header>
+ <Table.Body>
{#each configDiffRows as row, i (i)}
- <tr class:diffrow={row.differing}>
- <th>{row.label}</th>
+ <Table.Row class={row.differing ? 'diffrow' : ''}>
+ <Table.Head>{row.label}</Table.Head>
{#each row.vals as v, j (j)}
- <td class={row.differing ? 'num-diff num' : 'num'}>{v}</td>
+ <Table.Cell class={row.differing ? 'num-diff num' : 'num'}>{v}</Table.Cell>
{/each}
- </tr>
+ </Table.Row>
{/each}
- </tbody>
- </table>
- </div>
+ </Table.Body>
+ </Table.Root>
+ </Card.Root>
{#if comparable.length > 1}
- <div class="card stack">
+ <Card.Root size="sm" class="stack">
<h2>收益曲线对齐比较(首日归一)</h2>
<Chart data={compare.data} series={compare.series} ariaLabel="多回测对比曲线" height={340} />
<p class="hint">起点对齐为 1,仅叠加不同起点的曲线时只在各自区间内展示。</p>
- </div>
+ </Card.Root>
{:else}
<Status busy={false} empty="请再选中至少一个已完成的回测以展示比较" />
{/if}