浏览代码

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

zhongzewei 7 年之前
父节点
当前提交
50a8a2d548

+ 1 - 0
.gitignore

@@ -4,5 +4,6 @@ dist/
 .idea/
 tmp/*.xlsx
 tmp/*.pdf
+tmp/*.jsp
 test/unit/logs
 *.log

+ 101 - 23
modules/main/controllers/bills_controller.js

@@ -1,9 +1,15 @@
 /**
  * Created by jimiz on 2017/4/7.
  */
+let mongoose = require('mongoose');
 var billsData = require('../models/bills');
+let ration_model = require('../models/ration');
 let ProjectsData = require('../../pm/models/project_model').project;
 let logger = require("../../../logs/log_helper").logger;
+let quantity_detail = require("../facade/quantity_detail_facade");
+let ration_glj = mongoose.model('ration_glj');
+let ration_coe = mongoose.model('ration_coe');
+
 //统一回调函数
 var callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
@@ -84,6 +90,8 @@ module.exports = {
             data = JSON.parse(data);
             let tasks = generateSingleDeleteTasks(data);
             let resultData= await billsData.model.bulkWrite(tasks);
+            //删除工程量明细
+            await quantity_detail.deleteByQuery({projectID: data.projectID, billID: data.ID}) ;
             result.data=resultData;
         }catch (err){
             logger.err(err);
@@ -91,41 +99,111 @@ module.exports = {
             result.message = err.message;
         }
         res.json(result);
+    },
+    multiDelete:async function(req, res){
+        let result={
+            error:0
+        };
+        try {
+            let data = req.body.data;
+            data = JSON.parse(data);
+            result.data=await doBillsOrRationsDelete(data);
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        res.json(result);
     }
 
 };
 
+async function doBillsOrRationsDelete(data) {
+    let billTask = [];
+    let deleteBillIDs = [];
+    let rationTask=[];
+    let deleteRationIDs=[];
+    let qd_query=null;
+    let sub_query=null;
+    if(data['bills']){
+        billTask = generateUpdateTasks(data['bills'],data.projectID,data.user_id);
+        for(let b_key in data['bills']){
+            if(data['bills'][b_key]===true){
+                deleteBillIDs.push(b_key+'');
+            }
+        }
+        if(deleteBillIDs.length>0){
+            qd_query={projectID: data.projectID, billID: {"$in": deleteBillIDs}};
+        }
+    }
+    if(data['ration']){
+        rationTask = generateUpdateTasks(data['ration'],data.projectID,data.user_id);
+        for(let r_key in data['ration']){
+            if(data['ration'][r_key]===true){
+                deleteRationIDs.push(r_key+'');
+            }
+        }
+        if(deleteRationIDs.length>0){
+            if(qd_query==null){//说明没删除清单
+                qd_query={projectID: data.projectID, rationID: {"$in": deleteRationIDs}};
+            }else {
+                qd_query={
+                    "$or":[
+                        {projectID: data.projectID, billID: {"$in": deleteBillIDs}},
+                        {projectID: data.projectID, rationID: {"$in": deleteRationIDs}}
+                    ]
+                }
+            }
+            sub_query={projectID: data.projectID, rationID: {"$in": deleteRationIDs}};
+        }
+    }
+    //先删除工程量明细
+    if(qd_query!=null){
+        await quantity_detail.deleteByQuery(qd_query) ;
+    }
+    if(sub_query!=null){
+        await ration_coe.deleteMany(sub_query);//删除附注条件
+        await ration_glj.deleteMany(sub_query);//删除定额工料机
+    }
+    if(rationTask.length>0){
+        await  ration_model.model.bulkWrite(rationTask);//删除定额
+    }
+    if(billTask.length>0){
+        await billsData.model.bulkWrite(billTask);//删除清单
+    }
+    return 'success';
+}
+
+
 
 function  generateSingleDeleteTasks(data) {
-    let tasks=[];
     let updateData = data.updateData;
+    updateData[data.ID]=true;
+    let tasks = generateUpdateTasks(updateData,data.projectID,data.user_id);
+    return tasks;
+}
+
+function  generateUpdateTasks(data,projectID,user_id) {
+    let tasks=[];
+    let updateData = data;
+    let deleteInfo={deleted: true, deleteDateTime: new Date(), deleteBy: user_id};
     for(let key in updateData){
-        if(updateData[key]==true){
-            let deleteInfo={deleted: true, deleteDateTime: new Date(), deleteBy: data.user_id};
-            let task={
-                updateOne:{
-                    filter:{
-                        ID:key,
-                        projectID:data.projectID
-                    },
-                    update:{
-                        deleteInfo:deleteInfo
-                    }
+        let task={
+            updateOne:{
+                filter:{
+                    ID:key,
+                    projectID:projectID
                 }
+            }
+        };
+        if(updateData[key]===true){
+            task.updateOne.update={
+                deleteInfo:deleteInfo
             };
-            tasks.push(task);
         }else {
-            let task={
-                updateOne:{
-                    filter:{
-                        ID:key,
-                        projectID:data.projectID
-                    },
-                    update:updateData[key]
-                }
-            };
-            tasks.push(task);
+            task.updateOne.update=updateData[key];
         }
+        tasks.push(task);
     }
     return tasks;
 }

+ 6 - 1
modules/main/facade/quantity_detail_facade.js

@@ -28,7 +28,8 @@ module.exports={
     updateRegex:updateRegex,
     insertRecode:insertRecode,
     deleteRecode:deleteRecode,
-    swapRow:swapRow
+    swapRow:swapRow,
+    deleteByQuery:deleteByQuery
 };
 
 let operationMap={
@@ -543,6 +544,10 @@ function deleteByBill(data) {
     }
 }
 
+async function deleteByQuery(query) {
+   return await  quantity_detail_model.deleteMany(query);
+}
+
 function quantityEditChecking(doc,type,functions) {
     if(doc.updateType == commonConsts.UT_UPDATE&&doc.updateData.hasOwnProperty('isFromDetail')&&doc.updateData.isFromDetail==0) {
         if(type=='bills'){

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

@@ -12,8 +12,10 @@ module.exports = function (app) {
     billsRouter.post('/updateCharacterContent', billsController.updateCharacterContent);//特征及内容更新 zhong 2017-9-1
     // 批量更新bill数据
     billsRouter.post('/updateBill', billsController.updateBill);
-    //按条件更新清单
+    //删除单个清单,不删除子项
     billsRouter.post('/singleDelete',billsController.singleDelete);
+    billsRouter.post('/multiDelete',billsController.multiDelete);
+
     app.use('/bills', billsRouter);
 };
 

+ 33 - 8
modules/pm/models/project_model.js

@@ -662,18 +662,43 @@ ProjectsDAO.prototype.updateProjectProperty = async function(projectId, property
 };
 
 // CSL, 2018-01-11 获取指定ID节点(如单项工程、建设项目)下所有单位工程的各项汇总金额,用于报表计算汇总。
-ProjectsDAO.prototype.getSummaryFees = function (projectID, callback) {
-    Projects.find({'ParentID': projectID}, ['-_id','-property'], function (err, datas) {
-        if (err) {
-            callback(1, '查找单位工程失败');
-        } else {
+ProjectsDAO.prototype.getSummaryFees = async function (ID) {
+    async function getProject(ID){
+        return await Projects.findOne({'ID': ID, deleteInfo: null}, need);
+    };
+    async function getChildrenDocs(IDs){
+        return await Projects.find({'ParentID': {"$in":IDs}, deleteInfo: null}, need);
+    };
+    async function getEgrIDs(ID){
+        let _docs = await Projects.find({'ParentID': ID, deleteInfo: null}, ['ID', '-_id']);
+        let arr = [];
+        for (let doc of _docs){
+            arr.push(doc.ID);
+        };
+        return arr;
+    };
 
-            callback(0, datas);
-        }
-    });
+    let need = ['ID', 'ParentID', 'NextSiblingID', 'name', 'projType',
+        'fullFolder', 'summaryFees', '-_id'];
+    let _doc = await getProject(ID);
+    if (!_doc) return _doc;
+
+    if (_doc.projType.sameText('Engineering')){
+        return await getChildrenDocs([ID]);
+    }
+    else if (_doc.projType.sameText('Project')){
+        let eIDs = await getEgrIDs(ID);
+        return await getChildrenDocs(eIDs);
+    }
+    else{
+        return _doc;
+    };
 };
 
 
+
+
+
 module.exports ={    project: new ProjectsDAO(),
     projType: projectType,
     fileType: fileType

+ 2 - 2
modules/pm/models/templates/bills_template_model.js

@@ -25,7 +25,7 @@ class BillsTemplateModel extends BaseModel {
      */
     async getTemplateData (valuationId, engineering) {
         // 筛选字段
-        let field = {_id: 1, valuationId: 1, ID: 1, ParentID: 1, NextSiblingID: 1, code: 1, name: 1, unit: 1, flags: 1};
+        let field = {_id: 1, valuationId: 1, ID: 1, ParentID: 1, NextSiblingID: 1, code: 1, name: 1, unit: 1, flags: 1, calcBase: 1};
         let data = await this.findDataByCondition({valuationId: valuationId, engineering: engineering}, field, false);
 
         return data === null ? [] : data;
@@ -39,7 +39,7 @@ class BillsTemplateModel extends BaseModel {
      */
     async getTemplateDataForNewProj (valuationId, engineering) {
         // 筛选字段
-        let field = {_id: 0, ID: 1, ParentID: 1, NextSiblingID: 1, code: 1, name: 1, unit: 1, flags: 1,type:1};
+        let field = {_id: 0, ID: 1, ParentID: 1, NextSiblingID: 1, code: 1, name: 1, unit: 1, flags: 1,type:1, calcBase: 1};
         let data = await this.findDataByCondition({valuationId: valuationId, engineering: engineering}, field, false);
 
         return data === null ? [] : data;

+ 2 - 1
modules/pm/models/templates/schemas/bills_template.js

@@ -31,7 +31,8 @@ let BillsTemplateSchema = {
     valuationId: String,
     // 工程专业
     engineering: Number,
-    type:Number
+    type:Number,
+    calcBase: String
 };
 
 let model = mongoose.model(collectionName, new Schema(BillsTemplateSchema, {versionKey: false, collection: collectionName}));

+ 2 - 1
modules/ration_glj/facade/glj_calculate_facade.js

@@ -103,7 +103,7 @@ async function calculateQuantityPerGLJ(glj,index,coeList,assList,adjustState,noN
         if(noNeedCal==null){
             if(!glj._doc.hasOwnProperty('customQuantity')||glj.customQuantity==null||glj.customQuantity==""){
                 quantity =scMathUtil.roundTo(parseFloat(glj.rationItemQuantity),-decimal);
-                quantity =calculateAss(quantity,assList,glj);
+                quantity =scMathUtil.roundTo(calculateAss(quantity,assList,glj),-decimal);
                 quantity = calculateQuantityByCoes(quantity,coeList,glj);
             }else {
                 quantity = glj.customQuantity;
@@ -111,6 +111,7 @@ async function calculateQuantityPerGLJ(glj,index,coeList,assList,adjustState,noN
             }
             let customerCoe = _.last(coeList);
             if(customerCoe&&customerCoe.isAdjust==1){
+                quantity = scMathUtil.roundToString(quantity,decimal);
                 quantity = calculateQuantityByCustomerCoes(quantity,customerCoe,glj);
             }
             result.doc.quantity =scMathUtil.roundToString(quantity,decimal);

+ 20 - 5
modules/ration_glj/facade/ration_glj_facade.js

@@ -176,11 +176,14 @@ async function getInfoFromProjectGLJ(ration_glj) {
     try {
         let projectGljModel = new GLJListModel();
         let result = await projectGljModel.addList(data);
+        let typeString = result.type+"";
         ration_glj.marketPrice = result.unit_price.market_price;
         ration_glj.adjustPrice = result.unit_price.base_price;
         ration_glj.basePrice = result.unit_price.base_price;
         ration_glj.projectGLJID = result.id;
-        ration_glj.isEstimate = result.is_evaluate;
+        if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估
+            ration_glj.isEstimate = result.is_evaluate;
+        }
         if (result.hasOwnProperty('subList') && result.subList.length > 0) {
             ration_glj.subList = getMixRatioShowDatas(result.subList);
         }
@@ -591,12 +594,15 @@ async function addGLJ(rgList) {
     for (let g of rgList) {
         let projectGljModel = new GLJListModel();
         let result = await projectGljModel.addList(getGLJSearchInfo(g));
+        let typeString = result.type+'';
         g.marketPrice = result.unit_price.market_price;
         g.adjustPrice = result.unit_price.base_price;
         g.basePrice = result.unit_price.base_price;
         g.isAdd = result.unit_price.is_add;
         g.projectGLJID = result.id;
-        g.isEstimate = result.is_evaluate;
+        if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估
+            g.isEstimate = result.is_evaluate;
+        }
         g.ID = uuidV1();
         if (result.hasOwnProperty('subList') && result.subList.length > 0) {
             g.subList = getMixRatioShowDatas(result.subList);
@@ -621,6 +627,7 @@ async function replaceGLJ(data) {
     let rdata = {};
     let projectGljModel = new GLJListModel();
     let result = await projectGljModel.addList(getGLJSearchInfo(data));
+    let typeString = result.type+'';
     data.projectGLJID = result.id;
     let updateResult = await ration_glj.findOneAndUpdate({ID: data.ID, projectID: data.projectID}, data);//更新定额工料机
     //组装回传数据
@@ -628,7 +635,9 @@ async function replaceGLJ(data) {
     data.adjustPrice = result.unit_price.base_price;
     data.basePrice = result.unit_price.base_price;
     data.isAdd = result.unit_price.is_add;
-    data.isEstimate = result.is_evaluate;
+    if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估
+        data.isEstimate = result.is_evaluate;
+    }
     if (result.hasOwnProperty('subList') && result.subList.length > 0) {
         data.subList = getMixRatioShowDatas(result.subList);
     }
@@ -644,6 +653,7 @@ async function mReplaceGLJ(data) {
     let mresult = {};
     let projectGljModel = new GLJListModel();
     let result = await projectGljModel.addList(getGLJSearchInfo(data.doc));
+    let typeString = result.type+'';
     data.doc.projectGLJID = result.id;
     let rationList = await ration_glj.distinct('rationID', data.query);
     let updateResult = await ration_glj.update(data.query, data.doc, {multi: true});
@@ -652,7 +662,9 @@ async function mReplaceGLJ(data) {
     data.doc.adjustPrice = result.unit_price.base_price;
     data.doc.basePrice = result.unit_price.base_price;
     data.doc.isAdd = result.unit_price.is_add;
-    data.doc.isEstimate = result.is_evaluate;
+    if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估
+        data.doc.isEstimate = result.is_evaluate;
+    }
     if (result.hasOwnProperty('subList') && result.subList.length > 0) {
         data.doc.subList = getMixRatioShowDatas(result.subList);
     }
@@ -759,12 +771,15 @@ async function insertGLJAsRation(data) {
         let p_glj = getGLJSearchInfo(glj);
         let projectGljModel = new GLJListModel();
         let result = await projectGljModel.addList(p_glj);//逐条添加到项目工料机
+        let typeString = result.type+'';
         glj.marketPrice = result.unit_price.market_price;
         glj.adjustPrice = result.unit_price.base_price;
         glj.basePrice = result.unit_price.base_price;
         glj.isAdd = result.unit_price.is_add;
         glj.projectGLJID = result.id;
-        glj.isEstimate = result.is_evaluate;
+        if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估
+            glj.isEstimate = result.is_evaluate;
+        }
     }
     await ration.insertMany(gljList);
     console.log(gljList);

+ 1 - 1
modules/ration_glj/models/ration_glj_temp.js

@@ -139,7 +139,7 @@ var rationItemSchema = mongoose.Schema({
 mongoose.model("std_ration_lib_ration_items",rationItemSchema, "std_ration_lib_ration_items");
 
 let billsSchema = new Schema({
-    ID: Number,
+    ID: String,
     ParentID: Number,
     NextSiblingID: Number,
     projectID: Number,

+ 13 - 1
public/web/id_tree.js

@@ -560,6 +560,19 @@ var idTree = {
         };
 
         Tree.prototype.delete = function (node) {
+            var success = false;
+            success=this.cascadeRemove(node);
+            tools.sortTreeItems(this);
+            return success;
+        };
+        Tree.prototype.m_delete=function(nodes){
+            for(let node of nodes){
+                this.cascadeRemove(node);
+            }
+            tools.sortTreeItems(this);
+            return true;
+        };
+        Tree.prototype.cascadeRemove = function (node){
             var success = false, that = this;
             var deleteIdIndex = function (nodes) {
                 nodes.forEach(function (node) {
@@ -580,7 +593,6 @@ var idTree = {
                 } else {
                     this.roots.splice(node.siblingIndex(), 1);
                 }
-                tools.sortTreeItems(this);
                 success = true;
             }
             return success;

+ 10 - 8
public/web/treeDataHelper.js

@@ -7,14 +7,14 @@ let tree_Data_Helper = {
     buildTreeNodeDirectly: function(data) {
         let topArr = [], rst = [], tmpNodes = {}, prefix = "id_";
         let private_getTopNode = function (idArr) {
-            let rst = null;
+            let tmpNodeRst = null;
             for (let i = 0; i < idArr.length; i++) {
-                if (tmpNodes[prefix + idArr[i]][ADHOC_PRE_ID] === EMPTY_ID_VAL) {
-                    rst = tmpNodes[prefix + idArr[i]];
+                if (parseInt(tmpNodes[prefix + idArr[i]][ADHOC_PRE_ID]) === EMPTY_ID_VAL) {
+                    tmpNodeRst = tmpNodes[prefix + idArr[i]];
                     break;
                 }
             }
-            return rst;
+            return tmpNodeRst;
         };
         let private_buildNodeData = function(parentItem, idArr) {
             let iter = [], nextNode = private_getTopNode(idArr);
@@ -37,15 +37,17 @@ let tree_Data_Helper = {
             data[i][ADHOC_PRE_ID] = EMPTY_ID_VAL;
             data[i][SUB_ID] = [];
             data[i][CHILDREN_NODE] = [];
-            if (data[i][P_ID] === EMPTY_ID_VAL) {
+            if (parseInt(data[i][P_ID]) === EMPTY_ID_VAL) {
                 topArr.push(data[i][NODE_ID]);
             }
         }
         for (let i = 0; i < data.length; i++) {
-            if (data[i][NEXT_ID] !== EMPTY_ID_VAL) {
-                tmpNodes[prefix + data[i][NEXT_ID]][ADHOC_PRE_ID] = data[i][NODE_ID];
+            if (parseInt(data[i][NEXT_ID]) !== EMPTY_ID_VAL) {
+                if (tmpNodes[prefix + data[i][NEXT_ID]] !== undefined){
+                    tmpNodes[prefix + data[i][NEXT_ID]][ADHOC_PRE_ID] = data[i][NODE_ID];
+                }
             }
-            if (data[i][P_ID] !== EMPTY_ID_VAL) {
+            if (parseInt(data[i][P_ID]) !== EMPTY_ID_VAL) {
                 tmpNodes[prefix + data[i][P_ID]][SUB_ID].push(data[i][NODE_ID]);
             }
         }

+ 16 - 0
public/web/tree_sheet/tree_sheet_controller.js

@@ -56,6 +56,22 @@ var TREE_SHEET_CONTROLLER = {
                 }
             }
         };
+        controller.prototype.m_delete = function (nodes) {//删除选中的多行节点
+            var that = this, sels = this.sheet.getSelections();
+            if (this.tree.selected) {
+                if (this.tree.m_delete(nodes)) {
+                    TREE_SHEET_HELPER.massOperationSheet(this.sheet, function () {
+                        let rowCount = 0;
+                        for(let node of nodes){
+                            rowCount = rowCount+node.posterityCount() + 1;
+                        }
+                        that.sheet.deleteRows(sels[0].row, rowCount);
+                        that.setTreeSelected(that.tree.items[sels[0].row]);
+                    });
+                    cbTools.refreshFormulaNodes();
+                }
+            }
+        };
         controller.prototype.singleDelete = function () {//只删除当前节点,不删除子节点
             var that = this, sels = this.sheet.getSelections();
             if (this.tree.selected) {

+ 1 - 1
test/unit/reports/test_tpl_09_1.js

@@ -136,7 +136,7 @@ test('测试 - 测试模板啦: ', function (t) {
                     let maxPages = printCom.totalPages;
                     let pageRst = printCom.outputAsSimpleJSONPageArray(rptTpl, tplData, 1, maxPages, defProperties);
                     if (pageRst) {
-                        // fsUtil.wirteObjToFile(pageRst, "D:/GitHome/ConstructionCost/tmp/testBuiltPageResult.js");
+                        // fsUtil.writeObjToFile(pageRst, "D:/GitHome/ConstructionCost/tmp/testBuiltPageResult.jsp");
                     } else {
                         console.log("oh! no pages were created!");
                     }

+ 1 - 1
web/building_saas/main/js/controllers/project_controller.js

@@ -104,7 +104,7 @@ ProjectController = {
     },
     addRootBill:function (project, sheetController) {//添加大项费用
         if (!project || !sheetController) { return null; }
-        this.addSpecialBill(project, sheetController,null, null,true,billType.DXFY);
+        this.addSpecialBill(project, sheetController,null, project.mainTree.selected.nextSibling,true,billType.DXFY);
     },
     addFB:function(project, sheetController) {//添加分部
         if (!project || !sheetController) { return null; }

+ 171 - 6
web/building_saas/main/js/models/bills.js

@@ -237,19 +237,19 @@ var Bills = {
             return this.tree.delete(node);
         };
 
-        bills.prototype.singleDeleteBills=function(node,controller){
+        bills.prototype.singleDeleteBills=function(node,controller){//只删除选中的分部,不删除其子项
             let updateData = {};
             let updateNode={};
+            let newParent=null;
             let me = this;
             if(node){
-                updateData[node.data.ID]=true;
                 if(node.children.length>0){//有子项
                     if(node.preSibling){//有前兄弟,则子项变成前兄弟的子项
                         if(node.preSibling.children.length>0){//前兄弟有子项,
                             let preNode = node.preSibling.children[node.preSibling.children.length-1];
                             updateData[preNode.data.ID]={
                                 NextSiblingID:node.children[0].data.ID
-                            }
+                            };
                             updateNode[preNode.data.ID] = preNode;
                         }
                         for(let i=0;i<node.children.length;i++){
@@ -258,6 +258,7 @@ var Bills = {
                             };
                             updateNode[node.children[i].data.ID]=node.children[i];
                         }
+                        newParent=node.preSibling;
                     }else {//没有前兄弟,则子项升一级
                         let parent = node.nextSibling.parent;
                         for(let i=0;i<node.children.length;i++){
@@ -273,12 +274,11 @@ var Bills = {
                             }
                             updateNode[node.children[i].data.ID]=node.children[i];
                         }
+                        newParent=parent;
                     }
                 }
                 $.bootstrapLoading.start();
-                CommonAjax.post("/bills/singleDelete", {updateData:updateData,projectID:node.data.projectID,user_id:userID}, function () {
-                    controller.singleDelete();//删除树节点
-                    me.tree.singleDelete(node);
+                CommonAjax.post("/bills/singleDelete", {updateData:updateData,projectID:node.data.projectID,user_id:userID,ID:node.data.ID}, function () {
                     //更新缓存
                     console.log(updateNode);
                     _.remove(me.datas,{'ID':node.data.ID});
@@ -288,6 +288,9 @@ var Bills = {
                             updateNode[n_key].data[u_key] =updateDoc[u_key];
                         }
                     }
+                    project.calcProgram.calcAndSave(newParent);
+                    controller.singleDelete();//删除树节点
+                    me.tree.singleDelete(node.source);
                     $.bootstrapLoading.end();
                 }, function () {
                     $.bootstrapLoading.end();
@@ -482,6 +485,168 @@ var Bills = {
                 return false;
             }
         };
+        bills.prototype.calcEngineeringCostNode=function(controller){
+            let roots =  controller.tree.roots;
+            for(let root of roots){
+                if(project.Bills.isEngineeringCost(root)==true){
+                    project.calcProgram.calcAndSave(root);
+                    break;
+                }
+            }
+        };
+        bills.prototype.getEngineeringCostNode=function(controller){//取工程造价节点
+            let roots =  controller.tree.roots;
+            for(let root of roots){
+                if(project.Bills.isEngineeringCost(root)==true){
+                    return root;
+                }
+            }
+        };
+        bills.prototype.deleteSelectedNode=function(){//删除选中单行时的节点
+            let controller = projectObj.mainController, project = projectObj.project;
+            let selected = controller.tree.selected, parent = selected.parent;
+            if (selected) {
+                if (selected.sourceType === project.Bills.getSourceType()) {
+                    if (cbTools.isUsedByFormula(selected)){
+                        alert('该清单行被其它公式结点引用,不允许删除!');
+                        return;
+                    }
+                    project.Bills.deleteBills(selected.source);
+                    controller.delete();
+                } else if (selected.sourceType === project.Ration.getSourceType()) {
+                    project.Ration.delete(selected.source);
+                    controller.delete();
+                }else if(selected.sourceType==ModuleNames.ration_glj){
+                    project.ration_glj.updataOrdelete(selected.source);
+                }
+                if(parent){
+                    projectObj.converseCalculateBills(parent);
+                }else { //删除的是大项费用要重新计算工程造价节点
+                    project.Bills.calcEngineeringCostNode(controller);
+                }
+            }
+        };
+        bills.prototype.deleteSelectedNodes=function() {//删除选中多行时的节点
+            let controller = projectObj.mainController, project = projectObj.project;
+            let selected = controller.tree.selected, parent = selected.parent;
+            let me = this;
+            let idTreeMap = {};
+            let mainTreeMap = {};
+            let mainNodes = [];
+            let idTreeNodes=[];
+            let updateData={};
+            let includeRootNode=false;
+            let parentNodes = [];
+            let selection = projectObj.mainSpread.getActiveSheet().getSelections()[0];
+            for(let i =0;i<selection.rowCount;i++){
+                let tem_node = controller.tree.items[selection.row+i];
+                if(i==0){//第一个直接添加;
+                    mainTreeMap[tem_node.getID()] = tem_node;
+                    mainNodes.push(tem_node);
+                    if(tem_node.sourceType == project.Bills.getSourceType()){
+                        idTreeMap[tem_node.source.getID()] = tem_node.source;
+                        idTreeNodes.push(tem_node.source);
+                    }
+                }else {
+                    this.setNodeToMapAndArray(tem_node,mainTreeMap,mainNodes);
+                    if(tem_node.sourceType == project.Bills.getSourceType()){
+                        this.setNodeToMapAndArray(tem_node.source,idTreeMap,idTreeNodes);
+                    }
+                }
+            }
+            let updateNodes = [];//需要删除的所有节点;
+            let billsUpdate={};
+            let rationUpdate = {};
+            let updateBill = false;
+            let updateRation = false;
+            for(let m_node of mainNodes){
+                if(m_node.sourceType == project.Bills.getSourceType()){
+                    if(m_node.preSibling){
+                        billsUpdate[m_node.preSibling.data.ID] = {
+                            NextSiblingID:m_node.nextSibling?m_node.nextSibling.data.ID:-1
+                        };
+                        updateBill=true;
+                    }
+                }
+                if(m_node.parent==null&&includeRootNode==false){//删除的节点中包含了根节点,要重新计算工程造价,并且工程造价节点只要加入一次就行了
+                    parentNodes.push(me.getEngineeringCostNode(controller));
+                    includeRootNode=true
+                }else {
+                    parentNodes.push(m_node.parent);
+                }
+                updateNodes.push(m_node);
+                controller.tree.getAllSubNode(m_node,updateNodes);
+            }
+            for(let u_node of updateNodes){
+                if(u_node.sourceType == project.Bills.getSourceType()){
+                    billsUpdate[u_node.data.ID] = true;
+                    updateBill=true;
+                }
+                if(u_node.sourceType == project.Ration.getSourceType()){
+                    rationUpdate[u_node.data.ID] = true;
+                    updateRation = true;
+                }
+            }
+            updateBill==true?updateData['bills']=billsUpdate:'';
+            updateRation==true?updateData['ration']=rationUpdate:'';
+            updateData.projectID = selected.data.projectID;
+            updateData.user_id = userID;
+            $.bootstrapLoading.start();
+            CommonAjax.post("/bills/multiDelete", updateData, function () {
+                let quantity_detail_datas = project.quantity_detail.datas;
+                let ration_datas = project.Ration.datas;
+                let ration_glj_datas = project.ration_glj.datas;
+                let ration_coe_datas = project.ration_coe.datas;
+                let nodes = controller.tree.nodes;
+                let prefix = controller.tree.prefix;
+                //更新缓存
+                if(updateData['bills']){//更新bills
+                    for(let b_key in updateData['bills']){
+                        if(updateData['bills'][b_key]===true){//删除清单和工程量明细
+                            _.remove(me.datas,{'ID':b_key});
+                            _.remove(quantity_detail_datas,{'billID':b_key});
+                        }else {//更新清单属性
+                            for(let p_key in updateData['bills'][b_key]){
+                                nodes[prefix+b_key].data[p_key] = updateData['bills'][b_key][p_key]
+                            }
+                        }
+                    }
+                }
+                if(updateData['ration']){
+                    for(let r_key in updateData['ration']){//定额只有删除,没有更新
+                        _.remove(ration_datas,{'ID':r_key});
+                        _.remove(quantity_detail_datas,{'rationID':r_key});
+                        _.remove(ration_glj_datas,{'rationID':r_key});
+                        _.remove(ration_coe_datas,{'rationID':r_key});
+                    }
+                }
+                controller.m_delete(mainNodes);//删除树节点
+                me.tree.m_delete(idTreeNodes);
+                //重新计算
+                project.calcProgram.calcBillsAndSave(parentNodes);
+                $.bootstrapLoading.end();
+            }, function () {
+                $.bootstrapLoading.end();
+            });
+        };
+        bills.prototype.setNodeToMapAndArray=function (node,map,array) {
+            let nodeID = node.getID();
+            if(map[nodeID]==undefined||map[nodeID]==null){
+                newMap(node,node.parent,map,array)
+            }
+            function newMap(node,parent,map,array) {
+                let nodeID =node.getID();
+                if(parent==null){//说明已经是最顶层了
+                    map[nodeID]=node;
+                    array.push(node);
+                }else {
+                    let parentID = parent.getID();
+                    if(map[parentID]==undefined||map[parentID]==null){
+                        newMap(node,parent.parent,map,array);
+                    }
+                }
+            }
+        };
         return new bills(project);
     }
 };

+ 23 - 3
web/building_saas/main/js/models/cache_tree.js

@@ -366,6 +366,12 @@ var cacheTree = {
         };
         Tree.prototype.delete = function (node) {
             var success = false;
+            success=this.cascadeRemove(node);
+            this.sortTreeItems();
+            return success;
+        };
+        Tree.prototype.cascadeRemove = function (node) {
+            var success = false;
             var me = this;
             var removeNodes = function (node) {
                 delete me.nodes[me.prefix + node.getID()];
@@ -385,11 +391,19 @@ var cacheTree = {
                 } else {
                     this.roots.splice(node.siblingIndex(), 1);
                 }
-                this.sortTreeItems();
                 success = true;
             }
             return success;
         };
+
+        Tree.prototype.m_delete = function (nodes) {//删除多个节点,级联删除
+            for(let node of nodes){
+                this.cascadeRemove(node);
+            }
+            this.sortTreeItems();
+            return true;
+        };
+
         Tree.prototype.singleDelete = function (node) {//只删除当前节点,不删除子节点
             var success = false;
             var me = this;
@@ -418,9 +432,15 @@ var cacheTree = {
                     success = true;
                 }
             }
-            return success;
-
+            return success
+        };
+        Tree.prototype.getAllSubNode = function (node,nodeArray) {
+          for(let c of node.children){
+              nodeArray.push(c);
+              this.getAllSubNode(c,nodeArray);
+          }
         };
+        
         return new Tree(owner);
     }
 };

+ 73 - 9
web/building_saas/main/js/models/calc_program.js

@@ -166,7 +166,7 @@ let cpFeeTypes = [
     {type: 'machineDiff', name: '机械价差'},
     {type: 'adjustLabour', name: '调整人工费'},
     {type: 'adjustMachineLabour', name: '调整机上人工费'},
-    {type: 'zangu', name: '暂估'},
+    {type: 'estimate', name: '暂估'},
     {type: 'fee1', name: '甲供材料费'},
     // 模拟用户新增
     {type: 'common', name: '工程造价'}
@@ -751,8 +751,8 @@ class CalcProgram {
         for (let node of treeNodes){delete node.changed};
         projectObj.mainController.refreshTreeNode(treeNodes);
 
-        if (activeSubSheetIs(subSheetIndex.ssiCalcProgram)) {
-            calcProgramObj.showData(me.project.mainTree.selected, false);
+        if (activeSubSheetIs(subSheetIndex.ssiCalcProgram)) {    // 批量树结点计算后,计算程序早已今非昔比,所以这里要重新计算一下。
+            calcProgramObj.showData(me.project.mainTree.selected, true);
         };
     };
 
@@ -774,6 +774,7 @@ class CalcProgram {
         };
 
         function checkFee(treeNode, feeObj){
+            if (!feeObj) return;
             if (feeObj.fieldName == '') return;
 
             if (!treeNode.data.feesIndex[feeObj.fieldName]){
@@ -805,6 +806,66 @@ class CalcProgram {
             return ['labour', 'material', 'machine', 'mainMaterial', 'equipment'].indexOf(type) > -1;
         };
 
+        function estimateFee(treeNode){
+            if (!treeNode.data.gljList) return undefined;
+
+            let eTypes = [
+                gljType.GENERAL_MATERIAL, gljType.MAIN_MATERIAL, gljType.EQUIPMENT,
+                gljType.CONCRETE, gljType.MORTAR, gljType.MIX_RATIO,
+                gljType.COMMERCIAL_CONCRETE, gljType.COMMERCIAL_MORTAR];
+            let eDetailTypes = [gljType.MAIN_MATERIAL, gljType.CONCRETE, gljType.MORTAR, gljType.MIX_RATIO];
+
+            let GLJObjs = [];
+            for (let glj of treeNode.data.gljList) {
+                if (eTypes.indexOf(glj.type) >= 0) {
+                    if (glj.isEstimate){
+                        GLJObjs.push({code: glj.code, quantity: glj.quantity, marketPrice: glj.marketPrice});
+                    }
+                    else{   // 组成物
+                        if (eDetailTypes.indexOf(glj.type) >= 0){
+                            let mds = projectObj.project.composition.getCompositionByGLJ(glj);
+                            if (!mds) mds = [];
+                            for (let md of mds){
+                                if (md.isEstimate){
+                                    let isExist = false;
+                                    let mdQ = (parseFloatPlus(glj.quantity) * parseFloatPlus(md.consumption)).toDecimal(decimalObj.process);
+
+                                    for (let obj of GLJObjs){
+                                        if (md.code == obj.code){
+                                            isExist = true;
+                                            obj.quantity = (parseFloatPlus(obj.quantity) + mdQ).toDecimal(decimalObj.process);
+                                            break;
+                                        }
+                                    };
+                                    if (!isExist)
+                                        GLJObjs.push({code: md.code, quantity: mdQ, marketPrice: md.marketPrice});
+                                }
+                            }
+                        }
+                    }
+                };
+            };
+
+            let sumU = 0, sumT = 0, unitFee = 0, totalFee = 0;
+            for (let obj of GLJObjs){
+                sumU = sumU + (parseFloatPlus(obj.quantity) * parseFloatPlus(obj.marketPrice)).toDecimal(decimalObj.process);
+                sumU = sumU.toDecimal(decimalObj.process);
+
+                let q = (parseFloatPlus(obj.quantity) * parseFloatPlus(treeNode.data.quantity)).toDecimal(decimalObj.process);
+                sumT = sumT + (q * parseFloatPlus(obj.marketPrice)).toDecimal(decimalObj.process);
+                sumT = sumT.toDecimal(decimalObj.process);
+            };
+            unitFee = sumU.toDecimal(decimalObj.bills.unitPrice);
+            if (projectObj.project.property.zanguCalcMode == zanguCalcType.common){
+                totalFee = (parseFloatPlus(treeNode.data.quantity) * unitFee).toDecimal(decimalObj.bills.totalPrice);
+            }
+            else if (projectObj.project.property.zanguCalcMode == zanguCalcType.gatherMaterial){
+                totalFee = sumT.toDecimal(decimalObj.bills.totalPrice);
+            };
+
+            return {'fieldName': 'estimate', 'unitFee': unitFee, 'totalFee': totalFee};
+        };
+
         // 父清单汇总子项(定额或子清单)的费用类别
         if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees ||
             treeNode.calcType == treeNodeCalcType.ctGatherBillsFees){
@@ -1003,7 +1064,10 @@ class CalcProgram {
 
                     checkFee(treeNode, calcItem);
                 };
-            }
+            };
+
+            checkFee(treeNode, estimateFee(treeNode));
+
         };
 
         if (treeNode.changed && !changedArr.includes(treeNode)) changedArr.push(treeNode);
@@ -1035,11 +1099,11 @@ class CalcProgram {
         return changedNodes;
     };
 
-    /* 计算所有树结点(分3种情况),并返回发生变动的零散的多个树结点。
-    参数取值如下:
-    calcAllType.catAll       计算所有树结点 (不指定参数时的默认值)
-    calcAllType.catBills     计算所有清单 (改变项目属性中清单取费算法时会用到)
-    calcAllType.catRations   计算所有定额、工料机形式的定额、量价,因为它们都走自己的计算程序 (改变人工系数、费率值、工料机单价时会用到) */
+    /* 计算所有树结点(分3种情况),并返回发生变动的零散的多个树结点。参数取值如下:
+        calcAllType.catAll       计算所有树结点 (不指定参数时的默认值)
+        calcAllType.catBills     计算所有清单 (改变项目属性中清单取费算法时会用到)
+        calcAllType.catRations   计算所有定额、工料机形式的定额、量价,因为它们都走自己的计算程序 (改变人工系数、费率值、工料机单价时会用到)
+    */
     calcAllNodes(calcType = calcAllType.catAll){
         let me = this;
         let changedNodes = [];

+ 1 - 0
web/building_saas/main/js/views/glj_view.js

@@ -829,6 +829,7 @@ var gljOprObj = {
             }
             quantity = scMathUtil.roundForObj(quantity, getDecimal("ration.quantity"));//计算前进行4舍5入
             glj.quantity = scMathUtil.roundForObj(glj.quantity, getDecimal("glj.quantity"));
+            console.log(glj.quantity);
             glj.totalQuantity = scMathUtil.roundToString(quantity * glj.quantity, getDecimal("glj.quantity"));
             if (glj.hasOwnProperty('subList')) {//需要计算glj下挂的组成物的总消耗量
                 this.calcMixRationTotalQuantity(glj.subList,glj.totalQuantity);

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

@@ -152,7 +152,9 @@ let MainTreeCol = {
             return MainTreeCol.readOnly.glj(node) || MainTreeCol.readOnly.billsParent(node)
         },
         forMarketPrice: function (node) {
-            return MainTreeCol.readOnly.bills(node) || (node.sourceType === ModuleNames.ration && (node.data.type == rationType.ration||node.data.type== rationType.volumePrice)) || gljOprObj.marketPriceReadOnly(node);
+            return MainTreeCol.readOnly.bills(node) ||
+                (node.sourceType === ModuleNames.ration && node.data.type == rationType.ration) ||
+                gljOprObj.marketPriceReadOnly(node);
         },
         forContain:function (node) {
             return MainTreeCol.readOnly.non_ration(node)&&!MainTreeCol.readOnly.glj(node);

+ 123 - 86
web/building_saas/main/js/views/project_view.js

@@ -63,13 +63,14 @@ var projectObj = {
                 return false;
             }
         };
-        let canDelete = function (node) {
-            if (selected) {
-                if (selected.sourceType === that.project.Bills.getSourceType()) {
-                    if(selected.data.type == billType.DXFY&&selected.data.isAdd!=1){//如果
+        let canDelete = function (node,m_selection) {
+            if (node) {
+                if (node.sourceType === that.project.Bills.getSourceType()) {
+                    if(node.data.type == billType.DXFY&&node.data.isAdd!=1){
                         return false;
                     }
-                }if(selected.sourceType === that.project.ration_glj.getSourceType()){
+                }
+                if(m_selection!=true&&node.sourceType === that.project.ration_glj.getSourceType()){//多选的时候不做这一项判断
                     return false;
                 }
                 return true;
@@ -77,11 +78,32 @@ var projectObj = {
                 return false;
             }
         };
+        let canDelete_m = function (selection) {
+            for(let i =0;i<selection.rowCount;i++){
+                if(tree.items[selection.row+i]==undefined||tree.items[selection.row+i]==null){
+                    return false;
+                }
+                if(i==0&&tree.items[selection.row].sourceType === that.project.ration_glj.getSourceType()){
+                    return false
+                }
+                if(canDelete(tree.items[selection.row+i],true)==false){
+                    return false
+                }
+            }
+            return true
+        };
+
+        let selections = projectObj.mainSpread.getActiveSheet().getSelections();
+        if(selections[0].rowCount==1){//选中单行
+            setButtonValid(canDelete(selected), $('#delete'));
+        }else {
+            setButtonValid(canDelete_m(selections[0]), $('#delete'));
+        }
         setButtonValid(canUpLevel(selected), $('#upLevel'));
         setButtonValid(canDownLevel(selected), $('#downLevel'));
         setButtonValid(selected && (selected.depth() > 0) && selected.canUpMove(), $('#upMove'));
         setButtonValid(selected && (selected.depth() > 0) && selected.canDownMove(), $('#downMove'));
-        setButtonValid(canDelete(selected), $('#delete'));
+
     },
     checkCommonField: function (editingText, colSetting) {
         let value;
@@ -454,13 +476,15 @@ var projectObj = {
                     if(col.data.field ==='quantity'){
                         col.showHint = true;
                     }
-                    // for test digit. CSLAAAAA
-                    if (col.data.field.hasSubStr("totalFee"))
-                       col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.totalPrice, false)
-                    else if (col.data.field.hasSubStr("unitFee"))
-                        col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.unitPrice, false)
-                    else if (col.data.field == "quantity")
-                        col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.quantity, false);
+
+                    // 综合单价、综合合价,小数部分应补0对齐。  CSLAAAAA
+                    if (col.data.field.hasSubStr("common")){
+                        if (col.data.field.hasSubStr("totalFee"))
+                            col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.totalPrice, true)
+                        else if (col.data.field.hasSubStr("unitFee"))
+                            col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.unitPrice, true)
+                    }
+
                 });
 
                 that.mainController = TREE_SHEET_CONTROLLER.createNew(that.project.mainTree, that.mainSpread.getActiveSheet(), that.project.projSetting.mainGridSetting);
@@ -514,7 +538,7 @@ var projectObj = {
                     icon: 'fa-sign-in',
                     disabled: function () {
                         let selected = project.mainTree.selected;
-                        if(selected.sourceType==project.Bills.getSourceType()){
+                        if(selected&&selected.sourceType==project.Bills.getSourceType()){
                             if(selected.data.type==billType.FB){
                                 return false;
                             }
@@ -532,7 +556,11 @@ var projectObj = {
                         ProjectController.addFB(project, controller);
                     },
                     visible: function(key, opt){
-                        return project.Bills.isFBFX(project.mainTree.selected );//不属于分部分项的话隐藏
+                        if(project.mainTree.selected){
+                            return project.Bills.isFBFX(project.mainTree.selected );//不属于分部分项的话隐藏
+                        }else {
+                            return false;
+                        }
                     }
                 },
                 "insertFX": {
@@ -540,7 +568,7 @@ var projectObj = {
                     icon: 'fa-sign-in',
                     disabled: function () {
                         let selected = project.mainTree.selected;
-                        if(selected.sourceType==project.Bills.getSourceType()){
+                        if(selected&&selected.sourceType==project.Bills.getSourceType()){
                             if(selected.data.type==billType.FX){//焦点行是分项,有效显示
                                 return false
                             }
@@ -565,7 +593,11 @@ var projectObj = {
                         ProjectController.addFX(project, controller);
                     },
                     visible: function(key, opt){
-                        return project.Bills.isFBFX(project.mainTree.selected );//不属于分部分项的话隐藏
+                        if(project.mainTree.selected){
+                            return project.Bills.isFBFX(project.mainTree.selected );//不属于分部分项的话隐藏
+                        }else {
+                            return false;
+                        }
                     }
                 },
                 "insertBills": {
@@ -584,7 +616,11 @@ var projectObj = {
                         ProjectController.addBills(project, controller);
                     },
                      visible: function(key, opt){
-                         return  project.Bills.isFBFX(project.mainTree.selected)==true?false:true;//不属于分部分项的话隐藏
+                         if(project.mainTree.selected){
+                             return  project.Bills.isFBFX(project.mainTree.selected)==true?false:true;
+                         }else {
+                             return false;
+                         }
                      }
                 },
                 "insertRation": {
@@ -599,11 +635,14 @@ var projectObj = {
                     },
                     visible: function(key, opt){
                         var selected = project.mainTree.selected;
-                        if(selected.sourceType == ModuleNames.bills&&selected.data.type == billType.DXFY){
-                            return false
-                        }else {
-                            return true
+                        if(selected){
+                            if(selected.sourceType == ModuleNames.bills&&selected.data.type == billType.DXFY){
+                                return false
+                            }else {
+                                return true
+                            }
                         }
+                       return false;
                     }
                 },
                 "insertLJ": {
@@ -618,11 +657,14 @@ var projectObj = {
                     },
                     visible: function(key, opt){
                         var selected = project.mainTree.selected;
-                        if(selected.sourceType == ModuleNames.bills&&selected.data.type == billType.DXFY){
-                            return false
-                        }else {
-                            return true
+                        if(selected){
+                            if(selected.sourceType == ModuleNames.bills&&selected.data.type == billType.DXFY){
+                                return false
+                            }else {
+                                return true
+                            }
                         }
+                       return false;
                     }
                 },
                 "insertGLJ": {
@@ -646,11 +688,14 @@ var projectObj = {
                     },
                     visible: function(key, opt){
                         var selected = project.mainTree.selected;
-                        if(selected.sourceType == ModuleNames.bills&&selected.data.type == billType.DXFY){
-                            return false
-                        }else {
-                            return true
+                        if(selected){
+                            if(selected.sourceType == ModuleNames.bills&&selected.data.type == billType.DXFY){
+                                return false;
+                            }else {
+                                return true;
+                            }
                         }
+                        return false;
                     }
                 },
                 "spr1": '--------',
@@ -662,21 +707,7 @@ var projectObj = {
                         return !selected;
                     },
                     callback: function () {
-                        var selected = controller.tree.selected, parent = selected.parent;
-                        if (selected) {
-                            if (selected.sourceType === project.Bills.getSourceType()) {
-                                if (cbTools.isUsedByFormula(selected)){
-                                    alert('该清单行被其它公式结点引用,不允许删除!');
-                                    return;
-                                };
-                                project.Bills.deleteBills(selected.source);
-                                controller.delete();
-                            } else if (selected.sourceType === project.Ration.getSourceType()) {
-                                project.Ration.delete(selected.source);
-                                controller.delete();
-                            };
-                            projectObj.converseCalculateBills(parent);
-                        }
+                        $("#delete_row").modal({show:true});//弹出删除提示框;
                     }
                 },
                 "spr2":'--------',
@@ -1040,51 +1071,57 @@ $('#delete_row').on('shown.bs.modal', function (e) {
     var showinfo = "确认要删除当前选中行吗?";
     var showN = false;
     var cancelText = "否";
-    if(selected.sourceType == project.Bills.getSourceType()&&selected.data.type==billType.FB&&selected.children.length>0){
-         showinfo = "是否删除其下的子项?";
-         showN = true;
-         cancelText = "取消";
+    if(selected.sourceType == project.Bills.getSourceType()&&selected.data.type==billType.FB&&selected.children.length>0){//选中的是分部,并且有子项
+        if(isSingleSelect()||selectionChecking()){
+            showinfo = "是否删除其下的子项?";
+            showN = true;
+            cancelText = "取消";
+        }
     }
     $('#delete_showinfo').text(showinfo);
     showN==true? $('#deleteN').show():$('#deleteN').hide();
     $('#deleteCancel').text(cancelText);
+
+    function selectionChecking() {
+        let selection = projectObj.mainSpread.getActiveSheet().getSelections()[0];
+        let mainTreeMap = {};
+        for(let i =0;i<selection.rowCount;i++){
+            let tem_node = controller.tree.items[selection.row+i];
+            if(i==0){//第一个直接添加;
+                mainTreeMap[tem_node.getID()] = tem_node;
+            }else {
+                project.Bills.setNodeToMap(tem_node,mainTreeMap);
+            }
+        }
+        let nodes = changeMapToArray(mainTreeMap);
+        if(nodes.length==1){
+            return true
+        }
+        return false;
+    }
 });
 
+function changeMapToArray(map) {
+    let newArray = [];
+    for(let key in map){
+        newArray.push(map[key]);
+    }
+    return newArray;
+}
+
+
 $('#deleteY').click(function () { //正常删除,级联删除子项
-     let controller = projectObj.mainController, project = projectObj.project;
-     let selected = controller.tree.selected, parent = selected.parent;
-     if (selected) {
-         if (selected.sourceType === project.Bills.getSourceType()) {
-             if (cbTools.isUsedByFormula(selected)){
-                 alert('该清单行被其它公式结点引用,不允许删除!');
-                 return;
-             }
-             project.Bills.deleteBills(selected.source);
-             controller.delete();
-         } else if (selected.sourceType === project.Ration.getSourceType()) {
-             project.Ration.delete(selected.source);
-             controller.delete();
-         }else if(selected.sourceType==ModuleNames.ration_glj){
-            project.ration_glj.updataOrdelete(selected.source);
-         }
-         if(parent){
-             projectObj.converseCalculateBills(parent);
-         }else { //删除的是大项费用要重新计算工程造价节点
-             let roots =  controller.tree.roots;
-             for(let root of roots){
-                 if(project.Bills.isEngineeringCost(root)==true){
-                     project.calcProgram.calcAndSave(root);
-                     break;
-                 }
-             }
-         }
-     }
+    let project = projectObj.project;
+    if(isSingleSelect()){
+        project.Bills.deleteSelectedNode();
+    }else {
+        project.Bills.deleteSelectedNodes();
+    }
 });
 
 $('#deleteN').click(function () {//不删除子项
     let controller = projectObj.mainController, project = projectObj.project;
     let selected = controller.tree.selected, parent = selected.parent;
-    let updateData = {};
     if(selected){
         let preNode = selected.preSibling;
         let nextNode = selected.nextSibling;
@@ -1100,13 +1137,13 @@ $('#deleteN').click(function () {//不删除子项
             }
         }
         project.Bills.singleDeleteBills(selected,controller);
-
-
     }
-
-
-
-
-
-
 });
+
+function isSingleSelect() {//是否选中造价书中的单行
+    let selections = projectObj.mainSpread.getActiveSheet().getSelections();
+    if (selections[0].rowCount == 1) {
+        return true;
+    }
+    return false;
+}

+ 1 - 0
web/building_saas/main/js/views/sub_view.js

@@ -82,6 +82,7 @@ $("#linkGCLMX").click(function(){
 });
 
 $("#linkJSCX").click(function(){        // 计算程序
+    $.contextMenu( 'destroy', "#subSpread" );
     $("#subItems").children().hide();
     $("#subSpread").show();
     pageCCOprObj.active = false;

+ 1 - 1
web/building_saas/pm/js/pm_main.js

@@ -102,7 +102,7 @@ let ProjTreeSetting = {
                 getText: function (html, node, text) {
                     if(node.data.projType === projectType.tender){
                         // let engineeringCostText = node.data.engineeringCost ? node.data.engineeringCost : 0;
-                        let engineeringCostText = node.data.summaryFees ? node.data.summaryFees.totalFee : 0;
+                        let engineeringCostText = node.data.summaryFees ? parseFloat(node.data.summaryFees.totalFee).toFixed(2) : '0.00';
                         html.push(engineeringCostText);
                     }
                 }