import axios, { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios' import type { AppMemberUserInfoRespVO } from '@/api/common/types' export type onRefreshTokenResponse = (data: AxiosResponse | boolean) => { token: string; refreshToken: string } | false export type TRefreshTokenConstructorConfig = { refreshTokenApiUrl: string refreshTokenKey?: string tokenKey?: string axiosInstance: AxiosInstance onRefreshTokenResponse: onRefreshTokenResponse onRefreshTokenResquest?: () => { config?: AxiosRequestConfig data?: any } } export default class RefreshToken { static instance: RefreshToken static SOTRAGE_REFRESH_TOKEN_KEY = 'kl-tk' static SOTRAGE_TOKENKEY = 'kl-rfk' static SOTRAGE_USERID = 'kl-userId' static SOTRAGE_USERNAME = 'kl-userName' static SOTRAGE_USERINFO = 'kl-userInfo' private REFRESH_TOKEN_API_URL: string public pending = false private axios: AxiosInstance public callbacks: any[] = [] private onRefreshTokenResponse: onRefreshTokenResponse private onRefreshTokenResquest?: () => { config?: AxiosRequestConfig data?: any } protected constructor(config: TRefreshTokenConstructorConfig) { RefreshToken.SOTRAGE_REFRESH_TOKEN_KEY = config?.refreshTokenKey || 'kl-tk' RefreshToken.SOTRAGE_TOKENKEY = config?.refreshTokenKey || 'kl-rfk' RefreshToken.SOTRAGE_USERID = config?.refreshTokenKey || 'kl-userId' this.REFRESH_TOKEN_API_URL = config?.refreshTokenApiUrl || '' this.axios = config.axiosInstance this.onRefreshTokenResponse = config.onRefreshTokenResponse this.onRefreshTokenResquest = config.onRefreshTokenResquest } static create(config: TRefreshTokenConstructorConfig) { if (!RefreshToken.instance) { RefreshToken.instance = new RefreshToken(config) } return RefreshToken.instance } // 设置token setToken(token: string, refreshToken: string) { window.localStorage.setItem(RefreshToken.SOTRAGE_TOKENKEY, token) window.localStorage.setItem(RefreshToken.SOTRAGE_REFRESH_TOKEN_KEY, refreshToken) } // 清除token removeToken() { window.localStorage.removeItem(RefreshToken.SOTRAGE_TOKENKEY) window.localStorage.removeItem(RefreshToken.SOTRAGE_REFRESH_TOKEN_KEY) //清除token,一起把userID也清除了 window.localStorage.removeItem(RefreshToken.SOTRAGE_USERID) window.localStorage.removeItem(RefreshToken.SOTRAGE_USERNAME) window.localStorage.removeItem(RefreshToken.SOTRAGE_USERINFO) } //设置userID setUserId(userId: string) { window.localStorage.setItem(RefreshToken.SOTRAGE_USERID, userId) } setUserName(userName: string) { window.localStorage.setItem(RefreshToken.SOTRAGE_USERNAME, userName) } setUserInfo(userInfo: AppMemberUserInfoRespVO) { window.localStorage.setItem(RefreshToken.SOTRAGE_USERINFO, JSON.stringify(userInfo)) } // 获取token getToken() { const token = window.localStorage.getItem(RefreshToken.SOTRAGE_TOKENKEY) || '' const refreshToken = window.localStorage.getItem(RefreshToken.SOTRAGE_REFRESH_TOKEN_KEY) || '' const userId = window.localStorage.getItem(RefreshToken.SOTRAGE_USERID) || '' const userName = window.localStorage.getItem(RefreshToken.SOTRAGE_USERNAME) || '' const userInfo = window.localStorage.getItem(RefreshToken.SOTRAGE_USERINFO) || '' return { token, refreshToken, userId, userName, userInfo: userInfo ? JSON.parse(userInfo) : {}, } } // 刷新token refresh() { return new Promise<{ token: string; refreshToken: string } | boolean>((resolve) => { this.pending = true const config = (this.onRefreshTokenResquest && this.onRefreshTokenResquest()) || {} axios .post(this.REFRESH_TOKEN_API_URL, config.data || {}, config.config) .then((res) => { const ac = this.onRefreshTokenResponse(res) if (ac) { // 设置新的token this.setToken(ac.token, ac.refreshToken) resolve(ac) return } resolve(false) }) .catch((e) => { console.log(e) this.onRefreshTokenResponse(false) resolve(false) }) .finally(() => { this.pending = false }) }) } // 推入刷新token成功 回调队列 pushCallbacks(config: AxiosRequestConfig) { return new Promise((resolve) => { this.callbacks.push(() => { resolve(this.axios(config)) }) }) } // 推出队列回调 releaseQueue() { // const tokens = this.getToken() this.callbacks.forEach((item) => { item() }) this.callbacks = [] } }