2026-03-27 22:20:25 +08:00
|
|
|
|
import type { App, DirectiveBinding } from "vue";
|
|
|
|
|
|
import { useAuthStore } from "@/stores/auth";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 权限指令配置
|
|
|
|
|
|
*/
|
|
|
|
|
|
interface PermissionDirectiveValue {
|
|
|
|
|
|
// 权限码或权限码数组
|
|
|
|
|
|
permission: string | string[];
|
|
|
|
|
|
// 是否隐藏元素(默认 false,即禁用)
|
|
|
|
|
|
hide?: boolean;
|
|
|
|
|
|
// 是否需要所有权限(默认 false,即任一权限即可)
|
|
|
|
|
|
all?: boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查权限
|
|
|
|
|
|
*/
|
|
|
|
|
|
function checkPermission(
|
|
|
|
|
|
value: string | string[] | PermissionDirectiveValue,
|
|
|
|
|
|
all: boolean = false
|
|
|
|
|
|
): boolean {
|
|
|
|
|
|
// 在指令中,我们需要通过 getCurrentInstance 获取 store
|
|
|
|
|
|
// 但更好的方式是直接导入 store,因为 Pinia store 是全局的
|
|
|
|
|
|
const authStore = useAuthStore();
|
|
|
|
|
|
|
|
|
|
|
|
// 如果值是字符串或数组,直接检查权限
|
|
|
|
|
|
if (typeof value === "string") {
|
|
|
|
|
|
return authStore.hasPermission(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(value)) {
|
|
|
|
|
|
return all
|
|
|
|
|
|
? value.every((perm) => authStore.hasPermission(perm))
|
|
|
|
|
|
: authStore.hasAnyPermission(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果是对象配置
|
|
|
|
|
|
if (typeof value === "object" && value !== null) {
|
|
|
|
|
|
const { permission, all: needAll = false } = value as PermissionDirectiveValue;
|
|
|
|
|
|
if (typeof permission === "string") {
|
|
|
|
|
|
return authStore.hasPermission(permission);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (Array.isArray(permission)) {
|
|
|
|
|
|
return needAll
|
|
|
|
|
|
? permission.every((perm) => authStore.hasPermission(perm))
|
|
|
|
|
|
: authStore.hasAnyPermission(permission);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 处理元素权限
|
|
|
|
|
|
*/
|
|
|
|
|
|
function handlePermission(
|
|
|
|
|
|
el: HTMLElement,
|
|
|
|
|
|
binding: DirectiveBinding<string | string[] | PermissionDirectiveValue>
|
|
|
|
|
|
) {
|
|
|
|
|
|
const { value, modifiers } = binding;
|
|
|
|
|
|
|
|
|
|
|
|
// 如果没有值,默认允许
|
|
|
|
|
|
if (!value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否需要所有权限
|
|
|
|
|
|
const needAll = modifiers.all || false;
|
|
|
|
|
|
|
|
|
|
|
|
// 解析配置
|
|
|
|
|
|
let config: PermissionDirectiveValue;
|
|
|
|
|
|
if (typeof value === "string" || Array.isArray(value)) {
|
|
|
|
|
|
config = {
|
|
|
|
|
|
permission: value,
|
|
|
|
|
|
hide: modifiers.hide || false,
|
|
|
|
|
|
all: needAll,
|
|
|
|
|
|
};
|
|
|
|
|
|
} else {
|
|
|
|
|
|
config = {
|
|
|
|
|
|
permission: value.permission,
|
|
|
|
|
|
hide: value.hide ?? modifiers.hide ?? false,
|
|
|
|
|
|
all: value.all ?? needAll,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const hasPermission = checkPermission(config.permission, config.all);
|
|
|
|
|
|
|
|
|
|
|
|
if (config.hide) {
|
|
|
|
|
|
// 隐藏元素
|
|
|
|
|
|
if (hasPermission) {
|
|
|
|
|
|
el.style.display = "";
|
|
|
|
|
|
el.removeAttribute("data-permission-hidden");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
el.style.display = "none";
|
|
|
|
|
|
el.setAttribute("data-permission-hidden", "true");
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 禁用元素(默认行为)
|
|
|
|
|
|
if (hasPermission) {
|
|
|
|
|
|
// 恢复元素状态
|
|
|
|
|
|
if (el instanceof HTMLButtonElement || el instanceof HTMLInputElement) {
|
|
|
|
|
|
el.disabled = false;
|
|
|
|
|
|
el.classList.remove("permission-disabled");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
el.style.pointerEvents = "";
|
|
|
|
|
|
el.style.opacity = "";
|
|
|
|
|
|
el.classList.remove("permission-disabled");
|
|
|
|
|
|
}
|
|
|
|
|
|
el.removeAttribute("data-permission-disabled");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 禁用元素
|
|
|
|
|
|
if (el instanceof HTMLButtonElement || el instanceof HTMLInputElement) {
|
|
|
|
|
|
el.disabled = true;
|
|
|
|
|
|
el.classList.add("permission-disabled");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
el.style.pointerEvents = "none";
|
|
|
|
|
|
el.style.opacity = "0.6";
|
|
|
|
|
|
el.classList.add("permission-disabled");
|
|
|
|
|
|
}
|
|
|
|
|
|
el.setAttribute("data-permission-disabled", "true");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 权限指令
|
|
|
|
|
|
*/
|
|
|
|
|
|
const permissionDirective = {
|
|
|
|
|
|
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
|
|
|
|
|
handlePermission(el, binding);
|
|
|
|
|
|
},
|
|
|
|
|
|
updated(el: HTMLElement, binding: DirectiveBinding) {
|
|
|
|
|
|
handlePermission(el, binding);
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 注册权限指令
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function setupPermissionDirective(app: App) {
|
|
|
|
|
|
app.directive("permission", permissionDirective);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default permissionDirective;
|
|
|
|
|
|
|