diff --git a/.gitignore b/.gitignore index 2b3e889..eee2459 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ backend-cf/.dev.vars frontend/node_modules/ frontend/.nuxt/ +frontend/.output/ # wrangler files .wrangler diff --git a/frontend/app.vue b/frontend/app.vue index 381db79..0eb49c1 100644 --- a/frontend/app.vue +++ b/frontend/app.vue @@ -1,31 +1,168 @@ + + + + \ No newline at end of file diff --git a/frontend/assets/css/main.css b/frontend/assets/css/main.css index f0f4e6d..5045a42 100644 --- a/frontend/assets/css/main.css +++ b/frontend/assets/css/main.css @@ -2,6 +2,49 @@ @tailwind components; @tailwind utilities; +/* 1. 全局基础样式(亮色模式) */ +html { + color-scheme: light !important; /* 强制亮色原生控件 */ +} + body { - @apply bg-gray-50 text-gray-900 min-h-screen; + @apply bg-gray-50 text-gray-900 min-h-screen transition-colors duration-300; +} + +/* 2. 当 JS 加上 .dark 类时,强制深色模式 */ +html.dark { + color-scheme: dark !important; /* 【关键】强制深色原生控件(解决滚动条/表单亮色问题) */ +} + +html.dark body { + @apply bg-gray-950 text-gray-100; +} + +/* 3. 手动接管深色模式下的滚动条样式,确保视觉绝对统一 */ +html.dark { + --scrollbar-bg: #1f2937; /* gray-800 */ + --scrollbar-thumb: #4b5563; /* gray-600 */ + --scrollbar-thumb-hover: #6b7280; /* gray-500 */ +} + +/* Webkit 内核浏览器(Chrome, Safari, Edge) */ +html.dark ::-webkit-scrollbar { + width: 8px; + height: 8px; + background-color: var(--scrollbar-bg); +} + +html.dark ::-webkit-scrollbar-thumb { + background-color: var(--scrollbar-thumb); + border-radius: 4px; +} + +html.dark ::-webkit-scrollbar-thumb:hover { + background-color: var(--scrollbar-thumb-hover); +} + +/* Firefox 浏览器 */ +html.dark * { + scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-bg); + scrollbar-width: thin; } diff --git a/frontend/composables/useDarkMode.ts b/frontend/composables/useDarkMode.ts new file mode 100644 index 0000000..9c62731 --- /dev/null +++ b/frontend/composables/useDarkMode.ts @@ -0,0 +1,60 @@ +// composables/useDarkMode.ts +export function useDarkMode() { + // 1. 核心状态:Cookie 为空字符串代表“跟随系统” + const colorMode = useCookie('dark-mode', { + default: () => '', + watch: true, + maxAge: 60 * 60 * 24 * 365, // 1 year + }) + + // 2. 计算属性:有 Cookie 用 Cookie,没 Cookie 读系统偏好 + const isDark = computed({ + get: () => { + if (colorMode.value === 'dark') return true + if (colorMode.value === 'light') return false + + // SSR 阶段默认返回 false,客户端读取系统偏好 + if (import.meta.client) { + return window.matchMedia('(prefers-color-scheme: dark)').matches + } + return false + }, + set: (val: boolean) => { + // 只有手动设置时,才往 Cookie 写入明确的值 + colorMode.value = val ? 'dark' : 'light' + }, + }) + + // 3. 客户端专属逻辑:同步 class 与监听系统变化 + if (import.meta.client) { + // 监听 isDark 变化,同步到 标签 + watch(isDark, (val) => { + document.documentElement.classList.toggle('dark', val) + }, { immediate: true }) // immediate: true 确保首次加载时也能同步 + + // 【新增】监听系统主题变化(仅在“跟随系统”模式下生效) + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)') + const handleSystemChange = (e: MediaQueryListEvent) => { + // 只有当 Cookie 为空(即用户没有手动设置过偏好)时,才响应系统变化 + if (!colorMode.value) { + document.documentElement.classList.toggle('dark', e.matches) + } + } + mediaQuery.addEventListener('change', handleSystemChange) + + // 组件卸载时清理监听器 + onUnmounted(() => mediaQuery.removeEventListener('change', handleSystemChange)) + } + + // 4. 手动切换 + function toggle() { + isDark.value = !isDark.value + } + + // 5. 【新增】恢复跟随系统(清空 Cookie) + function clearPreference() { + colorMode.value = '' + } + + return { isDark, toggle, clearPreference } +} \ No newline at end of file diff --git a/frontend/nuxt.config.ts b/frontend/nuxt.config.ts index 4681883..04b4ef1 100644 --- a/frontend/nuxt.config.ts +++ b/frontend/nuxt.config.ts @@ -1,7 +1,17 @@ export default defineNuxtConfig({ compatibilityDate: "2026-07-14", devtools: { enabled: true }, - modules: ["@nuxtjs/tailwindcss"], + modules: ["@nuxtjs/tailwindcss", "@nuxt/icon"], + icon: { + serverBundle: { + collections: ["mdi"], + }, + }, + tailwindcss: { + config: { + darkMode: "class", + }, + }, nitro: { preset: "cloudflare_module", devProxy: { diff --git a/frontend/package.json b/frontend/package.json index 28d1ad5..bde0a43 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,11 +9,14 @@ "preview": "nuxt preview" }, "dependencies": { + "@nuxtjs/tailwindcss": "^6.13.0", "nuxt": "^3.15.0", - "vue": "^3.5.0", - "@nuxtjs/tailwindcss": "^6.13.0" + "vue": "^3.5.0" }, "devDependencies": { + "@iconify-json/fa-solid": "^1.2.2", + "@iconify-json/mdi": "^1.2.3", + "@nuxt/icon": "^1.15.0", "tailwindcss": "^3.4.0" } } diff --git a/frontend/pages/about.vue b/frontend/pages/about.vue index 9c9b320..b468f38 100644 --- a/frontend/pages/about.vue +++ b/frontend/pages/about.vue @@ -1,13 +1,13 @@