<template>
    <view class="hc-tree-box">
        <template v-if="nodeData.length > 0" v-for="item in nodeData" :key="item.key">
            <hc-tree-node :item="item"
                          :check="isCheck"
                          :strictly="isStrictly"
                          :radio="isRadio"
                          :counts="isCounts"
                          :currentKey="currentNodeKey"
                          @nodeLoad="treeLoadTap"
                          @nodeTap="treeNodeTap"
            />
        </template>
        <template v-else>
            <view class="no-data">暂无相关数据</view>
        </template>
    </view>
</template>

<script setup>
import {onMounted, ref} from 'vue'
import {getArrValue} from "js-fast-way";

//参数
const props = defineProps({
    nodeKey: {
        type: String,
        default: 'primaryKeyId',
    },
    labelKey: {
        type: String,
        default: 'title',
    },
    leafKey: {
        type: String,
        default: 'notExsitChild',
    },
    check: {
        type: Boolean,
        default: false,
    },
    //父子是否不关联
    strictly: {
        type: Boolean,
        default: false,
    },
    checkKey: {
        type: Array,
        default: () => ([]),
    },
    radio: {
        type: Boolean,
        default: false,
    },
    radioKey: {
        type: String,
        default: '',
    },
    currentKey: {
        type: String,
        default: '',
    },
    counts: {
        type: Boolean,
        default: false,
    },
})

//节点数据
const nodeData = ref([]);

//参数配置
const isCheck = ref(props.check)
const isRadio = ref(props.radio)
const isStrictly = ref(props.strictly)
const isCounts = ref(props.counts)
const currentNodeKey = ref(props.currentKey)

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

//渲染完成
onMounted(() => {
    getLazyLoad({
        level: 0,
        data: {},
        parentNodes: {},
        isLoad: false
    })
})

const treeLoadTap = (item) => {
    getLazyLoad(item)
}

//懒加载数据
const getLazyLoad = (item) => {
    if (!item.isLoad) {
        emit('load', item, (data) => {
            setLazyLoad(item, data)
        })
    }
}

//处理获取到的数据
const setLazyLoad = (data, arr) => {
    const children = getArrValue(arr), newNodeData = []
    if (children.length <= 0) {
        data.loading = false
        data.isExpand = false
        data.isLeaf = true
        data.isLoad = true
        //如果是跟节点，直接赋值
        if (data.level === 0) {
            nodeData.value = newNodeData
        }
    } else {
        for (let i = 0; i < children.length; i++) {
            const item = children[i]
            newNodeData.push({
                level: data.level + 1,
                key: item[props.nodeKey] ?? '',
                label: item[props.labelKey] ?? '',
                isLeaf: item[props.leafKey] ?? false,
                isExpand: false,
                loading: false,
                childNodes: [],
                isCheck: ifCheckData(data, item),
                isRadio: false,
                data: item,
                parentNodes: data,
                isLoad: item[props.leafKey] ?? false,
            })
        }
        //设置父级数据
        data.childNodes = newNodeData
        data.loading = false
        data.isExpand = setBrotherExpand(data.parentNodes)
        data.isLoad = true
        //如果是跟节点，直接赋值
        if (data.level === 0) {
            nodeData.value = newNodeData
        }
    }
}

//设置兄弟节点展开状态
const setBrotherExpand = (nodes) => {
    const children = getArrValue(nodes.childNodes)
    for (let i = 0; i < children.length; i++) {
        nodes.childNodes[i].isExpand = false
    }
    return true
}

//0未选中 1选中 2半选
const ifCheckData = (data, item) => {
    const keys = getArrValue(props.checkKey)
    if (keys.indexOf(item[props.nodeKey]) > -1) {
        return 1
    } else {
        return 0
    }
}

//树节点被点击
const treeNodeTap = (item) => {
    currentNodeKey.value = item.key
    emit('nodeTap', item)
}

//获取选中的key
const getCheckKeys = async () => {
    const nodes = nodeData.value
    const nodeKeys = {
        nodes: [], keys: [],
        halfNodes: [], halfKeys: [],
    }
    if (!isCheck.value) {
        return nodeKeys
    }
    await forCheckKeys(nodes, nodeKeys)
    return nodeKeys
}

//遍历获取选中的key
const forCheckKeys = async (nodes, nodeKeys) => {
    for (let i = 0; i < nodes.length; i++) {
        const item = nodes[i]
        //0未选中 1选中 2半选
        if (nodes[i].isCheck === 1) {
            nodeKeys.nodes.push(item)
            nodeKeys.keys.push(item.key)
        } else if (nodes[i].isCheck === 2) {
            nodeKeys.halfNodes.push(item)
            nodeKeys.halfKeys.push(item.key)
        }
        if (item.childNodes.length > 0) {
            await forCheckKeys(item.childNodes, nodeKeys)
        }
    }
}

//导出方法函数
defineExpose({
    getCheckKeys
})
</script>

<style lang="scss">
@import "./style.scss";
</style>
