import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { LanguageEnum } from '@/enums/appEnum' import { router } from '@/router' import { useSettingStore } from './setting' import { useWorktabStore } from './worktab' import { AppRouteRecord } from '@/types/router' import { setPageTitle } from '@/router/utils/utils' import { resetRouterState } from '@/router/guards/beforeEach' import { RoutesAlias } from '@/router/routesAlias' import { UserService } from '@/api/usersApi' // 新增导入 let refreshTimeout: ReturnType | null = null // 定时器变量 // 用户 export const useUserStore = defineStore( 'userStore', () => { const language = ref(LanguageEnum.ZH) const isLogin = ref(false) const isLock = ref(false) const lockPassword = ref('') const info = ref>({}) const searchHistory = ref([]) const accessToken = ref('') const refreshToken = ref('') const companyid = ref('') const companyabbr = ref('') const systemsid = ref('') const systemsabbr = ref('') const home_page = ref('') const loginType = ref<'feishu' | 'upwd'>('upwd') const tokenExpireAt = ref(0) const getUserInfo = computed(() => info.value) const getSettingState = computed(() => useSettingStore().$state) const getWorktabState = computed(() => useWorktabStore().$state) const setUserInfo = (newInfo: Api.User.UserInfo) => { info.value = newInfo } const setLoginStatus = (status: boolean) => { isLogin.value = status } const setLanguage = (lang: LanguageEnum) => { setPageTitle(router.currentRoute.value) language.value = lang } const setLoginType = (type: 'feishu' | 'upwd') => { loginType.value = type } const setSearchHistory = (list: AppRouteRecord[]) => { searchHistory.value = list } const setLockStatus = (status: boolean) => { isLock.value = status } const setLockPassword = (password: string) => { lockPassword.value = password } const setToken = (newAccessToken: string, newRefreshToken?: string, expiresIn?: number) => { accessToken.value = newAccessToken if (newRefreshToken) { refreshToken.value = newRefreshToken } if (expiresIn) { const expireAt = Date.now() + expiresIn * 1000 tokenExpireAt.value = expireAt localStorage.setItem('token_expire_at', String(expireAt)) // 检查是否需要重新设置定时器 const currentLeftSeconds = Math.floor((expireAt - Date.now()) / 1000) if (currentLeftSeconds > 0) { scheduleTokenRefresh(currentLeftSeconds) } } } const setCompany = (id: string, abbr: string) => { companyid.value = id companyabbr.value = abbr } const setSystems = (id: string, abbr: string) => { systemsid.value = id systemsabbr.value = abbr } // 设置首页 const sethome_page = (page: string) => { home_page.value = page } function restoreTokenTimer() { const expireAt = Number(localStorage.getItem('token_expire_at') || '0') if (accessToken.value && expireAt > Date.now()) { const leftSeconds = Math.floor((expireAt - Date.now()) / 1000) scheduleTokenRefresh(leftSeconds) } } let isScheduled = false function scheduleTokenRefresh(expiresIn: number) { if (refreshTimeout) { clearTimeout(refreshTimeout) refreshTimeout = null } // 提前1分钟刷新 const refreshTime = (expiresIn - 100) * 1000 if (refreshTime > 0) { if (!isScheduled) { isScheduled = true refreshTimeout = setTimeout(() => { refreshTokenAction().finally(() => { isScheduled = false // 重置标志位 }) }, refreshTime) } else { console.log('scheduleTokenRefresh is already scheduled, skipping...') } } else { console.error('Invalid refreshTime:', refreshTime) } } async function refreshTokenAction() { try { const { data } = await UserService.refreshToken({ refresh_token: refreshToken.value }) // 动态计算剩余时间 const currentTime = Date.now() const expireAt = currentTime + data.expires_in * 1000 const leftSeconds = Math.floor((expireAt - currentTime) / 1000) setToken(data.access_token, data.refresh_token, leftSeconds) } catch (e) { console.error('Token refresh failed:', e) logOut() } } const logOut = () => { // 清空所有本地缓存 localStorage.clear() sessionStorage.clear() systemsabbr.value = '' systemsid.value = '' companyabbr.value = '' companyid.value = '' home_page.value = '' info.value = {} isLogin.value = false isLock.value = false lockPassword.value = '' accessToken.value = '' refreshToken.value = '' if (refreshTimeout) clearTimeout(refreshTimeout) // 清理定时器 // 清理工作台标签页 useWorktabStore().clearAll() // 清理sessionStorage中的用户信息缓存 sessionStorage.removeItem('lastUserInfo') sessionStorage.removeItem('iframeRoutes') // 重置路由状态 resetRouterState(router) // 跳转到登录页 router.push(RoutesAlias.Login) } return { language, isLogin, isLock, lockPassword, info, companyid, companyabbr, systemsid, systemsabbr, home_page, searchHistory, loginType, accessToken, refreshToken, tokenExpireAt, getUserInfo, getSettingState, getWorktabState, setUserInfo, setLoginStatus, setLanguage, setSearchHistory, setLockStatus, setLockPassword, setToken, setCompany, setSystems, setLoginType, sethome_page, logOut, restoreTokenTimer } }, { persist: { key: 'user', storage: localStorage, afterRestore: (ctx: { store: { restoreTokenTimer: () => void } }) => { ctx.store.restoreTokenTimer() } } as any } )