fix:将侧边栏兼容移动端

This commit is contained in:
2026-01-20 17:54:45 +08:00
parent 0b57581799
commit e3e70114fb
18 changed files with 3059 additions and 316 deletions
+142 -15
View File
@@ -1,6 +1,7 @@
import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'
import {getRefreshToken,refreshAccessToken} from "@/api/login.js";
// 基础URL
const baseUrl = 'https://apiservertest.s1f.ren' // SSL证书有问题
@@ -10,18 +11,100 @@ const baseUrl = 'https://apiservertest.s1f.ren' // SSL证书有问题
// 检查URL是否需要认证
const urlNeedAuth = (url) => {
// 这里可以添加不需要认证的URL列表
const noAuthUrls = ['/v1/user/login', '/v1/user/check/get_code_img', '/v1/user/register']
const noAuthUrls = ['/v1/user/login', '/v1/user/check/get_code_img', '/v1/user/register', '/v1/user/refresh_token']
return !noAuthUrls.some(noAuthUrl => url.includes(noAuthUrl))
}
// 检查token是否过期
const isTokenExpired = () => {
const token = localStorage.getItem('token')
const expire = localStorage.getItem('tokenExpire')
if (!token) return true
// 这里可以添加token过期检查逻辑,如果有JWT可以解析它
// 简单实现,仅检查token是否存在
return false
// 检查过期时间
if (expire) {
const expireTime = parseInt(expire) * 1000 // 转换为毫秒
const now = Date.now()
return now >= expireTime
}
// 没有过期时间时,默认认为Token已过期(因为无法验证有效性)
return true
}
// 检查token是否即将过期(5分钟内)
const isTokenExpiringSoon = () => {
const expire = localStorage.getItem('tokenExpire')
if (!expire) return false
const expireTime = parseInt(expire) * 1000 // 转换为毫秒
const now = Date.now()
const fiveMinutes = 5 * 60 * 1000 // 5分钟
// 如果已过期,返回false(由isTokenExpired处理)
if (now >= expireTime) return false
// 如果在5分钟内过期,返回true
return (expireTime - now) <= fiveMinutes
}
// 正在刷新token的标志
let isRefreshing = false
// 等待刷新token的请求队列
let refreshSubscribers = []
// 添加请求到队列
const subscribeTokenRefresh = (callback) => {
refreshSubscribers.push(callback)
}
// 刷新token后执行队列中的请求
const onTokenRefreshed = (newToken) => {
refreshSubscribers.forEach(callback => callback(newToken))
refreshSubscribers = []
}
// 执行token刷新
const doRefreshToken = async () => {
try {
const domain = window.location.hostname
// 获取交换token
const refreshTokenRes = await getRefreshToken(domain,{
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`
}
})
if (refreshTokenRes.data?.code === 200 && refreshTokenRes.data?.data?.refresh_token) {
// 使用交换token获取新的access token
const newTokenRes = await refreshAccessToken(refreshTokenRes.data.data.refresh_token)
if (newTokenRes.data?.code === 200 && newTokenRes.data?.data?.token) {
const { token, expire } = newTokenRes.data.data
localStorage.setItem('token', token)
if (expire) {
localStorage.setItem('tokenExpire', expire.toString())
}
return token
}
}
// 刷新失败,触发登出逻辑
localStorage.removeItem('token')
localStorage.removeItem('tokenExpire')
localStorage.removeItem('userInfo')
ElMessage.warning('登录过期,请重新登录')
router.push('/login')
return null
} catch (error) {
console.error('Token刷新失败:', error)
// 刷新失败,触发登出逻辑
localStorage.removeItem('token')
localStorage.removeItem('tokenExpire')
localStorage.removeItem('userInfo')
ElMessage.warning('登录过期,请重新登录')
router.push('/login')
return null
}
}
class Request {
@@ -122,19 +205,63 @@ export const http2 = axios.create({
headers: {},
});
http2.interceptors.request.use(config => {
const token = localStorage.getItem('token'); // 假设 token 存储在 localStorage
if(urlNeedAuth(config.url) && isTokenExpired()){
if (token){
localStorage.removeItem('token');
ElMessage.warning('登陆过期,请重新登陆')
http2.interceptors.request.use(async config => {
const token = localStorage.getItem('token')
// 检查是否需要认证
if (urlNeedAuth(config.url)) {
// 检查token是否已过期
if (isTokenExpired()) {
if (token) {
localStorage.removeItem('token')
localStorage.removeItem('tokenExpire')
localStorage.removeItem('userInfo')
ElMessage.warning('登录过期,请重新登录')
}
router.push('/login')
return Promise.reject(new Error('Token已过期'))
}
// 检查token是否即将过期,进行无感刷新
if (isTokenExpiringSoon() && !isRefreshing) {
isRefreshing = true
try {
const newToken = await doRefreshToken()
if (newToken) {
console.log('Token已无感刷新')
onTokenRefreshed(newToken)
config.headers.Authorization = `Bearer ${newToken}`
} else {
// 刷新失败,doRefreshToken已处理登出逻辑,直接拒绝请求
return Promise.reject(new Error('Token刷新失败'))
}
} catch (error) {
console.error('Token刷新异常:', error)
// 刷新异常,doRefreshToken已处理登出逻辑,直接拒绝请求
return Promise.reject(error)
} finally {
isRefreshing = false
}
} else if (isRefreshing) {
// 正在刷新,等待刷新完成
return new Promise((resolve, reject) => {
subscribeTokenRefresh((newToken) => {
if (newToken) {
config.headers.Authorization = `Bearer ${newToken}`
// 重新发送原始请求
resolve(config)
} else {
reject(new Error('Token刷新失败'))
}
})
})
} else {
// 正常情况,直接使用token
config.headers.Authorization = `Bearer ${token}`
}
router.push('/login')
return Promise.reject();
}
config.headers.Authorization = `Bearer ${token}`;
config.url = config.url
// 不需要认证的请求,不添加token
return config
})
+55 -3
View File
@@ -18,7 +18,7 @@ export const formatDate = (dateStr) => {
return `${year}-${month}-${day} ${hours}:${minutes}`
}
/**
* 时间格式转 Unix 时间戳(秒级)
* 时间格式转 Unix 时间戳(秒级)
* @param {string|Date} time - 输入时间(支持 '2025-10-28 00:00:00'、'2025/10/28'、Date 对象等)
* @returns {number|null} 转换后的毫秒级时间戳(失败返回 null)
*/
@@ -50,10 +50,62 @@ export function timeToTimestamp(time) {
return null;
}
return Math.floor(timestamp / 1000); // 返回秒级时间戳(如 1751107200000
return Math.floor(timestamp / 1000); // 返回秒级时间戳(如 1751107200000
}
export function reducenum(num){
return num / 100
}
}
/**
* 将 ISO 格式时间字符串转换为毫秒级时间戳(用于时间选择器)
* @param {string|Date|number} time - 输入时间(支持 ISO 格式字符串如 '2023-11-08T01:10:00+08:00'、Date 对象、时间戳等)
* @returns {number|null} 转换后的毫秒级时间戳(失败或无效时间返回 null)
*/
export function isoToMilliseconds(time) {
// 处理空值
if (!time || time === null || time === undefined) {
return null
}
// 处理特殊的无效时间标识
if (typeof time === 'string' && (time === '0001-01-01T00:00:00Z' || time === '0001-01-01T00:00:00+00:00')) {
return null
}
// 如果已经是数字(时间戳),直接返回
if (typeof time === 'number') {
// 如果是秒级时间戳(小于 13 位),转换为毫秒
if (time < 1000000000000) {
return time * 1000
}
return time
}
// 处理 Date 对象
if (time instanceof Date) {
const timestamp = time.getTime()
return isNaN(timestamp) ? null : timestamp
}
// 处理字符串格式
if (typeof time === 'string') {
try {
const date = new Date(time)
const timestamp = date.getTime()
// 检查是否为有效时间
if (isNaN(timestamp)) {
return null
}
return timestamp
} catch (error) {
console.error('时间转换失败:', error)
return null
}
}
return null
}