<script>
import size from '@/components/base/size';
import { resolveComponent } from 'vue';
export default {
    mixins: [size],
    name:'baseTree',
    data () {
        return {
            globalConfig: {
                emptyText: '暂无数据',
                multiSelect: false,
                resources: '',
                method: '',
                response: '',
                selectkey: '',
                idField:'',
                parentField:'',
                idClass:'',
                searchParam: null,
                readOnly: false,
                showIcon:false,
                keepExpand:false,
                expandData:[],
                showIconList:[],
                showCheckBox: false,
                showRootNode:false,
                showTitle:true,
                expand:true,
                rootNode:{},
                setNodeDisabled:'',
                bordered:true,
                disHover:false,
                selectedRoot:false,
                className:'efutre-tree-node'
            },
            myConfig: {

            },
            gridConfig:{

            },
            showCondition:true,
            data:[],
            oldData:[],
            selectedData:[],
            conditionSearchParam:{},
            searchBeforeSearchParam:{},
            rootNode:{},
            showTree:true,
            showGrid:false,
            extraHeight:0,
            outsideHeight:0,
            treeData:[],
            asyncLoad:false,
            _autoExpandId: '',

        };
    },
    created () {
        this.init();
    },
    props:{
        config: {
            type: Object,
            default: () => {
                return {};
            }
        },
        dictData: {
            type: Object,
            default:null
        }
    },
    methods:{
        init() {
            //获取初期默认值
            this.myConfig = Object.assign({}, this.globalConfig, this.myConfig);

            //获取配置
            if (this.config) {
                this.myConfig = Object.assign({}, this.myConfig, this.config);
            }

            let  rootCode = '0';
            let  rootName = '根节点';
            if (this.myConfig.showRootNode) {
                if (this.myConfig.rootNode !== undefined && this.myConfig.rootNode.code !== undefined) {
                    rootCode = this.myConfig.rootNode.code;
                }
                if (this.myConfig.rootNode !== undefined && this.myConfig.rootNode.name !== undefined) {
                    rootName = this.myConfig.rootNode.name;
                }
            }
            if (this.myConfig.responseId === undefined) {
                this.myConfig.responseId = this.myConfig.responseCode;
            }
            this.rootNode[this.myConfig.idField] = rootCode + '';
            this.rootNode[this.myConfig.responseId] = rootCode + '';
            this.rootNode[this.myConfig.responseCode] = rootCode + '';
            this.rootNode[this.myConfig.responseName] = rootName;
            if (this.myConfig.idClass !== undefined) {
                this.rootNode[this.myConfig.idClass] = 0;
            }
            //多选 才允许出现复选框
            if (this.myConfig.multiSelect !== true) {
                this.myConfig.showCheckBox = false;
            }
            this.setSizeConfig(this.myConfig);

            if (this.myConfig.asyncLoad) {
                this.asyncLoad = true;
            }
            //特定化处理
            if (this.customInit) {
                this.customInit();
            }

        },
        setIcon(data) {
            let nodeClass = data[this.myConfig.idClass];
            if (!nodeClass) {
                nodeClass = 0;
            } else {
                nodeClass = Number(nodeClass);
            }
            if (!this.myConfig.showRootNode) {
                if (nodeClass &&  nodeClass !== 0) {
                    nodeClass = nodeClass - 1;
                }
            }
            if (nodeClass >= this.myConfig.showIconList.length) {
                nodeClass = this.myConfig.showIconList.length - 1;
            }

            const icon = this.myConfig.showIconList[nodeClass];
            data.icon = icon.type;
            if (icon.size) {
                data.iconSize = icon.size;
            }
            if (icon.color) {
                data.iconColor = icon.color;
            }
            return data;
        },
        iconRender(h, params) {

            let icon = params.data.icon
            let size = params.data.iconSize
            let color = params.data.iconColor

            const hasChildren =
                params.data.children &&
                params.data.children.length > 0

            if (!icon) {
                if (hasChildren) {
                    icon = params.data.expand
                        ? '_base_mulu'
                        : '_base_close_mulu'
                } else {
                    icon = '_base_wenjian'
                }
            }

            if (!size) {
                size = 14
            }

            let para = {
                type: icon,
                size,
                color
            }

            if (this.myConfig.setTreeNodeIcon) {
                para = this.myConfig.setTreeNodeIcon(params, para)
            } else if (this.setTreeNodeIcon) {
                para = this.setTreeNodeIcon(params, para)
            }

            // 处理自定义 iconfont
            if (para.type && para.type.startsWith('_')) {
                const resultIcon =
                    'iconfont icon-' + para.type.substring(1)

                para.custom = resultIcon
                delete para.type
            }

            let nodeClass = 'efuture-treenode'

            if (this.myConfig.setNodeClass) {
                nodeClass = this.myConfig.setNodeClass(params)
            }

            return h(
                'div',
                {
                    class: { [nodeClass]: true },
                    style: {
                        display: 'flex',
                        userSelect: 'none'
                    },
                    onDblclick: () => {
                        this.$nextTick(() => {
                            this.setExpend(params.data)
                        })
                        this.$emit('dbclick', params.data)
                    }
                },
                [
                    h(
                        'div',
                        {
                            style: { paddingLeft: '5px' }
                        },
                        [
                            h(resolveComponent('Icon'), para)
                        ]
                    ),

                    h(resolveComponent('ShowText'), {
                        label: params.data.title,
                        contentAlign: 'left'
                    })
                ]
            )
        },
        iconRenderOld(h,params) {
            let icon = params.data.icon;
            let size = params.data.iconSize;
            let color = params.data.iconColor;
            if (!icon) {
                if (params.node && params.node.children && params.node.children.length > 0) {
                    if (params.data.expand) {
                        icon = '_base_mulu';
                    } else {
                        icon = '_base_close_mulu';
                    }

                } else {
                    icon = '_base_wenjian';
                }
            }
            if (!size) {
                size = 14;
            }
             let para = {
                type:icon,
                size:size,
                color:color
            }
            if (this.myConfig.setTreeNodeIcon) {
                para = this.myConfig.setTreeNodeIcon(params,para);
            } else if (this.setTreeNodeIcon) {
                para = this.setTreeNodeIcon(params,para);
            }
            if (para.type.indexOf('_') === 0) {
                let resulIcon = para.type.substring(1,para.type.length);
                resulIcon = 'iconfont icon-' + resulIcon;
                para.custom = resulIcon;
                delete para.type;
            }
            let nodeClass = 'efuture-treenode';
            if (this.myConfig.setNodeClass) {
                nodeClass =this.myConfig.setNodeClass(params)
            }
            let classstyle = {};
            classstyle[nodeClass] = true;
            return h(
                    'div',
                    {
                        style: {
                            display: 'flex',
                            userSelect: 'none'
                        },
                        class:classstyle,
                        onDblclick:() => {
                            this.$nextTick(() => {
                                this.setExpend(params.data);
                            });
                            this.$emit('dbclick', params.data);
                        }
                    },
                    [
                    h(
                        'div',
                        {
                        style: {
                            'padding-left':'5px'
                        }
                        },
                        [
                        h(resolveComponent('Icon'), para)
                        ]
                    ),
                    h(resolveComponent('ShowText'), {
                        label:params.data.title,
                        contentAlign:'left'
                    })
                    ]);
        },
        toTreeData(expandMap = new Set(), selectedId = null) {
            let pos = {};
            let tree = [];
            let i = 0;

            const idField = this.myConfig.idField;
            const parentField = this.myConfig.parentField;
            const rootId = this.rootNode[idField];

            const focusId = (selectedId !== null && selectedId !== undefined)
                ? selectedId
                : this._autoExpandId;

            let autoExpandParents = new Set();

            // 根据 focusId 反查父链（并防环）
            if (focusId !== null && focusId !== undefined) {
                let current = this.data.find(item => item[idField] === focusId);
                const visited = new Set();

                while (current) {
                    const cid = current[idField];
                    if (visited.has(cid)) {
                        console.warn('[toTreeData] parent chain cycle detected:', cid);
                        break;
                    }
                    visited.add(cid);

                    autoExpandParents.add(cid); // 选中节点本身 + 全部祖先都加入展开集合

                    const pid = current[parentField];
                    if (pid == null) break; // 注意：不要写 !pid，避免 0 被误判

                    current = this.data.find(item => item[idField] === pid);
                }
            }


            let data = this.$Method.copy(this.data);
            data.forEach(el => {
                this.setSelected(el); // 保留你原逻辑
            });
            let tempData = this.$Method.copy(data);

            // 统一状态赋值（避免到处重复写漏）
            const applyNodeState = (node) => {
                const nid = node[idField];

                // 展开：外部传入 expandMap 或者 focusId 的祖先链
                if (expandMap.has(nid) || autoExpandParents.has(nid)) {
                    node.expand = true;
                }

                // 选中：focusId 命中
                node.selected = (focusId !== null && focusId !== undefined && nid === focusId);
            };

            // 防死循环控制
            let guard = 0;
            const maxGuard = data.length * 5 + 20;
            let movedInRound = 0;

            while (data.length !== 0) {
                const current = data[i];
                const currentId = current[idField];
                const parentId = current[parentField];

                // 父是否存在于原始数据（判断孤儿）
                const index = tempData.findIndex(item => item[idField] === parentId);

                if (parentId === rootId || index < 0) {
                    applyNodeState(current);

                    tree.push(current);
                    pos[currentId] = [tree.length - 1];
                    data.splice(i, 1);
                    i--;
                    movedInRound++;
                } else {
                    const posArr = pos[parentId];
                    if (posArr) {
                        let obj = tree[posArr[0]];
                        for (let j = 1; j < posArr.length; j++) {
                            obj = obj.children[posArr[j]];
                        }

                        applyNodeState(current);

                        obj.children.push(current);
                        pos[currentId] = posArr.concat([obj.children.length - 1]);
                        data.splice(i, 1);
                        i--;
                        movedInRound++;
                    }
                }

                i++;
                if (i > data.length - 1) {
                    // 一轮下来没挂上任何节点 -> 环/坏链路，兜底退出
                    if (movedInRound === 0 && data.length > 0) {
                        console.warn('[toTreeData] unresolved/cyclic nodes, force attach to root level:', data);

                        data.forEach(node => {
                            applyNodeState(node);
                            const nid = node[idField];
                            tree.push(node);
                            pos[nid] = [tree.length - 1];
                        });

                        data = [];
                        break;
                    }

                    movedInRound = 0;
                    i = 0;

                    guard++;
                    if (guard > maxGuard) {
                        console.warn('[toTreeData] safety break triggered');
                        break;
                    }
                }
            }


            if (this.myConfig.showRootNode) {
                let root = {
                    title: '  ' + this.myConfig.rootNode.name,
                    expand: true,
                    disabled: this.myConfig.readOnly,
                    children: tree,
                    selected: false
                };

                if (this.myConfig.rootNode.disabled !== undefined) {
                    root.disabled = this.myConfig.rootNode.disabled;
                }
                Object.assign(root, this.rootNode);

                if (this.myConfig.showIcon) {
                    if (this.myConfig.idClass && this.myConfig.showIconList && this.myConfig.showIconList.length > 0) {
                        root[this.myConfig.idClass] = 0;
                        root = this.setIcon(root);
                    }
                }

                root.render = this.myConfig.nodeRender ? this.myConfig.nodeRender : this.iconRender;

                this._autoExpandId = null;
                return [root];
            } else {
                this._autoExpandId = null;
                return tree;
            }
        },
        setSelected (reTemp) {
            if (this.myConfig.expand) {
                reTemp.expand = this.myConfig.expand;
            }
            if (this.asyncLoad) {
                if (Number(reTemp[this.myConfig.idClass]) !== Number(this.myConfig.maxClass)) {
                    reTemp.loading = false;
                }
            }
            /*if (this.myConfig.keepExpand) {
                let index = this.myConfig.expandData.findIndex(el => el === reTemp[this.myConfig.responseId]);
                if (index > -1) {
                    reTemp.expand = true;
                }
            }*/
            if (this.myConfig.showCodeWithName) {
                reTemp.title = '  [' + reTemp[this.myConfig.responseCode] + ']  ' + reTemp[this.myConfig.responseName];
            } else {
                reTemp.title = '  ' + reTemp[this.myConfig.responseName];
            }
            if (this.myConfig.readOnly) {
                reTemp.disabled = true;
            } else {
                reTemp.disabled = false;
            }
            if (this.myConfig.setNodeDisabled) {
                reTemp.disabled = this.myConfig.setNodeDisabled(reTemp);
            }
            if (this.myConfig.showIcon) {
                if (this.myConfig.idClass && this.myConfig.showIconList && this.myConfig.showIconList.length > 0) {
                    reTemp = this.setIcon(reTemp);
                }
            }

            if (this.myConfig.nodeRender) {
                reTemp.render = this.myConfig.nodeRender;
            } else{
                reTemp.render = this.iconRender;
            }
            if (reTemp.children === undefined) {
                reTemp.children= [];
            } else {
                let children = [];
                reTemp.children.forEach(el => {
                    children.push(this.setSelected(el));
                });
                reTemp.children = children;
            }
            return reTemp;
        },
        refurbish(para) {
            if(!para) {
                para = {};
            }
            if (this.asyncLoad) {
                para[this.myConfig.idClass] = 1;
            }
            let self = this;
            self.synchroPost(self.myConfig.resources, self.myConfig.method, self.getSearchParam(para), function(data) {
                let root = [];
                if (data && data[self.myConfig.response]) {
                    if (self.checkData(data[self.myConfig.response])) {
                        root = data[self.myConfig.response];
                    } else {
                        return false;
                    }
                }
                if (self.myConfig.customData && self.myConfig.customData.length > 0) {
                    root = self.myConfig.customData.concat(root);
                }
                self.data = root;
                self.treeData = self.toTreeData();
                if (self.myConfig.selectedRoot) {
                    if (self.selectedData && self.selectedData.length  === 0) {
                        self.selectedData.push(self.rootNode);
                    }
                }
            },null);
        },
        getAsyncNode(para){
            let self = this;
            let asyncData = [];
            self.synchroPost(self.myConfig.resources, self.myConfig.method, self.getSearchParam(para), function(data) {
                if (data && data[self.myConfig.response]) {
                    if (self.checkData(data[self.myConfig.response])) {
                        asyncData = data[self.myConfig.response];
                    }
                }
            },null);
            return asyncData;
        },
        checkData(data) {
            let index = data.findIndex(el => el[this.myConfig.idField] === el[this.myConfig.parentField]);
            if (index > -1) {
                this.alert('存在' + this.myConfig.idField +'与' + this.myConfig.parentField+'都为[' + data[index][this.myConfig.idField]+']的数据,请检查',null,2);
                return false;
            }
            return true;
        },
        setReadOnly(flag) {
            this.myConfig = Object.assign({},this.myConfig,{readOnly:flag});
        },
        getRootNode () {
            return this.$Method.copy(this.rootNode);
        },

        getData() {
            if (!this.treeData) return []

            return this.myConfig.showCheckBox
                ? this.getNodesByKey('checked', this.treeData)
                : this.getNodesByKey('selected', this.treeData)
        },
        // getNodesByKey(key, data, result = []) {
        //     data.forEach(item => {
        //         if (item[key]) {
        //             result.push(item)
        //         }
        //         if (Array.isArray(item.children)) {
        //             this.getNodesByKey(key, item.children, result)
        //         }
        //     })
        //     return result
        // },

        getNodesByKey(key, data, result = []) {
            data.forEach(item => {
                if (item[key]) {
                    result.push(item)
                }
                if (Array.isArray(item.children) && item.children.length > 0) {
                    this.getNodesByKey(key, item.children, result)
                }
            })
            return result
        },


        setData(data) {
            this.selectedData =  this.$Method.copy(data);
            this.oldData = this.$Method.copy(data);
        },
        setDisplayData(data) {
            if (this.checkData(data)) {
                this.data =  this.$Method.copy(data);
                this.treeData = this.toTreeData();
            }
        },
        clearExpand() {
            this.myConfig.expandData = [];
        },
        setPro(data) {
            if (data) {
                this.myConfig = Object.assign({},this.myConfig,data);
            }
        },
        getPro(name) {
            return this.myConfig[name];
        },
        onSelectChange: function(res,node) { //点击树节点时触发返回当前已选中的节点数组
            this.$emit('onSelectChange', res, node);
        },
        onCheckChange: function(res,node) { //勾选树节点时触发返回当前已勾选的节点数组
            if (this.myConfig.showCheckBox) {
                let obj = [];
                res.forEach(el => {
                    let temp = {};
                    temp[this.myConfig.responseId] = el[this.myConfig.responseId];
                    obj.push(temp);
                });
                this.selectedData = this.$Method.copy(obj);
            }
            this.$emit('onCheckChange', res,node);
        },
        onToggleExpand: function(res) { //展开和收起子列表时触发返回当前节点的数据
            /*if (res.expand) {
                // 去重
                let index = this.myConfig.expandData.findIndex(el => el === res[this.myConfig.responseId]);
                if (index  === -1) {
                    this.myConfig.expandData.push(res[this.myConfig.responseId])
                }
            } else {
                let children = [];
                this.getChildren(res,children);
                // 收起当前节点
                children.push(res[this.myConfig.responseId]);
                children.forEach(el => {
                    let index2 = this.myConfig.expandData.findIndex(el2 => el === el2);
                    if (index2 > -1) {
                        this.myConfig.expandData.splice(index2, 1);
                    }
                });
            }*/
            this.$emit('onToggleExpand', res);
        },
        getChildren(res,childrens) {
            this.data.forEach(el => {
                if (el[this.myConfig.parentField] === res[this.myConfig.idField]) {
                    childrens.push(el[this.myConfig.responseId]);
                    this.getChildren(el, childrens);
                }
            });
        },
        popValueChanged (para) {
            let reData = [];
            let self = this;
            let searchParam = Object.assign({},self.getSearchParam(),para);
            self.synchroPost(self.myConfig.resources,self.myConfig.method,searchParam,function(data) {
                if (data && data[self.myConfig.response]) {
                    reData = data[self.myConfig.response];
                }
            },null);
            return reData;
        },
        clearData() {
            this.data = [];
            this.oldData = [];
            this.selectedData =[];
            this.treeData = [];
            this.conditionSearchParam = {};
            this.myConfig.expandData = [];
        },
        getSelectedNodes() {
            return this.$refs.tree.getSelectedNodes();
        },

        getCheckedNodes() {
            if (!this.treeData) return []
            return this.getNodesByKey('checked', this.treeData)
        },

        getCheckedAndIndeterminateNodes() {
            return this.$refs.tree.getCheckedAndIndeterminateNodes();
        },
        isChange() {
            // 初期值为空时，结果是否有值
            let data = this.getData();
            if (this.oldData.length === 0) {
                if (data.length > 0) {
                    return true;
                } else {
                    return false;
                }
            }
             // 判断初期值是否在结果中
            let resultFlag = false;
            let tempflag = false;
            this.oldData.forEach(el => {
                tempflag = false;
                data.forEach(el2 => {
                    if (el[this.myConfig.idField] === el2[this.myConfig.idField]) {
                        tempflag = true;
                        return;
                    }
                });
                if (!tempflag) {
                    resultFlag = true;
                    return;
                }
            });
            if (resultFlag) {
                return true;
            }
            // 初期值全部在结果中，是否多了新值
            let num = 0;
            data.forEach(el => {
                if (el.children === undefined || (el.children && el.children.length === 0))  {
                    num++;
                }
            });
            if (this.oldData.length !== num) {
                return true;
            } else {
                return false;
            }
        },
        setSearchBeforeSearchParam(obj) {
            this.searchBeforeSearchParam = Object.assign({},{},obj);
        },
        clearSearchBeforeSearchParam() {
            this.searchBeforeSearchParam = {};
        },
        getFatherNode(node) {
            if (!node || !node[this.myConfig.parentField]) {
                return {};
            }
            if (this.data && this.data.length > 0) {
                const index = this.data.findIndex(el => el[this.myConfig.idField] === node[this.myConfig.parentField]);
                if (index > -1) {
                    return this.$Method.copy(this.data[index]);
                } else {
                    return {};
                }
            }
        },
        isChildren (node) {
            let flag = false;
            if (this.data && this.data.length > 0) {
                const index = this.data.findIndex(el => el[this.myConfig.parentField] === node[this.myConfig.idField]);
                if (index > -1) {
                    flag = true;
                }
            }
            return flag;
        },
        setExtraHeight () {
            let height = 0;
            if (this.$refs.condition) {
                height = this.$refs.condition.offsetHeight;
            }
            this.extraHeight = height;
        },
        setOutsideHeight(value) {
            this.outsideHeight = value;
        },
        setAllNode(name, value) {
            let tempName = name;
            if (name === 'readOnly') {
                tempName = 'disabled';
            } else if (name === 'selected') {
                if (this.myConfig.multiSelect &&  this.myConfig.showCheckBox) {
                    tempName ='checked';
                } else {
                    tempName = 'selected';
                }
            }
            const updateNode = (nodes) => {
                if (!nodes) return

                nodes.forEach(node => {
                    if (node[tempName] !== value) {
                        node[tempName] = value
                    }

                    if (node.children && node.children.length > 0) {
                        updateNode(node.children)
                    }
                })
            }

            updateNode(this.data)

        },

        setNodes(data, name, value) {
            let tempName = name;
            if (name === 'readOnly') {
                tempName = 'disabled';
            } else if (name === 'selected') {
                if (this.myConfig.multiSelect &&  this.myConfig.showCheckBox) {
                    tempName ='checked';
                } else {
                    tempName = 'selected';
                }
            }
            let responseId = this.myConfig.responseId;
            this.$refs.tree.flatState.forEach(el => {
                let index = data.findIndex(
                    el2 => el.node[responseId] === el2[responseId]
                );
                if (index > -1) {
                    if (el.node[tempName] !== value) {
                        let obj ={};
                        obj[tempName] = value;
                        Object.assign(el.node,obj);
                    }
                } else {
                    if (el.node[tempName] !== !value) {
                        let obj ={};
                        obj[tempName] = !value;
                        Object.assign(el.node,obj);
                    }
                }
            });
        },

        setNodese(data = [], name, value) {
            let tempName = name;
            if (name === 'readOnly') {
                tempName = 'disabled';
            } else if (name === 'selected') {
                tempName = (this.myConfig.multiSelect && this.myConfig.showCheckBox) ? 'checked' : 'selected';
            }

            const responseId = this.myConfig.idField || this.myConfig.responseId;

            // 统一字符串，避免 1 / "1" 不匹配
            const idSet = new Set(
                (data || []).map(item => String(item?.[responseId]))
            );

            // 确认真实渲染源
            const source = Array.isArray(this.data)
                ? this.data
                : (Array.isArray(this.treeData) ? this.treeData : []);

            let hitCount = 0;

            const updateNode = (nodes) => {
                if (!Array.isArray(nodes)) return;

                nodes.forEach(node => {
                    const exists = idSet.has(String(node?.[responseId]));
                    if (exists) hitCount++;

                    let newValue;

                    // 只有“选中=true”时，才清空其他节点（单选常见需求）
                    if (name === 'selected' && value === true) {
                        newValue = exists;
                    } else if (exists) {
                        // 其他场景只改命中节点
                        newValue = value;
                    } else {
                        newValue = node[tempName];
                    }

                    if (node[tempName] !== newValue) {
                        // Vue2: 动态键必须用 $set 才响应
                        // this.$set(node, tempName, newValue);
                        node[tempName] = newValue;
                    }

                    if (node.children && node.children.length > 0) {
                        updateNode(node.children);
                    }
                });
            };

            updateNode(source);

            // 兜底触发视图更新
            if (source === this.data) this.data = [...source];
            if (source === this.treeData) this.treeData = [...source];

            console.log('[setNodes]', { tempName, responseId, targetIds: [...idSet], hitCount });
            return hitCount;
        },
        setNodes2(data, name, value) {
            let tempName = name;
            if (name === 'readOnly') {
                tempName = 'disabled';
            } else if (name === 'selected') {
                if (this.myConfig.multiSelect &&  this.myConfig.showCheckBox) {
                    tempName ='checked';
                } else {
                    tempName = 'selected';
                }
            }
            let responseId = this.myConfig.idField || this.myConfig.responseId;
            // 把目标列表变成 Set，提高查找效率
            const idSet = new Set(
                data.map(item => item[responseId])
            )

            const updateNode = (nodes) => {
                if (!nodes) return

                nodes.forEach(node => {

                    const exists = idSet.has(node[responseId])

                    const newValue = exists ? value : !value

                    if (node[tempName] !== newValue) {
                        node[tempName] = newValue
                    }

                    if (node.children && node.children.length > 0) {
                        updateNode(node.children)
                    }

                })
            }

            updateNode(this.data)
        },
        saveExpandState() {
            const expandSet = new Set();

            const loop = (nodes) => {
                if (!nodes) return;

                nodes.forEach(node => {
                    if (node.expand) {
                        expandSet.add(node[this.myConfig.idField]);
                    }
                    if (node.children && node.children.length) {
                        loop(node.children);
                    }
                });
            };

            loop(this.treeData);

            return expandSet;
        },
        updateNode(data, flag) {
            const idField = this.myConfig.idField
            const parentField = this.myConfig.parentField
            const targetId = data[idField]

            // ① 保存当前展开状态
            const expandSet = this.saveExpandState()
            // ② 数据更新
            const index = this.data.findIndex(
                el => el[idField] === targetId
            )

            if (flag === 'U') {
                if (index > -1) {
                    Object.assign(this.data[index], data)
                } else {
                    this.data.push(data)

                    // ===== 新增时自动展开父链 =====
                    let parentId = data[parentField]

                    while (parentId) {
                        expandSet.add(parentId)

                        const parent = this.data.find(
                            el => el[idField] === parentId
                        )

                        if (!parent) break

                        parentId = parent[parentField]
                    }
                }
            }

            if (flag === 'D') {
                if (index > -1) {
                    this.data.splice(index, 1)
                }
            }
            // ③ 重建树（带展开状态）
            this.treeData = this.toTreeData(expandSet, targetId)
        },
        updateNodeod(data,flag) {
             let tmp = data;
             if(flag !== 'D') {
                 tmp = this.setSelected(data);
             }
             tmp.selected = true;
             if (this.$refs.tree && this.$refs.tree.flatState) {
                let index = -1;
                if (flag === 'U') {
                     index = this.$refs.tree.flatState.findIndex(el => el.node[this.myConfig.idField] === tmp[this.myConfig.idField]);
                     if (index > -1) {
                        if (this.$refs.tree.flatState[index].node.children && this.$refs.tree.flatState[index].node.children.length > 0) {
                            delete tmp.children;
                        }
                        Object.assign(this.$refs.tree.flatState[index].node,tmp);
                     } else {
                        index = this.$refs.tree.flatState.findIndex(el => el.node[this.myConfig.idField] === tmp[this.myConfig.parentField]);
                        if (index > -1) {
                            if (!this.$refs.tree.flatState[index].node.children){
                                this.$refs.tree.flatState[index].node.children = [];
                            }
                            this.$refs.tree.flatState[index].node.children.forEach(el2 => {
                                let tmpIndex = this.$refs.tree.flatState.findIndex(el => el.node[this.myConfig.idField] === el2[this.myConfig.idField] && el.node.selected);
                                if (tmpIndex > -1) {
                                    Object.assign(this.$refs.tree.flatState[tmpIndex].node,{selected:false});
                                }
                            });
                            Object.assign(this.$refs.tree.flatState[index].node,{selected:false, expand:true});
                            this.$refs.tree.flatState[index].node.children.push(tmp)
                        }
                     }
                }
                if (flag === 'D') {
                    index = this.$refs.tree.flatState.findIndex(el => el.node[this.myConfig.idField] === tmp[this.myConfig.parentField]);
                    if (index > -1) {
                        let tmpIndex = this.$refs.tree.flatState[index].node.children.findIndex(el => el[this.myConfig.idField] === tmp[this.myConfig.idField]);
                        if (tmpIndex > -1) {
                            this.$refs.tree.flatState[index].node.children.splice(tmpIndex, 1);
                            if (this.$refs.tree.flatState[index].node.children.length === 0) {
                                Object.assign(this.$refs.tree.flatState[index].node,{expand:false});
                            }
                        }
                    }
                }
            }
            this.treeData = [...this.treeData];
        },
        setExpend(data) {
            let index =  this.$refs.tree.flatState.findIndex(el => el.node[this.myConfig.idField] === data[this.myConfig.idField]);
            if (index > -1) {
                let tmp = {expand:!this.$refs.tree.flatState[index].node.expand};
                if (tmp.expand && this.asyncLoad) {
                    if (!this.$refs.tree.flatState[index].node.loading && this.$refs.tree.flatState[index].node.children.length === 0) {
                        tmp.loading = true;
                    };
                    let callback = (data) => {
                        data.forEach(el => {
                            el.selected = false;
                            this.$refs.tree.flatState[index].node.children.push(el);
                        })
                        Object.assign(this.$refs.tree.flatState[index].node,{loading:false});
                    }
                    if (this.$refs.tree.flatState[index].node.children.length === 0){
                        this.loadData(data,callback);
                    }

                }
                Object.assign(this.$refs.tree.flatState[index].node,tmp);
            }
        },
        loadData (item, callback) {
            let para = {};
            para[this.myConfig.parentField] = item[this.myConfig.idField];
            let data = this.getAsyncNode(para);
            setTimeout(() => {
                data.forEach(el => {
                    this.setSelected(el);
                });
                callback(data);
            }, 200);
        }
    },
    mounted () {
        //this._setCustomHeight(this.clientHeight);
    },
    watch: {
        'myConfig.readOnly':function(val){
            this.setAllNode('readOnly', val);
        },
        selectedData:function (val) {
            this.setNodes(val,'selected', true);
        }
    }
};
</script>
<style>
    .efutre-tree-node .ivu-tree-title{
        width: 95%;
        padding-left: 2px;
    }
</style>
