customInstructions.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { Directive, ObjectDirective, DirectiveBinding, render, createVNode, h } from 'vue';
  2. import { ElTooltip } from 'element-plus';
  3. import 'element-plus/theme-chalk/el-tooltip.css';
  4. // 权限控制
  5. const PermissionDirective: Directive = { // 数组, 权限 code 和 布尔值,
  6. // mounted(el: HTMLElement, binding: { value: (string | boolean)[] }, vnode: any) {
  7. updated(el: HTMLElement, binding: { value: (string | boolean)[] }, vnode: any) {
  8. const routePath: string = vnode.ctx.appContext.config.globalProperties.$route.path;
  9. const userInfo: { userInfo: { functionList: { code: string }[] } } | null = JSON.parse(sessionStorage.getItem('storeInfo') || '');
  10. const authorityCodes: string[] = (userInfo?.userInfo?.functionList || []).map(({ code }) => code);
  11. const permissions: (string | boolean)[] = binding.value;
  12. const hasPermission: any[] = (binding.value || []).filter(item => typeof item !== 'boolean');
  13. if (!Array.isArray(permissions)) {
  14. console.error('权限必须以数组形式提供');
  15. return;
  16. }
  17. if (permissions.some((element): element is boolean => element === true)) {
  18. return;
  19. }
  20. if (!hasPermission.every(permission => authorityCodes.includes(permission))) {
  21. el.parentNode && el.parentNode.removeChild(el);
  22. }
  23. },
  24. };
  25. // input 字符串数字
  26. const PositiveIntegerDirective: ObjectDirective = {
  27. mounted(el: HTMLElement) {
  28. el.addEventListener('input', handleInput);
  29. },
  30. beforeUnmount(el: HTMLElement) {
  31. el.removeEventListener('input', handleInput);
  32. },
  33. };
  34. // 检测文字是否被省略并显示工具提示
  35. const EllipsisTooltipDirective: ObjectDirective = {
  36. mounted(el: HTMLElement) {
  37. const tooltipVNode = createVNode(ElTooltip, {
  38. content: el.textContent,
  39. placement: 'top',
  40. effect: 'dark'
  41. }, {
  42. default: () => h('span', '')
  43. });
  44. const tooltipWrapper = document.createElement('div');
  45. document.body.appendChild(tooltipWrapper);
  46. render(tooltipVNode, tooltipWrapper);
  47. el.addEventListener('mouseenter', (event: MouseEvent) => {
  48. if (isTextEllipsis(el)) {
  49. tooltipVNode.component!.props.content = el.textContent;
  50. tooltipVNode.component!.props.visible = true;
  51. const targetElement = event.currentTarget as HTMLElement;
  52. const { clientWidth, clientHeight } = targetElement;
  53. const { top, left } = targetElement.getBoundingClientRect();
  54. tooltipWrapper.style.position = 'absolute';
  55. tooltipWrapper.style.left = `${left + 10}px`;
  56. tooltipWrapper.style.top = `${top}px`;
  57. // tooltipWrapper.style.width = `${clientWidth}px`;
  58. // tooltipWrapper.style.height = `${clientHeight}px`;
  59. }
  60. });
  61. el.addEventListener('mouseleave', () => {
  62. tooltipVNode.component!.props.visible = false;
  63. });
  64. },
  65. unmounted(el: HTMLElement) {
  66. el.removeEventListener('mouseenter', () => { });
  67. el.removeEventListener('mouseleave', () => { });
  68. }
  69. }
  70. // 对应方法
  71. function handleInput(event: Event) { // 处理输入
  72. const input = event.target as HTMLInputElement;
  73. const regex = /^\d*\.?\d*$/;
  74. if (!regex.test(input.value)) {
  75. input.value = input.value.replace(/[^\d\.]/g, '');
  76. }
  77. }
  78. function isTextEllipsis(element: HTMLElement): boolean { // 判断文字是否被省略
  79. return element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight;
  80. }
  81. // 导出的自定义指令
  82. const customize = [
  83. { key: 'permission', directive: PermissionDirective, name: '角色权限' },
  84. { key: 'enterNumber', directive: PositiveIntegerDirective, name: 'input正整数' },
  85. { key: 'ellipsisTooltip', directive: EllipsisTooltipDirective, name: '文字省略显示工具提示' },
  86. ]
  87. export default customize;