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
+112
View File
@@ -0,0 +1,112 @@
import Taro from '@tarojs/taro'
import { getMe, logout, getToken } from './api'
import { getUserInfoRaw, clearUserInfo, isMockOpenid } from './store'
const CACHE_KEY = 'smart_auth_verified'
const TTL = 30 * 60 * 1000
interface CacheEntry {
openid: string
ok: boolean
at: number
}
/**
* 登录态全局缓存:首次校验通过后用内存+本地双缓存记住结果,
* 之后进设计清单/订单等受保护页面不再重复请求后端。
* 登录、退出登录、切换账号都会通过 invalidateAuthCache() 清掉缓存。
*/
let verifiedCache: CacheEntry | null = null
let inflight: Promise<boolean> | null = null
export function invalidateAuthCache(): void {
verifiedCache = null
inflight = null
try {
Taro.removeStorageSync(CACHE_KEY)
} catch {
/* ignore */
}
}
function readCache(openid: string): boolean | null {
const entry = verifiedCache || (() => {
try {
const raw = Taro.getStorageSync(CACHE_KEY)
return raw && typeof raw === 'object' ? raw as CacheEntry : null
} catch {
return null
}
})()
if (!entry || entry.openid !== openid) return null
if (Date.now() - entry.at > TTL) return null
verifiedCache = entry
return entry.ok
}
function writeCache(openid: string, ok: boolean): void {
const entry: CacheEntry = { openid, ok, at: Date.now() }
verifiedCache = entry
try {
Taro.setStorageSync(CACHE_KEY, entry)
} catch {
/* ignore */
}
}
/**
* 本地已有真实 openid + token 时视为“本地已登录”。
* 后端校验失败(网络抖动/服务端暂时不可用)不直接锁死页面,
* 由后续 401 或主动登出再重置状态。
*/
function hasLocalSession(): boolean {
const user = getUserInfoRaw()
return !!user?.openid && !isMockOpenid(user.openid) && !!user.accessToken && !!getToken()
}
export async function isAuthVerified(): Promise<boolean> {
const localUser = getUserInfoRaw()
if (!localUser?.openid) {
console.log('[AuthGuard] 无本地用户,判定未登录')
return false
}
console.log('[AuthGuard] 本地用户 openid=', localUser.openid)
if (isMockOpenid(localUser.openid)) {
clearUserInfo()
logout()
invalidateAuthCache()
return false
}
const cached = readCache(localUser.openid)
if (cached !== null) {
console.log('[AuthGuard] 命中本地缓存 ok=', cached)
return cached
}
if (!inflight) {
inflight = getMe()
.then((me) => {
console.log('[AuthGuard] getMe 返回:', JSON.stringify(me))
const consistent = !!me && !!me.id && me.openid === localUser.openid
console.log('[AuthGuard] 一致性=', consistent)
if (consistent) {
writeCache(localUser.openid, true)
return true
}
clearUserInfo()
logout()
invalidateAuthCache()
return false
})
.catch((e) => {
console.error('[AuthGuard] getMe 失败,走本地会话兜底:', e)
return hasLocalSession()
})
.finally(() => {
inflight = null
})
}
return inflight
}
+17 -6
View File
@@ -2,6 +2,7 @@ import Taro from '@tarojs/taro'
import type { DesignItem, OrderItem, AddressItem, StickerItem } from '../types'
import { PRODUCT_ICON_MAP } from './productConfig'
import { invalidateAuthCache } from './authState'
// 重新导出类型,供各页面从 store 直接引用(修正原「声明但不导出」的编译错误)
export type { DesignItem, OrderItem, AddressItem, StickerItem }
@@ -66,6 +67,8 @@ export function setUserInfoRaw(info: any) {
Taro.setStorageSync(`user_info_${info.openid}`, info)
saveToRegistry(info.openid)
}
invalidateAuthCache()
Taro.eventCenter?.trigger('authStateChanged', { openid: info?.openid || '' })
}
export function getUserInfoByOpenid(openid: string): any | null {
@@ -82,6 +85,8 @@ export function clearUserInfo() {
// 仅退出登录,不删除用户数据
Taro.removeStorageSync(USER_KEY)
Taro.removeStorageSync(ACTIVE_USER_KEY)
invalidateAuthCache()
Taro.eventCenter?.trigger('authStateChanged', { openid: '' })
}
export function setUserInfo(info: any) {
@@ -259,17 +264,23 @@ export function setTheme(theme: ThemeMode) {
Taro.setStorageSync(THEME_KEY, theme)
}
// 跟随系统模式下,系统主题由 onThemeChange/getAppBaseInfo 写入缓存,供 resolveTheme 使用
let detectedSystemTheme: 'light' | 'dark' | null = null
export function setDetectedSystemTheme(t: 'light' | 'dark'): void {
detectedSystemTheme = t
}
/** 根据自动模式解析实际生效主题 */
export function resolveTheme(mode: ThemeMode): 'light' | 'dark' {
if (mode === 'auto') {
// 需 app.json 开启 darkmode 后 theme 字段才有效;getSystemInfoSync 已废弃,改用 getAppBaseInfo
// darkmode 开启后 getAppBaseInfo().theme 能拿到系统主题;缓存仅用于启动时加速
if (detectedSystemTheme) return detectedSystemTheme
try {
const info = Taro.getAppBaseInfo()
return info.theme === 'dark' ? 'dark' : 'light'
} catch {
const info = Taro.getSystemInfoSync()
return info.theme === 'dark' ? 'dark' : 'light'
}
if (info.theme === 'dark' || info.theme === 'light') return info.theme
} catch { /* ignore */ }
return 'light'
}
return mode
}