|
@@ -1,15 +1,16 @@
|
|
|
import type {
|
|
import type {
|
|
|
- ILoginForm,
|
|
|
|
|
|
|
+ ILoginForm,
|
|
|
} from '@/api/login'
|
|
} from '@/api/login'
|
|
|
import type { IAuthLoginRes } from '@/api/types/login'
|
|
import type { IAuthLoginRes } from '@/api/types/login'
|
|
|
import { defineStore } from 'pinia'
|
|
import { defineStore } from 'pinia'
|
|
|
import { computed, ref } from 'vue' // 修复:导入 computed
|
|
import { computed, ref } from 'vue' // 修复:导入 computed
|
|
|
import {
|
|
import {
|
|
|
- login as _login,
|
|
|
|
|
- logout as _logout,
|
|
|
|
|
- refreshToken as _refreshToken,
|
|
|
|
|
- wxLogin as _wxLogin,
|
|
|
|
|
- getWxCode,
|
|
|
|
|
|
|
+ login as _login,
|
|
|
|
|
+ logout as _logout,
|
|
|
|
|
+ refreshToken as _refreshToken,
|
|
|
|
|
+ wxLogin as _wxLogin,
|
|
|
|
|
+ getUserProfile,
|
|
|
|
|
+ getWxCode,
|
|
|
} from '@/api/login'
|
|
} from '@/api/login'
|
|
|
import { isDoubleTokenRes, isSingleTokenRes } from '@/api/types/login'
|
|
import { isDoubleTokenRes, isSingleTokenRes } from '@/api/types/login'
|
|
|
import { isDoubleTokenMode } from '@/utils'
|
|
import { isDoubleTokenMode } from '@/utils'
|
|
@@ -17,274 +18,277 @@ import { useUserStore } from './user'
|
|
|
|
|
|
|
|
// 初始化状态
|
|
// 初始化状态
|
|
|
const tokenInfoState = isDoubleTokenMode
|
|
const tokenInfoState = isDoubleTokenMode
|
|
|
- ? {
|
|
|
|
|
- accessToken: '',
|
|
|
|
|
- accessExpiresIn: 0,
|
|
|
|
|
- refreshToken: '',
|
|
|
|
|
- refreshExpiresIn: 0,
|
|
|
|
|
|
|
+ ? {
|
|
|
|
|
+ accessToken: '',
|
|
|
|
|
+ accessExpiresIn: 0,
|
|
|
|
|
+ refreshToken: '',
|
|
|
|
|
+ refreshExpiresIn: 0,
|
|
|
}
|
|
}
|
|
|
- : {
|
|
|
|
|
- token: '',
|
|
|
|
|
- expiresIn: 0,
|
|
|
|
|
|
|
+ : {
|
|
|
|
|
+ token: '',
|
|
|
|
|
+ expiresIn: 0,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
export const useTokenStore = defineStore(
|
|
export const useTokenStore = defineStore(
|
|
|
- 'token',
|
|
|
|
|
- () => {
|
|
|
|
|
- // 定义用户信息
|
|
|
|
|
- const tokenInfo = ref<IAuthLoginRes>({ ...tokenInfoState })
|
|
|
|
|
- // 设置用户信息
|
|
|
|
|
- const setTokenInfo = (val: IAuthLoginRes) => {
|
|
|
|
|
- tokenInfo.value = val
|
|
|
|
|
|
|
+ 'token',
|
|
|
|
|
+ () => {
|
|
|
|
|
+ // 定义用户信息
|
|
|
|
|
+ const tokenInfo = ref<IAuthLoginRes>({ ...tokenInfoState })
|
|
|
|
|
+ // 设置用户信息
|
|
|
|
|
+ const setTokenInfo = (val: IAuthLoginRes) => {
|
|
|
|
|
+ tokenInfo.value = val
|
|
|
|
|
|
|
|
- // 计算并存储过期时间
|
|
|
|
|
- const now = Date.now()
|
|
|
|
|
- if (isSingleTokenRes(val)) {
|
|
|
|
|
- // 单token模式
|
|
|
|
|
- const expireTime = now + val.expiresIn * 1000
|
|
|
|
|
- uni.setStorageSync('accessTokenExpireTime', expireTime)
|
|
|
|
|
- }
|
|
|
|
|
- else if (isDoubleTokenRes(val)) {
|
|
|
|
|
- // 双token模式
|
|
|
|
|
- const accessExpireTime = now + val.accessExpiresIn * 1000
|
|
|
|
|
- const refreshExpireTime = now + val.refreshExpiresIn * 1000
|
|
|
|
|
- uni.setStorageSync('accessTokenExpireTime', accessExpireTime)
|
|
|
|
|
- uni.setStorageSync('refreshTokenExpireTime', refreshExpireTime)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 判断token是否过期
|
|
|
|
|
- */
|
|
|
|
|
- const isTokenExpired = computed(() => {
|
|
|
|
|
- if (!tokenInfo.value) {
|
|
|
|
|
- return true
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const now = Date.now()
|
|
|
|
|
- const expireTime = uni.getStorageSync('accessTokenExpireTime')
|
|
|
|
|
|
|
+ // 计算并存储过期时间
|
|
|
|
|
+ const now = Date.now()
|
|
|
|
|
+ if (isSingleTokenRes(val)) {
|
|
|
|
|
+ // 单token模式
|
|
|
|
|
+ const expireTime = now + val.expiresIn * 1000
|
|
|
|
|
+ uni.setStorageSync('accessTokenExpireTime', expireTime)
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (isDoubleTokenRes(val)) {
|
|
|
|
|
+ // 双token模式
|
|
|
|
|
+ const accessExpireTime = now + val.accessExpiresIn * 1000
|
|
|
|
|
+ const refreshExpireTime = now + val.refreshExpiresIn * 1000
|
|
|
|
|
+ uni.setStorageSync('accessTokenExpireTime', accessExpireTime)
|
|
|
|
|
+ uni.setStorageSync('refreshTokenExpireTime', refreshExpireTime)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (!expireTime)
|
|
|
|
|
- return true
|
|
|
|
|
- return now >= expireTime
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 判断token是否过期
|
|
|
|
|
+ */
|
|
|
|
|
+ const isTokenExpired = computed(() => {
|
|
|
|
|
+ if (!tokenInfo.value) {
|
|
|
|
|
+ return true
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 判断refreshToken是否过期
|
|
|
|
|
- */
|
|
|
|
|
- const isRefreshTokenExpired = computed(() => {
|
|
|
|
|
- if (!isDoubleTokenMode)
|
|
|
|
|
- return true
|
|
|
|
|
|
|
+ const now = Date.now()
|
|
|
|
|
+ const expireTime = uni.getStorageSync('accessTokenExpireTime')
|
|
|
|
|
|
|
|
- const now = Date.now()
|
|
|
|
|
- const refreshExpireTime = uni.getStorageSync('refreshTokenExpireTime')
|
|
|
|
|
|
|
+ if (!expireTime)
|
|
|
|
|
+ return true
|
|
|
|
|
+ return now >= expireTime
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- if (!refreshExpireTime)
|
|
|
|
|
- return true
|
|
|
|
|
- return now >= refreshExpireTime
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 判断refreshToken是否过期
|
|
|
|
|
+ */
|
|
|
|
|
+ const isRefreshTokenExpired = computed(() => {
|
|
|
|
|
+ if (!isDoubleTokenMode)
|
|
|
|
|
+ return true
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 登录成功后处理逻辑
|
|
|
|
|
- * @param tokenInfo 登录返回的token信息
|
|
|
|
|
- */
|
|
|
|
|
- async function _postLogin(tokenInfo: IAuthLoginRes) {
|
|
|
|
|
- setTokenInfo(tokenInfo)
|
|
|
|
|
- const userStore = useUserStore()
|
|
|
|
|
- await userStore.fetchUserInfo()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const now = Date.now()
|
|
|
|
|
+ const refreshExpireTime = uni.getStorageSync('refreshTokenExpireTime')
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 用户登录
|
|
|
|
|
- * 有的时候后端会用一个接口返回token和用户信息,有的时候会分开2个接口,一个获取token,一个获取用户信息
|
|
|
|
|
- * (各有利弊,看业务场景和系统复杂度),这里使用2个接口返回的来模拟
|
|
|
|
|
- * @param loginForm 登录参数
|
|
|
|
|
- * @returns 登录结果
|
|
|
|
|
- */
|
|
|
|
|
- const login = async (loginForm: ILoginForm) => {
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await _login(loginForm)
|
|
|
|
|
- console.log('普通登录-res: ', res)
|
|
|
|
|
- await _postLogin(res)
|
|
|
|
|
- uni.showToast({
|
|
|
|
|
- title: '登录成功',
|
|
|
|
|
- icon: 'success',
|
|
|
|
|
- })
|
|
|
|
|
- return res
|
|
|
|
|
- }
|
|
|
|
|
- catch (error) {
|
|
|
|
|
- console.error('登录失败:', error)
|
|
|
|
|
- uni.showToast({
|
|
|
|
|
- title: '登录失败,请重试',
|
|
|
|
|
- icon: 'error',
|
|
|
|
|
|
|
+ if (!refreshExpireTime)
|
|
|
|
|
+ return true
|
|
|
|
|
+ return now >= refreshExpireTime
|
|
|
})
|
|
})
|
|
|
- throw error
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 微信登录
|
|
|
|
|
- * 有的时候后端会用一个接口返回token和用户信息,有的时候会分开2个接口,一个获取token,一个获取用户信息
|
|
|
|
|
- * (各有利弊,看业务场景和系统复杂度),这里使用2个接口返回的来模拟
|
|
|
|
|
- * @returns 登录结果
|
|
|
|
|
- */
|
|
|
|
|
- const wxLogin = async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- // 获取微信小程序登录的code
|
|
|
|
|
- const code = await getWxCode()
|
|
|
|
|
- console.log('微信登录-code: ', code)
|
|
|
|
|
- const res = await _wxLogin(code)
|
|
|
|
|
- console.log('微信登录-res: ', res)
|
|
|
|
|
- await _postLogin(res)
|
|
|
|
|
- uni.showToast({
|
|
|
|
|
- title: '登录成功',
|
|
|
|
|
- icon: 'success',
|
|
|
|
|
- })
|
|
|
|
|
- return res
|
|
|
|
|
- }
|
|
|
|
|
- catch (error) {
|
|
|
|
|
- console.error('微信登录失败:', error)
|
|
|
|
|
- uni.showToast({
|
|
|
|
|
- title: '微信登录失败,请重试',
|
|
|
|
|
- icon: 'error',
|
|
|
|
|
- })
|
|
|
|
|
- throw error
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 登录成功后处理逻辑
|
|
|
|
|
+ * @param tokenInfo 登录返回的token信息
|
|
|
|
|
+ */
|
|
|
|
|
+ async function _postLogin(tokenInfo: IAuthLoginRes) {
|
|
|
|
|
+ setTokenInfo(tokenInfo)
|
|
|
|
|
+ // const userStore = useUserStore()
|
|
|
|
|
+ // await userStore.fetchUserInfo()
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 退出登录 并 删除用户信息
|
|
|
|
|
- */
|
|
|
|
|
- const logout = async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- // TODO 实现自己的退出登录逻辑
|
|
|
|
|
- await _logout()
|
|
|
|
|
- }
|
|
|
|
|
- catch (error) {
|
|
|
|
|
- console.error('退出登录失败:', error)
|
|
|
|
|
- }
|
|
|
|
|
- finally {
|
|
|
|
|
- // 无论成功失败,都需要清除本地token信息
|
|
|
|
|
- // 清除存储的过期时间
|
|
|
|
|
- uni.removeStorageSync('accessTokenExpireTime')
|
|
|
|
|
- uni.removeStorageSync('refreshTokenExpireTime')
|
|
|
|
|
- console.log('退出登录-清除用户信息')
|
|
|
|
|
- tokenInfo.value = { ...tokenInfoState }
|
|
|
|
|
- uni.removeStorageSync('token')
|
|
|
|
|
- const userStore = useUserStore()
|
|
|
|
|
- userStore.clearUserInfo()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 用户登录
|
|
|
|
|
+ * 有的时候后端会用一个接口返回token和用户信息,有的时候会分开2个接口,一个获取token,一个获取用户信息
|
|
|
|
|
+ * (各有利弊,看业务场景和系统复杂度),这里使用2个接口返回的来模拟
|
|
|
|
|
+ * @param loginForm 登录参数
|
|
|
|
|
+ * @returns 登录结果
|
|
|
|
|
+ */
|
|
|
|
|
+ const login = async (loginForm: ILoginForm) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await _login(loginForm)
|
|
|
|
|
+ console.log('普通登录-res: ', res)
|
|
|
|
|
+ await _postLogin(res)
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '登录成功',
|
|
|
|
|
+ icon: 'success',
|
|
|
|
|
+ })
|
|
|
|
|
+ return res
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (error) {
|
|
|
|
|
+ console.error('登录失败:', error)
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '登录失败,请重试',
|
|
|
|
|
+ icon: 'error',
|
|
|
|
|
+ })
|
|
|
|
|
+ throw error
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 刷新token
|
|
|
|
|
- * @returns 刷新结果
|
|
|
|
|
- */
|
|
|
|
|
- const refreshToken = async () => {
|
|
|
|
|
- if (!isDoubleTokenMode) {
|
|
|
|
|
- console.error('单token模式不支持刷新token')
|
|
|
|
|
- throw new Error('单token模式不支持刷新token')
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 微信登录
|
|
|
|
|
+ * 有的时候后端会用一个接口返回token和用户信息,有的时候会分开2个接口,一个获取token,一个获取用户信息
|
|
|
|
|
+ * (各有利弊,看业务场景和系统复杂度),这里使用2个接口返回的来模拟
|
|
|
|
|
+ * @returns 登录结果
|
|
|
|
|
+ */
|
|
|
|
|
+ const wxLogin = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 获取用户信息
|
|
|
|
|
+ const profile = await getUserProfile()
|
|
|
|
|
+ console.log('微信登录-profile: ', profile)
|
|
|
|
|
+ // 获取微信小程序登录的code
|
|
|
|
|
+ const code = await getWxCode()
|
|
|
|
|
+ console.log('微信登录-code: ', code.code)
|
|
|
|
|
+ const res = await _wxLogin(code.code)
|
|
|
|
|
+ console.log('微信登录-res: ', res)
|
|
|
|
|
+ await _postLogin(res)
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '登录成功',
|
|
|
|
|
+ icon: 'success',
|
|
|
|
|
+ })
|
|
|
|
|
+ return res
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (error) {
|
|
|
|
|
+ console.error('微信登录失败:', error)
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '微信登录失败,请重试',
|
|
|
|
|
+ icon: 'error',
|
|
|
|
|
+ })
|
|
|
|
|
+ throw error
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- try {
|
|
|
|
|
- // 安全检查,确保refreshToken存在
|
|
|
|
|
- if (!isDoubleTokenRes(tokenInfo.value) || !tokenInfo.value.refreshToken) {
|
|
|
|
|
- throw new Error('无效的refreshToken')
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 退出登录 并 删除用户信息
|
|
|
|
|
+ */
|
|
|
|
|
+ const logout = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // TODO 实现自己的退出登录逻辑
|
|
|
|
|
+ await _logout()
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (error) {
|
|
|
|
|
+ console.error('退出登录失败:', error)
|
|
|
|
|
+ }
|
|
|
|
|
+ finally {
|
|
|
|
|
+ // 无论成功失败,都需要清除本地token信息
|
|
|
|
|
+ // 清除存储的过期时间
|
|
|
|
|
+ uni.removeStorageSync('accessTokenExpireTime')
|
|
|
|
|
+ uni.removeStorageSync('refreshTokenExpireTime')
|
|
|
|
|
+ console.log('退出登录-清除用户信息')
|
|
|
|
|
+ tokenInfo.value = { ...tokenInfoState }
|
|
|
|
|
+ uni.removeStorageSync('token')
|
|
|
|
|
+ const userStore = useUserStore()
|
|
|
|
|
+ userStore.clearUserInfo()
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const refreshToken = tokenInfo.value.refreshToken
|
|
|
|
|
- const res = await _refreshToken(refreshToken)
|
|
|
|
|
- console.log('刷新token-res: ', res)
|
|
|
|
|
- setTokenInfo(res)
|
|
|
|
|
- return res
|
|
|
|
|
- }
|
|
|
|
|
- catch (error) {
|
|
|
|
|
- console.error('刷新token失败:', error)
|
|
|
|
|
- throw error
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 刷新token
|
|
|
|
|
+ * @returns 刷新结果
|
|
|
|
|
+ */
|
|
|
|
|
+ const refreshToken = async () => {
|
|
|
|
|
+ if (!isDoubleTokenMode) {
|
|
|
|
|
+ console.error('单token模式不支持刷新token')
|
|
|
|
|
+ throw new Error('单token模式不支持刷新token')
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 获取有效的token
|
|
|
|
|
- * 注意:在computed中不直接调用异步函数,只做状态判断
|
|
|
|
|
- * 实际的刷新操作应由调用方处理
|
|
|
|
|
- */
|
|
|
|
|
- const getValidToken = computed(() => {
|
|
|
|
|
- // token已过期,返回空
|
|
|
|
|
- if (isTokenExpired.value) {
|
|
|
|
|
- return ''
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 安全检查,确保refreshToken存在
|
|
|
|
|
+ if (!isDoubleTokenRes(tokenInfo.value) || !tokenInfo.value.refreshToken) {
|
|
|
|
|
+ throw new Error('无效的refreshToken')
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (!isDoubleTokenMode) {
|
|
|
|
|
- return isSingleTokenRes(tokenInfo.value) ? tokenInfo.value.token : ''
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- return isDoubleTokenRes(tokenInfo.value) ? tokenInfo.value.accessToken : ''
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ const refreshToken = tokenInfo.value.refreshToken
|
|
|
|
|
+ const res = await _refreshToken(refreshToken)
|
|
|
|
|
+ console.log('刷新token-res: ', res)
|
|
|
|
|
+ setTokenInfo(res)
|
|
|
|
|
+ return res
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (error) {
|
|
|
|
|
+ console.error('刷新token失败:', error)
|
|
|
|
|
+ throw error
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 检查是否有登录信息(不考虑token是否过期)
|
|
|
|
|
- */
|
|
|
|
|
- const hasLoginInfo = computed(() => {
|
|
|
|
|
- if (!tokenInfo.value) {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
- if (isDoubleTokenMode) {
|
|
|
|
|
- return isDoubleTokenRes(tokenInfo.value) && !!tokenInfo.value.accessToken
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- return isSingleTokenRes(tokenInfo.value) && !!tokenInfo.value.token
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取有效的token
|
|
|
|
|
+ * 注意:在computed中不直接调用异步函数,只做状态判断
|
|
|
|
|
+ * 实际的刷新操作应由调用方处理
|
|
|
|
|
+ */
|
|
|
|
|
+ const getValidToken = computed(() => {
|
|
|
|
|
+ // token已过期,返回空
|
|
|
|
|
+ if (isTokenExpired.value) {
|
|
|
|
|
+ return ''
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 检查是否已登录且token有效
|
|
|
|
|
- */
|
|
|
|
|
- const hasValidLogin = computed(() => {
|
|
|
|
|
- console.log('hasValidLogin', hasLoginInfo.value, !isTokenExpired.value)
|
|
|
|
|
- return hasLoginInfo.value && !isTokenExpired.value
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ if (!isDoubleTokenMode) {
|
|
|
|
|
+ return isSingleTokenRes(tokenInfo.value) ? tokenInfo.value.token : ''
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ return isDoubleTokenRes(tokenInfo.value) ? tokenInfo.value.accessToken : ''
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 尝试获取有效的token,如果过期且可刷新,则刷新token
|
|
|
|
|
- * @returns 有效的token或空字符串
|
|
|
|
|
- */
|
|
|
|
|
- const tryGetValidToken = async (): Promise<string> => {
|
|
|
|
|
- if (!getValidToken.value && isDoubleTokenMode && !isRefreshTokenExpired.value) {
|
|
|
|
|
- try {
|
|
|
|
|
- await refreshToken()
|
|
|
|
|
- return getValidToken.value
|
|
|
|
|
- }
|
|
|
|
|
- catch (error) {
|
|
|
|
|
- console.error('尝试刷新token失败:', error)
|
|
|
|
|
- return ''
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 检查是否有登录信息(不考虑token是否过期)
|
|
|
|
|
+ */
|
|
|
|
|
+ const hasLoginInfo = computed(() => {
|
|
|
|
|
+ if (!tokenInfo.value) {
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isDoubleTokenMode) {
|
|
|
|
|
+ return isDoubleTokenRes(tokenInfo.value) && !!tokenInfo.value.accessToken
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ return isSingleTokenRes(tokenInfo.value) && !!tokenInfo.value.token
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 检查是否已登录且token有效
|
|
|
|
|
+ */
|
|
|
|
|
+ const hasValidLogin = computed(() => {
|
|
|
|
|
+ console.log('hasValidLogin', hasLoginInfo.value, !isTokenExpired.value)
|
|
|
|
|
+ return hasLoginInfo.value && !isTokenExpired.value
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 尝试获取有效的token,如果过期且可刷新,则刷新token
|
|
|
|
|
+ * @returns 有效的token或空字符串
|
|
|
|
|
+ */
|
|
|
|
|
+ const tryGetValidToken = async (): Promise<string> => {
|
|
|
|
|
+ if (!getValidToken.value && isDoubleTokenMode && !isRefreshTokenExpired.value) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await refreshToken()
|
|
|
|
|
+ return getValidToken.value
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (error) {
|
|
|
|
|
+ console.error('尝试刷新token失败:', error)
|
|
|
|
|
+ return ''
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return getValidToken.value
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- return getValidToken.value
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- return {
|
|
|
|
|
- // 核心API方法
|
|
|
|
|
- login,
|
|
|
|
|
- wxLogin,
|
|
|
|
|
- logout,
|
|
|
|
|
|
|
+ return {
|
|
|
|
|
+ // 核心API方法
|
|
|
|
|
+ login,
|
|
|
|
|
+ wxLogin,
|
|
|
|
|
+ logout,
|
|
|
|
|
|
|
|
- // 认证状态判断(最常用的)
|
|
|
|
|
- hasLogin: hasValidLogin,
|
|
|
|
|
|
|
+ // 认证状态判断(最常用的)
|
|
|
|
|
+ hasLogin: hasValidLogin,
|
|
|
|
|
|
|
|
- // 内部系统使用的方法
|
|
|
|
|
- refreshToken,
|
|
|
|
|
- tryGetValidToken,
|
|
|
|
|
- validToken: getValidToken,
|
|
|
|
|
|
|
+ // 内部系统使用的方法
|
|
|
|
|
+ refreshToken,
|
|
|
|
|
+ tryGetValidToken,
|
|
|
|
|
+ validToken: getValidToken,
|
|
|
|
|
|
|
|
- // 调试或特殊场景可能需要直接访问的信息
|
|
|
|
|
- tokenInfo,
|
|
|
|
|
- setTokenInfo,
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- // 添加持久化配置,确保刷新页面后token信息不丢失
|
|
|
|
|
- persist: true,
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ // 调试或特殊场景可能需要直接访问的信息
|
|
|
|
|
+ tokenInfo,
|
|
|
|
|
+ setTokenInfo,
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ // 添加持久化配置,确保刷新页面后token信息不丢失
|
|
|
|
|
+ persist: true,
|
|
|
|
|
+ },
|
|
|
)
|
|
)
|