feat: 添加自定义权限指令,工作台模块添加权限控制

This commit is contained in:
ray
2024-11-19 13:02:20 +08:00
parent 3e496f75d7
commit 0288e975dc
7 changed files with 104 additions and 18 deletions

View File

@@ -153,10 +153,10 @@ export interface UserInfo {
avatar?: string;
/** 角色 */
roles: string[];
roles?: string[];
/** 权限 */
perms: string[];
perms?: string[];
}
/**

10
src/directive/index.ts Normal file
View File

@@ -0,0 +1,10 @@
import type { App } from "vue";
import { hasPerm, hasRole } from "./permission";
// 全局注册 directive
export function setupDirective(app: App<Element>) {
// 使 v-hasPerm 在所有组件中都可用
app.directive("hasPerm", hasPerm);
app.directive("hasRole", hasRole);
}

View File

@@ -0,0 +1,69 @@
import type { Directive, DirectiveBinding } from "vue";
import { useUserStore } from "@/store";
/**
* 按钮权限
*/
export const hasPerm: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
const requiredPerms = binding.value;
console.log("requiredPerms", requiredPerms);
if (!requiredPerms) {
return;
}
// 校验传入的权限值是否合法
if (!requiredPerms || (typeof requiredPerms !== "string" && !Array.isArray(requiredPerms))) {
throw new Error(
"需要提供权限标识例如v-has-perm=\"'sys:user:add'\" 或 v-has-perm=\"['sys:user:add', 'sys:user:edit']\""
);
}
const { roles = [], perms = [] } = useUserStore().userInfo || {};
// 超级管理员拥有所有权限
if (roles?.includes("ROOT")) {
return;
}
// 检查权限
const hasAuth = Array.isArray(requiredPerms)
? requiredPerms.some((perm) => perms.includes(perm))
: perms.includes(requiredPerms);
// 如果没有权限,移除该元素
if (!hasAuth && el.parentNode) {
el.parentNode.removeChild(el);
}
},
};
/**
* 角色权限指令
*/
export const hasRole: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
const requiredRoles = binding.value;
// 校验传入的角色值是否合法
if (!requiredRoles || (typeof requiredRoles !== "string" && !Array.isArray(requiredRoles))) {
throw new Error(
"需要提供角色标识例如v-has-role=\"'ADMIN'\" 或 v-has-role=\"['ADMIN', 'TEST']\""
);
}
const { roles = [] } = useUserStore().userInfo || {};
// 检查是否有对应角色权限
const hasAuth = Array.isArray(requiredRoles)
? requiredRoles.some((role) => roles.includes(role))
: roles.includes(requiredRoles);
// 如果没有权限,移除元素
if (!hasAuth && el.parentNode) {
el.parentNode.removeChild(el);
}
},
};

View File

@@ -1,5 +1,7 @@
import { createSSRApp } from "vue";
import App from "./App.vue";
import setupPlugins from "@/plugins";
import "uno.css";
import { setupStore } from "@/store";
@@ -8,7 +10,7 @@ export function createApp() {
const app = createSSRApp(App);
setupStore(app);
app.use(setupPlugins);
return {
app,
};

View File

@@ -6,6 +6,7 @@
<wd-grid-item
v-for="(child, index) in item.children"
:key="index"
v-has-perm="child.prem"
use-slot
link-type="navigateTo"
:url="child.url"
@@ -30,36 +31,34 @@ const gridList = reactive([
icon: "/static/icons/user.png",
title: "用户管理",
url: "/pages/work/user/index",
prem: "sys:user:query",
},
{
icon: "/static/icons/role.png",
title: "角色管理",
},
{
icon: "/static/icons/menu.png",
title: "菜单管理",
prem: "sys:role:query",
},
{
icon: "/static/icons/dept.png",
title: "部门管理",
prem: "sys:dept:query",
},
{
icon: "/static/icons/dict.png",
title: "字典管理",
prem: "sys:dict:query",
},
{
icon: "/static/icons/config.png",
title: "系统配置",
url: "/pages/work/system/config/config",
url: "/pages/work/config",
prem: "sys:config:query",
},
{
icon: "/static/icons/notice.png",
title: "通知公告",
},
{
icon: "/static/icons/more.png",
title: "更多模块",
prem: "sys:notice:query",
},
],
},
@@ -74,15 +73,12 @@ const gridList = reactive([
icon: "/static/icons/log.png",
title: "日志管理",
url: "/pages/work/log/index",
prem: "sys:log:query",
},
{
icon: "/static/icons/performance.png",
title: "性能监控",
},
{
icon: "/static/icons/more.png",
title: "更多模块",
},
],
},
]);

9
src/plugins/index.ts Normal file
View File

@@ -0,0 +1,9 @@
import type { App } from "vue";
import { setupDirective } from "@/directive";
export default {
install(app: App<Element>) {
// 自定义指令(directive)
setupDirective(app);
},
};

View File

@@ -4,7 +4,7 @@ import UserAPI, { type UserInfo } from "@/api/system/user";
import { setToken, getUserInfo, setUserInfo, clearAll } from "@/utils/cache";
export const useUserStore = defineStore("user", () => {
const userInfo = ref<UserInfo | null>(getUserInfo());
const userInfo = ref<UserInfo | undefined>(getUserInfo());
// 登录
const login = (data: LoginFormData) => {
@@ -45,7 +45,7 @@ export const useUserStore = defineStore("user", () => {
console.error("登出失败", error);
} finally {
clearAll(); // 清除本地的 token 和用户信息缓存
userInfo.value = null; // 清空用户信息
userInfo.value = undefined; // 清空用户信息
}
};