| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 | const createDragTree = function (setting) {    class DragTree {        /**         * 构造函数         */        constructor(setting) {            // 无索引            this.datas = [];            // 以key为索引indexedDB            this.items = {};            // 以排序为索引            this.nodes = [];            // 根节点            this.children = [];            // 树设置            this.setting = setting;        }        /**         * 树结构根据显示排序         */        sortTreeNode(isResort) {            const self = this;            const addSortNodes = function (nodes) {                if (!nodes) { return }                for (let i = 0; i < nodes.length; i++) {                    self.nodes.push(nodes[i]);                    nodes[i].index = self.nodes.length - 1;                    if (!isResort) {                        nodes[i].children = self.getChildren(nodes[i]);                    } else {                        nodes[i].children.sort((a, b) => { return a[self.setting.order] - b[self.setting.order]; })                    }                    addSortNodes(nodes[i].children);                }            };            this.nodes = [];            if (!isResort) {                this.children = this.getChildren();            } else {                this.children.sort((a, b) => { return a[self.setting.order] - b[self.setting.order]; });            }            addSortNodes(this.children);        }        /**         * 加载数据(初始化), 并给数据添加部分树结构必须数据         * @param datas         */        loadDatas(datas) {            const self = this;            // 清空旧数据            this.items = {};            this.nodes = [];            this.datas = [];            this.children = [];            // 加载全部数据            datas.sort(function (a, b) {                return a[self.setting.level] - b[self.setting.level];            });            for (const data of datas) {                const keyName = itemsPre + data[this.setting.id];                if (this.items[keyName]) continue;                const item = JSON.parse(JSON.stringify(data));                item.children = [];                item.expanded = true;                item.visible = true;                if (item[setting.pid] === setting.rootId) {                    this.children.push(item);                } else {                    const parent = this.getParent(item);                    if (!parent) continue;                    parent.children.push(item);                }                this.items[keyName] = item;                this.datas.push(item);            }            this.children.sort((a, b) => { return a[self.setting.order] - b[self.setting.order]; });            this.sortTreeNode(true);        }        getItemsByIndex(index) {            return this.nodes[index];        }        /**         * 根据id获取树结构节点数据         * @param {Number} id         * @returns {Object}         */        getItems(id) {            return this.items[itemsPre + id];        };        getNodeIndex(node) {            return this.nodes.indexOf(node);        }        /**         * 查找node的parent         * @param {Object} node         * @returns {Object}         */        getParent(node) {            return this.getItems(node[this.setting.pid]);        };        getTopParent(node) {            const parents = this.getAllParents(node);            parents.sort((a, b) => { return a.level - b.level; });            return parents[0];        };        getAllParents(node) {            const parents = [];            if (!node) return parents;            let vP = this.getParent(node);            while (vP) {                parents.push(vP);                vP = this.getParent(vP);            }            return parents;        }        /**         * 查找node的前兄弟节点         * @param node         * @returns {*}         */        getPreSiblingNode(node) {            if (!node) return null;            const parent = this.getParent(node);            const siblings = parent ? parent.children : this.children;            const index = siblings.indexOf(node);            return (index > 0) ? siblings[index - 1] : null;        }        /**         * 查找node的后兄弟节点         * @param node         * @returns {*}         */        getNextSiblingNode(node) {            const parent = this.getParent(node);            const siblings = parent ? parent.children : this.children;            const index = siblings.indexOf(node);            if (index >= 0 && index < siblings.length - 1) {                return siblings[index + 1];            } else {                return null;            }        }        /**         * 查询node的已下载子节点         * @param {Object} node         * @returns {Array}         */        getChildren(node) {            const setting = this.setting;            const pid = node ? node[setting.id] : setting.rootId;            const children = this.datas.filter(function (x) {                return x[setting.pid] === pid;            });            children.sort((a, b) => { return a[setting.order] - b[setting.order]; });            return children;        };        /**         * 递归方式 查询node的已下载的全部后代 (兼容full_path不存在的情况)         * @param node         * @returns {*}         * @private         */        _recursiveGetPosterity(node) {            let posterity = node.children;            for (const c of node.children) {                posterity = posterity.concat(this._recursiveGetPosterity(c));            }            return posterity;        };        /**         * 查询node的已下载的全部后代         * @param {Object} node         * @returns {Array}         */        getPosterity(node) {            const self = this;            const posterity = this._recursiveGetPosterity(node);            posterity.sort(function (x, y) {                return self.getNodeIndex(x) - self.getNodeIndex(y);            });            return posterity;        };        /**         * 查询node是否是父节点的最后一个子节点         * @param {Object} node         * @returns {boolean}         */        isLastSibling(node) {            const siblings = this.getChildren(this.getParent(node));            return (siblings && siblings.length > 0) ? node[this.setting.order] === siblings[siblings.length - 1][this.setting.order] : false;        };        /**         * 查询node是否是父节点的最后一个可见子节点         * @param {Object} node         * @returns {boolean}         */        isLastViewSibling(node) {            const siblings = (this.getChildren(this.getParent(node))).filter(x => { return !x.filter });            return (siblings && siblings.length > 0) ? node.order === siblings[siblings.length - 1].order : false;        };        /**         * 得到树结构构成id         * @param node         * @returns {*}         */        getNodeKey(node) {            return node[this.setting.id];        };        /**         * 刷新子节点是否可见         * @param {Object} node         * @private         */        _refreshChildrenVisible(node) {            if (!node.children) {                node.children = this.getChildren(node);            }            if (node.children && node.children.length > 0) {                for (const child of node.children) {                    child.visible = node.expanded && node.visible && !child.filter;                    this._refreshChildrenVisible(child);                }            }        };        /**         * 设置节点是否展开, 并控制子节点可见         * @param {Object} node         * @param {Boolean} expanded         */        setExpanded(node, expanded) {            node.expanded = expanded;            this._refreshChildrenVisible(node);        };        /**         * 递归 设置节点展开状态         * @param {Array} nodes - 需要设置状态的节点         * @param {Object} parent - nodes的父节点         * @param {Function} checkFun - 判断节点展开状态的方法         * @private         */        _recursiveExpand(nodes, parent, checkFun) {            for (const node of nodes) {                const expanded = checkFun(node);                if (node.expanded !== expanded) {                    node.expanded = expanded;                }                node.visible = parent ? (parent.expanded && parent.visible && !node.filter) : !node.filter;                this._recursiveExpand(node.children, node, checkFun);            }        }        /**         * 自定义展开规则         * @param checkFun         */        expandByCustom(checkFun) {            this._recursiveExpand(this.children, null, checkFun);            // this._saveMarkExpandFold();        }        /**         * 展开到第几层         * @param {Number} level - 展开层数         */        expandByLevel(level) {            const levelField = this.setting.level;            this.expandByCustom(function (n) {                return n[levelField] < level;            });        }        /**         * 自动展开节点node         * @param node         * @returns {*}         */        autoExpandNode(node) {            const parents = this.getAllParents(node);            const reload = [];            for (const p of parents) {                if (!p.expanded) {                    reload.push(p);                    this.setExpanded(p, true);                }            }            return reload;        }        /**         * 加载数据(动态),只加载不同部分         * @param {Array} datas         * @return {Array} 加载到树的数据         * @privateA         */        _updateData(datas) {            datas = datas instanceof Array ? datas : [datas];            let loadedData = [];            for (const data of datas) {                let node = this.getItems(data[this.setting.id]);                if (node) {                    for (const prop in data) {                        if (data[prop] !== undefined && data[prop] !== node[prop]) {                            if (prop === this.setting.pid) {                                loadedData.push(this.getItems(node[this.setting.pid]));                                loadedData.push(this.getItems(data[this.setting.pid]));                            }                            if (prop === this.setting.order) {                                loadedData = loadedData.concat(this.getPosterity(node));                            }                            node[prop] = data[prop];                        }                    }                    loadedData.push(node);                }            }            loadedData = _.uniq(loadedData);            for (const node of loadedData) {                if (node) {                    node.children = this.getChildren(node);                    node.expanded = node.children.length === 0 ? true : node.children[0].visible;                } else {                    this.children = this.getChildren(null);                }            }            this.sortTreeNode(true);            return loadedData;        };        /**         * 加载数据(动态),只加载不同部分         * @param {Array} datas         * @return {Array} 加载到树的数据         * @privateA         */        _loadData(datas) {            datas = datas instanceof Array ? datas : [datas];            const loadedData = [], resortData = [];            for (const data of datas) {                let node = this.getItems(data[this.setting.id]);                if (node) {                    const parent = this.getItems(node[this.setting.pid]);                    for (const prop in data) {                        if (data[prop] !== undefined && data[prop] !== node[prop]) {                            node[prop] = data[prop];                            if (parent && resortData.indexOf(parent) === -1) {                                resortData.push(parent);                            }                        }                    }                    loadedData.push(node);                } else {                    const keyName = itemsPre + data[this.setting.id];                    const node = JSON.parse(JSON.stringify(data));                    this.items[keyName] = node;                    this.datas.push(node);                    node.expanded = true;                    node.visible = true;                    loadedData.push(node);                    if (resortData.indexOf(node) === -1) {                        resortData.push(node);                    }                    const parent = this.getItems(node[this.setting.pid]);                    if (parent && resortData.indexOf(parent) === -1) {                        resortData.push(parent);                    } else {                        resortData.push(this.setting.rootId);                    }                }            }            for (const node of resortData) {                if (node && node !== this.setting.rootId) {                    node.children = this.getChildren(node);                } else {                    this.children = this.getChildren(null);                }            }            this.sortTreeNode(true);            for (const node of loadedData) {                if (!node.expanded) {                    this.setExpanded(node, true);                }            }            return loadedData;        };        /**         * 清理数据(动态)         * @param datas         * @private         */        _freeData(datas) {            datas = datas instanceof Array ? datas : [datas];            const freeDatas = [];            const removeArrayData = function (array, data) {                const index = array.indexOf(data);                array.splice(index, 1);            };            for (const data of datas) {                const node = this.getItems(data);                if (node) {                    freeDatas.push(node);                    node.deleteIndex = this.nodes.indexOf(node);                    delete this.items[itemsPre + node[this.setting.id]];                    if (node[this.setting.pid] !== this.setting.rootId) {                        const parent = this.getItems(node[this.setting.pid]);                        if (parent) {                            removeArrayData(parent.children, node);                        }                    } else {                        removeArrayData(this.children, node);                    }                    removeArrayData(this.datas, node);                }            }            for (const node of freeDatas) {                removeArrayData(this.nodes, node);            }            return freeDatas;        };        /**         * 因为提交其他数据,引起的树结构数据更新,调用该方法         *         * @param data - 更新的数据 {update, create, delete}         * @returns {{}}         */        loadPostData(data) {            const result = {};            if (data.delete) {                result.delete = this._freeData(data.delete);            }            if (data.create) {                result.create = this._loadData(data.create);            }            if (data.update) {                result.update = this._updateData(data.update);            }            return result;        }        recursiveFun(children, fun) {            if (!fun) return;            if (!children || children.length === 0) return;            for (const c of children) {                this.recursiveFun(c.children, fun);                fun(c);            }        }    }    return new DragTree(setting);};
 |