| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 | 'use strict';/** * * * @author Mai * @date * @version */const itemsPre = 'id_';class baseTree {    /**     * 构造函数     */    constructor (ctx, setting) {        this.ctx = ctx;        // 无索引        this.datas = [];        // 以key为索引        this.items = {};        // 以排序为索引        this.nodes = [];        // 根节点        this.children = [];        // 树设置        this.setting = setting;    }    /**     * 根据id获取树结构节点数据     * @param {Number} id     * @returns {Object}     */    getItems (id) {        return this.items[itemsPre + id];    };    /**     * 查找node的parent     * @param {Object} node     * @returns {Object}     */    getParent (node) {        return this.getItems(node[this.setting.pid]);    };    /**     * 查询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(function (a, b) {            return a.order - b.order;        });        return children;    };    /**     * 获取节点的 index     * @param node     * @returns {number}     */    getNodeSerialNo(node) {        return this.nodes.indexOf(node);    }    /**     * 树结构根据显示排序     */    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(function (a, b) {                        return a.order - b.order;                    })                }                addSortNodes(nodes[i].children);            }        };        this.nodes = [];        if (!isResort) {            this.children = this.getChildren();        } else {            this.children.sort(function (a, b) {                return a.order - b.order;            })        }        addSortNodes(this.children);    }    /**     * 加载数据(初始化), 并给数据添加部分树结构必须数据     * @param datas     */    loadDatas (datas) {        // 清空旧数据        this.items = {};        this.nodes = [];        this.datas = [];        this.children = [];        // 加载全部数据        datas.sort(function (a, b) {            return a.level - b.level;        });        for (const data of datas) {            const keyName = itemsPre + data[this.setting.id];            if (!this.items[keyName]) {                const item = JSON.parse(JSON.stringify(data));                item.children = [];                item.expanded = true;                item.visible = true;                this.items[keyName] = item;                this.datas.push(item);                if (item[this.setting.pid] === this.setting.rootId) {                    this.children.push(item);                } else {                    const parent = this.getParent(item);                    if (parent) {                        parent.children.push(item);                    }                }            }        }        this.children.sort(function (a, b) {            return a.order - b.order;        });        this.sortTreeNode(true);    }    /**     * 递归方式 查询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;        let posterity;        if (node.full_path !== '') {            const reg = new RegExp('^' + node.full_path + '-');            posterity = this.datas.filter(function (x) {                return reg.test(x.full_path);            });        } else {            posterity = this._recursiveGetPosterity(node);        }        posterity.sort(function (x, y) {            return self.getNodeSerialNo(x) - self.getNodeSerialNo(y);        });        return posterity;    };    /**     * 根据 字段名称 获取数据     * @param fields     * @returns {Array}     */    getDatas (fields) {        const datas = [];        for (const node of this.nodes) {            if (node.b_code && node.b_code !== '') node.chapter = this.ctx.helper.getChapterCode(node.b_code);            const data = {};            for (const field of fields) {                data[field] = node[field];            }            datas.push(data);        }        return datas;    }    /**     * 排除 某些字段 获取数据     * @param fields     * @returns {Array}     */    getDatasWithout (fields, filter) {        const datas = [];        for (const node of this.nodes) {            if (filter && filter(node)) {                continue;            }            if (node.b_code && node.b_code !== '') node.chapter = this.ctx.helper.getChapterCode(node.b_code);            const data = {};            for (const field in node) {                if (fields.indexOf(field) === -1) {                    data[field] = node[field];                }            }            datas.push(data);        }        return datas;    }    /**     * 获取默认数据 剔除一些树结构需要的缓存数据     * @returns {Array}     */    getDefaultDatas(filter) {        return this.getDatasWithout(['expanded', 'visible', 'children', 'index'], filter);    }    _mapTreeNode () {        let map = {}, maxLevel = 0;        for (const node of this.nodes) {            let levelArr = map[node.level];            if (!levelArr) {                levelArr = [];                map[node.level] = levelArr;            }            if (node.level > maxLevel) {                maxLevel = node.level;            }            levelArr.push(node);        }        return [maxLevel, map];    }    _calculateNode (node, fun) {        const self = this;        if (node.children && node.children.length > 0) {            const gather = node.children.reduce(function (rst, x) {                const result = {};                for (const cf of self.setting.calcFields) {                    result[cf] = self.ctx.helper.add(rst[cf], x[cf]);                }                return result;            });            // 汇总子项            for (const cf of this.setting.calcFields) {                if (gather[cf]) {                    node[cf] = gather[cf];                } else {                    node[cf] = null;                }            }        }        // 自身运算        if (fun) {            fun(node);        } else if (this.setting.calc) {            this.setting.calc(node);        }    }    calculateAll(fun) {        const [maxLevel, levelMap] = this._mapTreeNode();        for (let i = maxLevel; i >= 0; i--) {            const levelNodes = levelMap[i];            if (levelNodes && levelNodes.length > 0) {                for (const node of levelNodes) {                    this._calculateNode(node, fun);                }            }        }    }}class billsTree extends baseTree {    /**     * 检查节点是否是最底层项目节     * @param node     * @returns {boolean}     */    isLeafXmj(node) {        if (node.b_code && node.b_code !== '') {            return false;        }        for (const child of node.children) {            if (!child.b_code || child.b_code === '') {                return false;            }        }        return true;    }    /**     * 查询最底层项目节(本身或父项)     * @param {Object} node - 查询节点     * @returns {Object}     */    getLeafXmjParent(node) {        let parent = node;        while (parent) {            if (this.isLeafXmj(parent)) {                return parent;            } else {                parent = this.getParent(parent);            }        }        return null;    }}class filterTree extends baseTree {    addData(data, fields) {        const item = {};        for (const prop in data) {            if (fields.indexOf(prop) >= 0) {                item[prop] = data[prop];            }        }        const keyName = itemsPre + item[this.setting.id];        if (!this.items[keyName]) {            item.children = [];            item.is_leaf = true;            item.expanded = true;            item.visible = true;            this.items[keyName] = item;            this.datas.push(item);            if (item[this.setting.pid] === this.setting.rootId) {                this.children.push(item);            } else {                const parent = this.getParent(item);                if (parent) {                    parent.is_leaf = false;                    parent.children.push(item);                }            }        } else {            return this.items[keyName];        }        return item;    }}class filterGatherTree extends baseTree {    clearDatas() {        this.items = {};        this.nodes = [];        this.datas = [];        this.children = [];    }    get newId() {        if (!this._maxId) {            this._maxId = 0;        }        this._maxId++;        return this._maxId;    }    addNode(data, parent) {        data[this.setting.pid] = parent ? parent[this.setting.id] : this.setting.rootId;        let item = this.ctx.helper._.find(this.items, data);        if (item) return item;        item = data;        item.drawing_code = [];        item.memo = [];        item.postil = [];        item[this.setting.id] = this.newId;        const keyName = itemsPre + item[this.setting.id];        item.children = [];        item.is_leaf = true;        item.expanded = true;        item.visible = true;        this.items[keyName] = item;        this.datas.push(item);        if (parent) {            item[this.setting.fullPath] = parent[this.setting.fullPath] + '-' + item[this.setting.id];            item[this.setting.level] = parent[this.setting.level] + 1;            item[this.setting.order] = parent.children.length + 1;            parent.is_leaf = false;            parent.children.push(item);        } else {            item[this.setting.fullPath] = '' + item[this.setting.id];            item[this.setting.level] = 1;            item[this.setting.order] = this.children.length + 1;            this.children.push(item);        }        return item;    }    generateSortNodes() {        const self = this;        const addSortNode = function (node) {            self.nodes.push(node);            for (const c of node.children) {                addSortNode(c);            }        };        this.nodes = [];        for (const n of this.children) {            addSortNode(n);        }    }    sortTreeNodeCustom(fun) {        const sortNodes = function (nodes) {            nodes.sort(fun);            for (const [i, node] of nodes.entries()) {                node.order = i + 1;            }            for (const node of nodes) {                if (node.children && node.children.length > 1) {                    sortNodes(node.children);                }            }        };        this.nodes = [];        this.children = this.getChildren(null);        sortNodes(this.children);        this.generateSortNodes();    }}class gatherTree extends baseTree {    constructor(ctx, setting) {        super(ctx, setting);        this._newId = 1;    }    get newId() {        return this._newId++;    }    loadGatherNode(node, parent, loadFun) {        const siblings = parent ? parent.children : this.children;        let cur = siblings.find(function (x) {            return node.b_code                ? x.b_code === node.b_code && x.name === node.name && x.unit === node.unit && x.unit_price === node.unit_price                : x.code === node.code && x.name === node.name;        });        if (!cur) {            const id = this.newId;            cur = {                id: id,                pid: parent ? parent.id : this.setting.rootId,                full_path: parent ? parent.full_path + '-' + id : '' + id,                level: parent ? parent.level + 1 : 1,                order: siblings.length + 1,                children: [],                code: node.code, b_code: node.b_code, name: node.name,                unit: node.unit, unit_price: node.unit_price,            };            siblings.push(cur);            this.datas.push(cur);        }        loadFun(cur, node);        for (const c of node.children) {            this.loadGatherNode(c, cur, loadFun);        }    }    generateSortNodes() {        const self = this;        const addSortNode = function (node) {            self.nodes.push(node);            for (const c of node.children) {                addSortNode(c);            }        };        this.nodes = [];        for (const n of this.children) {            addSortNode(n);        }    }    loadGatherTree(sourceTree,  loadFun) {        for (const c of sourceTree.children) {            this.loadGatherNode(c, null, loadFun);        }        // todo load Pos Data;    }    calculateSum() {        if (this.setting.calcSum) {            for (const d of this.datas) {                this.setting.calcSum(d, this.count);            }        }    }}class pos {    /**     * 构造函数     * @param {id|Number, masterId|Number} setting     */    constructor (setting) {        // 无索引        this.datas = [];        // 以key为索引        this.items = {};        // 以分类id为索引的有序        this.ledgerPos = {};        // pos设置        this.setting = setting;    }    /**     * 加载部位明细数据     * @param datas     */    loadDatas(datas) {        this.datas = datas;        this.items = {};        this.ledgerPos = {};        for (const data of this.datas) {            const key = itemsPre + data[this.setting.id];            this.items[key] = data;            const masterKey = itemsPre + data[this.setting.ledgerId];            if (!this.ledgerPos[masterKey]) {                this.ledgerPos[masterKey] = [];            }            this.ledgerPos[masterKey].push(data);        }        for (const prop in this.ledgerPos) {            this.resortLedgerPos(this.ledgerPos[prop]);        }    }    getLedgerPos(mid) {        return this.ledgerPos[itemsPre + mid];    }    resortLedgerPos(ledgerPos) {        if (ledgerPos instanceof Array) {            ledgerPos.sort(function (a, b) {                return a.porder - b.porder;            })        }    }    /**     * 计算全部     */    calculateAll(fun) {        const calcFun = fun ? fun : this.setting.calc;        if (!calcFun) return;        for (const pos of this.datas) {            calcFun(pos);        }    }    getDatas () {        return this.datas;    }}module.exports = {    billsTree,    pos,    filterTree,    filterGatherTree,    gatherTree,};
 |