From 65cf80fb511e4e2905555452450833aaec476565 Mon Sep 17 00:00:00 2001 From: Chaos Date: Sat, 22 Nov 2025 22:45:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(layout):=20=E5=AE=9E=E7=8E=B0=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E5=B8=83=E5=B1=80=E5=92=8C=E4=BE=A7=E8=BE=B9=E6=A0=8F?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加侧边栏组件,支持展开/收缩和移动端适配 - 实现导航菜单,支持高亮当前路由 - 添加主题选择器组件 - 集成认证状态显示和登出功能 - 优化侧边栏在不同屏幕尺寸下的行为 - 添加多种图标支持,包括logo、菜单、主页等 - 创建NavItem类型定义,用于导航菜单项 - 扩展sidebarStore,增加手动控制状态管理 - 添加数据看板页面占位内容 - 更新全局布局文件以支持主题和侧边栏状态管理 --- src/lib/components/icon/Sprite.svelte | 106 +++++++++++++++++ src/lib/stores/sidebarStore.ts | 20 +++- src/lib/types/icon-ids.ts | 9 +- src/lib/types/layout.ts | 13 +++ src/lib/widget/ThemeSelector.svelte | 1 - src/routes/+layout.svelte | 42 +++++-- src/routes/app/+layout.svelte | 152 ++++++++++++++++++++++++- src/routes/app/dashboard/+page.svelte | 62 ---------- src/routes/app/statistics/+page.svelte | 1 + 9 files changed, 325 insertions(+), 81 deletions(-) create mode 100644 src/lib/types/layout.ts create mode 100644 src/routes/app/statistics/+page.svelte diff --git a/src/lib/components/icon/Sprite.svelte b/src/lib/components/icon/Sprite.svelte index 997546e..2624d1a 100644 --- a/src/lib/components/icon/Sprite.svelte +++ b/src/lib/components/icon/Sprite.svelte @@ -14,4 +14,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/lib/stores/sidebarStore.ts b/src/lib/stores/sidebarStore.ts index 8372918..50dd5d9 100644 --- a/src/lib/stores/sidebarStore.ts +++ b/src/lib/stores/sidebarStore.ts @@ -4,28 +4,44 @@ import { writable } from 'svelte/store'; interface SidebarState { isOpen: boolean; isExpanded: boolean; + isManualOverride: boolean; } export const sidebarStore = writable({ isOpen: false, isExpanded: false, + isManualOverride: false, }) + + /** * 切换侧边栏打开、隐藏(偏移隐藏)状态 */ -export const toggleSidebar = () => { +export const toggleSidebarOpen = () => { sidebarStore.update(state => ({ ...state, isOpen: !state.isOpen, + isManualOverride: true, + })); +} + +/** + * 重置手动控制状态 + */ +export const resetManualOverride = () => { + sidebarStore.update(state => ({ + ...state, + isManualOverride: false, })); } /** * 切换侧边栏展开状态 */ -export const toggleSidebarOpen = () => { +export const toggleSidebar = () => { + sidebarStore.update(state => ({ ...state, isExpanded: !state.isExpanded, diff --git a/src/lib/types/icon-ids.ts b/src/lib/types/icon-ids.ts index b1efa9c..50848c0 100644 --- a/src/lib/types/icon-ids.ts +++ b/src/lib/types/icon-ids.ts @@ -1,4 +1,11 @@ export type IconId = "panel-right-close" | - "panel-right-close-solid" + "panel-right-close-solid"| + "panel-left-close"| + "panel-left-close-solid"| + "data-pie"| + "starburst"| + "home"| + "menu"| + "logo" ; \ No newline at end of file diff --git a/src/lib/types/layout.ts b/src/lib/types/layout.ts new file mode 100644 index 0000000..7a672a0 --- /dev/null +++ b/src/lib/types/layout.ts @@ -0,0 +1,13 @@ +import type { IconId } from '$lib/types/icon-ids.ts'; +import type { RouteId } from '$app/types'; + +export interface NavItem { + id: string; + icon: IconId; + label: string; + href: RouteId; + isActive?: boolean; + isDisabled?: boolean; + isHidden?: boolean; + subItems?: NavItem[]; +} \ No newline at end of file diff --git a/src/lib/widget/ThemeSelector.svelte b/src/lib/widget/ThemeSelector.svelte index 1d4cb76..808c9b3 100644 --- a/src/lib/widget/ThemeSelector.svelte +++ b/src/lib/widget/ThemeSelector.svelte @@ -3,7 +3,6 @@ import { DAISYUI_THEME_OPTIONS, type DaisyUIThemeID } from '$lib/types/theme.ts'; import ThemePreview from '$lib/widget/ThemePreview.svelte'; - // ... 逻辑保持不变 ... const handleThemeChange = (themeValue: DaisyUIThemeID) => { themeStore.set(themeValue); }; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 1aa901e..c1f5754 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -4,7 +4,6 @@ import { themeStore } from '$lib/stores/themeStore.ts'; let { children } = $props(); - import { onMount } from 'svelte'; import { sidebarStore } from '$lib/stores/sidebarStore.ts'; import Sprite from '$lib/components/icon/Sprite.svelte'; @@ -15,32 +14,51 @@ const handleMediaQueryChange = (event: MediaQueryListEvent) => { const isCurrentlyDesktop = event.matches; - console.log(isCurrentlyDesktop); - sidebarStore.update((store) => ({ - ...store, - isOpen: isCurrentlyDesktop - })); + + sidebarStore.update((store) => { + + if (!store.isManualOverride) { + return { + ...store, + isOpen: isCurrentlyDesktop + }; + } + + + if (isCurrentlyDesktop) { + return { + ...store, + isOpen: true, + isManualOverride: false // PC端时,恢复自动模式 + }; + } + + + return store; + }); } - let isMounted = $state(false); // 客户端渲染标志 + let isMounted = $state(false); + onMount(()=>{ isMounted = true; - const isDesktop = window.matchMedia(MD_BREAKPOINT).matches; - console.log(isDesktop); + const mediaQuery = window.matchMedia(MD_BREAKPOINT); + const isDesktop = mediaQuery.matches; + sidebarStore.update((store) => ({ ...store, isOpen: isDesktop, + isManualOverride: false, })); - - const mediaQuery = window.matchMedia(MD_BREAKPOINT); - mediaQuery.addEventListener('change', handleMediaQueryChange); return () => { mediaQuery.removeEventListener('change', handleMediaQueryChange); } }) + + diff --git a/src/routes/app/+layout.svelte b/src/routes/app/+layout.svelte index 93b55a3..38ed622 100644 --- a/src/routes/app/+layout.svelte +++ b/src/routes/app/+layout.svelte @@ -1,8 +1,154 @@ -
- {@render children()} -
\ No newline at end of file +
+ + {#if $sidebarStore.isOpen} +
e.key === 'Escape' && handleMobileClose()} + transition:fade={{ duration: 200 }} + >
+ + + + {/if} + +
+
+
+ +
+
+
+ + {#if $authStore.isAuthenticated} + + {:else} +
+
+ +
+
+ {/if} +
+
+ +
+ {@render children()} +
+
+
\ No newline at end of file diff --git a/src/routes/app/dashboard/+page.svelte b/src/routes/app/dashboard/+page.svelte index d53f2a4..6b81c32 100644 --- a/src/routes/app/dashboard/+page.svelte +++ b/src/routes/app/dashboard/+page.svelte @@ -1,68 +1,6 @@ -
- - -
-
- - {#if $authStore.isAuthenticated} - - {:else } -
-
- -
-
- {/if} -
- - -
-
\ No newline at end of file diff --git a/src/routes/app/statistics/+page.svelte b/src/routes/app/statistics/+page.svelte new file mode 100644 index 0000000..d329b11 --- /dev/null +++ b/src/routes/app/statistics/+page.svelte @@ -0,0 +1 @@ +这是数据 \ No newline at end of file