This commit is contained in:
FengHui
2026-05-15 14:16:31 +08:00
parent 5910b19131
commit e857c008b4
5 changed files with 197 additions and 47 deletions

View File

@@ -61,6 +61,10 @@ const handleIdCardLogin = async (idCard) => {
if (res.token) { if (res.token) {
// 登录成功存储token并获取用户信息 // 登录成功存储token并获取用户信息
if (res.refreshToken) {
userStore.setRefreshToken(res.refreshToken)
}
userStore.setLoginTime(Date.now())
await userStore.loginSetToken(res.token) await userStore.loginSetToken(res.token)
// 获取用户详细信息 // 获取用户详细信息

View File

@@ -337,6 +337,10 @@ const submitVerification = async () => {
if (res.token && res.code === 200) { if (res.token && res.code === 200) {
// 登录成功存储token // 登录成功存储token
if (res.refreshToken) {
userStore.setRefreshToken(res.refreshToken)
}
userStore.setLoginTime(Date.now())
await userStore.loginSetToken(res.token).then((resume) => { await userStore.loginSetToken(res.token).then((resume) => {
// 更新用户类型到缓存 // 更新用户类型到缓存
if (res.isCompanyUser !== undefined) { if (res.isCompanyUser !== undefined) {

View File

@@ -373,6 +373,10 @@ const wxLogin = () => {
// 调用后端接口进行登录 // 调用后端接口进行登录
$api.createRequest('/app/appLogin', loginParams, 'post').then((resData) => { $api.createRequest('/app/appLogin', loginParams, 'post').then((resData) => {
if (resData.token) { if (resData.token) {
if (resData.refreshToken) {
userStore.setRefreshToken(resData.refreshToken)
}
userStore.setLoginTime(Date.now())
userStore.loginSetToken(resData.token).then((resume) => { userStore.loginSetToken(resData.token).then((resume) => {
// 更新用户类型到缓存 // 更新用户类型到缓存
if (resData.isCompanyUser !== undefined) { if (resData.isCompanyUser !== undefined) {
@@ -442,6 +446,10 @@ const testLogin = () => {
$api.createRequest('/app/login', params, 'post').then((resData) => { $api.createRequest('/app/login', params, 'post').then((resData) => {
uni.hideLoading(); uni.hideLoading();
if (resData.refreshToken) {
userStore.setRefreshToken(resData.refreshToken)
}
userStore.setLoginTime(Date.now())
userStore.loginSetToken(resData.token).then((resume) => { userStore.loginSetToken(resData.token).then((resume) => {
// 更新用户类型到缓存 // 更新用户类型到缓存
if (resData.isCompanyUser !== undefined) { if (resData.isCompanyUser !== undefined) {

View File

@@ -49,9 +49,12 @@ const useUserStore = defineStore("user", () => {
const userInfo = ref({}); const userInfo = ref({});
const role = ref({}); const role = ref({});
const token = ref('') const token = ref('')
const refreshToken = ref('')
const loginTime = ref(0)
const resume = ref({}) const resume = ref({})
const Completion = ref('0%') const Completion = ref('0%')
const seesionId = ref(uni.getStorageSync('seesionId') || '') const seesionId = ref(uni.getStorageSync('seesionId') || '')
const SEVEN_DAYS = 7 * 24 * 60 * 60 * 1000
const login = (value) => { const login = (value) => {
hasLogin.value = true; hasLogin.value = true;
@@ -67,11 +70,15 @@ const useUserStore = defineStore("user", () => {
const logOut = (showLoginModal = true) => { const logOut = (showLoginModal = true) => {
hasLogin.value = false; hasLogin.value = false;
token.value = '' token.value = ''
refreshToken.value = ''
loginTime.value = 0
resume.value = {} resume.value = {}
userInfo.value = {} userInfo.value = {}
role.value = {} role.value = {}
uni.removeStorageSync('userInfo') uni.removeStorageSync('userInfo')
uni.removeStorageSync('token') uni.removeStorageSync('token')
uni.removeStorageSync('refreshToken')
uni.removeStorageSync('loginTime')
uni.removeStorageSync('Padmin-Token') uni.removeStorageSync('Padmin-Token')
// 如果需要显示登录弹窗,则通过事件通知页面显示微信登录弹窗 // 如果需要显示登录弹窗,则通过事件通知页面显示微信登录弹窗
// if (showLoginModal) { // if (showLoginModal) {
@@ -122,6 +129,73 @@ const useUserStore = defineStore("user", () => {
return getUserResume() return getUserResume()
} }
const setRefreshToken = (refreshTokenVal) => {
refreshToken.value = refreshTokenVal
uni.setStorageSync('refreshToken', refreshTokenVal)
}
const setLoginTime = (time) => {
loginTime.value = time
uni.setStorageSync('loginTime', time.toString())
}
const isLoginExpired = () => {
if (!loginTime.value) {
const storedTime = uni.getStorageSync('loginTime')
if (storedTime) {
loginTime.value = parseInt(storedTime)
}
}
if (!loginTime.value) return true
return Date.now() - loginTime.value > SEVEN_DAYS
}
const refreshAccessToken = async () => {
if (isLoginExpired()) {
logOut(false)
return Promise.reject(new Error('登录已过期'))
}
const storedRefreshToken = uni.getStorageSync('refreshToken') || refreshToken.value
if (!storedRefreshToken) {
logOut(false)
return Promise.reject(new Error('没有刷新token'))
}
return new Promise((resolve, reject) => {
uni.request({
url: 'http://ks.zhaopinzao8dian.com/api/ks/refreshToken',
method: 'POST',
data: {
refreshToken: storedRefreshToken
},
success: (resData) => {
if (resData.statusCode === 200) {
const { code, msg, token: newToken } = resData.data
if (code === 200 && newToken) {
token.value = newToken
uni.setStorageSync('token', newToken)
resolve(newToken)
} else if (code === 401) {
logOut(false)
reject(new Error(msg || '认证失败'))
} else {
logOut(false)
reject(new Error(msg || '刷新token失败'))
}
} else {
logOut(false)
reject(new Error('网络请求失败'))
}
},
fail: (err) => {
logOut(false)
reject(err)
}
})
})
}
const setUserInfo = (values) => { const setUserInfo = (values) => {
userInfo.value = values.data; userInfo.value = values.data;
resume.value = values.data; // 将用户信息同时存储到resume中 resume.value = values.data; // 将用户信息同时存储到resume中
@@ -156,10 +230,14 @@ const useUserStore = defineStore("user", () => {
const restoreUserInfo = () => { const restoreUserInfo = () => {
const cachedUserInfo = uni.getStorageSync('userInfo'); const cachedUserInfo = uni.getStorageSync('userInfo');
const cachedToken = uni.getStorageSync('token'); const cachedToken = uni.getStorageSync('token');
const cachedRefreshToken = uni.getStorageSync('refreshToken');
const cachedLoginTime = uni.getStorageSync('loginTime');
if (cachedUserInfo && cachedToken) { if (cachedUserInfo && cachedToken) {
userInfo.value = cachedUserInfo; userInfo.value = cachedUserInfo;
resume.value = cachedUserInfo; resume.value = cachedUserInfo;
token.value = cachedToken; token.value = cachedToken;
refreshToken.value = cachedRefreshToken || '';
loginTime.value = cachedLoginTime ? parseInt(cachedLoginTime) : 0;
hasLogin.value = true; hasLogin.value = true;
Completion.value = getResumeCompletionPercentage(cachedUserInfo); Completion.value = getResumeCompletionPercentage(cachedUserInfo);
return true; return true;
@@ -172,10 +250,16 @@ const useUserStore = defineStore("user", () => {
hasLogin, hasLogin,
userInfo, userInfo,
token, token,
refreshToken,
loginTime,
resume, resume,
login, login,
logOut, logOut,
loginSetToken, loginSetToken,
setRefreshToken,
setLoginTime,
isLoginExpired,
refreshAccessToken,
getUserResume, getUserResume,
initSeesionId, initSeesionId,
seesionId, seesionId,

View File

@@ -2,6 +2,9 @@ import config from "@/config.js"
import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto'; import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto';
import useUserStore from '@/stores/useUserStore'; import useUserStore from '@/stores/useUserStore';
let isRefreshing = false;
let refreshSubscribers = [];
const needToEncryptSet = new Set([ const needToEncryptSet = new Set([
'POST:/app/login', 'POST:/app/login',
'GET:/app/user/resume', 'GET:/app/user/resume',
@@ -36,6 +39,20 @@ const encryptPathPrefixes = [
'/refreshToken', '/refreshToken',
]; ];
const addRefreshSubscriber = (callback) => {
refreshSubscribers.push(callback);
};
const notifyRefreshSubscribers = (token) => {
refreshSubscribers.forEach((callback) => callback(token));
refreshSubscribers = [];
};
const resetRefreshState = () => {
isRefreshing = false;
refreshSubscribers = [];
};
const noEncryptSet = new Set([ const noEncryptSet = new Set([
'DELETE:/app/job/applyJobCencal', 'DELETE:/app/job/applyJobCencal',
]); ]);
@@ -172,6 +189,8 @@ export function createRequest(url, data = {}, method = 'GET', loading = false, h
header["Authorization"] = Authorization; header["Authorization"] = Authorization;
} }
const requestData = isEncryptNeeded(method, url) ? encryptRequestData(data) : data; const requestData = isEncryptNeeded(method, url) ? encryptRequestData(data) : data;
const doRequest = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
uni.request({ uni.request({
url: config.baseUrl + url, url: config.baseUrl + url,
@@ -182,8 +201,8 @@ export function createRequest(url, data = {}, method = 'GET', loading = false, h
// 响应拦截 // 响应拦截
if (resData.statusCode === 200) { if (resData.statusCode === 200) {
const responseData = handleResponseData(resData.data) const responseData = handleResponseData(resData.data)
console.log('[请求] 接口地址:', config.baseUrl + url) // console.log('[请求] 接口地址:', config.baseUrl + url)
console.log('[请求] 解密后数据:', responseData) // console.log('[请求] 解密后数据:', responseData)
const { const {
code, code,
msg msg
@@ -194,14 +213,11 @@ export function createRequest(url, data = {}, method = 'GET', loading = false, h
} }
// 处理业务错误 // 处理业务错误
if (responseData?.code === 401 || responseData?.code === 402) { if (responseData?.code === 401 || responseData?.code === 402) {
useUserStore().logOut() handleTokenExpired(resolve, reject, doRequest, loading)
return
} }
// 显示具体的错误信息 // 显示具体的错误信息
const errorMsg = msg || '请求出现异常,请联系工作人员' const errorMsg = msg || '请求出现异常,请联系工作人员'
// uni.showToast({
// title: errorMsg,
// icon: 'none'
// })
const err = new Error(errorMsg) const err = new Error(errorMsg)
err.error = resData err.error = resData
reject(err) reject(err)
@@ -222,6 +238,40 @@ export function createRequest(url, data = {}, method = 'GET', loading = false, h
} }
}); });
}) })
}
return doRequest()
}
const handleTokenExpired = (resolve, reject, retryRequest, loading) => {
if (isRefreshing) {
addRefreshSubscriber((token) => {
if (token) {
retryRequest().then(resolve).catch(reject)
} else {
reject(new Error('刷新token失败'))
}
})
return
}
isRefreshing = true
useUserStore().refreshAccessToken().then((newToken) => {
notifyRefreshSubscribers(newToken)
retryRequest().then(resolve).catch(reject)
}).catch((error) => {
resetRefreshState()
uni.showToast({
title: '登录过期,请重新登录',
icon: 'none'
})
reject(error)
}).finally(() => {
if (loading) {
uni.hideLoading()
}
})
} }