import { state, getCurrentUser } from '@/utils/store.uts' import { clearAdminRoleCache, refreshAdminRole } from './role.uts' import supa, { supaReady } from '@/components/supadb/aksupainstance.uts' let __isHandlingExpired = false /** * 统一“登录过期”闭环处理 * - 防止重复弹窗 * - 清理所有认证、用户相关缓存 * - 重置状态树 * - 统一跳转回登录页 */ export function handleSessionExpired(reason?: string) { if (__isHandlingExpired) return __isHandlingExpired = true console.warn('[AdminAuth] 执行会话过期统一闭环:', reason ?? '未知原因') // 1. 弹出提示 (确保只弹一次) uni.showToast({ title: '登录已过期,请重新登录', icon: 'none', duration: 2000 }) // 2. 清除本地相关存储 try { supa.signOut() } catch(e){} clearAdminRoleCache() // 3. 重置全局业务状态树,防止其他组件看到旧内存残影 state.isLoggedIn = false state.authUser = null state.userProfile = { username: '', email: '' } // 4. 跳转登录页 setTimeout(() => { uni.reLaunch({ url: '/pages/user/login' }) setTimeout(() => { __isHandlingExpired = false }, 1000) }, 1000) } /** * 统一的后台启动恢复授权流程 * 返回是否恢复/保持有效的登录态 */ export async function ensureAdminSession(): Promise { try { // ① 等待 hydrateSessionFromStorage() 完成(从storage恢复token→异步网络请求) // 必须在 getSession() 之前 await,否则刷新后 this.session 仍为 null, // 会被误判为未登录并触发 handleSessionExpired。 try { await supaReady } catch (_) {} const sessionInfo = supa.getSession() if (sessionInfo.session == null) { console.warn('[AdminAuth] 没有发现凭证,要求重新登录') handleSessionExpired('No credentials found') return false } // 主动检查并补齐 const role = await refreshAdminRole() if (role === 'unknown' || (state.userProfile != null && state.userProfile!.id == null)) { // 等等,如果是断网状态呢?其实 store 里已经用 status <= 0 判断过断网了。 // 上一步在 store/getCurrentUser 时,如果返回 401 才会真正导致清空。 console.warn('[AdminAuth] Session被认为无效或用户确权失败') handleSessionExpired('Role verification failed') return false } return true } catch (e) { console.error('[AdminAuth] 鉴权启动异常:', e) handleSessionExpired('Auth exception') return false } }