Преглед изворни кода

养护清单规则双击新逻辑

zhongzewei пре 7 година
родитељ
комит
b1f6427ba1

+ 9 - 0
modules/main/controllers/bills_controller.js

@@ -262,6 +262,15 @@ module.exports = {
             }
 
         });
+    },
+    insertBills: async function (req, res) {
+        let data = JSON.parse(req.body.data);
+        try {
+            await bill_facade.insertBills(data.postData);
+            callback(req, res, 0, 'success', null);
+        } catch (err) {
+            callback(req, res, 1, err, null);
+        }
     }
 };
 

+ 13 - 0
modules/main/facade/bill_facade.js

@@ -110,6 +110,19 @@ module.exports={
         return results;
 
     },
+   insertBills: async function(datas) {
+        let bulks = [];
+        for (let data of datas) {
+            if (data.updateType === 'update') {
+                bulks.push({updateOne: {filter: {ID: data.updateData.ID}, update: {NextSiblingID: data.updateData.NextSiblingID}}});
+            } else {
+                bulks.push({insertOne: {document: data.updateData}});
+            }
+        }
+        if (bulks.length > 0) {
+            await bill_Model.bulkWrite(bulks);
+        }
+    }
 };
 
 async function pasteOtherData(data) {

+ 1 - 0
modules/main/routes/bills_route.js

@@ -21,6 +21,7 @@ module.exports = function (app) {
     billsRouter.post('/pasteBlock', billsController.pasteBlock);
     billsRouter.post('/import', billsController.import);
     billsRouter.get('/downloadExamp', billsController.downloadExample);
+    billsRouter.post('/insertBills', billsController.insertBills);
     app.use('/bills', billsRouter);
 };
 

+ 12 - 0
public/web/id_tree.js

@@ -608,7 +608,19 @@ var idTree = {
                 let next = data.NextSiblingID == -1 ? null : this.nodes[this.prefix + data.NextSiblingID];
                 node.nextSibling = next;
                 if(next){
+                    //将原本nextSibing的前节点的设置为node的上兄弟节点
+                    if (next.preSibling && next.preSibling.nextSibling !== node) {
+                        next.preSibling.nextSibling = node;
+                        next.preSibling.data.NextSiblingID = node.data.ID;
+                        node.preSibling = next.preSibling;
+                    }
                     next.preSibling = node;
+                } else {//插入了最末子节点,更新上一个最末子节点
+                    let lastChild = parent ? parent.children[parent.children.length - 2] : this.roots[this.roots.length - 2];
+                    if (lastChild && lastChild.nextSibling !== node) {
+                        lastChild.nextSibling = node;
+                        lastChild.data.NextSiblingID = node.data.ID;
+                    }
                 }
             }
             //resort

+ 6 - 12
web/building_saas/main/js/controllers/project_controller.js

@@ -62,8 +62,7 @@ ProjectController = {
                 nextSiblingID = project.Bills.tree.setting.rootId;
                 nodeParentID = target.getID();
                 nodeNextSiblingID = project.mainTree.rootID();
-            }
-            else{
+            } else{
                 parentID = target.source.getParentID();
                 nextSiblingID = target.source.getNextSiblingID();
                 nodeParentID = target.getParentID();
@@ -84,21 +83,17 @@ ProjectController = {
                     let subType = getSubType(target);
                     if(target.sourceType === project.Bills.getSourceType() && target.data.type === billType.DXFY && subType === billType.FB){
                         return false;
-                    }
-                    //焦点行是分部
-                    else if(target.sourceType === project.Bills.getSourceType() && target.data.type === billType.FB){
+                    } else if(target.sourceType === project.Bills.getSourceType() && target.data.type === billType.FB){//焦点行是分部
                         if(!subType || subType === billType.FX){
                             parentID = target.source.getID();
                             nextSiblingID = project.Bills.tree.setting.rootId;
                             nodeParentID = target.getID();
                             nodeNextSiblingID = project.mainTree.rootID();
-                        }
-                        else{
+                        } else{
                             return false;
                         }
                     }
-                }
-                else {
+                } else {
                     std.type = billType.BILL;
                 }
 
@@ -161,13 +156,13 @@ ProjectController = {
         }
     },
     addSpecialBill(project,sheetController,parent,nextSibling,isUserAdd,type){
-        let newSource = null, newNode = null;
+        let newNode = null;
         let b_nexID = nextSibling==null?-1:nextSibling.source.getID();//主树和清单树,对应的树节点ID不一样
         let m_nexID = nextSibling==null?-1:nextSibling.getID();
         let b_parent = parent==null?-1:parent.source.getID();
         let m_parent = parent==null?-1:parent.getID();
 
-        newSource = project.Bills.insertSpecialBill(b_parent, b_nexID,isUserAdd,type);
+        let newSource = project.Bills.insertSpecialBill(b_parent, b_nexID,isUserAdd,type);
         newNode = project.mainTree.insert(m_parent,m_nexID, newSource.data.ID);
         if (newNode) {
             newNode.source = newSource;
@@ -179,7 +174,6 @@ ProjectController = {
     },
 
     addRation: function (project, sheetController, rationType, std) {
-        debugger;
         if (!project || !sheetController) { return; }
 
         let selected = project.mainTree.selected, newSource = null, newNode = null;

+ 12 - 0
web/building_saas/main/js/models/cache_tree.js

@@ -390,7 +390,19 @@ var cacheTree = {
                 let next = data.NextSiblingID == -1 ? null : this.nodes[this.prefix + data.NextSiblingID];
                 node.nextSibling = next;
                 if(next){
+                    //将原本nextSibing的前节点的设置为node的上兄弟节点
+                    if (next.preSibling && next.preSibling.nextSibling !== node) {
+                        next.preSibling.nextSibling = node;
+                        next.preSibling.data.NextSiblingID = data.ID;
+                        node.preSibling = next.preSibling;
+                    }
                     next.preSibling = node;
+                } else {
+                    let lastChild = parent ? parent.children[parent.children.length - 2] : this.roots[this.roots.length - 2];
+                    if (lastChild && lastChild.nextSibling !== node) {
+                        lastChild.nextSibling = node;
+                        lastChild.data.NextSiblingID = data.ID;
+                    }
                 }
             }
             //resort

+ 0 - 68
web/building_saas/main/js/models/calc_base.js

@@ -165,76 +165,8 @@ let cbTools = {
                     mapObj[figureClass][figure] = baseFigures[figure];
                 }
             }
-            /*if(filter.indexOf(baseFigures[figure]['base']) === -1){
-                mapObj['CONSTRUCTION_ORGANIZATION'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'QTXMF' && baseFigures[figure]['base'] !== 'SQGCZJ' && baseFigures[figure]['base'] !== 'AQWMSGZXF'){
-                mapObj['OTHER'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'GF' && baseFigures[figure]['base'] !== 'SQGCZJ' && baseFigures[figure]['base'] !== 'AQWMSGZXF'){
-                mapObj['CHARGE'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'SJ' && baseFigures[figure]['base'] !== 'SQGCZJ'){
-                mapObj['TAX'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'SQGCZJ'){
-                mapObj['ENGINEERINGCOST'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'SQGCZJ' && baseFigures[figure]['base'] !== 'AQWMSGZXF'){
-                mapObj['OTHERS'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] === 'SQGCZJ'){
-                mapObj['SAFETY_CONSTRUCTION'][figure] = baseFigures[figure];
-            }*/
         }
-       // mapObj['SAFETY_CONSTRUCTION'] = Object.assign(mapObj['SAFETY_CONSTRUCTION'], mapObj['CONSTRUCTION_ORGANIZATION']);
-
     },
-    /*setBaseFigureClass: function (baseFigures, mapObj) {
-        mapObj['CONSTRUCTION_ORGANIZATION'] = Object.create(null);
-        mapObj['SAFETY_CONSTRUCTION'] = Object.create(null);
-        mapObj['OTHER'] = Object.create(null);
-        mapObj['CHARGE'] = Object.create(null);
-        mapObj['TAX'] = Object.create(null);
-        mapObj['OTHERS'] = Object.create(null);
-        mapObj['ENGINEERINGCOST'] = Object.create(null);
-        let filter = ['CSXMF', 'ZZCSXMF', 'ZZCSXMDEJJZJGCF', 'ZZCSXMDEJJRGF', 'ZZCSXMDEJJCLF', 'ZZCSXMDEJJJXF', 'QTXMF', 'GF', 'SJ', 'SQGCZJ', 'AQWMSGZXF'];
-        let needFixedBillsClass = ['FBFX', 'CXSM', 'QTXM', 'GF', 'SJ'];
-        //不需要关联节点的、但是下挂在固定清单分类下的基数
-        let noneFixedBillsFigures = ['JZMJ'];
-        //安全文明施工专项费用只有税金和工程造价能用
-        for(let figure in baseFigures){
-            if(!noneFixedBillsFigures.includes(baseFigures[figure]['base'])){
-                //过滤相关清单固定行不存在的
-                if(needFixedBillsClass.includes(baseFigures[figure]['class']) && !baseFigures[figure]['fixedBill']){
-                    continue;
-                }
-            }
-            if(filter.indexOf(baseFigures[figure]['base']) === -1){
-                mapObj['CONSTRUCTION_ORGANIZATION'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'QTXMF' && baseFigures[figure]['base'] !== 'SQGCZJ' && baseFigures[figure]['base'] !== 'AQWMSGZXF'){
-                mapObj['OTHER'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'GF' && baseFigures[figure]['base'] !== 'SQGCZJ' && baseFigures[figure]['base'] !== 'AQWMSGZXF'){
-                mapObj['CHARGE'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'SJ' && baseFigures[figure]['base'] !== 'SQGCZJ'){
-                mapObj['TAX'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'SQGCZJ'){
-                mapObj['ENGINEERINGCOST'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] !== 'SQGCZJ' && baseFigures[figure]['base'] !== 'AQWMSGZXF'){
-                mapObj['OTHERS'][figure] = baseFigures[figure];
-            }
-            if(baseFigures[figure]['base'] === 'SQGCZJ'){
-                mapObj['SAFETY_CONSTRUCTION'][figure] = baseFigures[figure];
-            }
-        }
-        mapObj['SAFETY_CONSTRUCTION'] = Object.assign(mapObj['SAFETY_CONSTRUCTION'], mapObj['CONSTRUCTION_ORGANIZATION']);
-
-    },*/
     getFigure: function (node) {
         let calcBase = projectObj.project.calcBase;
         let parent = node.parent;

+ 1 - 10
web/building_saas/main/js/views/project_view.js

@@ -601,16 +601,6 @@ var projectObj = {
         let code = node.data.code ? node.data.code : '';
         if(node.sourceType == ModuleNames.bills){//当清单是“分部分项工程”、“措施项目工程”时,要展开清单规则节点
             if(BILLS.isFXorBX(node)||(node.data.type == billType.BILL && BILLS.isMeasure(node))){//是分项或补项,是清单并且属于措施项目节点
-              /*  if(billsLibObj.stdBillsTree === null){
-                    billsLibObj.doAfterLoadBills = function () {
-                        this.locateAtBills(code);
-                        this.doAfterLoadBills = null;
-                    };
-                }
-                else {
-                    billsLibObj.locateAtBills(code);
-                }
-                if(!$("#qd").is(":visible"))  $('#stdBillsTab').click();*/
                 if(!billsGuidance.bills.tree){
                     doAfterLoadGuidance = function () {
                         billsGuidance.locateAtBills(code);
@@ -2939,6 +2929,7 @@ function doAfterImportPosition(positionData){
         }
         //插入清单节点
         projectObj.project.Bills.tree.insertByDatas(positionData.insert.bill);
+        projectObj.project.Bills.datas = projectObj.project.Bills.datas.concat(positionData.insert.bill);
         //插入主树节点
         let newNodes = projectObj.project.mainTree.insertByDatas(positionData.insert.bill);
         for(let node of newNodes){

+ 271 - 3
web/building_saas/main/js/views/std_billsGuidance_lib.js

@@ -12,6 +12,8 @@
 let doAfterLoadGuidance = null;
 
 const billsGuidance = (function () {
+    //更新类型
+    const updateType = {update: 'update', create: 'create'};
     let currentLib = null;
     //库类型
     const libType = {'guidance': 1, 'elf': 2}; //清单指引、清单精灵
@@ -20,6 +22,8 @@ const billsGuidance = (function () {
     let stdBillsJobData = [];
     //项目特征
     let stdBillsFeatureData = [];
+    //正在插入
+    let isInserting = false;
     const bills = {
         dom: $('#billsGuidance_bills'),
         workBook: null,
@@ -105,7 +109,8 @@ const billsGuidance = (function () {
                 if(!node){
                     return;
                 }
-                if(node.children.length > 0){
+                //展开收起(非最底层节点且双击的是第一列)
+                if (args.col === 0 && node.children.length > 0) {
                     node.setExpanded(!node.expanded);
                     //设置展开收起状态
                     sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
@@ -118,12 +123,275 @@ const billsGuidance = (function () {
                         args.sheet.invalidateLayout();
                     });
                     args.sheet.repaint();
-                } else if(!projectReadOnly) {
-                    billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, node);
+                } else if (!projectReadOnly && !isInserting && (args.col !== 0 || node.children.length === 0)) {
+                    //选中部分的最底层(只是选中部分的最底)
+                    let lowestNodes = [bills.tree.items[args.row]];
+                    insertBills(lowestNodes);
                 }
             }
         }
     };
+    //插入清单
+    function insertBills(lowestNodes) {
+        let selTree = getSelTree(lowestNodes);
+        let compareData = compareTree(projectObj.project.Bills.tree, selTree);
+        let sheet = projectObj.mainSpread.getActiveSheet(),
+            row = sheet.getActiveColumnIndex(),
+            col = sheet.getActiveColumnIndex();
+        if (compareData.postData.length > 0) {
+            isInserting = true;
+            CommonAjax.post('/bills/insertBills', {postData: compareData.postData}, function () {
+                //插入
+                let insertData = _.filter(compareData.postData, {updateType: updateType.create});
+                let treeData = [];
+                for (let data of insertData) {
+                    treeData.push(data.updateData);
+                }
+                //插入清单节点
+                projectObj.project.Bills.tree.insertByDatas(treeData);
+                projectObj.project.Bills.datas = projectObj.project.Bills.datas.concat(treeData);
+                //插入主树节点
+                let newNodes = projectObj.project.mainTree.insertByDatas(treeData);
+                for (let node of newNodes) {
+                    node.source = projectObj.project.Bills.tree.nodes[projectObj.project.Bills.tree.prefix + node.getID()];
+                    node.data = node.source.data;
+                    node.sourceType = projectObj.project.Bills.getSourceType();
+                }
+                ProjectController.syncDisplayNewNodes(projectObj.mainController, newNodes, true);
+                row = newNodes[newNodes.length - 1].serialNo();
+                //有新的节点插入,也有可能定位至旧节点(批量选用的情况下)
+                if (compareData.locateNode) {
+                    row = compareData.locateNode.serialNo();
+                }
+                sheet.setSelection(row, col, 1, 1);
+                projectObj.mainController.setTreeSelected(projectObj.mainController.tree.items[row]);//触发树节点选中事件
+                sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);
+                isInserting = false;
+            }, function () {
+                isInserting = false;
+            });
+        } else if (compareData.locateNode) {
+            row = compareData.locateNode.serialNo();
+            sheet.setSelection(row, col, 1, 1);
+            projectObj.mainController.setTreeSelected(projectObj.mainController.tree.items[row]);//触发树节点选中事件
+            sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);
+        }
+    }
+    /*
+    *
+    * 1.选中的树结构(清单规则选中的节点及其所有父项)与主树对比(主树中节点“编码-名称-单位”与选中树~组合相同视为同一节点),
+    *   将主树中不含有的选中节点全部插入
+    * 2.插入位置由1对比得出,主树有与选中树结构相同层次结构的片段,这个相同片段为插入位置
+    * 3.选中树结构除去相同片段,为需要插入的节点,插入时,遇到同层节点,根据编码的字符编码值确定顺序
+    *   a.code <= b.code,则a节点在b节点前
+    * */
+    //获取选中的树(将选中的节点及其所有父项,组合成一棵树,没有重复节点)
+    //@param {Array}lowestNodes(选中的最底层节点)  @return {Array}
+    function getSelTree(lowestNodes) {
+        let allNodes = [];
+        //获取树上所有的节点
+        for (let node of lowestNodes) {
+            while (node && !allNodes.includes(node)) {
+                allNodes.push(node);
+                node = node.parent;
+            }
+        }
+        //根据原节点serialNo排序,排序后,后一项节点只可能前节点的后兄弟项,或子项(根据原节点ID-ParentID判定)
+        allNodes.sort(function (a, b) {
+            let aV = a.serialNo(),
+                bV = b.serialNo();
+            if (aV > bV) {
+                return 1;
+            } else if (aV < bV) {
+                return -1;
+            }
+            return 0;
+        });
+        //生成树数据
+        let treeData = [];
+        //旧ID与新ID映射
+        let IDMapping = {};
+        for (let i = 0; i < allNodes.length; i++) {
+            //原节点
+            let preN = allNodes[i - 1],
+                thisN = allNodes[i];
+            let newNodeData = {ID: uuid.v1(), NextSiblingID: -1, ParentID: -1, orgID: thisN.data.ID};
+            IDMapping[newNodeData.orgID] = newNodeData.ID;
+            treeData.push(newNodeData);
+            //新树数据
+            let preData = treeData[i - 1],
+                thisData = treeData[i];
+            //节点与上节点为同层节点,则此节点设为上节点的后兄弟
+            if (preN && preN.data.ParentID === thisN.data.ParentID) {
+                preData.NextSiblingID = thisData.ID;
+                //节点与上节点不为同层节点,则此节点为某上节点的子几点
+            } else if (preN && preN.data.ParentID !== thisN.data.ParentID) {
+                let parentID = IDMapping[thisN.data.ParentID];
+                thisData.ParentID = parentID;
+            }
+        }
+        let selTree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
+        selTree.loadDatas(treeData);
+        return selTree;
+    }
+    /*
+    * 选中树与清单主树进行对比,(自上而下,从roots开始)获取插入、更新数据
+    * 找到的清单树中清单子项含有非清单项或输入了计算基数,则中止该清单的对比,不可插入数据
+    * */
+
+    //获取节点的匹配数据:编码-名称-单位
+    //@param {Object}node @return {String}
+    function getMatchContent(node) {
+        return `${node.data.code ? node.data.code : '*'}-${node.data.name ? node.data.name : '*'}-${node.data.unit ? node.data.unit: '*'}`;
+    }
+    //**对比清单主树与选中树,获取需要更新和插入的数据**
+    //@param {Object}mainTree {Object}selTree
+    function compareTree(billsTree, selTree) {
+        //需要插入、更新的数据
+        let postData = [],
+            //跟树结构自动定位至的清单节点(最近匹配到的节点)
+            locateNode = null;
+        if (!billsTree || !selTree) {
+            return postData;
+        }
+        comparePeer(null, billsTree.roots, selTree.roots);
+        return {postData, locateNode};
+        /*
+        * 该清单节点是否可以继续往下递归匹配,即该节点是否还可插入子项(在该层匹配到的时候判断)
+        * 1.该底层节点不能含有非清单子项
+        * 2.该节点不能含有计算基数
+        * todo 3.数量单价等相关概念做完了再补上
+        * @param {Object}billsNode(清单树中的某节点) @return {Boolean}
+        * */
+        function canRecursive(billsNode) {
+            //不含有子清单节点但却含有子节点,说明该节点含有非清单子项
+            if (billsNode.children > 0 && billsNode.source.children === 0) {
+                return false;
+            } else if (billsNode.data.calcBase) {
+                return false;
+            }
+            return true;
+        }
+        //获取某选中节点要往清单主树同层插入的位置
+        function insertPos(peerNodes, node) {
+            //node选中树中没有记录原清单的数据,只记录了原清单ID,需要node的数据,则要找回原清单
+            let orgNode = bills.tree.nodes[`${bills.tree.prefix}${node.data.orgID}`];
+            if (!orgNode) {
+                return -1;
+            }
+            let insertCode = orgNode.data.code ? orgNode.data.code : '';
+            //插入最顶层节点或者无编码,则直接插入到清单主树最后面
+            if (orgNode.depth() === 0 || insertCode === '') {
+                return peerNodes.length;
+            }
+            for (let i = 0; i < peerNodes.length; i++) {
+                let thisNode = peerNodes[i];
+                let thisCode = thisNode.data.code ? thisNode.data.code : '';
+                //确定同层节点的顺序,编码小于等于在前,大于在后
+                if (insertCode <= thisCode) {
+                    return i;
+                } else if (insertCode > thisCode) {
+                    continue;
+                }
+            }
+            return peerNodes.length;
+        }
+        //获取插入清单数据
+        function getInsertData(insertObj) {
+            let stdNode = bills.tree.nodes[`${bills.tree.prefix}${insertObj.orgID}`];
+            if (!stdNode) {
+                return null;
+            }
+            let stdData = {};
+            stdData.projectID = projectInfoObj.projectInfo.ID;
+            stdData.isAdd = 1;
+            stdData.ID = insertObj.ID;
+            stdData.ParentID = insertObj.ParentID;
+            stdData.NextSiblingID = insertObj.NextSiblingID;
+            //顶层节点是大项费用
+            stdData.type = stdNode.parent ? billType.BILL : billType.DXFY;
+            stdData.code = stdNode.data.code;
+            stdData.name = stdNode.data.name;
+            stdData.unit = stdNode.data.unit;
+            stdData.ruleText = stdNode.data.ruleText;
+            stdData.comments = stdNode.data.comments;
+            stdData.programID = stdNode.data.engineering;
+            stdData.billsLibId = stdNode.data.billsLibId;
+            return stdData;
+        }
+        //从同层节点中获取更新数据
+        //@param {Object}parentNode(同层节点挂载的父节点,清单主树中) {Array}peerNodes(同层节点,含有清单树和选中树节点)
+        //       {Array}billsNodes(该层清单树节点) {Array}selNodes(该层选中树节点) @return {Array}
+        function getUpdateDataFromPeer(parentNode, peerNodes, billsNodes, selNodes) {
+            let rst = [];
+            //向下获取插入数据直到最底层
+            function getDataTillDeepest(node) {
+                if (node) {
+                    let insertData = getInsertData(node.data);
+                    if (insertData) {
+                        rst.push({updateType: updateType.create, updateData: insertData});
+                    }
+                    for (let child of node.children) {
+                        getDataTillDeepest(child);
+                    }
+                }
+            }
+            for (let i = 0; i < peerNodes.length; i++) {
+                let thisNode = peerNodes[i],
+                    nextNode = peerNodes[i + 1];
+                //更新原清单节点NextSiblingID
+                if (billsNodes.includes(thisNode) && selNodes.includes(nextNode)) {
+                    rst.push({updateType: updateType.update, updateData: {ID: thisNode.data.ID, NextSiblingID: nextNode.data.ID}});
+                } else if (selNodes.includes(thisNode) && billsNodes.includes(nextNode)) { //变更选中节点的NextSiblingID
+                    thisNode.data.NextSiblingID = nextNode.data.ID;
+                }
+                //所有选中的同层节点设为清单树父节点的子项,获取插入数据(插入该同层节点及其所有子节点)
+                if (selNodes.includes(thisNode)) {
+                    thisNode.data.ParentID = parentNode ? parentNode.data.ID : -1;
+                    getDataTillDeepest(thisNode);
+                }
+            }
+            return rst;
+        }
+        //同层节点之间比较,匹配到的则继续往下匹配,匹配不到的节点则按照规定的顺序进行排序,插入更新(更新清单树节点中NextSiblingID改变的节点)
+        function comparePeer(parentNode, billsNodes, selNodes) {
+            let peerNodes = [].concat(billsNodes); //同层节点
+            let matchNode = null; //匹配到的清单主树节点
+            for (let selNode of selNodes) {
+                let stdNode = bills.tree.nodes[`${bills.tree.prefix}${selNode.data.orgID}`],
+                    selMatch = getMatchContent(stdNode),
+                    isMatched = false;
+                for( let billsNode of billsNodes) {
+                    let billsMatch = getMatchContent(billsNode);
+                    if (selMatch === billsMatch) {//只进行一次成功匹配
+                        matchNode = billsNode;
+                        isMatched = true;
+                        if (selNode.children.length === 0) {//成功匹配且为选中的最底节点,则为自动定位节点
+                            locateNode = matchNode;
+                        }
+                        break;
+                    }
+                }
+                if (isMatched && canRecursive(matchNode)) {//匹配成功,且该匹配到的节点可插入子项,递归匹配子项
+                    comparePeer(matchNode, matchNode.children, selNode.children);
+                } else if (!isMatched) { //匹配不成功,其节点与该层清单节点同层,根据编码插入同层数组中
+                    let pos = insertPos(peerNodes, selNode);
+                    if (pos >= 0) {
+                        peerNodes.splice(pos, 0, selNode);
+                    }
+                }
+            }
+            //同层节点比清单树节点多了,说明在该层有选中节点插入清单树中
+            if (peerNodes.length > billsNodes.length) {
+                let updateData = getUpdateDataFromPeer(parentNode, peerNodes, billsNodes, selNodes);
+                postData = postData.concat(updateData);
+            }
+        }
+    }
+
+
+
+
     //项目指引类型
     const itemType = {
         job: 0,

+ 3 - 1
web/building_saas/main/js/views/std_bills_lib.js

@@ -2,7 +2,9 @@
  * Standard Bills Lib
  * Created by Mai on 2017/5/16.
  */
-
+/*
+* 废弃的
+* */
 var billsLibObj = {
     doAfterLoadBills: null, //外部设置拉取清单数据后的回调
     stdBillsTree: null,