fix(ui): 初始背景跟随外观 + 修复跟随系统

- app.config 移除写死的浅色背景,交给 theme.json 按系统外观选择首帧底色
- 跟随系统模式增加 setInterval 轮询兜底,onThemeChange 不回调时也能跟上切换
This commit is contained in:
2026-08-18 23:42:01 +08:00
parent fd58135fdb
commit d72e297eb6
6 changed files with 38 additions and 13 deletions
Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
{"darkmode":true,"themeLocation":"theme.json","pages":["pages/index/index","pages/shop/index","pages/shop/detail/index","pages/product/index","pages/diy/index","pages/diy/stickerEdit/index","pages/checkout/index","pages/designList/index","pages/orders/index","pages/profile/index","pages/service/index","pages/wordcloud/index","pages/orderDetail/index","pages/address/index","pages/settings/index","pages/agreement/index","pages/userDatabase/index"],"window":{"backgroundTextStyle":"dark","navigationStyle":"custom","navigationBarBackgroundColor":"#faf7f2","backgroundColor":"#faf7f2","backgroundColorTop":"#faf7f2","backgroundColorBottom":"#faf7f2","navigationBarTextStyle":"black"},"tabBar":{"custom":true,"list":[{"pagePath":"pages/index/index","text":"首页"},{"pagePath":"pages/shop/index","text":"商品"},{"pagePath":"pages/designList/index","text":"设计清单"},{"pagePath":"pages/orders/index","text":"订单"},{"pagePath":"pages/profile/index","text":"我的"}]}}
{"darkmode":true,"themeLocation":"theme.json","pages":["pages/index/index","pages/shop/index","pages/shop/detail/index","pages/product/index","pages/diy/index","pages/diy/stickerEdit/index","pages/checkout/index","pages/designList/index","pages/orders/index","pages/profile/index","pages/service/index","pages/wordcloud/index","pages/orderDetail/index","pages/address/index","pages/settings/index","pages/agreement/index","pages/userDatabase/index"],"window":{"navigationStyle":"custom"},"tabBar":{"custom":true,"list":[{"pagePath":"pages/index/index","text":"首页"},{"pagePath":"pages/shop/index","text":"商品"},{"pagePath":"pages/designList/index","text":"设计清单"},{"pagePath":"pages/orders/index","text":"订单"},{"pagePath":"pages/profile/index","text":"我的"}]}}
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -9
View File
@@ -23,16 +23,9 @@ export default defineAppConfig({
'pages/userDatabase/index'
],
window: {
backgroundTextStyle: 'dark',
// 初始窗口/导航背景交给 theme.json 按系统外观自动选择,
// 避免首帧先固定成浅色再被 JS 切到深色而闪烁。
navigationStyle: 'custom',
// 顶部/窗口颜色先显式固定为小程序浅色主题,避免 iOS 顶部区域跟随系统深色;
// 应用启动后页面 Hook 会按小程序内主题实时覆盖上面的值。
navigationBarBackgroundColor: '#faf7f2',
backgroundColor: '#faf7f2',
backgroundColorTop: '#faf7f2',
backgroundColorBottom: '#faf7f2',
// 状态栏文字默认黑字;各页面 useStatusBar 会按小程序主题覆盖它。
navigationBarTextStyle: 'black',
},
tabBar: {
custom: true,
+20 -1
View File
@@ -1,4 +1,4 @@
import { createContext, useContext, useState, useCallback, useEffect } from 'react'
import { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react'
import Taro, { useDidShow } from '@tarojs/taro'
import { View } from '@tarojs/components'
import { getTheme, setTheme as saveTheme, resolveTheme, setDetectedSystemTheme, type ThemeMode } from '../utils/store'
@@ -31,6 +31,7 @@ type ThemeChangeApi = {
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, set] = useState<ThemeMode>(getTheme())
const [resolvedTheme, setResolved] = useState<'light' | 'dark'>(resolveTheme(getTheme()))
const systemThemeRef = useRef<'light' | 'dark' | null>(null)
const updateResolved = useCallback((mode: ThemeMode) => {
setResolved(resolveTheme(mode))
@@ -42,6 +43,7 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
*/
const updateFromSystem = useCallback((t: 'light' | 'dark') => {
setDetectedSystemTheme(t)
systemThemeRef.current = t
if (getTheme() === 'auto') {
setResolved(t)
}
@@ -102,6 +104,23 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
}
}, [updateFromSystem])
// 部分机型/工具上 onThemeChange 不回调,自动模式再轮询兜底,保证系统切换能跟上
useEffect(() => {
if (theme !== 'auto') return
const timer = setInterval(() => {
try {
const info = Taro.getAppBaseInfo()
const next = info.theme === 'dark' ? 'dark' : 'light'
if (next !== systemThemeRef.current) {
updateFromSystem(next)
}
} catch {
/* ignore */
}
}, 2000)
return () => clearInterval(timer)
}, [theme, updateFromSystem])
// 广播实际生效主题,供 custom-tab-bar 等独立组件订阅
useEffect(() => {
Taro.eventCenter.trigger(THEME_CHANGE_EVENT, resolvedTheme)
+13
View File
@@ -42,3 +42,16 @@ test('app sets page background before first render without a blinking full fade'
assert.match(appSource, /componentWillMount/)
assert.doesNotMatch(appCss, /animation:\s*page-fade-in/)
})
test('delegates initial background to themeLocation instead of hardcoding light', () => {
const config = read('src/app.config.ts')
assert.match(config, /themeLocation:\s*'theme\.json'/)
assert.doesNotMatch(config, /navigationBarBackgroundColor:\s*'#faf7f2'/)
assert.doesNotMatch(config, /backgroundColorTop:\s*'#faf7f2'/)
})
test('polls the system theme while following the system', () => {
const ctx = read('src/context/ThemeContext.tsx')
assert.match(ctx, /setInterval/)
assert.match(ctx, /getAppBaseInfo\(\)/)
})