<script>
/**
 * vs-layertree 2022-06-28
 * 
 * draggable 是否开启拖拽节点功能 false
 * width 图层树宽度 360px
 * height 图层树高度 550px
 * title 图层树标题 图层树
 * top 图层树距离顶部位置 50
 * left 图层树距离左侧位置 50
 * isContextmenu 是否使用右键菜单 true
 * contextmenu 右键菜单配置数据 []
 * 
 * @node-dblclick 当节点被双击的时候触发 具体参考elementui
 * @contextmenu-click 右键菜单点击事件
 * 
 * getTreeRef 获取el-tree组件的方法
 * 
 * 直接中转elementui el-tree剩余属性，事件
 */
export default {
    name: "vs-layer-tree",
};
</script>
<script setup>

import {
    ref,
    reactive,
    onMounted,
    defineExpose,
    nextTick,
    getCurrentInstance
} from "vue";
const props = defineProps({
    draggable: {
        type: Boolean,
        default: false,
    },
    width: {
        type: String,
        default: '360px',
    },
    height: {
        type: String,
        default: '550px',
    },
    title: {
        type: String,
        default: '图层树',
    },
    top: {
        type: String,
        default: '100px',
    },
    left: {
        type: String,
        default: '50px',
    },
    isContextmenu: {
        type: Boolean,
        default: true,
    },
    contextmenu: {
        type: Array,
        default: () => [
            {
                direct: 'add',
                label: '新建'
            }, {
                direct: 'remove',
                label: '删除'
            }, {
                direct: 'edit',
                label: '编辑'
            },
        ]
    }
});

const emit = defineEmits(["contextmenu-click", "node-dblclick"]);

const { proxy } = getCurrentInstance();

//当节点被点击的时候触发
let clickCount = ref(0);
const nodeclick = function () {

    clickCount.value++

    const fnEmitDblClick = proxy.$lodash.debounce(() => {
        if (clickCount.value > 1) {
            emit('node-dblclick', ...arguments);
        }
        //  else {
        //     emit('node-click', ...arguments);
        // }
        clickCount.value = 0
    }, 300)
    fnEmitDblClick()
}

//节点右键触发的事件
const contextmenuObj = reactive({
    show: false,
    node: null,
    left: props.left,
    top: props.top
})
const posi = reactive({
    left: '0px',
    top: '0px',

})

const dragStop = function (e) {
    contextmenuObj.left = e.x;
    contextmenuObj.top = e.y
}


const contextmenuRef = ref(null);
const nodecontextmenu = function (event, node1, node2, node3) {

    let posiTop = 0;
    let posiLeft = 0;
    contextmenuObj.show = true;
    nextTick(() => {
        const top = event.screenY - 150 - parseInt(contextmenuObj.top);
        const left = event.screenX - parseInt(contextmenuObj.left);

        const contextmenuWidth = contextmenuRef.value.offsetWidth;
        const contextmenuHeight = contextmenuRef.value.offsetHeight;

        if ((left + contextmenuWidth) > (parseInt(props.width) - 15)) {
            posiLeft = left - contextmenuWidth
        } else {
            posiLeft = left
        }

        if ((top + contextmenuHeight) > (parseInt(props.height) - 50 - 20)) {
            posiTop = top - contextmenuHeight
        } else {
            posiTop = top
        }

        event.composedPath().forEach((item, index) => {
            if (item.className === 'vs-dialog--content--scorll') {
                posi.left = posiLeft + 'px';
                posi.top = posiTop + item.scrollTop + 'px'
                contextmenuObj.node = node2
            }
        })
    })


}

//右键菜单点击事件
const contextmenuClick = function (item) {
    emit("contextmenu-click", item, contextmenuObj.node);
    contextmenuObj.show = false
}

const clickHndle = function (event) {
    if (!event.target.className.indexOf || event.target.className.indexOf('vs-contextmenu') === -1) {
        contextmenuObj.show = false
    }
}

onMounted(() => {
});

//返回el-tree的方法提供父组件调用
const treeRef = ref(null);
const getTreeRef = function () {
    return treeRef.value
}
defineExpose({
    getTreeRef
});

</script>

<template>
    <div @click.capture="clickHndle($event)">
        <vs-dialog :isDrag="!draggable" :width="width" :height="height" :title="title" :top="props.top" :left="props.left"
            @dragstop="dragStop">
            <div class="vs-layertree">
                <el-tree ref="treeRef" v-postStyle="'el-tree'" :draggable="draggable" @node-click="nodeclick"
                    @node-contextmenu="nodecontextmenu" v-bind="$attrs" />
                <template v-if="isContextmenu">
                    <div ref="contextmenuRef" v-show="contextmenuObj.show" class="vs-contextmenu" :style="posi">
                        <div class="vs-contextmenu--item" v-for="item in contextmenu" :key="item.direct"
                            @click="contextmenuClick(item)">
                            <span class="vs-contextmenu--item--span">{{ item.label }}</span>
                        </div>
                    </div>
                </template>
            </div>
        </vs-dialog>
    </div>
</template>

<style  lang="scss" scope>
$main: var(--main);
$auxiliary: var(--auxiliary);
$light: var(--light);

.vs-layertree {
    padding: 0px 15px;
    box-sizing: border-box;
    display: flex;
    justify-content: space-around;
    position: relative;

    .vs-contextmenu {
        position: absolute;
        z-index: 9;
        padding: 5px 10px;
        box-sizing: border-box;
        border-radius: 3px;
        background: $main;
        box-shadow: 3px 3px 10px 3px rgba(0, 0, 0, 0.3);
        border: 1px $auxiliary solid;
        max-width: 120px;

        .vs-contextmenu--item {
            min-width: 60px;
            text-align: center;
            letter-spacing: 2px;
            padding: 5px 0px;
            font-size: 13px;
            cursor: pointer;
            border-bottom: 1px rgb(170, 170, 170) solid
        }

        .vs-contextmenu--item:last-child {
            border: none
        }

        .vs-contextmenu--item:hover {
            background: $main;
        }
    }
}
</style>
