import type { RouteRecordRaw } from 'vue-router'; import type { MenuRecordRaw } from '@vben-core/typings'; import { acceptHMRUpdate, defineStore } from 'pinia'; // Token 共享存储的固定 key const SHARED_TOKEN_KEY = 'vben-shared-auth-tokens'; // 保存 token 到共享存储 function saveSharedTokens(accessToken: string | null, refreshToken: string | null) { try { if (accessToken || refreshToken) { localStorage.setItem(SHARED_TOKEN_KEY, JSON.stringify({ accessToken, refreshToken })); } else { localStorage.removeItem(SHARED_TOKEN_KEY); } } catch (e) { console.error('[Token] 保存共享token失败:', e); } } type AccessToken = null | string; interface AccessState { /** * 权限码 */ accessCodes: string[]; /** * 可访问的菜单列表 */ accessMenus: MenuRecordRaw[]; /** * 可访问的路由列表 */ accessRoutes: RouteRecordRaw[]; /** * 登录 accessToken */ accessToken: AccessToken; /** * 是否已经检查过权限 */ isAccessChecked: boolean; /** * 是否锁屏状态 */ isLockScreen: boolean; /** * 锁屏密码 */ lockScreenPassword?: string; /** * 登录是否过期 */ loginExpired: boolean; /** * 登录 accessToken */ refreshToken: AccessToken; } /** * @zh_CN 访问权限相关 */ export const useAccessStore = defineStore('core-access', { actions: { getMenuByPath(path: string) { function findMenu( menus: MenuRecordRaw[], path: string, ): MenuRecordRaw | undefined { for (const menu of menus) { if (menu.path === path) { return menu; } if (menu.children) { const matched = findMenu(menu.children, path); if (matched) { return matched; } } } } return findMenu(this.accessMenus, path); }, lockScreen(password: string) { this.isLockScreen = true; this.lockScreenPassword = password; }, setAccessCodes(codes: string[]) { this.accessCodes = codes; }, setAccessMenus(menus: MenuRecordRaw[]) { this.accessMenus = menus; }, setAccessRoutes(routes: RouteRecordRaw[]) { this.accessRoutes = routes; }, setAccessToken(token: AccessToken) { // 避免重复设置相同的值 if (this.accessToken === token) { return; } this.accessToken = token; // 同步到共享存储 saveSharedTokens(token, this.refreshToken); }, setIsAccessChecked(isAccessChecked: boolean) { this.isAccessChecked = isAccessChecked; }, setLoginExpired(loginExpired: boolean) { this.loginExpired = loginExpired; }, setRefreshToken(token: AccessToken) { // 避免重复设置相同的值 if (this.refreshToken === token) { return; } this.refreshToken = token; // 同步到共享存储 saveSharedTokens(this.accessToken, token); }, unlockScreen() { this.isLockScreen = false; this.lockScreenPassword = undefined; }, }, persist: { // Token 通过手动方式同步到固定 key,这里只持久化其他字段 pick: ['accessCodes', 'isLockScreen', 'lockScreenPassword'], }, state: (): AccessState => ({ accessCodes: [], accessMenus: [], accessRoutes: [], accessToken: null, isAccessChecked: false, isLockScreen: false, lockScreenPassword: undefined, loginExpired: false, refreshToken: null, }), }); // 解决热更新问题 const hot = import.meta.hot; if (hot) { hot.accept(acceptHMRUpdate(useAccessStore, hot)); }