diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-18 18:11:53 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-18 18:11:53 +0800 |
| commit | c52a727d11b87d70ec00a7e2569841e6e6abcd9c (patch) | |
| tree | c7bc7217cb0ef02613b34e5a1f228ac3a68431a9 /frontend/src/pages/ProjectBacktestTab.svelte | |
| parent | 63098a260dadf9e5d01650afb02570343abe20d9 (diff) | |
| download | strategy-lab-c52a727d11b87d70ec00a7e2569841e6e6abcd9c.tar.gz | |
[变更性质] 用户旅程重排:项目首页指标摘要+项目卡、结果页首屏 capital 三卡+交易分页、数据/策略/回测 CTA 与三态统一,token 白名单清扫(docs/ui-user-journey-round6.md §1/§2)
Diffstat (limited to 'frontend/src/pages/ProjectBacktestTab.svelte')
| -rw-r--r-- | frontend/src/pages/ProjectBacktestTab.svelte | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/frontend/src/pages/ProjectBacktestTab.svelte b/frontend/src/pages/ProjectBacktestTab.svelte index b640189..7d5b172 100644 --- a/frontend/src/pages/ProjectBacktestTab.svelte +++ b/frontend/src/pages/ProjectBacktestTab.svelte @@ -11,11 +11,13 @@ runStatusBadge } from '../lib/format'; import { summarizeCoverage } from '../lib/coverage'; - import type { Run, Dataset } from '../lib/types'; + import { go } from '../lib/router'; +import type { Run, Dataset } from '../lib/types'; import { Button } from '$lib/components/ui/button'; import { Alert } from '$lib/components/ui/alert'; import { Badge } from '$lib/components/ui/badge'; import * as Card from '$lib/components/ui/card'; +import * as Textarea from '$lib/components/ui/textarea'; import * as Table from '$lib/components/ui/table'; import * as Select from '$lib/components/ui/select'; import { Input } from '$lib/components/ui/input'; @@ -224,15 +226,26 @@ const canRerun = $derived(latest?.status === 'succeeded' || latest?.status === 'failed' || latest?.status === 'cancelled'); </script> -<div class="flex flex-col gap-3"> - <Card.Root size="sm" class="p-4 flex flex-col gap-3"> - <h2 class="text-lg font-semibold">发起回测</h2> - <Status busy={busyDatasets} error={cfgErr} busyText="检查就绪的数据集…" empty={null} /> +<div class="flex flex-col gap-4 md:gap-6"> + <Card.Root size="sm" class="p-4 flex flex-col gap-4"> + <div class="flex justify-between items-center gap-4"> + <h2 class="text-lg font-semibold m-0">发起回测</h2> + <Button class="w-fit" onclick={startRun} disabled={!datasetId}>开始回测</Button> + </div> + {#if busyDatasets} + <Status busy skeletonRows={3} busyText="检查就绪的数据集…" empty={null} /> + {:else if cfgErr} + <Status busy={false} error={cfgErr} empty={null}/> + {/if} {#if !busyDatasets && datasetsReady.length === 0 && !cfgErr} - <Status busy={false} empty="没有就绪的数据集" emptyHint="先在「数据」标签创建并等待数据集状态变为【就绪】,再回到这里发起回测" /> + <Status busy={false} empty="没有就绪的数据集" emptyHint="先在「数据」标签创建并等待数据集状态变为【就绪】,再回到这里发起回测"> + {#snippet emptyCta()} + <Button onclick={() => go(`/projects/${projectId}/data`)}>去接入数据</Button> + {/snippet} + </Status> {/if} {#if datasetsReady.length > 0} - <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3"> + <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> <div> <Label for="bt-dataset">数据集</Label> <Select.Root @@ -261,7 +274,7 @@ <Label for="bt-capital">起始资金</Label> <Input id="bt-capital" class="tabular-nums" type="number" bind:value={capital} min="1" step="1000" /> </div> - <div class="grid grid-cols-1 sm:grid-cols-2 gap-3"> + <div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div> <Label for="bt-commission">佣金率</Label> <Input id="bt-commission" class="tabular-nums" type="number" bind:value={commission} min="0" max="0.1" step="0.0001" /> @@ -277,7 +290,7 @@ </div> <div class="sm:col-span-2 lg:col-span-3"> <Label for="bt-params">策略参数(JSON,可选)</Label> - <textarea id="bt-params" class="flex w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" rows="1" bind:value={paramsText} placeholder="输入 JSON 参数,例如 fast/slow 周期"></textarea> + <Textarea.Root id="bt-params" class="w-full" rows={1} bind:value={paramsText} placeholder="输入 JSON 参数,例如 fast/slow 周期" /> </div> </div> {#if needAck} @@ -288,28 +301,31 @@ <ul class="list-disc pl-5 mt-1"> {#each datasetWarnMsgs as m, i (i)}<li>{m}</li>{/each} </ul> - <label class="inline-flex items-center gap-2 mt-1"> + <label class="inline-flex items-center gap-4 mt-1"> <input type="checkbox" bind:checked={acknowledged} /> 我已知晓并用当前数据继续 </label> </div> </Alert> {/if} - <div class="flex items-center gap-2 flex-wrap"> - <Button onclick={startRun} disabled={!datasetId}>开始回测</Button> + <div class="flex items-center gap-4 flex-wrap"> {#if selectedDataset} - <span class="text-sm text-muted-foreground">本次回测与该数据集、当前策略快照一同记录,可按原始条件重跑</span> + <span class="text-xs text-muted-foreground">本次回测与该数据集、当前策略快照一同记录,可按原始条件重跑</span> {/if} </div> - <Status busy={false} error={cfgErr} empty={actionMsg} /> + {#if cfgErr} + <Status busy={false} error={cfgErr} empty={null} /> + {:else if actionMsg} + <Status busy={false} empty={actionMsg} /> + {/if} {/if} </Card.Root> - <Card.Root size="sm" class="p-4 flex flex-col gap-3"> - <div class="flex flex-wrap justify-between items-center gap-2"> - <h2 class="text-lg font-semibold">最近一次回测</h2> + <Card.Root size="sm" class="p-4 flex flex-col gap-4"> + <div class="flex flex-wrap justify-between items-center gap-4"> + <h2 class="text-lg font-semibold m-0">最近一次回测</h2> {#if latest} - <span class="flex items-center gap-2"> + <span class="flex items-center gap-4"> <Badge variant="outline">Run 分支 {latest.version_id?.slice(0,8) ?? '—'}</Badge> <Badge variant={runStatusBadge[latest.status] === 'ok' ? 'secondary' : runStatusBadge[latest.status] === 'warn' ? 'outline' : 'destructive'}>{runStatusLabel[latest.status]}</Badge> </span> @@ -349,7 +365,7 @@ {#if latest.status === 'succeeded' && latest.result} <Button variant="outline" href={`#/projects/${projectId}/results?run=${latest.id}`} class="w-fit">查看完整结果与图表</Button> {/if} - <div class="flex items-center gap-2 flex-wrap"> + <div class="flex items-center gap-4 flex-wrap"> {#if canCancel} <Button variant="destructive" onclick={onCancel} disabled={cancelBusy}> {cancelBusy ? '取消中…' : '取消回测'} @@ -366,7 +382,7 @@ {/if} </Card.Root> - <div class="flex flex-col gap-3"> + <div class="flex flex-col gap-4"> <h2 class="text-lg font-semibold">回测历史</h2> <Status busy={historyBusy} error={historyErr} busyText="载入历史…" empty={null} /> {#if history && history.length > 0} |
