feat: 按钮权限自定义指令

This commit is contained in:
WANGFAN\wangf 2025-04-10 11:45:46 +08:00
parent 0025244927
commit d3ff41aa8b
8 changed files with 148 additions and 23 deletions

View File

@ -1,7 +1,8 @@
import { App } from "vue"; import { App } from "vue";
import antiShake from "@/directives/modules/anti-shake"; import antiShake from "@/directives/modules/global/anti-shake";
import throttle from "@/directives/modules/throttle"; import throttle from "@/directives/modules/global/throttle";
import custom from "@/directives/modules/custom"; import custom from "@/directives/modules/global/custom";
import hasPerm from "@/directives/modules/permission/has-perm";
// 定义安装函数 // 定义安装函数
// install 函数是一个对象中的方法,其作用是将一系列指令对象安装到 Vue 应用实例中它自带两个参数app 和 options // install 函数是一个对象中的方法,其作用是将一系列指令对象安装到 Vue 应用实例中它自带两个参数app 和 options
@ -13,6 +14,7 @@ const directives = {
app.directive("antiShake", antiShake); app.directive("antiShake", antiShake);
app.directive("throttle", throttle); app.directive("throttle", throttle);
app.directive("custom", custom); app.directive("custom", custom);
app.directive("hasPerm", hasPerm);
} }
}; };

View File

@ -0,0 +1,57 @@
import { Directive } from "vue";
import { useUserInfoStore } from "@/store/modules/user-info";
/**
*
* @param value
* @returns {Array<string>}
*/
const bindingValueEmpty = (value: unknown): Array<string> => {
// 处理未定义或空值情况
if (!value) throw new Error("v-permission 指令需要配置权限标识");
// 标准化为数组格式
// 如果 value 是一个数组,则直接返回该数组
// 如果 value 不是数组,则将其转换为包含单个字符串元素的数组
return Array.isArray(value) ? (value as string[]) : [String(value)];
};
/**
*
* @param {HTMLElement} el dom元素
* @param {unknown} bindingValue
*/
const checkPermissions = (el: HTMLElement, bindingValue: unknown) => {
try {
// 检测自定义指令并转化为数组格式
const requiredPermissions = bindingValueEmpty(bindingValue);
// 超级管理员标识
const all_permission = "*:*:*";
// 获取用户权限标识-Array[string]
let { permissions } = useUserInfoStore().account;
// 如果是超级管理员则放行
if (permissions.includes(all_permission)) return;
const hasPermissions = requiredPermissions.some((perm: string) => permissions.includes(perm));
// 无权限、父节点存在时
if (!hasPermissions && el.parentNode) {
// 则删除当前子节点
el.parentNode.removeChild(el);
}
} catch (error) {
console.error(`权限指令错误: ${error}`);
// 删除当前节点
if (el.parentNode) el.parentNode.removeChild(el);
}
};
const hasPerm: Directive = {
mounted: (el, binding) => checkPermissions(el, binding.value),
updated: (el, binding) => checkPermissions(el, binding.value)
};
export default hasPerm;

View File

@ -1474,7 +1474,7 @@ export const permissionData = [
hide: false, hide: false,
disable: false, disable: false,
roles: ["admin", "common"], roles: ["admin", "common"],
permission: "common:btn:delete", permission: "common:btn:add",
sort: 1, sort: 1,
type: 3 type: 3
} }
@ -1487,7 +1487,7 @@ export const permissionData = [
hide: false, hide: false,
disable: false, disable: false,
roles: ["admin", "common"], roles: ["admin", "common"],
permission: "common:btn:delete", permission: "common:btn:edit",
sort: 2, sort: 2,
type: 3 type: 3
} }

View File

@ -13,11 +13,33 @@
<a-typography-title :heading="4"> 当前页面角色权限 </a-typography-title> <a-typography-title :heading="4"> 当前页面角色权限 </a-typography-title>
<code-view :code-json="pageRule" style="width: 100%" /> <code-view :code-json="pageRule" style="width: 100%" />
<br /> <br />
<a-space> <a-row :gutter="[24, 12]">
<a-button type="primary">新增</a-button> <a-col :span="24">
<a-button type="primary" status="success">编辑</a-button> <code-view type="vue" :code-json="sysBtn" style="width: 100%" />
<a-button type="primary" status="danger">删除</a-button> </a-col>
</a-space> <a-col :span="24">
<a-space>
<span>权限按钮</span>
<a-button v-hasPerm="['sys:btn:add']" type="primary">新增</a-button>
<a-button v-hasPerm="['sys:btn:edit']" type="primary" status="success">编辑</a-button>
<a-button v-hasPerm="['sys:btn:delete']" type="primary" status="danger">删除</a-button>
</a-space>
</a-col>
</a-row>
<br />
<a-row :gutter="[24, 12]">
<a-col :span="24">
<code-view type="vue" :code-json="commonBtn" style="width: 100%" />
</a-col>
<a-col :span="24">
<a-space>
<span>权限按钮</span>
<a-button v-hasPerm="['common:btn:add']" type="primary">新增</a-button>
<a-button v-hasPerm="['common:btn:edit']" type="primary" status="success">编辑</a-button>
<a-button v-hasPerm="['common:btn:delete']" type="primary" status="danger">删除</a-button>
</a-space>
</a-col>
</a-row>
</div> </div>
</div> </div>
</template> </template>
@ -30,7 +52,18 @@ let userInfoStore = useUserInfoStore();
let { account } = storeToRefs(userInfoStore); let { account } = storeToRefs(userInfoStore);
const permissions = computed(() => JSON.stringify(account.value.permissions, null)); const permissions = computed(() => JSON.stringify(account.value.permissions, null));
const pageRule = computed(() => JSON.stringify(route.meta.roles, null)); const pageRule = computed(() => JSON.stringify(route.meta.roles, null));
console.log("权限数据", account.value);
let sysBtn = `<a-space>
<a-button v-hasPerm="['sys:btn:add']" type="primary">新增</a-button>
<a-button v-hasPerm="['sys:btn:edit']" type="primary" status="success">编辑</a-button>
<a-button v-hasPerm="['sys:btn:delete']" type="primary" status="danger">删除</a-button>
</a-space>`;
let commonBtn = `<a-space>
<a-button v-hasPerm="['common:btn:add']" type="primary">新增</a-button>
<a-button v-hasPerm="['common:btn:edit']" type="primary" status="success">编辑</a-button>
<a-button v-hasPerm="['common:btn:delete']" type="primary" status="danger">删除</a-button>
</a-space>`;
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -2,22 +2,44 @@
<div class="snow-page"> <div class="snow-page">
<div class="snow-inner"> <div class="snow-inner">
<a-alert> <a-alert>
当前页面 当前页面
<a-tag color="green"> 超级管理员 </a-tag> <a-tag color="green"> 超级管理员 </a-tag>
权限页面
<a-tag color="orange"> 普通角色 </a-tag> <a-tag color="green"> 普通角色 </a-tag>
无法查看 都可以查看
</a-alert> </a-alert>
<a-typography-title :heading="4"> 当前用户权限 </a-typography-title> <a-typography-title :heading="4"> 当前用户权限 </a-typography-title>
<code-view :code-json="userPermissions" style="width: 100%" /> <code-view :code-json="permissions" style="width: 100%" />
<a-typography-title :heading="4"> 当前页面角色权限 </a-typography-title> <a-typography-title :heading="4"> 当前页面角色权限 </a-typography-title>
<code-view :code-json="pageRule" style="width: 100%" /> <code-view :code-json="pageRule" style="width: 100%" />
<br /> <br />
<a-space> <a-row :gutter="[24, 12]">
<a-button type="primary">新增</a-button> <a-col :span="24">
<a-button type="primary" status="success">编辑</a-button> <code-view type="vue" :code-json="sysBtn" style="width: 100%" />
<a-button type="primary" status="danger">删除</a-button> </a-col>
</a-space> <a-col :span="24">
<a-space>
<span>权限按钮</span>
<a-button v-hasPerm="['sys:btn:add']" type="primary">新增</a-button>
<a-button v-hasPerm="['sys:btn:edit']" type="primary" status="success">编辑</a-button>
<a-button v-hasPerm="['sys:btn:delete']" type="primary" status="danger">删除</a-button>
</a-space>
</a-col>
</a-row>
<br />
<a-row :gutter="[24, 12]">
<a-col :span="24">
<code-view type="vue" :code-json="commonBtn" style="width: 100%" />
</a-col>
<a-col :span="24">
<a-space>
<span>权限按钮</span>
<a-button v-hasPerm="['common:btn:add']" type="primary">新增</a-button>
<a-button v-hasPerm="['common:btn:edit']" type="primary" status="success">编辑</a-button>
<a-button v-hasPerm="'common:btn:delete'" type="primary" status="danger">删除</a-button>
</a-space>
</a-col>
</a-row>
</div> </div>
</div> </div>
</template> </template>
@ -28,9 +50,20 @@ import { useUserInfoStore } from "@/store/modules/user-info";
const route = useRoute(); const route = useRoute();
let userInfoStore = useUserInfoStore(); let userInfoStore = useUserInfoStore();
let { account } = storeToRefs(userInfoStore); let { account } = storeToRefs(userInfoStore);
const userPermissions = computed(() => JSON.stringify(account.value.permissions, null)); const permissions = computed(() => JSON.stringify(account.value.permissions, null));
const pageRule = computed(() => JSON.stringify(route.meta.roles, null)); const pageRule = computed(() => JSON.stringify(route.meta.roles, null));
console.log("权限数据", account.value);
let sysBtn = `<a-space>
<a-button v-hasPerm="['sys:btn:add']" type="primary">新增</a-button>
<a-button v-hasPerm="['sys:btn:edit']" type="primary" status="success">编辑</a-button>
<a-button v-hasPerm="['sys:btn:delete']" type="primary" status="danger">删除</a-button>
</a-space>`;
let commonBtn = `<a-space>
<a-button v-hasPerm="['common:btn:add']" type="primary">新增</a-button>
<a-button v-hasPerm="['common:btn:edit']" type="primary" status="success">编辑</a-button>
<a-button v-hasPerm="['common:btn:delete']" type="primary" status="danger">删除</a-button>
</a-space>`;
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>