Skip to content

Commit d7e2c1b

Browse files
committed
feat(ux): 添加暗色/亮色模式切换(跟随系统,持久化 localStorage)
1 parent 2c832ba commit d7e2c1b

3 files changed

Lines changed: 50 additions & 2 deletions

File tree

app/app.vue

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
<template>
2-
<NConfigProvider>
2+
<NConfigProvider :theme="theme">
33
<NuxtLoadingIndicator color="#18a058" />
44
<NuxtLayout>
55
<NuxtPage />
66
</NuxtLayout>
77
</NConfigProvider>
88
</template>
9+
10+
<script setup lang="ts">
11+
import { darkTheme, lightTheme } from 'naive-ui'
12+
13+
const { isDark } = useTheme()
14+
const theme = computed(() => isDark.value ? darkTheme : lightTheme)
15+
</script>
16+
17+
<style>
18+
body {
19+
background-color: v-bind('isDark ? "#101014" : "#f5f5f5"');
20+
transition: background-color 0.3s;
21+
}
22+
</style>

app/components/AppHeader.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,14 @@
2727
<NIcon><MailOutline /></NIcon>
2828
</NButton>
2929
</NBadge>
30+
</template>
31+
32+
<!-- 深色/浅色模式切换 -->
33+
<NButton text style="font-size: 20px; line-height: 1" @click="toggle">
34+
<NIcon><component :is="isDark ? SunnyOutline : MoonOutline" /></NIcon>
35+
</NButton>
3036

37+
<template v-if="authStore.isLoggedIn">
3138
<!-- 登出按钮 -->
3239
<NButton size="small" @click="handleLogout">
3340
登出
@@ -44,10 +51,11 @@
4451
</template>
4552

4653
<script setup lang="ts">
47-
import { MailOutline } from '@vicons/ionicons5'
54+
import { MailOutline, MoonOutline, SunnyOutline } from '@vicons/ionicons5'
4855
4956
const authStore = useAuthStore()
5057
const msgApi = useMessageApi()
58+
const { isDark, toggle } = useTheme()
5159
5260
const unreadCount = ref(0)
5361

app/composables/useTheme.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export const useTheme = () => {
2+
const isDark = useState('theme:dark', () => false)
3+
4+
// 初始化:读取 localStorage,fallback 到系统主题
5+
if (import.meta.client) {
6+
const saved = localStorage.getItem('theme')
7+
if (saved === 'dark') {
8+
isDark.value = true
9+
}
10+
else if (saved === 'light') {
11+
isDark.value = false
12+
}
13+
else {
14+
isDark.value = window.matchMedia('(prefers-color-scheme: dark)').matches
15+
}
16+
}
17+
18+
const toggle = () => {
19+
isDark.value = !isDark.value
20+
if (import.meta.client) {
21+
localStorage.setItem('theme', isDark.value ? 'dark' : 'light')
22+
}
23+
}
24+
25+
return { isDark, toggle }
26+
}

0 commit comments

Comments
 (0)