<template>
    <a-tree-select
            allowClear
            labelInValue
            style="width: 100%"
            :getPopupContainer="(node) => node.parentNode"
            :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
            :placeholder="placeholder"
            :loadData="asyncLoadTreeData"
            :value="treeValue"
            :treeData="treeData"
            :multiple="multiple"
            v-bind="attrs"
            @change="onChange"
            @search="onSearch">
    </a-tree-select>
</template>
<script lang="ts" setup>
    /*
    * 异步树加载组件 通过传入表名 显示字段 存储字段 加载一个树控件
    * <j-tree-select dict="aa_tree_test,aad,id" pid-field="pid" ></j-tree-select>
    * */
    import {ref, watch, unref} from 'vue'
    import {defHttp} from '/@/utils/http/axios'
    import {propTypes} from '/@/utils/propTypes'
    import {useAttrs} from '/@/hooks/core/useAttrs'
    import {TreeSelect} from 'ant-design-vue'
    import {useMessage} from '/@/hooks/web/useMessage';

    enum Api {
        url = '/sys/dict/loadTreeData',
        view = '/sys/dict/loadDictItem/',
    }

    const props = defineProps({
        value: propTypes.string.def(''),
        placeholder: propTypes.string.def('请选择'),
        dict: propTypes.string.def('id'),
        parentCode: propTypes.string.def(''),
        pidField: propTypes.string.def('pid'),
        pidValue: propTypes.string.def(''),
        hasChildField: propTypes.string.def(''),
        condition: propTypes.string.def(''),
        multiple: propTypes.bool.def(false),
        loadTriggleChange: propTypes.bool.def(false),
    });
    const attrs = useAttrs();
    const emit = defineEmits(['change', 'update:value'])
    const {createMessage} = useMessage();
    //树形下拉数据
    const treeData = ref<any[]>([]);
    //选择数据
    const treeValue = ref<any>(null);
    const tableName = ref<any>('');
    const text = ref<any>('');
    const code = ref<any>('');
    /**
     * 监听value数据并初始化
     */
    watch(() => props.value, () => loadItemByCode(), {deep: true, immediate: true});
    /**
     * 监听dict变化
     */
    watch(() => props.dict,
        () => {
            initDictInfo();
            loadRoot();
        },
        {deep: true, immediate: true}
    );

    /**
     * 根据code获取下拉数据并回显
     */
    async function loadItemByCode() {
        if (!props.value || props.value == "0") {
            treeValue.value = null
        } else {
            let params = {key: props.value};
            let result = await defHttp.get({url: `${Api.view}${props.dict}`, params}, {isTransformResponse: false});
            if (result.success) {
                let values = props.value.split(',');
                treeValue.value = result.result.map((item, index) => ({
                    key: values[index],
                    value: values[index],
                    label: item
                }));
                onLoadTriggleChange(result.result[0]);
            }
        }
    }

    function onLoadTriggleChange(text) {
        //只有单选才会触发
        if (!props.multiple && props.loadTriggleChange) {
            emit('change', props.value, text)
        }
    }

    /**
     * 初始化数据
     */
    function initDictInfo() {
        let arr = props.dict?.split(",");
        tableName.value = arr[0];
        text.value = arr[1];
        code.value = arr[2]
    }

    /**
     * 加载下拉树形数据
     */
    async function loadRoot() {
        let params = {
            pid: props.pidValue,
            pidField: props.pidField,
            hasChildField: props.hasChildField,
            condition: props.condition,
            tableName: unref(tableName),
            text: unref(text),
            code: unref(code)
        };
        let res = await defHttp.get({url: Api.url, params}, {isTransformResponse: false});
        if (res.success && res.result) {
            for (let i of res.result) {
                i.value = i.key;
                i.isLeaf = !!i.leaf;
            }
            treeData.value = [...res.result];
        } else {
            console.log("数根节点查询结果异常", res)
        }
    }

    /**
     * 异步加载数据
     */
    async function asyncLoadTreeData(treeNode) {
        if (treeNode.dataRef.children) {
            return Promise.resolve()
        }
        let pid = treeNode.dataRef.key;
        let params = {
            pid: pid,
            pidField: props.pidField,
            hasChildField: props.hasChildField,
            condition: props.condition,
            tableName: unref(tableName),
            text: unref(text),
            code: unref(code),
        };
        let res = await defHttp.get({url: Api.url, params}, {isTransformResponse: false});
        if (res.success) {
            for (let i of res.result) {
                i.value = i.key;
                i.isLeaf = !!i.leaf;
            }
            //添加子节点
            addChildren(pid, res.result, treeData.value);
            treeData.value = [...treeData.value];
        }
        return Promise.resolve()
    }

    /**
     * 加载子节点
     */
    function addChildren(pid, children, treeArray) {
        if (treeArray && treeArray.length > 0) {
            for (let item of treeArray) {
                if (item.key == pid) {
                    if (!children || children.length == 0) {
                        item.isLeaf = true;
                    } else {
                        item.children = children
                    }
                    break
                } else {
                    addChildren(pid, children, item.children)
                }
            }
        }
    }

    /**
     * 选中树节点事件
     */
    function onChange(value) {
        if (!value) {
            emitValue('')
        } else if (value instanceof Array) {
            emitValue(value.map(item => item.value).join(','))
        } else {
            emitValue(value.value)
        }
        treeValue.value = value
    }

    function emitValue(value) {
        emit('change', value);
        emit('update:value', value)
    }

    /**
     * 文本框值变化
     */
    function onSearch(value) {
        console.log(value)
    }

    /**
     * 校验条件配置是否有误
     */
    function validateProp() {
        let mycondition = props.condition;
        return new Promise((resolve, reject) => {
            if (!mycondition) {
                resolve();
            } else {
                try {
                    let test = JSON.parse(mycondition);
                    if (typeof test == 'object' && test) {
                        resolve()
                    } else {
                        createMessage.error("组件JTreeSelect-condition传值有误，需要一个json字符串!");
                        reject()
                    }
                } catch (e) {
                    createMessage.error("组件JTreeSelect-condition传值有误，需要一个json字符串!");
                    reject()
                }
            }
        })
    }

    // onCreated
    validateProp().then(() => {
        initDictInfo();
        loadRoot();
        loadItemByCode();
    })
</script>

<style lang="less">
</style>
