AuthDropDown.vue 2.55 KB
<script lang="ts" setup>
  import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
  import { computed, useSlots } from 'vue';
  import Icon from '../Icon';
  import { usePermission } from '/@/hooks/web/usePermission';

  export interface AuthDropDownProps {
    dropMenuList: AuthDropMenuList[];
    trigger?: ('contextmenu' | 'click' | 'hover')[];
  }

  export interface AuthDropMenuList {
    icon?: string;
    event: string | number;
    text: string;
    disabled?: boolean;
    divider?: boolean;
    auth?: string;
    onClick?: Fn;
    popconfirm?: {
      cancelText?: string;
      okText?: string;
      okType?: string;
      title?: string;
      icon?: string;
      disabled?: boolean;
      onCancel?: Fn;
      onConfirm?: Fn;
      onVisibleChange?: Fn;
    };
  }

  const props = defineProps<AuthDropDownProps>();

  const slot = useSlots();

  const { hasPermission } = usePermission();

  const getMenuList = computed(() => {
    const { dropMenuList } = props;
    return dropMenuList.filter((menu) => (menu.auth ? hasPermission(menu.auth) : true));
  });

  const hasDefaultSlot = computed(() => {
    return !!slot.default;
  });
</script>

<template>
  <Dropdown :trigger="$props.trigger">
    <template #overlay>
      <Menu v-if="getMenuList.length">
        <template v-for="item in getMenuList" :key="item.event">
          <Menu.Divider v-if="item.divider" />
          <Menu.Item :disabled="item.disabled" v-if="!item.popconfirm" @click="item.onClick">
            <span class="flex justify-center items-center">
              <Icon :icon="item.icon" />
              <span class="ml-2">{{ item.text }}</span>
            </span>
          </Menu.Item>
          <Menu.Item :disabled="item.disabled" v-if="item.popconfirm">
            <Popconfirm :disabled="item.disabled" v-bind="item.popconfirm">
              <template v-if="item.popconfirm.icon" #icon>
                <Icon :icon="item.popconfirm.icon" />
              </template>
              <span class="flex justify-center items-center">
                <Icon :icon="item.icon" />
                <span class="ml-2">{{ item.text }}</span>
              </span>
            </Popconfirm>
          </Menu.Item>
        </template>
      </Menu>
    </template>
    <Icon
      v-if="!hasDefaultSlot"
      class="items-center justify-center"
      icon="ant-design:ellipsis-outlined"
      :class="!getMenuList.length ? '!text-gray-200 !cursor-not-allowed' : ''"
    />
    <slot name="default"></slot>
  </Dropdown>
</template>