summaryrefslogtreecommitdiff
path: root/frontend/src/pages
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-18 09:50:57 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-18 09:50:57 +0800
commit4390ca3472b8a4a201835e358ad0ad2065e8b7c6 (patch)
tree6fcd197f97e75128c056b7c97b6208c3592d556b /frontend/src/pages
parente6ff0f697160ce152b363be97ecbeee13792cf6f (diff)
downloadstrategy-lab-4390ca3472b8a4a201835e358ad0ad2065e8b7c6.tar.gz
feat(frontend): 375px 底部 Tab Bar、窄标题栏与项目面包屑
[变更性质] 新增移动端导航形态,前端重设计第二轮之二。 [新增功能] ≤767px 呈现底部 Tab Bar(projects/datasets/runs/account 徽标+标签+aria-current)与窄标题栏(品牌/面包屑/账户),≥768px 原桌面布局不变;ProjectPage 顶部新增"我的项目/项目名/功能页"面包屑。 [实现方案] matchMedia('(max-width: 767px)') 反应式驱动的 (Safari <14 兼容addListener 回退),tests 以 matchMedia stub 驱动真实渲染断言;保留 900px 既有断点结构以兼容 mobileCss.test.ts 正则。 [影响范围] Layout.svelte、ProjectPage.svelte;新增 mobileTabbar.test.ts。
Diffstat (limited to 'frontend/src/pages')
-rw-r--r--frontend/src/pages/ProjectPage.svelte48
1 files changed, 48 insertions, 0 deletions
diff --git a/frontend/src/pages/ProjectPage.svelte b/frontend/src/pages/ProjectPage.svelte
index b31caa3..fe9be7f 100644
--- a/frontend/src/pages/ProjectPage.svelte
+++ b/frontend/src/pages/ProjectPage.svelte
@@ -1,5 +1,6 @@
<script lang="ts">
import type { Route } from '../lib/router';
+ import { projectsStore, projectOf, projectInvisible } from '../lib/listsStore.svelte';
import ProjectDataTab from '../pages/ProjectDataTab.svelte';
import ProjectStrategyTab from '../pages/ProjectStrategyTab.svelte';
import ProjectBacktestTab from '../pages/ProjectBacktestTab.svelte';
@@ -9,8 +10,28 @@
route: Route;
}
let { route }: Props = $props();
+
+ // 极简面包屑:我的项目 / 项目名 / 当前标签
+ const isProject = $derived(route.name.startsWith('project-'));
+ const projectName = $derived(
+ projectOf(route.params.id)?.name ?? (projectInvisible(route.params.id) ? '不可见项目' : '加载中…')
+ );
+ const tabLabel = $derived(
+ (({ data: '数据', strategy: '策略', backtest: '回测', results: '结果' })[route.name.replace('project-', '')] ?? '')
+ );
+ $effect(() => {
+ if (isProject) void projectsStore.ensure(route.params.id).catch(() => undefined);
+ });
</script>
+<nav class="crumbs" aria-label="面包屑">
+ <a href="#/projects">我的项目</a>
+ <span aria-hidden="true">/</span>
+ <span class="crumb-name">{projectName}</span>
+ <span aria-hidden="true">/</span>
+ <span class="crumb-tab">{tabLabel}</span>
+</nav>
+
<!-- Layout is provided once by App.svelte; wrapping here produced the doubled sidebar bug. -->
{#if route.name === 'project-data'}
<ProjectDataTab projectId={route.params.id} />
@@ -21,3 +42,30 @@
{:else if route.name === 'project-results'}
<ProjectResultsTab projectId={route.params.id} runId={route.query.get('run') ?? undefined} />
{/if}
+
+<style>
+ /* 极简面包屑(桌面 + 移动端顶部共用) */
+ .crumbs {
+ display: flex;
+ align-items: center;
+ gap: 0.45rem;
+ padding: 0.35rem 0 0.7rem;
+ font-size: 0.82rem;
+ color: var(--text-3);
+ min-width: 0;
+ }
+ .crumbs a {
+ color: var(--text-3);
+ transition: color 150ms ease;
+ }
+ .crumbs a:hover { color: var(--primary); text-decoration: none; }
+ .crumb-name {
+ color: var(--foreground);
+ font-weight: 600;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ max-width: 45vw;
+ }
+ .crumb-tab { color: var(--text-2); }
+</style>