通过 VITE_AUTO_FILL_TEST 环境变量控制,在 .env.test 中启用, 使测试环境构建后登录框也能自动填充测试账号,方便测试人员使用。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
147 lines
3.9 KiB
TypeScript
147 lines
3.9 KiB
TypeScript
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;
|
||
|