refactor: ♻️ userStore 代码重构优化
Former-commit-id: ef31b8420a48a91dd2449d62fb615941d528bf24
This commit is contained in:
@@ -2,9 +2,10 @@
|
|||||||
* 登录用户信息
|
* 登录用户信息
|
||||||
*/
|
*/
|
||||||
export interface UserInfo {
|
export interface UserInfo {
|
||||||
userId: number;
|
userId?: number;
|
||||||
nickname: string;
|
username?: string;
|
||||||
avatar: string;
|
nickname?: string;
|
||||||
|
avatar?: string;
|
||||||
roles: string[];
|
roles: string[];
|
||||||
perms: string[];
|
perms: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { Directive, DirectiveBinding } from "vue";
|
|||||||
export const hasPerm: Directive = {
|
export const hasPerm: Directive = {
|
||||||
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||||
// 「超级管理员」拥有所有的按钮权限
|
// 「超级管理员」拥有所有的按钮权限
|
||||||
const { roles, perms } = useUserStoreHook();
|
const { roles, perms } = useUserStoreHook().user;
|
||||||
if (roles.includes("ROOT")) {
|
if (roles.includes("ROOT")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ export const hasRole: Directive = {
|
|||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
const requiredRoles = value; // DOM绑定需要的角色编码
|
const requiredRoles = value; // DOM绑定需要的角色编码
|
||||||
const { roles } = useUserStoreHook();
|
const { roles } = useUserStoreHook().user;
|
||||||
const hasRole = roles.some((perm) => {
|
const hasRole = roles.some((perm) => {
|
||||||
return requiredRoles.includes(perm);
|
return requiredRoles.includes(perm);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<!-- 用户头像 -->
|
<!-- 用户头像 -->
|
||||||
<el-dropdown trigger="click">
|
<el-dropdown trigger="click">
|
||||||
<div class="avatar-container">
|
<div class="avatar-container">
|
||||||
<img :src="userStore.avatar + '?imageView2/1/w/80/h/80'" />
|
<img :src="userStore.user.avatar + '?imageView2/1/w/80/h/80'" />
|
||||||
<i-ep-caret-bottom class="w-3 h-3" />
|
<i-ep-caret-bottom class="w-3 h-3" />
|
||||||
</div>
|
</div>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
NProgress.done();
|
NProgress.done();
|
||||||
} else {
|
} else {
|
||||||
const userStore = useUserStoreHook();
|
const userStore = useUserStoreHook();
|
||||||
const hasRoles = userStore.roles && userStore.roles.length > 0;
|
const hasRoles = userStore.user.roles && userStore.user.roles.length > 0;
|
||||||
if (hasRoles) {
|
if (hasRoles) {
|
||||||
// 未匹配到任何路由,跳转404
|
// 未匹配到任何路由,跳转404
|
||||||
if (to.matched.length === 0) {
|
if (to.matched.length === 0) {
|
||||||
@@ -40,7 +40,7 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
next({ ...to, replace: true });
|
next({ ...to, replace: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 移除 token 并跳转登录页
|
// 移除 token 并跳转登录页
|
||||||
await userStore.resetToken();
|
await userStore.resetStore();
|
||||||
next(`/login?redirect=${to.path}`);
|
next(`/login?redirect=${to.path}`);
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RouteRecordRaw, useRouter } from "vue-router";
|
import { RouteRecordRaw } from "vue-router";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { constantRoutes } from "@/router";
|
import { constantRoutes } from "@/router";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
|
|||||||
@@ -11,16 +11,15 @@ import { UserInfo } from "@/api/user/types";
|
|||||||
import { useStorage } from "@vueuse/core";
|
import { useStorage } from "@vueuse/core";
|
||||||
|
|
||||||
export const useUserStore = defineStore("user", () => {
|
export const useUserStore = defineStore("user", () => {
|
||||||
// state
|
const user: UserInfo = {
|
||||||
const userId = ref();
|
roles: [],
|
||||||
|
perms: [],
|
||||||
|
};
|
||||||
|
|
||||||
const token = useStorage("accessToken", "");
|
const token = useStorage("accessToken", "");
|
||||||
const nickname = ref("");
|
|
||||||
const avatar = ref("");
|
|
||||||
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
|
|
||||||
const perms = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录调用
|
* 登录
|
||||||
*
|
*
|
||||||
* @param {LoginData}
|
* @param {LoginData}
|
||||||
* @returns
|
* @returns
|
||||||
@@ -45,16 +44,14 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
getUserInfo()
|
getUserInfo()
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return reject("Verification failed, please Login again.");
|
reject("Verification failed, please Login again.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (!data.roles || data.roles.length <= 0) {
|
if (!data.roles || data.roles.length <= 0) {
|
||||||
reject("getUserInfo: roles must be a non-null array!");
|
reject("getUserInfo: roles must be a non-null array!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
userId.value = data.userId;
|
Object.assign(user, { ...data });
|
||||||
nickname.value = data.nickname;
|
|
||||||
avatar.value = data.avatar;
|
|
||||||
roles.value = data.roles;
|
|
||||||
perms.value = data.perms;
|
|
||||||
resolve(data);
|
resolve(data);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -68,8 +65,7 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
logoutApi()
|
logoutApi()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
resetRouter();
|
resetStore();
|
||||||
resetToken();
|
|
||||||
location.reload(); // 清空路由
|
location.reload(); // 清空路由
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
@@ -79,28 +75,19 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置
|
/** 清空缓存 */
|
||||||
function resetToken() {
|
function resetStore() {
|
||||||
|
resetRouter();
|
||||||
token.value = "";
|
token.value = "";
|
||||||
nickname.value = "";
|
Object.assign(user, { roles: [], perms: [] });
|
||||||
avatar.value = "";
|
|
||||||
roles.value = [];
|
|
||||||
perms.value = [];
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
nickname,
|
user,
|
||||||
avatar,
|
|
||||||
roles,
|
|
||||||
perms,
|
|
||||||
login,
|
login,
|
||||||
getInfo,
|
getInfo,
|
||||||
logout,
|
logout,
|
||||||
resetToken,
|
resetStore,
|
||||||
/**
|
|
||||||
* 当前登录用户ID
|
|
||||||
*/
|
|
||||||
userId,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -74,10 +74,10 @@ orderCount.value = 2000;
|
|||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img
|
<img
|
||||||
class="user-avatar"
|
class="user-avatar"
|
||||||
:src="userStore.avatar + '?imageView2/1/w/80/h/80'"
|
:src="userStore.user.avatar + '?imageView2/1/w/80/h/80'"
|
||||||
/>
|
/>
|
||||||
<span class="ml-[10px] text-[16px]">
|
<span class="ml-[10px] text-[16px]">
|
||||||
{{ userStore.nickname }}
|
{{ userStore.user.nickname }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ import { storeToRefs } from "pinia";
|
|||||||
|
|
||||||
const emit = defineEmits(["change"]);
|
const emit = defineEmits(["change"]);
|
||||||
const store = storeToRefs(useUserStoreHook());
|
const store = storeToRefs(useUserStoreHook());
|
||||||
const { roles } = store;
|
const { roles } = store.user.value;
|
||||||
|
|
||||||
const switchRoles = computed({
|
const switchRoles = computed({
|
||||||
get: () => roles.value[0],
|
get: () => roles[0],
|
||||||
set: (val) => {
|
set: (val) => {
|
||||||
roles.value = [val];
|
Object.assign(roles, [val]);
|
||||||
emit("change");
|
emit("change");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user