summaryrefslogtreecommitdiff
path: root/frontend/src/components/ProjectMetricRow.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/components/ProjectMetricRow.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/components/ProjectMetricRow.svelte')
-rw-r--r--frontend/src/components/ProjectMetricRow.svelte83
1 files changed, 35 insertions, 48 deletions
diff --git a/frontend/src/components/ProjectMetricRow.svelte b/frontend/src/components/ProjectMetricRow.svelte
index 7980622..6dd3f0e 100644
--- a/frontend/src/components/ProjectMetricRow.svelte
+++ b/frontend/src/components/ProjectMetricRow.svelte
@@ -1,7 +1,8 @@
<script lang="ts">
- // 首页指标卡行(leader round2 spec §1)
+ // 首页指标卡行(round2 spec §1;round3 迁移 shadcn-svelte Card)
// 数据通过 props 注入(ProjectsPage 拉取并共享聚合输入,见 dashboardMetrics.ts)。
import { aggregateDashboard } from '../lib/dashboardMetrics';
+ import * as Card from '$lib/components/ui/card';
interface Props {
/** 注入的聚合输入;null/undefined 视为"取不到"(占位 -) */
@@ -15,33 +16,34 @@
const metric = $derived(aggregateDashboard({ projects, datasets, runs, usage }));
</script>
-<div class="metric-row" role="list" aria-label="工作台概览">
- <div class="metric-card" data-testid="metric-card" role="listitem">
- <span class="mlabel">我的项目</span>
- <span class="mvalue">{metric.projectCount}</span>
+ <div class="metric-row" role="list" aria-label="工作台概览">
+ <Card.Root class="metric-r3" size="sm" data-testid="metric-card" role="listitem">
+ <span class="mlabel">我的项目</span>
+ <span class="mvalue">{metric.projectCount}</span>
+ </Card.Root>
+ <Card.Root class="metric-r3" size="sm" data-testid="metric-card" role="listitem">
+ <span class="mlabel">数据集</span>
+ <span class="mvalue">{metric.datasetCount}</span>
+ </Card.Root>
+ <Card.Root class="metric-r3" size="sm" data-testid="metric-card" role="listitem">
+ <span class="mlabel">回测</span>
+ <span class="mvalue">
+ <span class="run-split"><i>运行中</i> {metric.runningRuns}</span>
+ <span class="run-split"><i>已完成</i> {metric.doneRuns}</span>
+ </span>
+ </Card.Root>
+ <Card.Root
+ class="metric-r3"
+ size="sm"
+ data-testid="metric-card"
+ role="listitem"
+ data-todo={metric.usageLabel === '-' ? 'TODO: /api/ai/usage 未返回 totals.requests(使用记录为空)时保持占位 -' : undefined}
+ >
+ <span class="mlabel">AI 用量</span>
+ <span class="mvalue">{metric.usageLabel}</span>
+ {#if metric.usageTokens}<span class="mvalue-sub">{metric.usageTokens}</span>{/if}
+ </Card.Root>
</div>
- <div class="metric-card" data-testid="metric-card" role="listitem">
- <span class="mlabel">数据集</span>
- <span class="mvalue">{metric.datasetCount}</span>
- </div>
- <div class="metric-card" data-testid="metric-card" role="listitem">
- <span class="mlabel">回测</span>
- <span class="mvalue">
- <span class="run-split"><i>运行中</i> {metric.runningRuns}</span>
- <span class="run-split"><i>已完成</i> {metric.doneRuns}</span>
- </span>
- </div>
- <div
- class="metric-card"
- data-testid="metric-card"
- role="listitem"
- data-todo={metric.usageLabel === '-' ? 'TODO: /api/ai/usage 未返回 totals.requests(使用记录为空)时保持占位 -' : undefined}
- >
- <span class="mlabel">AI 用量</span>
- <span class="mvalue">{metric.usageLabel}</span>
- {#if metric.usageTokens}<span class="mvalue-sub">{metric.usageTokens}</span>{/if}
- </div>
-</div>
<style>
.metric-row {
@@ -50,26 +52,12 @@
gap: 0.6rem;
margin-bottom: 1.1rem;
}
- .metric-card {
- background: var(--surface);
- border: 1px solid var(--border);
- border-radius: calc(var(--radius) * 1.4);
- padding: 0.65rem 0.85rem;
- display: flex;
- flex-direction: column;
- gap: 0.1rem;
+ .metric-row :global(.metric-r3) {
+ gap: 0.12rem;
min-width: 0;
- transition: box-shadow 150ms ease, transform 150ms ease;
}
- /* 桌面端 hover 轻微上浮阴影 */
- @media (hover: hover) and (min-width: 768px) {
- .metric-card:hover {
- box-shadow: var(--shadow);
- transform: translateY(-1px);
- }
- }
- .metric-card .mvalue {
- font-size: 1.35rem;
+ .metric-row :global(.metric-r3 .mvalue) {
+ font-size: 1.5rem;
font-weight: 700;
letter-spacing: -0.01em;
color: var(--foreground);
@@ -77,7 +65,6 @@
line-height: 1.2;
overflow-wrap: anywhere;
}
- .run-split { display: inline-flex; align-items: baseline; gap: 0.3rem; }
- .run-split i { font-style: normal; font-size: 0.68rem; color: var(--text-3); font-weight: 500; }
- .mvalue-sub { font-size: 0.72rem; color: var(--text-3); }
+
+ .mvalue-sub { color: var(--text-3); }
</style>