From c43f1d738953a14da79690f5448e0b01f9aab438 Mon Sep 17 00:00:00 2001 From: cnliucheng Date: Wed, 8 Jul 2026 11:33:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=B1=E8=89=B2=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E8=AE=BE=E6=96=BD=20(system=20theme=20+=20?= =?UTF-8?q?=E8=B7=9F=E9=9A=8F=E7=B3=BB=E7=BB=9F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 11 +++++++++++ app.json | 2 ++ app.wxss | 1 + theme.json | 16 ++++++++++++++++ utils/darkMode.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++ utils/theme.js | 13 +++++++++---- 6 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 theme.json create mode 100644 utils/darkMode.js diff --git a/app.js b/app.js index 5654775..3cb81a3 100644 --- a/app.js +++ b/app.js @@ -1,9 +1,20 @@ const themeMod = require('./utils/theme') const cloud = require('./utils/cloud') const storage = require('./utils/storage') +const darkMod = require('./utils/darkMode') App({ async onLaunch() { + // Init dark mode listener (refreshes all open pages when system theme changes) + darkMod.watchDarkMode((isDark) => { + const pages = getCurrentPages() + pages.forEach(p => { + if (p && typeof p.applyThemeToPage === 'function') { + p.applyThemeToPage() + } + }) + }) + // Init cloud storage (no-op if not configured) cloud.init() diff --git a/app.json b/app.json index c28af1c..345e880 100644 --- a/app.json +++ b/app.json @@ -25,5 +25,7 @@ { "pagePath": "pages/settings/settings", "text": "设置" } ] }, + "darkmode": true, + "themeLocation": "theme.json", "sitemapLocation": "sitemap.json" } diff --git a/app.wxss b/app.wxss index 84a2f35..a390cae 100644 --- a/app.wxss +++ b/app.wxss @@ -11,6 +11,7 @@ page { font-size: 28rpx; color: var(--text); background-color: var(--bg) !important; + transition: background-color 0.3s ease, color 0.3s ease; } .container { diff --git a/theme.json b/theme.json new file mode 100644 index 0000000..7951b87 --- /dev/null +++ b/theme.json @@ -0,0 +1,16 @@ +{ + "light": { + "navigationBarBackgroundColor": "#FF6B35", + "navigationBarTextStyle": "white", + "backgroundColor": "#F5F5F5", + "backgroundColorTop": "#F5F5F5", + "backgroundColorBottom": "#F5F5F5" + }, + "dark": { + "navigationBarBackgroundColor": "#FF6B35", + "navigationBarTextStyle": "white", + "backgroundColor": "#0F0F12", + "backgroundColorTop": "#0F0F12", + "backgroundColorBottom": "#0F0F12" + } +} diff --git a/utils/darkMode.js b/utils/darkMode.js new file mode 100644 index 0000000..2611d99 --- /dev/null +++ b/utils/darkMode.js @@ -0,0 +1,49 @@ +/** + * 系统深色模式监听 — 提供初始值与变更回调 + * 旧设备 wx.onThemeChange 失败时退化为只读一次 + */ + +const STORAGE_KEY = 'dark_mode_pref' + +function _readSystemTheme() { + try { + const info = wx.getSystemInfoSync() + return info.theme === 'dark' ? true : false + } catch (e) { + return false + } +} + +function getInitialDarkMode() { + const pref = wx.getStorageSync(STORAGE_KEY) || 'system' + if (pref === 'system') return _readSystemTheme() + return pref === 'dark' +} + +function getPref() { + return wx.getStorageSync(STORAGE_KEY) || 'system' +} + +function setPref(value) { + if (!['system', 'light', 'dark'].includes(value)) return + wx.setStorageSync(STORAGE_KEY, value) +} + +function watchDarkMode(onChange) { + if (typeof wx.onThemeChange !== 'function') return + try { + wx.onThemeChange(({ theme }) => { + const pref = getPref() + if (pref === 'system') onChange(theme === 'dark') + }) + } catch (e) { + // 旧设备不支持,忽略 + } +} + +module.exports = { + getInitialDarkMode, + getPref, + setPref, + watchDarkMode +} diff --git a/utils/theme.js b/utils/theme.js index c7eab33..67109de 100644 --- a/utils/theme.js +++ b/utils/theme.js @@ -94,19 +94,24 @@ const setTheme = (id) => { return theme } -const getThemeStyle = (theme) => { +const getThemeStyle = (theme, isDark = false) => { const t = theme || getCurrentTheme() - return `${BASE_VARS}--primary:${t.primary};--primary-light:${t.primaryLight};--primary-bg:${t.primaryBg};--primary-rgb:${t.primaryRgb};` + const baseVars = isDark + ? '--text:#E5E5E7;--text-secondary:#98989F;--bg:#0F0F12;--card-bg:#1C1C1E;--border:#2C2C2E;--success:#30D158;' + : '--text:#333333;--text-secondary:#999999;--bg:#F5F5F5;--card-bg:#FFFFFF;--border:#EEEEEE;--success:#4CAF50;' + return `${baseVars}--primary:${t.primary};--primary-light:${t.primaryLight};--primary-bg:${t.primaryBg};--primary-rgb:${t.primaryRgb};` } const applyThemeToPage = (self) => { + const darkMod = require('./darkMode') const theme = getCurrentTheme() - const nextStyle = getThemeStyle(theme) + const isDark = darkMod.getInitialDarkMode() + const nextStyle = getThemeStyle(theme, isDark) // Skip setData if nothing changed — avoid unnecessary re-renders on every onShow if (self.data && self.data.themeStyle === nextStyle) { return } - self.setData({ theme, themeStyle: nextStyle }) + self.setData({ theme, themeStyle: nextStyle, isDark }) _setNavBarColor(theme.primary) }