refactor(storage): ♻️ 简化缓存管理方式,统一使用Storage类直接操作token和缓存
This commit is contained in:
7
src/constants/cache-keys.ts
Normal file
7
src/constants/cache-keys.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* 缓存键常量
|
||||||
|
*/
|
||||||
|
export const ACCESS_TOKEN_KEY = "access_token";
|
||||||
|
export const REFRESH_TOKEN_KEY = "refresh_token";
|
||||||
|
export const DICT_CACHE_KEY = "dict_cache";
|
||||||
|
// 可在此处添加其他缓存键
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Client, IMessage, StompSubscription } from "@stomp/stompjs";
|
import { Client, IMessage, StompSubscription } from "@stomp/stompjs";
|
||||||
import { getAccessToken } from "@/utils/auth";
|
import { Storage } from "@/utils/storage";
|
||||||
|
import { ACCESS_TOKEN_KEY } from "@/constants/cache-keys";
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
|
|
||||||
export interface UseStompOptions {
|
export interface UseStompOptions {
|
||||||
@@ -66,7 +67,7 @@ export function useStomp(options: UseStompOptions = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 每次连接前重新获取最新令牌,不依赖之前的token值
|
// 每次连接前重新获取最新令牌,不依赖之前的token值
|
||||||
const currentToken = getAccessToken();
|
const currentToken = Storage.get(ACCESS_TOKEN_KEY, "");
|
||||||
|
|
||||||
// 检查令牌是否为空,如果为空则不进行连接
|
// 检查令牌是否为空,如果为空则不进行连接
|
||||||
if (!currentToken) {
|
if (!currentToken) {
|
||||||
@@ -120,7 +121,7 @@ export function useStomp(options: UseStompOptions = {}) {
|
|||||||
client.value = null;
|
client.value = null;
|
||||||
|
|
||||||
// 检查当前是否有有效令牌
|
// 检查当前是否有有效令牌
|
||||||
const freshToken = getAccessToken();
|
const freshToken = Storage.get(ACCESS_TOKEN_KEY, "");
|
||||||
if (freshToken) {
|
if (freshToken) {
|
||||||
initializeClient();
|
initializeClient();
|
||||||
connect();
|
connect();
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { ref, onMounted, onUnmounted, watch } from "vue";
|
import { ref, onMounted, onUnmounted, watch } from "vue";
|
||||||
import { useStomp } from "../core/useStomp";
|
import { useStomp } from "../core/useStomp";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { getAccessToken } from "@/utils/auth";
|
import { Storage } from "@/utils/storage";
|
||||||
|
import { ACCESS_TOKEN_KEY } from "@/constants/cache-keys";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在线用户计数Hook
|
* 在线用户计数Hook
|
||||||
@@ -99,7 +100,7 @@ export function useOnlineCount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否有可用的令牌
|
// 检查是否有可用的令牌
|
||||||
const hasToken = !!getAccessToken();
|
const hasToken = !!Storage.get(ACCESS_TOKEN_KEY, "");
|
||||||
if (!hasToken) {
|
if (!hasToken) {
|
||||||
console.log("没有检测到有效令牌,不尝试WebSocket连接");
|
console.log("没有检测到有效令牌,不尝试WebSocket连接");
|
||||||
return;
|
return;
|
||||||
@@ -121,7 +122,7 @@ export function useOnlineCount() {
|
|||||||
closeWebSocket();
|
closeWebSocket();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 再次检查令牌有效性
|
// 再次检查令牌有效性
|
||||||
if (getAccessToken()) {
|
if (Storage.get(ACCESS_TOKEN_KEY, "")) {
|
||||||
initWebSocket();
|
initWebSocket();
|
||||||
} else {
|
} else {
|
||||||
console.log("令牌无效,放弃重连");
|
console.log("令牌无效,放弃重连");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { NavigationGuardNext, RouteLocationNormalized, RouteRecordRaw } from "vue-router";
|
import type { NavigationGuardNext, RouteLocationNormalized, RouteRecordRaw } from "vue-router";
|
||||||
import NProgress from "@/utils/nprogress";
|
import NProgress from "@/utils/nprogress";
|
||||||
import { getAccessToken } from "@/utils/auth";
|
import { Storage } from "@/utils/storage";
|
||||||
|
import { ACCESS_TOKEN_KEY } from "@/constants/cache-keys";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import { usePermissionStore, useUserStore } from "@/store";
|
import { usePermissionStore, useUserStore } from "@/store";
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ export function setupPermission() {
|
|||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
NProgress.start();
|
NProgress.start();
|
||||||
|
|
||||||
const isLogin = !!getAccessToken(); // 判断是否登录
|
const isLogin = !!Storage.get(ACCESS_TOKEN_KEY, ""); // 判断是否登录
|
||||||
if (isLogin) {
|
if (isLogin) {
|
||||||
if (to.path === "/login") {
|
if (to.path === "/login") {
|
||||||
// 已登录,访问登录页,跳转到首页
|
// 已登录,访问登录页,跳转到首页
|
||||||
|
|||||||
0
src/plugins/permission.ts.bak
Normal file
0
src/plugins/permission.ts.bak
Normal file
@@ -1,5 +1,6 @@
|
|||||||
import { useDictSync } from "@/hooks/websocket/services/useDictSync";
|
import { useDictSync } from "@/hooks/websocket/services/useDictSync";
|
||||||
import { getAccessToken } from "@/utils/auth";
|
import { Storage } from "@/utils/storage";
|
||||||
|
import { ACCESS_TOKEN_KEY } from "@/constants/cache-keys";
|
||||||
|
|
||||||
// 用于防止重复初始化的状态标记
|
// 用于防止重复初始化的状态标记
|
||||||
let isInitialized = false;
|
let isInitialized = false;
|
||||||
@@ -24,7 +25,7 @@ export function setupWebSocket() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查token是否存在
|
// 检查token是否存在
|
||||||
const token = getAccessToken();
|
const token = Storage.get(ACCESS_TOKEN_KEY, "");
|
||||||
if (!token) {
|
if (!token) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"[WebSocketPlugin] 未找到访问令牌,WebSocket初始化已跳过。用户登录后将自动重新连接。"
|
"[WebSocketPlugin] 未找到访问令牌,WebSocket初始化已跳过。用户登录后将自动重新连接。"
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import { useDictStoreHook } from "@/store/modules/dict.store";
|
|||||||
import AuthAPI, { type LoginFormData } from "@/api/auth.api";
|
import AuthAPI, { type LoginFormData } from "@/api/auth.api";
|
||||||
import UserAPI, { type UserInfo } from "@/api/system/user.api";
|
import UserAPI, { type UserInfo } from "@/api/system/user.api";
|
||||||
|
|
||||||
import { setAccessToken, setRefreshToken, getRefreshToken, clearToken } from "@/utils/auth";
|
import { Storage } from "@/utils/storage";
|
||||||
|
import { ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY } from "@/constants/cache-keys";
|
||||||
|
|
||||||
export const useUserStore = defineStore("user", () => {
|
export const useUserStore = defineStore("user", () => {
|
||||||
const userInfo = useStorage<UserInfo>("userInfo", {} as UserInfo);
|
const userInfo = useStorage<UserInfo>("userInfo", {} as UserInfo);
|
||||||
@@ -21,8 +22,8 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
AuthAPI.login(LoginFormData)
|
AuthAPI.login(LoginFormData)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
const { accessToken, refreshToken } = data;
|
const { accessToken, refreshToken } = data;
|
||||||
setAccessToken(accessToken); // eyJhbGciOiJIUzI1NiJ9.xxx.xxx
|
Storage.set(ACCESS_TOKEN_KEY, accessToken);
|
||||||
setRefreshToken(refreshToken);
|
Storage.set(REFRESH_TOKEN_KEY, refreshToken);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -73,13 +74,13 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
* 刷新 token
|
* 刷新 token
|
||||||
*/
|
*/
|
||||||
function refreshToken() {
|
function refreshToken() {
|
||||||
const refreshToken = getRefreshToken();
|
const refreshToken = Storage.get(REFRESH_TOKEN_KEY, "");
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
AuthAPI.refreshToken(refreshToken)
|
AuthAPI.refreshToken(refreshToken)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
const { accessToken, refreshToken } = data;
|
const { accessToken, refreshToken } = data;
|
||||||
setAccessToken(accessToken);
|
Storage.set(ACCESS_TOKEN_KEY, accessToken);
|
||||||
setRefreshToken(refreshToken);
|
Storage.set(REFRESH_TOKEN_KEY, refreshToken);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -96,7 +97,8 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
useDictStoreHook().clearDictCache();
|
useDictStoreHook().clearDictCache();
|
||||||
usePermissionStoreHook().resetRouter();
|
usePermissionStoreHook().resetRouter();
|
||||||
clearToken();
|
Storage.remove(ACCESS_TOKEN_KEY);
|
||||||
|
Storage.remove(REFRESH_TOKEN_KEY);
|
||||||
userInfo.value = {} as UserInfo;
|
userInfo.value = {} as UserInfo;
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
// 访问 token 缓存的 key
|
|
||||||
const ACCESS_TOKEN_KEY = "access_token";
|
|
||||||
// 刷新 token 缓存的 key
|
|
||||||
const REFRESH_TOKEN_KEY = "refresh_token";
|
|
||||||
|
|
||||||
function getAccessToken(): string {
|
|
||||||
return localStorage.getItem(ACCESS_TOKEN_KEY) || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAccessToken(token: string) {
|
|
||||||
localStorage.setItem(ACCESS_TOKEN_KEY, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRefreshToken(): string {
|
|
||||||
return localStorage.getItem(REFRESH_TOKEN_KEY) || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function setRefreshToken(token: string) {
|
|
||||||
localStorage.setItem(REFRESH_TOKEN_KEY, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearToken() {
|
|
||||||
localStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
||||||
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { getAccessToken, setAccessToken, clearToken, getRefreshToken, setRefreshToken };
|
|
||||||
@@ -2,7 +2,8 @@ import axios, { type InternalAxiosRequestConfig, type AxiosResponse } from "axio
|
|||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import { useUserStoreHook } from "@/store/modules/user.store";
|
import { useUserStoreHook } from "@/store/modules/user.store";
|
||||||
import { ResultEnum } from "@/enums/api/result.enum";
|
import { ResultEnum } from "@/enums/api/result.enum";
|
||||||
import { getAccessToken } from "@/utils/auth";
|
import { Storage } from "@/utils/storage";
|
||||||
|
import { ACCESS_TOKEN_KEY } from "@/constants/cache-keys";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
|
||||||
// 创建 axios 实例
|
// 创建 axios 实例
|
||||||
@@ -15,7 +16,7 @@ const service = axios.create({
|
|||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
service.interceptors.request.use(
|
service.interceptors.request.use(
|
||||||
(config: InternalAxiosRequestConfig) => {
|
(config: InternalAxiosRequestConfig) => {
|
||||||
const accessToken = getAccessToken();
|
const accessToken = Storage.get(ACCESS_TOKEN_KEY, "");
|
||||||
// 如果 Authorization 设置为 no-auth,则不携带 Token
|
// 如果 Authorization 设置为 no-auth,则不携带 Token
|
||||||
if (config.headers.Authorization !== "no-auth" && accessToken) {
|
if (config.headers.Authorization !== "no-auth" && accessToken) {
|
||||||
config.headers.Authorization = `Bearer ${accessToken}`;
|
config.headers.Authorization = `Bearer ${accessToken}`;
|
||||||
@@ -69,7 +70,7 @@ async function handleTokenRefresh(config: InternalAxiosRequestConfig) {
|
|||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// 封装需要重试的请求
|
// 封装需要重试的请求
|
||||||
const retryRequest = () => {
|
const retryRequest = () => {
|
||||||
config.headers.Authorization = `Bearer ${getAccessToken()}`;
|
config.headers.Authorization = `Bearer ${Storage.get(ACCESS_TOKEN_KEY, "")}`;
|
||||||
resolve(service(config));
|
resolve(service(config));
|
||||||
};
|
};
|
||||||
waitingQueue.push(retryRequest);
|
waitingQueue.push(retryRequest);
|
||||||
|
|||||||
37
src/utils/storage.ts
Normal file
37
src/utils/storage.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* 存储工具类
|
||||||
|
* 提供localStorage和sessionStorage操作方法
|
||||||
|
*/
|
||||||
|
export class Storage {
|
||||||
|
/**
|
||||||
|
* localStorage 存储
|
||||||
|
*/
|
||||||
|
static set(key: string, value: any): void {
|
||||||
|
localStorage.setItem(key, JSON.stringify(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static get<T>(key: string, defaultValue?: T): T {
|
||||||
|
const value = localStorage.getItem(key);
|
||||||
|
return value ? JSON.parse(value) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static remove(key: string): void {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sessionStorage 存储
|
||||||
|
*/
|
||||||
|
static sessionSet(key: string, value: any): void {
|
||||||
|
sessionStorage.setItem(key, JSON.stringify(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static sessionGet<T>(key: string, defaultValue?: T): T {
|
||||||
|
const value = sessionStorage.getItem(key);
|
||||||
|
return value ? JSON.parse(value) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sessionRemove(key: string): void {
|
||||||
|
sessionStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user