fix: 顶栏颜色跟随小程序主题并保留跟随系统

This commit is contained in:
2026-08-06 19:54:05 +08:00
parent 9716148f15
commit f4f54a8720
84 changed files with 484 additions and 124 deletions
+34 -38
View File
@@ -1,56 +1,52 @@
import Taro from '@tarojs/taro'
import { useEffect, useState } from 'react'
import { useEffect, useState, useCallback } from 'react'
import { View, Text } from '@tarojs/components'
import { getMe, logout } from '../../utils/api'
import { getUserInfoRaw, clearUserInfo, isMockOpenid } from '../../utils/store'
import { isAuthVerified } from '../../utils/authState'
import { THEME_CHANGE_EVENT } from '../../context/ThemeContext'
type GuardState = 'checking' | 'ok' | 'denied'
/**
* 登录守卫:不仅看本地是否有 openid,还要求本地用户与云端校验一致。
* - 本地 openid 是历史 mock 残留 -> 判定不一致,清掉并引导重新登录
* - 本地有 openid 但后端 getMe 校验失败/用户不存在 -> 判定不一致,清掉并引导重新登录
* - 本地与云端 ID/openid 一致 -> 放行
* 登录守卫:首次进入做一次云端校验并缓存结果,
* 之后同一 openid 直接读取缓存放行,不再重复请求后端。
* 每次 Tab 切换/重新显示时再核对一次,避免登录完成后还停留在旧的“未登录”态。
*/
export default function LoginGuard(props: { children: React.ReactNode }) {
const [state, setState] = useState<GuardState>('checking')
useEffect(() => {
const localUser = getUserInfoRaw()
// 本地根本没登录信息
if (!localUser?.openid) {
setState('denied')
return
}
// 本地是旧版 mock 残留:与真实云端不一致,强制重新登录
if (isMockOpenid(localUser.openid)) {
clearUserInfo()
logout()
setState('denied')
return
}
// 本地有真实 openid:到后端校验是否与云端一致
getMe()
.then((me) => {
const consistent = !!me && !!me.id && me.openid === localUser.openid
if (consistent) {
setState('ok')
} else {
clearUserInfo()
logout()
setState('denied')
}
const verify = useCallback(() => {
let cancelled = false
isAuthVerified()
.then((ok) => {
if (!cancelled) setState(ok ? 'ok' : 'denied')
})
.catch(() => {
// 后端不可用时的谨慎处理:不静默放行,也不抹掉本地,
// 返回 denied 让用户尝试重新登录(后端恢复后即可通过)
setState('denied')
if (!cancelled) setState('denied')
})
return () => {
cancelled = true
}
}, [])
useEffect(() => {
const cancel = verify()
const onTab = () => {
verify()
}
const onTheme = () => {
verify()
}
Taro.eventCenter.on('tabBarChange', onTab)
Taro.eventCenter.on(THEME_CHANGE_EVENT, onTheme)
Taro.eventCenter.on('authStateChanged', onTab)
return () => {
cancel()
Taro.eventCenter.off('tabBarChange', onTab)
Taro.eventCenter.off(THEME_CHANGE_EVENT, onTheme)
Taro.eventCenter.off('authStateChanged', onTab)
}
}, [verify])
if (state === 'checking') {
return (
<View className='login-guard'>
+26
View File
@@ -0,0 +1,26 @@
import { PageMeta, NavigationBar } from '@tarojs/components'
import { useThemeContext } from '../../context/ThemeContext'
interface ThemedPageMetaProps {
/** 强制顶部使用深色背景(用于浅色主题但顶部是深色大图的页面) */
darkTop?: boolean
}
export default function ThemedPageMeta({ darkTop = false }: ThemedPageMetaProps) {
const { resolvedTheme } = useThemeContext()
const isDark = resolvedTheme === 'dark' || darkTop
const bg = isDark ? '#191919' : '#ffffff'
const frontColor = isDark ? '#ffffff' : '#000000'
return (
<PageMeta
backgroundColor={bg}
backgroundColorTop={bg}
backgroundColorBottom={bg}
backgroundTextStyle={isDark ? 'light' : 'dark'}
rootBackgroundColor={bg}
>
<NavigationBar frontColor={frontColor} backgroundColor={bg} />
</PageMeta>
)
}