213 lines
6.2 KiB
TypeScript
213 lines
6.2 KiB
TypeScript
|
|
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<typeof setTimeout> | 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<Partial<Api.User.UserInfo>>({})
|
||
|
|
const searchHistory = ref<AppRouteRecord[]>([])
|
||
|
|
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<number>(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 - 60) * 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
|
||
|
|
}
|
||
|
|
)
|