<template>
    <ElTree class="hc-tree-node" ref="ElTreeRef" :props="ElTreeProps" :load="ElTreeLoadNode" lazy highlight-current accordion node-key="primaryKeyId"
            :default-expanded-keys="defaultExpandedCids" @node-click="ElTreeClick" @node-contextmenu="ElTreeLabelContextMenu">
        <template #default="{ node, data }">
            <div class="data-custom-tree-node" :id="`${idPrefix}${data['primaryKeyId']}`">
                <!--树组件，节点名称-->
                <div class="label" :class="node.level === 1?'level-name':''">
                    <span :class="data?.colorStatus === 2?'text-blue':data?.colorStatus === 3?'text-orange':data?.colorStatus === 4?'text-green':''" v-if="isColor">{{ node.label }}</span>
                    <span v-else>{{ node.label }}</span>
                </div>
                <!--树组件，操作菜单-->
                <div class="menu-icon" :class="node.showTreeMenu?'show':''" v-if="node.level !== 1 && menusData.length > 0" @click.stop>
                    <n-dropdown placement="bottom-end" trigger="click" size="huge" :options="menusData" @select="ElTreeMenuClick($event,node,data)" @update:show="ElTreeMenuShow($event,node)">
                        <div class="cu-tree-node-popover-menu-icon">
                            <HcIcon name="menu" ui="text-2xl"/>
                        </div>
                    </n-dropdown>
                </div>
                <!--树组件，操作菜单 END-->
            </div>
        </template>
    </ElTree>
    <n-dropdown placement="bottom" trigger="manual" :x="menusX" :y="menusY" size="huge" :options="menusData" :show="showDropdown" @clickoutside="onClickoutside" @select="handleMenuSelect" v-if="menusData.length > 0"/>
</template>

<script setup>
import {ref,nextTick,watch} from "vue";
import {hIconJs} from "~src/plugins/renderele";
import dataFillQuery from '~api/data-fill/query';
import {isItem} from "vue-utils-plus"
import {NDropdown} from 'naive-ui';

//参数
const props = defineProps({
    menus: {
        type: Array,
        default: () => ([])
    },
    projectId: {
        type: [String,Number],
        default: ''
    },
    contractId: {
        type: [String,Number],
        default: ''
    },
    autoExpandKeys: {
        type: Array,
        default: () => ([])
    },
    isMark: {
        type: Boolean,
        default: false
    },
    idPrefix: {
        type: String,
        default: '`wbs-tree-'
    },
    isAutoKeys: {
        type: Boolean,
        default: true
    },
    isAutoClick: {
        type: Boolean,
        default: true
    },
    isColor: {
        type: Boolean,
        default: false
    },
})

//变量
const ElTreeRef = ref(null)
const showDropdown = ref(false)
const treeRefNode = ref(null)
const treeRefData = ref(null)
const ElTreeProps = ref({
    label: 'title',
    children: 'children',
    isLeaf: 'notExsitChild'
})
const menusData = ref(props.menus)
const menusX = ref(0);
const menusY = ref(0);

const menuMark = ref(props.isMark)
const isAutoKeys = ref(props.isAutoKeys)
const TreeExpandKey = ref(props.autoExpandKeys)
const projectId = ref(props.projectId);
const contractId = ref(props.contractId);
const idPrefix = ref(props.idPrefix);

//监听
watch(() => [
    props.menus,
    props.isMark,
    props.isAutoKeys,
    props.autoExpandKeys,
    props.projectId,
    props.contractId,
    props.idPrefix,
], ([menus, isMark, AutoKeys, expandKeys, UserProjectId, UserContractId,UserIdPrefix]) => {
    menusData.value = menus
    menuMark.value = isMark
    isAutoKeys.value = AutoKeys
    TreeExpandKey.value = expandKeys
    projectId.value = UserProjectId
    contractId.value = UserContractId
    idPrefix.value = UserIdPrefix
})

//树形结构异步加载数据
const defaultExpandedCids = ref([])
const ElTreeLoadNode = async (node, resolve) => {
    let contractIdRelation = '', parentId = '';
    if (node.level !== 0) {
        const nodeData = node?.data ?? {};
        contractIdRelation = nodeData?.contractIdRelation ?? ''
        parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
    }
    //获取数据
    const { data } = await dataFillQuery.queryWbsTreeData({
        contractId: contractId.value || '',
        contractIdRelation,
        parentId
    })
    //处理数据
    let clickKey = '', defaultExpandedArr = [];
    const keys = TreeExpandKey.value || []
    const resData = data?.data || []
    if (keys.length > 0) {
        let lastKey = keys[keys.length-1];
        for (const item of resData) {
            //自动展开
            if (isItem(keys,item?.primaryKeyId)) {
                defaultExpandedArr.push(item?.primaryKeyId)
            }
            //最后一个，选中点击
            if (item?.primaryKeyId === lastKey) {
                clickKey = item?.primaryKeyId
            }
        }
    } else if (node.level === 0) {
        defaultExpandedArr.push(resData[0]?.primaryKeyId)
    }
    //自动展开
    defaultExpandedCids.value = defaultExpandedArr
    resolve(resData)
    //最后一个，执行点击
    if (props.isAutoClick && clickKey) {
        await nextTick(() => {
            document.getElementById(`${idPrefix.value}${clickKey}`)?.click()
        })
    }
}

//事件
const emit = defineEmits(['menuTap','nodeTap'])

//节点被点击
const ElTreeClick = async (data,node) => {
    if (isAutoKeys.value) {
        let autoKeysArr = []
        await getNodeExpandKeys(node, autoKeysArr)
        const autoKeys = autoKeysArr.reverse()
        emit('nodeTap', {node, data, keys: autoKeys})
    } else {
        emit('nodeTap', {node, data, keys: []})
    }
}

//处理自动展开的节点KEY
const getNodeExpandKeys = async (node, newKeys) => {
    const parent = node?.parent ?? []
    const primaryKeyId = node?.data?.primaryKeyId ?? ''
    if (primaryKeyId) {
        newKeys.push(primaryKeyId)
        await getNodeExpandKeys(parent, newKeys)
    }
}

//鼠标右键事件
const ElTreeLabelContextMenu = (e,data,node) => {
    const rows = menusData.value || [];
    if (node.level !== 1 && rows.length > 0) {
        e.preventDefault();
        treeRefNode.value = node;
        treeRefData.value = data;
        if (menuMark.value) {
            setMenuMarkVal(rows,data)
        }
        nextTick(() => {
            menusX.value = e.clientX;
            menusY.value = e.clientY;
            showDropdown.value = true;
        });
    }
}

//设置菜单标记状态
const setMenuMarkVal = (rows,item) => {
    for (let i = 0; i < rows.length; i++) {
        if (rows[i].key === 'mark' || rows[i].key === 'cancel_mark') {
            if (item.isFirst) {
                menusData.value[i].label = '取消标记为首件';
                menusData.value[i].key = 'cancel_mark';
                menusData.value[i].icon = hIconJs({
                    name: 'grade', fill: true
                });
            } else {
                menusData.value[i].label = '标记为首件';
                menusData.value[i].key = 'mark';
                menusData.value[i].icon = hIconJs({name: 'grade'});
            }
            break;
        }
    }
}

//鼠标右键菜单被点击
const handleMenuSelect = (key) => {
    const node = treeRefNode.value;
    const data = treeRefData.value;
    showDropdown.value = false;
    emit('menuTap', {key,node,data})
}
const onClickoutside = () => {
    treeRefNode.value = null;
    treeRefData.value = null;
    showDropdown.value = false;
}

//菜单被点击
const ElTreeMenuClick = (key,node,data) => {
    emit('menuTap', {key,node,data})
}
//菜单是否显示
const ElTreeMenuShow = (key,node) => {
    node.showTreeMenu = key
}

//设置树菜单的标记数据
const setElTreeMenuMark = (keys,isFirst) => {
    keys.forEach(item => {
        //根据 data 或者 key 拿到 Tree 组件中的 node
        let node = ElTreeRef.value.getNode(item)
        if (!!node) node.data.isFirst = isFirst;
    })
}

//设置树菜单的标记数据
const removeElTreeNode = (key) => {
    //根据 data 或者 key 拿到 Tree 组件中的 node
    let node = ElTreeRef.value.getNode(key)
    //删除 Tree 中的一个节点，使用此方法必须设置 node-key 属性
    ElTreeRef.value.remove(node)
}

// 暴露出去
defineExpose({
    setElTreeMenuMark,
    removeElTreeNode
})
</script>

<style lang="scss" scoped>
.data-custom-tree-node {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    color: var(--ui-TC);
    .label {
        flex: auto;
        font-size: 16px;
    }
    .label.level-name {
        font-size: 18px;
        font-weight: bold;
    }
    .menu-icon {
        position: relative;
        font-size: 20px;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.2s;
        .cu-tree-node-popover-menu-icon {
            display: flex;
            align-items: center;
            justify-content: center;
        }
    }
    &:hover {
        .menu-icon {
            opacity: 1;
            pointer-events: all;
            cursor: context-menu;
        }
    }
    .menu-icon.show {
        opacity: 1;
        pointer-events: all;
        cursor: context-menu;
    }
}
</style>
