<!-- 操作权限 -->
<template>
    <div class="app-auth">
        <teleport to="body" v-if="type === 'contextmenu'">
            <div class="app-auth__contextmenu" @contextmenu.prevent.capture @click="closeContextmenu"
                v-show="contextmenuOption.show">
                <ul :style="styles">
                    <li :class="item.code" v-for="(item, index) in dataList" :key="index"
                        @click.stop="openComponent(item.code)">
                        <el-icon v-if="item.icon">
                            <component :is="item.icon" />
                        </el-icon>
                        <span>{{ item.title }}</span>
                    </li>
                </ul>
            </div>
        </teleport>
        <div class="app-auth__button" v-else>
            <el-dropdown trigger="click" v-if="type === 'dropdown'">
                <el-button size="small" icon="MoreFilled" round />
                <template #dropdown>
                    <el-dropdown-menu>
                        <el-dropdown-item :class="item.code" v-for="(item, index) in dataList" :key="index"
                            :icon="item.icon" @click="openComponent(item.code)">
                            {{ item.title }}
                        </el-dropdown-item>
                    </el-dropdown-menu>
                </template>
            </el-dropdown>
            <ul v-else>
                <li v-for="(item, index) in dataList" :key="index">
                    <el-button :class="item.className" :type="item.buttonType" :disabled="item.code === componentId"
                        @click="openComponent(item.code)" :link="linkButton">
                        <el-icon v-if="item.icon">
                            <component :is="item.icon" />
                        </el-icon>
                        <span v-if="item.title">{{ item.title }}</span>
                    </el-button>
                </li>
            </ul>
        </div>
        <component :is="componentMap.get(componentId)" :code="componentId" v-bind="options" @closed="closeComponent"
            v-if="componentId" />
    </div>
</template>

<script lang="ts" setup>
import { onMounted, onUnmounted, shallowRef, PropType, computed, watch } from 'vue'
import { useMenu } from '@/hooks/menu'

const emit = defineEmits(['click', 'closed'])

const props = defineProps({
    code: String,
    // 组件参数
    options: Object,
    // 菜单列表
    menus: Array as PropType<string[]>,
    // 操作类型
    type: {
        type: String as PropType<'button' | 'dropdown' | 'contextmenu'>,
        default: 'button',
    },
    // 右键菜单
    contextmenu: {
        type: Object as PropType<{ show: boolean; clientX: number; clientY: number; }>,
        default: () => ({
            show: false,
            clientX: 0,
            clientY: 0,
        }),
    },
    // 链接按钮
    linkButton: {
        type: Boolean,
        default: false,
    },
})

const { componentMap, getAuthButtons } = useMenu(props.code);
const componentId = shallowRef<string>();
const contextmenuOption = shallowRef(props.contextmenu);
const auth = shallowRef<Ermcp.UserRoutes[]>([]);

// 数据列表
const dataList = computed(() => {
    const menus = props.menus
    if (menus) {
        if (menus.length) {
            return auth.value.filter((e) => menus.includes(e.code) || menus.includes(e.buttonName));
        }
        return [];
    } else {
        return auth.value;
    }
})

// 右键菜单坐标
const styles = computed(() => {
    const { clientX, clientY } = contextmenuOption.value;
    return {
        left: clientX + 'px',
        top: clientY + 'px',
    }
})

// 关闭右键菜单
const closeContextmenu = () => {
    contextmenuOption.value.show = false;
}

// 打开组件
const openComponent = (code: string) => {
    closeContextmenu();
    componentId.value = code;
    emit('click', code);
}

// 关闭组件
const closeComponent = (isCallback?: boolean) => {
    componentId.value = undefined;
    isCallback && emit('closed');
}

watch(() => props.contextmenu, (val) => contextmenuOption.value = val)

onMounted(() => auth.value = getAuthButtons())
onUnmounted(() => closeComponent())
</script>

<style lang="less">
@import './index.less';
</style>