fix: 顶栏颜色跟随小程序主题并保留跟随系统
This commit is contained in:
@@ -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'>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user