import { Directive, ObjectDirective, DirectiveBinding, render, createVNode, h } from 'vue'; import { ElTooltip } from 'element-plus'; import 'element-plus/theme-chalk/el-tooltip.css'; // 权限控制 const PermissionDirective: Directive = { // 数组, 权限 code 和 布尔值, // mounted(el: HTMLElement, binding: { value: (string | boolean)[] }, vnode: any) { updated(el: HTMLElement, binding: { value: (string | boolean)[] }, vnode: any) { const routePath: string = vnode.ctx.appContext.config.globalProperties.$route.path; const userInfo: { userInfo: { functionList: { code: string }[] } } | null = JSON.parse(sessionStorage.getItem('storeInfo') || ''); const authorityCodes: string[] = (userInfo?.userInfo?.functionList || []).map(({ code }) => code); const permissions: (string | boolean)[] = binding.value; const hasPermission: any[] = (binding.value || []).filter(item => typeof item !== 'boolean'); if (!Array.isArray(permissions)) { console.error('权限必须以数组形式提供'); return; } if (permissions.some((element): element is boolean => element === true)) { return; } if (!hasPermission.every(permission => authorityCodes.includes(permission))) { el.parentNode && el.parentNode.removeChild(el); } }, }; // input 字符串数字 const PositiveIntegerDirective: ObjectDirective = { mounted(el: HTMLElement) { el.addEventListener('input', handleInput); }, beforeUnmount(el: HTMLElement) { el.removeEventListener('input', handleInput); }, }; // 检测文字是否被省略并显示工具提示 const EllipsisTooltipDirective: ObjectDirective = { mounted(el: HTMLElement) { const tooltipVNode = createVNode(ElTooltip, { content: el.textContent, placement: 'top', effect: 'dark' }, { default: () => h('span', '') }); const tooltipWrapper = document.createElement('div'); document.body.appendChild(tooltipWrapper); render(tooltipVNode, tooltipWrapper); el.addEventListener('mouseenter', (event: MouseEvent) => { if (isTextEllipsis(el)) { tooltipVNode.component!.props.content = el.textContent; tooltipVNode.component!.props.visible = true; const targetElement = event.currentTarget as HTMLElement; const { clientWidth, clientHeight } = targetElement; const { top, left } = targetElement.getBoundingClientRect(); tooltipWrapper.style.position = 'absolute'; tooltipWrapper.style.left = `${left + 10}px`; tooltipWrapper.style.top = `${top}px`; // tooltipWrapper.style.width = `${clientWidth}px`; // tooltipWrapper.style.height = `${clientHeight}px`; } }); el.addEventListener('mouseleave', () => { tooltipVNode.component!.props.visible = false; }); }, unmounted(el: HTMLElement) { el.removeEventListener('mouseenter', () => { }); el.removeEventListener('mouseleave', () => { }); } } // 对应方法 function handleInput(event: Event) { // 处理输入 const input = event.target as HTMLInputElement; const regex = /^\d*\.?\d*$/; if (!regex.test(input.value)) { input.value = input.value.replace(/[^\d\.]/g, ''); } } function isTextEllipsis(element: HTMLElement): boolean { // 判断文字是否被省略 return element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight; } // 导出的自定义指令 const customize = [ { key: 'permission', directive: PermissionDirective, name: '角色权限' }, { key: 'enterNumber', directive: PositiveIntegerDirective, name: 'input正整数' }, { key: 'ellipsisTooltip', directive: EllipsisTooltipDirective, name: '文字省略显示工具提示' }, ] export default customize;