diff --git a/app/app.vue b/app/app.vue index 8bf81d9..2f90720 100644 --- a/app/app.vue +++ b/app/app.vue @@ -1,15 +1,17 @@ @@ -76,7 +78,8 @@ provide('slideDirection', slideDirection) .slide-right-leave-to { transform: translateX(100%); } -:root{ + +:root { --safe-area-inset-bottom: env(safe-area-inset-bottom); } \ No newline at end of file diff --git a/app/plugins/http.js b/app/plugins/http.ts similarity index 100% rename from app/plugins/http.js rename to app/plugins/http.ts diff --git a/app/plugins/i18n.js b/app/plugins/i18n.ts similarity index 85% rename from app/plugins/i18n.js rename to app/plugins/i18n.ts index 127eda7..ad5fb7c 100644 --- a/app/plugins/i18n.js +++ b/app/plugins/i18n.ts @@ -1,4 +1,4 @@ - +import type { Locale as TypeLocale } from '#i18n' import { Locale } from 'vant' import enUS from 'vant/es/locale/lang/en-US' import zhCN from 'vant/es/locale/lang/zh-CN' @@ -6,7 +6,7 @@ import jaJP from 'vant/es/locale/lang/ja-JP' import zhTW from 'vant/es/locale/lang/zh-TW' export default defineNuxtPlugin(() => { - + // 载入 vant 语言包 Locale.use('zh-CN', zhCN) Locale.use('en-US', enUS) Locale.use('ja-JP', jaJP) @@ -15,9 +15,11 @@ export default defineNuxtPlugin(() => { if (import.meta.client) { const i18n = useNuxtApp().$i18n const { setLocale } = i18n + const lang = localStorage.getItem('lang') + if (lang) { - setLocale(lang) + setLocale(lang as TypeLocale) Locale.use(lang) } else { diff --git a/app/styles/default-theme.css b/app/styles/default-theme.css new file mode 100644 index 0000000..67a6e9b --- /dev/null +++ b/app/styles/default-theme.css @@ -0,0 +1,4 @@ +:root:root { + --van-primary-color: var(--c-primary); + --van-cell-group-inset-padding: 0; +} diff --git a/app/styles/global.css b/app/styles/global.css new file mode 100644 index 0000000..386966d --- /dev/null +++ b/app/styles/global.css @@ -0,0 +1,14 @@ +#__nuxt { + margin: 0; + padding: 0; +} + +html { + background: var(--van-gray-1); + color-scheme: light; +} + +html.dark { + background: #222; + color-scheme: dark; +} diff --git a/app/styles/vars.css b/app/styles/vars.css new file mode 100644 index 0000000..07f427f --- /dev/null +++ b/app/styles/vars.css @@ -0,0 +1,4 @@ +:root { + --c-primary: #3554AF; + --c-primary-active: #3554AF; +} diff --git a/nuxt.config.js b/nuxt.config.js index 1d3da5c..7645cea 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -1,18 +1,9 @@ -// 导入环境变量处理库 import dotenv from 'dotenv' -// 导入 Node.js 进程模块 import process from 'node:process' -// 导入预加载工具函数 import preload from './app/utils/preload' -// 导入国际化语言配置 import { currentLocales } from './i18n/i18n' - -// 设置环境变量文件路径,默认使用 .env.test const envFile = process.env.ENV_FILE || '.env.test' -// 加载环境变量配置 dotenv.config({ path: `./env/${envFile}` }) - -// 过滤出以 NUXT_PUBLIC_ 开头的环境变量作为公共配置 const publicConfig = Object.entries(process.env) .filter(([key]) => key.startsWith('NUXT_PUBLIC_')) .reduce((config, [key, value]) => { @@ -21,38 +12,38 @@ const publicConfig = Object.entries(process.env) }, {}) export default defineNuxtConfig({ - // 注册 Nuxt 模块 - modules: [ - '@nuxt/image', // 图片优化模块 - '@vant/nuxt', // Vant UI 组件库 - '@unocss/nuxt', // 原子化 CSS 框架 - '@nuxtjs/i18n', // 国际化模块 - ], - // 运行时配置 + modules: [ + '@vant/nuxt', + '@unocss/nuxt', + '@nuxt/image', + '@nuxtjs/color-mode', + '@nuxtjs/i18n', + ], runtimeConfig: { - // 私有配置,只在服务端可用 + // 私有配置,只有在服务端可用 apiSecret: process.env.NUXT_API_SECRET || 'default_secret', // 公共配置,客户端和服务端都可用 public: publicConfig, }, - // CSS 配置 css: [ - '@unocss/reset/tailwind.css', // 重置默认样式 + '@unocss/reset/tailwind.css', '@/static/styles/default-theme.css', ], - // PostCSS 配置 + postcss: { plugins: { - 'autoprefixer': {}, // 自动添加 CSS 前缀 - // 移动端适配插件配置 + 'autoprefixer': {}, + + // https://github.com/wswmsword/postcss-mobile-forever 'postcss-mobile-forever': { - appSelector: '#__nuxt', // 根选择器 - viewportWidth: 375, // 设计稿宽度 - maxDisplayWidth: 600, // 最大显示宽度 - exclude: /@nuxt/, // 排除的文件 - border: true, // 显示边框 + appSelector: '#__nuxt', + viewportWidth: 375, + maxDisplayWidth: 600, + // devtools excluded + exclude: /@nuxt/, + border: true, rootContainingBlockSelectorList: [ 'van-tabbar', 'van-popup', @@ -61,153 +52,89 @@ export default defineNuxtConfig({ }, }, - // 国际化配置 - i18n: { - locales: currentLocales, // 支持的语言列表 - lazy: true, // 懒加载语言包 - strategy: 'no_prefix', // URL 策略:不添加语言前缀 - detectBrowserLanguage: { - useCookie: true, // 使用 cookie 存储语言选择 - cookieKey: 'i18n_redirected', // cookie 键名 - redirectOn: 'root', // 仅在根路径重定向 - alwaysRedirect: true, // 总是重定向 - fallbackLocale: 'zh-CN' // 默认语言 - }, - langDir: 'locales', // 语言文件目录 - defaultLocale: 'zh-CN', // 默认语言 - vueI18n: './i18n/i18n.config.ts', // Vue I18n 配置文件 + colorMode: { + classSuffix: '', + preference: 'system', + fallback: 'light', + storageKey: 'nuxt-color-mode', + }, + + i18n: { + locales: currentLocales, + lazy: true, + strategy: 'no_prefix', + detectBrowserLanguage: { + useCookie: true, + cookieKey: 'i18n_redirected', + redirectOn: 'root', + alwaysRedirect: true, + fallbackLocale: 'zh-CN' + }, + langDir: 'locales', + defaultLocale: 'zh-CN', + vueI18n: './i18n/i18n.config.ts', }, - // 应用配置 app: { - // 布局过渡动画 layoutTransition: { name: 'layout', mode: 'out-in' }, - // 头部配置 head: { - // 视口配置 viewport: 'width=device-width,initial-scale=1,viewport-fit=cover', - // 链接配置 link: [ - { rel: 'icon', href: '/favicon.ico', sizes: 'any' }, // 网站图标 - { rel: 'preload', as: 'style', href: '/critical.css' }, // 预加载关键 CSS - { rel: 'preconnect', href: '你的API域名' }, // 预连接 API 域名 - { rel: 'dns-prefetch', href: '你的API域名' }, // DNS 预解析 + { rel: 'icon', href: '/favicon.ico', sizes: 'any' }, ], - // Meta 标签配置 meta: [ - { name: 'apple-mobile-web-app-capable', content: 'yes' }, // iOS 应用模式 - { name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' }, // iOS 状态栏样式 - { name: 'theme-color', media: '(prefers-color-scheme: light)', content: '#ffffff' }, // 浅色主题色 - { name: 'theme-color', media: '(prefers-color-scheme: dark)', content: '#222222' }, // 深色主题色 - { name: 'description', content: '你的网站描述' }, // SEO 描述 - { 'http-equiv': 'x-dns-prefetch-control', content: 'on' }, // DNS 预解析控制 + { name: 'viewport', content: 'width=device-width, initial-scale=1, viewport-fit=cover,user-scalable=no' }, + { name: 'apple-mobile-web-app-capable', content: 'yes' }, + { name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' }, + { name: 'theme-color', media: '(prefers-color-scheme: light)', content: '#ffffff' }, + { name: 'theme-color', media: '(prefers-color-scheme: dark)', content: '#222222' }, ], - // 脚本配置 script: [ - { innerHTML: preload(), type: 'text/javascript', tagPosition: 'head' }, // 预加载脚本 - // 性能监控脚本 - { - innerHTML: ` - window.performance.mark('app-start'); - new PerformanceObserver((entryList) => { - for (const entry of entryList.getEntries()) { - console.log('FCP:', entry.startTime); - } - }).observe({entryTypes: ['paint']}); - `, - type: 'text/javascript', - tagPosition: 'head' - } + { innerHTML: preload(), type: 'text/javascript', tagPosition: 'head' }, ], }, }, - // Vite 构建配置 vite: { build: { - target: 'esnext', // 构建目标 - // Rollup 配置 - rollupOptions: { - output: { - manualChunks: { - 'vant': ['vant'], // Vant 单独打包 - 'vendor': ['vue', 'vue-router'] // 核心库单独打包 - } - } - }, - minify: 'terser', // 使用 terser 压缩 - terserOptions: { - compress: { - drop_console: true, // 移除 console - drop_debugger: true // 移除 debugger - } - } + target: 'esnext', }, - // 依赖优化配置 optimizeDeps: { include: [ - '@intlify/core-base', // I18n 核心 - '@intlify/shared', // I18n 共享库 - 'is-https', // HTTPS 检测 - 'vant', // Vant UI - '@vant/use', // Vant Hooks - '@vueuse/core', // VueUse 工具集 + '@intlify/core-base', + '@intlify/shared', + 'is-https', ], }, }, - // 实验性功能 experimental: { - typedPages: true, // 启用页面类型 + typedPages: true, }, - // 开发工具 devtools: { - enabled: true, // 启用开发工具 + enabled: true, }, - // TypeScript 配置 typescript: { - shim: false, // 禁用 shim + shim: false, }, - // 功能特性配置 features: { - inlineStyles: false, // 禁用内联样式 + // For UnoCSS + inlineStyles: false, }, - // 未来特性配置 future: { - compatibilityVersion: 4, // 兼容性版本 + compatibilityVersion: 4, }, - - // Nuxt 兼容性日期 - compatibilityDate: '2025-01-09', // 确保未来版本兼容性 - - // 开发服务器配置 + // 指定 Nuxt 应用程序的兼容性日期,确保应用程序在未来的 Nuxt 版本中保持稳定性 + compatibilityDate: '2025-01-09', devServer: { - host: '0.0.0.0', // 主机地址 - port: 3000, // 端口号 + host: '0.0.0.0', // Set the host to 'localhost' + port: 3000, // Set the port to 3000 or any other port you prefer }, - - // 图片优化配置 - image: { - provider: 'ipx', // 图片处理提供者 - // 响应式断点 - screens: { - xs: 320, // 超小屏幕 - sm: 640, // 小屏幕 - md: 768, // 中等屏幕 - lg: 1024, // 大屏幕 - xl: 1280, // 超大屏幕 - xxl: 1536, // 特大屏幕 - }, - quality: 80, // 图片质量 - format: ['webp', 'jpg'], // 支持的格式 - placeholder: true, // 启用占位图 - blur: 3 // 模糊加载效果 - } }) \ No newline at end of file