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

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/YangHuCost

TonyKang пре 5 година
родитељ
комит
6caa76cc20
40 измењених фајлова са 704 додато и 222 уклоњено
  1. 6 2
      modules/main/facade/project_facade.js
  2. 17 2
      modules/main/facade/ration_facade.js
  3. 61 32
      modules/pm/facade/pm_facade.js
  4. 6 0
      public/common_constants.js
  5. 24 1
      public/common_util.js
  6. BIN
      public/static/清单示例.xlsx
  7. 5 0
      public/web/gljUtil.js
  8. 85 1
      public/web/id_tree.js
  9. 1 1
      public/web/sheet/sheet_common.js
  10. 91 0
      public/web/tree_sheet/tree_sheet_controller.js
  11. 6 6
      web/building_saas/complementary_glj_lib/html/tools-gongliaoji.html
  12. 5 0
      web/building_saas/complementary_glj_lib/js/glj.js
  13. 2 2
      web/building_saas/complementary_ration_lib/html/dinge.html
  14. 2 2
      web/building_saas/complementary_ration_lib/js/init.js
  15. 5 0
      web/building_saas/css/custom.css
  16. 6 3
      web/building_saas/glj/html/project_glj.html
  17. 1 1
      web/building_saas/js/global.js
  18. 9 8
      web/building_saas/main/html/main.html
  19. 2 2
      web/building_saas/main/js/main.js
  20. 24 0
      web/building_saas/main/js/models/bills.js
  21. 1 1
      web/building_saas/main/js/models/cache_tree.js
  22. 2 1
      web/building_saas/main/js/models/calc_base.js
  23. 1 0
      web/building_saas/main/js/models/calc_program.js
  24. 2 14
      web/building_saas/main/js/models/project.js
  25. 1 0
      web/building_saas/main/js/models/project_glj.js
  26. 4 1
      web/building_saas/main/js/models/quantity_detail.js
  27. 25 3
      web/building_saas/main/js/models/ration.js
  28. 1 0
      web/building_saas/main/js/views/glj_view_contextMenu.js
  29. 19 2
      web/building_saas/main/js/views/importBills.js
  30. 18 22
      web/building_saas/main/js/views/locate_view.js
  31. 6 1
      web/building_saas/main/js/views/material_calc_view.js
  32. 84 6
      web/building_saas/main/js/views/project_glj_view.js
  33. 12 1
      web/building_saas/main/js/views/project_info.js
  34. 128 100
      web/building_saas/main/js/views/project_view.js
  35. 0 1
      web/building_saas/main/js/views/sub_view.js
  36. 0 1
      web/building_saas/main/js/views/zmhs_view.js
  37. 10 5
      web/building_saas/pm/js/pm_newMain.js
  38. 18 0
      web/over_write/js/nongcun_2020.js
  39. 7 0
      web/over_write/js/shandong_2016.js
  40. 7 0
      web/over_write/js/sichuan_2013.js

+ 6 - 2
modules/main/facade/project_facade.js

@@ -342,13 +342,14 @@ function getReportData(nameList,items,prjTypeNames,compilationScopes,decimal,isP
     }
     setChildrenDatas(items,datas);
     let totalExp = totalItem.calcBase;
-    if(isProgressiveType&&progressiveInterval){
+    if(isProgressiveType&&progressiveInterval){//有累进的要重新计算总金额和技术经济综合指标
       for(let t of datas){
         totalExp = totalExp.replace(t.ID,t.billsTtlPrice+"");
       }
       totalExp = totalExp.replace(/@/g,"");
       let nTotal = eval(totalExp);
       totalItem.billsTtlPrice = scMathUtil.roundForObj(nTotal,decimal.bills.totalPrice);
+      totalItem['技术经济综合指标'] = (totalItem.billsTtlAmt && parseFloat(totalItem.billsTtlAmt) !== 0)?scMathUtil.roundForObj(totalItem.billsTtlPrice/totalItem.billsTtlAmt,2):scMathUtil.roundForObj(totalItem.billsTtlPrice,2);
     }
 
     for(let d of datas){
@@ -373,8 +374,11 @@ function getReportData(nameList,items,prjTypeNames,compilationScopes,decimal,isP
             arr.push(tbill);
             let sumChildren = setChildrenDatas(c.children,arr,level+1,rootFlag);  
             if(isProgressiveType && progressiveInterval && rootFlag == fixedFlag.MAINTENANCE_EXPENSES){//如果要累进的,父节点要重新汇总
+              if(c.children.length > 0){
+                tbill.billsTtlPrice = sumChildren;
+                tbill['技术经济综合指标'] = (tbill.billsTtlAmt && parseFloat(tbill.billsTtlAmt) !== 0)?scMathUtil.roundForObj(tbill.billsTtlPrice/tbill.billsTtlAmt,2):scMathUtil.roundForObj(tbill.billsTtlPrice,2);
+              } 
               if(level>0) temTotalPrice = scMathUtil.roundForObj(tbill.billsTtlPrice + temTotalPrice,decimal.bills.totalPrice); 
-              if(c.children.length > 0) tbill.billsTtlPrice = sumChildren;
             }
         }
         return temTotalPrice;

+ 17 - 2
modules/main/facade/ration_facade.js

@@ -1199,15 +1199,30 @@ async function CalculateQuantity (ration,billsItemID,projectID) {
     let decimalObject =await decimal_facade.getProjectDecimal(projectID,project);
     let quantity_decimal = (decimalObject&&decimalObject.ration&&decimalObject.ration.quantity)?decimalObject.ration.quantity:3;
     let pbill = await bill_model.model.findOne({projectID:projectID,ID:billsItemID});
+    let rationTimes = 1 ;//清单单位转定额单位的倍数,如 kg 转 t 时是1000
+    let t_unit = ration.unit?ration.unit:"";
+    let b_unit = pbill.unit?pbill.unit:"";
+    ration.quantityEXP="QDL";
+    if((/.*kg$/i).test(b_unit)){
+      if((/t/i).test(t_unit)) {
+        rationTimes = 1000;//如 kg 转 t 时是1000
+        ration.quantityEXP="QDL*0.001"
+      }
+      if((/10t/i).test(t_unit)){
+        rationTimes = 10000;//如 kg 转 10t 时是1000
+        ration.quantityEXP="QDL*0.0001"
+      } 
+    }
+    
    /* let  t_unit = ration.unit?ration.unit.replace(/^\d+/,""):""; 2019-02-01 养护去掉清单与定额单位的这个判断
     if(t_unit!=pbill.unit){//如果定额工程量的单位去除前面的数字后不等于清单单位,定额工程量保持不变
         return ;
     }*/
     let billsQuantity = pbill.quantity ? pbill.quantity : 0;
     let bill_decimal = await decimal_facade.getBillsQuantityDecimal(projectID,pbill.unit,project);
+    let ftimes = rationTimes == 1?FilterNumberFromUnit(ration.unit):rationTimes;
     billsQuantity=scMathUtil.roundForObj(billsQuantity,bill_decimal);
-    ration.quantityEXP="QDL";
-    ration.quantity = scMathUtil.roundForObj(billsQuantity / FilterNumberFromUnit(ration.unit),quantity_decimal);//不管是否打勾都做转换
+    ration.quantity = scMathUtil.roundForObj(billsQuantity / ftimes ,quantity_decimal);//不管是否打勾都做转换
     ration.contain =  scMathUtil.roundForObj(ration.quantity/billsQuantity,6);
 };
 

+ 61 - 32
modules/pm/facade/pm_facade.js

@@ -484,17 +484,11 @@ async function copyProject(userID, compilationID, data, newProjectID = null, del
         //费率文件、单价文件重名检查
         let feeRate = await feeRateFileModel.findOne({ rootProjectID: originalProperty.rootProjectID, name: feeRateFileName, deleteInfo: null });
         if (feeRate) {//存在重名的文件
-            if (isSaveAs) {
-                throw `费率文件[${feeRateFileName}]已存在,请手工检查数据是否正确。`;
-            }
             feeRateFileName = feeRateFileName + '(' + moment(Date.now()).tz("Asia/Shanghai").format('MM-DD HH:mm:ss') + '复制)';
         }
         projectMap['copy'].document.property.feeFile.name = feeRateFileName;
         let unitPriceFile = await unitPriceFileModel.findOne({ root_project_id: originalProperty.rootProjectID, name: unitPriceFileName, deleteInfo: null });
         if (unitPriceFile) {//存在重名的文件
-            if (isSaveAs) {
-                throw `单价文件[${unitPriceFileName}]已存在,请手工检查数据是否正确。`;
-            }
             unitPriceFileName = unitPriceFileName + '(' + moment(Date.now()).tz("Asia/Shanghai").format('MM-DD HH:mm:ss') + '复制)';
         }
         projectMap['copy'].document.property.unitPriceFile.name = unitPriceFileName;
@@ -691,13 +685,24 @@ async function copyUnitPriceFile(newProjectID,rootProjectID,userID,originaluUnit
     }
 
     async function copySubList(srcFID,newFID,model,UUID=false) {
-        let mList = await model.find({unit_price_file_id: srcFID}, '-_id');
+        let mList = await model.find({unit_price_file_id: srcFID}, '-_id').lean();
         let rList = [];
-        for(let m of mList){
-            m._doc.unit_price_file_id = newFID;
-            UUID == true?m._doc.ID = uuidV1():m._doc.id = await getCounterID(model.modelName);
-            rList.push(m._doc);
-        }
+        if(UUID == true){
+          for(let m of mList){
+            m.unit_price_file_id = newFID;
+            m.ID = uuidV1();
+            rList.push(m);
+          }
+        }else{
+          let IDcounter = await counter.counterDAO.getIDAfterCountSync(model.modelName, mList.length);
+          let firstID = IDcounter.sequence_value - (mList.length - 1);
+          for(let m of mList){
+              m.unit_price_file_id = newFID;
+              m.id = firstID;    
+              firstID+=1
+              rList.push(m);
+          }
+        }    
         await insertMany(rList,model)
     }
 }
@@ -910,10 +915,10 @@ async function getCounterID(collectionName){
 }
 
 async function insertMany(datas,model) {
-    while (datas.length>1000){//因为mongoose限制了批量插入的条数为1000.所以超出限制后需要分批插入
+   /*  while (datas.length>1000){//因为mongoose限制了批量插入的条数为1000.所以超出限制后需要分批插入
         let newList = datas.splice(0,1000);//一次插入1000条
         await model.insertMany(newList);
-    }
+    } */
     await model.insertMany(datas);
 
 }
@@ -1588,10 +1593,34 @@ async function importProject(data,req,updateData) {
             }
             let [constructionProjectID,projectIDMap,labourCoeFileIDMap,calcProgramFileIDMap] = await handleMainProjectDatas(mainData,updateData,req.session.sessionUser.id);
             result.constructionProjectID = constructionProjectID;
-            if(datas.length > 1 ){
+            if(datas.length > 1 ){//生成后统一次插入 2020-05-29
+              let newProjectSettings=[],bills=[],rations=[],projectGLJs=[],rationGLJs=[],rationCoes=[],quantityDetails=[],rationInstallations=[],rationTemplates=[],newCalcProgramsFiles=[],newLabourCoes=[];
                 for(let i = 1;i<datas.length;i++){
-                    await handleEachProject(datas[i],projectIDMap,labourCoeFileIDMap,calcProgramFileIDMap)
+                  let [newProjectSetting,tbills,trations,tprojectGLJs,trationGLJs,trationCoes,tquantityDetails,trationInstallations,trationTemplates,newCalcProgramsFile,newLabourCoe] =  await handleEachProject(datas[i],projectIDMap,labourCoeFileIDMap,calcProgramFileIDMap)
+                  if(newProjectSetting) newProjectSettings.push(newProjectSetting);
+                  if(tbills.length > 0) bills = bills.concat(tbills);
+                  if(trations.length > 0) rations = rations.concat(trations);
+                  if(tprojectGLJs.length > 0) projectGLJs = projectGLJs.concat(tprojectGLJs); 
+                  if(trationGLJs.length > 0) rationGLJs = rationGLJs.concat(trationGLJs);
+                  if(trationCoes.length > 0) rationCoes = rationCoes.concat(trationCoes);
+                  if(tquantityDetails.length > 0) quantityDetails = quantityDetails.concat(tquantityDetails);
+                  if(trationInstallations.length > 0) rationInstallations= rationInstallations.concat(trationInstallations);
+                  if(trationTemplates.length > 0) rationTemplates = rationTemplates.concat(trationTemplates); 
+                  if(newCalcProgramsFile) newCalcProgramsFiles.push(newCalcProgramsFile);
+                  if(newLabourCoe) newLabourCoes.push(newLabourCoe);
                 }
+
+                if(newProjectSettings.length > 0) await insertMany(newProjectSettings,projectSettingModel);
+                if(bills.length > 0) await insertMany(bills,billsModel);
+                if(rations.length > 0) await insertMany(rations,rationModel);
+                if(projectGLJs.length > 0) await insertMany(projectGLJs,gljListModel);
+                if(rationGLJs.length > 0) await insertMany(rationGLJs,rationGLJModel);
+                if(rationCoes.length > 0) await insertMany(rationCoes,rationCoeModel);
+                if(quantityDetails.length > 0) await insertMany(quantityDetails,quantityDetailModel);
+                if(rationInstallations.length > 0) await insertMany(rationInstallations,rationInstallationModel);
+                if(rationTemplates.length > 0) await insertMany(rationTemplates,rationTemplateModel);
+                if(newCalcProgramsFiles.length > 0) await insertMany(newCalcProgramsFiles,calcProgramsModel);
+                if(newLabourCoes.length>0) await insertMany(newLabourCoes,labourCoesModel);
             }
 
          }
@@ -1670,19 +1699,7 @@ async function handleEachProject(data,projectIDMap,labourCoeFileIDMap,calcProgra
         newLabourCoe = data.labourCoes;
         delete newLabourCoe._id;
     }
-
-    if(newProjectSetting) await projectSettingModel.create(newProjectSetting);
-    if(bills.length > 0) await insertMany(bills,billsModel);
-    if(rations.length > 0) await insertMany(rations,rationModel);
-    if(projectGLJs.length > 0) await insertMany(projectGLJs,gljListModel);
-    if(rationGLJs.length > 0) await insertMany(rationGLJs,rationGLJModel);
-    if(rationCoes.length > 0) await insertMany(rationCoes,rationCoeModel);
-    if(quantityDetails.length > 0) await insertMany(quantityDetails,quantityDetailModel);
-    if(rationInstallations.length > 0) await insertMany(rationInstallations,rationInstallationModel);
-    if(rationTemplates.length > 0) await insertMany(rationTemplates,rationTemplateModel);
-    if(newCalcProgramsFile) await calcProgramsModel.create(newCalcProgramsFile);
-    if(newLabourCoe) await labourCoesModel.create(newLabourCoe);
-
+    return [newProjectSetting,bills,rations,projectGLJs,rationGLJs,rationCoes,quantityDetails,rationInstallations,rationTemplates,newCalcProgramsFile,newLabourCoe]
 
 }
 
@@ -1789,14 +1806,26 @@ async function importUnitPriceFiles(mainData,projectIDMap,unitPriceFileIDMap,use
     if(freights.length > 0) await insertMany(freights,freightModel);
     if(originals.length > 0) await insertMany(originals,originalModel);
     if(com_electrovalences.length > 0) await insertMany(com_electrovalences,comElectrovalenceModel);
-
     async function setSubList(oList,nList,fileID,model,UUID=false) {
-        for(let o of oList){
+        if(UUID == true){
+          for(let o of oList){
             delete o._id;
             o.unit_price_file_id = fileID;
-            UUID == true?o.ID = uuidV1():o.id = await getCounterID(model.modelName);
+            o.ID = uuidV1();
             nList.push(o)
+          }
+        }else{
+          let IDcounter = await counter.counterDAO.getIDAfterCountSync(model.modelName, oList.length);
+          let firstID = IDcounter.sequence_value - (oList.length - 1);
+            for(let o of oList){
+                delete o._id;
+                o.unit_price_file_id = fileID;
+                o.id = firstID;
+                firstID+=1
+                nList.push(o)
+            }
         }
+        
     }
 
 

+ 6 - 0
public/common_constants.js

@@ -107,10 +107,16 @@
         BOQ: 'ration'
     };
 
+    const SourceType = {
+        BILLS: 'bills',
+        RATION: 'ration',
+    };
+
     return {
         fixedFlag,
         COMPLEMENTARY_LIB,
         COMPILATION,
         ValuationType,
+        SourceType,
     };
 })

+ 24 - 1
public/common_util.js

@@ -44,9 +44,32 @@
         }
     }
 
+    // 给数值加上分割
+    // eg: 1234567.00 => 1,234,567.00
+    function standardNumber(str) {
+        if (typeof str === 'number') {
+            str = String(str);
+        }
+        if (typeof str !== 'string') {
+            return '';
+        }
+        const [intPart, decimalPart] = str.split('.');
+        // 给整数部分加上“,”
+        const temp = [];
+        for (let i = intPart.length - 1, j = 1; i >= 0; i--, j++) {
+            temp.push(intPart[i]);
+            if (j !==0 && j % 3 === 0 && i - 1 >= 0) {
+                temp.push(',');
+            }
+        }
+        const standardIntPart = temp.reverse().join('');
+        return `${standardIntPart}${decimalPart ? '.' + decimalPart : ''}`;
+    }
+
     return {
         isDef,
         isEmptyVal,
-        getSortedTreeData
+        getSortedTreeData,
+        standardNumber,
     };
 });

BIN
public/static/清单示例.xlsx


+ 5 - 0
public/web/gljUtil.js

@@ -511,6 +511,11 @@ let gljUtil = {
             }
         }
     },
+    isKGtoT:function(bills_unit,ration_unit){//是否由KG转成T,b_unit清单单位,t_unit定额单位
+      let t_unit = ration_unit?ration_unit:"";
+      let b_unit = bills_unit?bills_unit:"";
+      return (/.*kg$/i).test(b_unit) && (/.*t$/i).test(t_unit);
+    },
     fixedFlag : {
         // 分部分项工程
         SUB_ENGINERRING: 1,

+ 85 - 1
public/web/id_tree.js

@@ -292,7 +292,7 @@ var idTree = {
         Node.prototype.upLevel = function () {
             var result = {success: false, updateDatas: []};
             var iIndex = this.parent.children.indexOf(this), orgParent = this.parent, newNextSibling = this.parent.nextSibling;
-            if (this.canUpLevel) {
+            if (this.canUpLevel()) {
                 // NextSiblings become child
                 tools.addNodes(this.tree, this, this.parent.children.slice(iIndex + 1));
                 // Orginal Parent remove node and nextSiblings
@@ -813,6 +813,90 @@ var idTree = {
             let node = this.nodes[this.prefix+ID];
             return node;
         };
+        // nodes必须是有效的同层节点(选中的可升级的节点)
+        Tree.prototype.getMultiUpLevelData = function (nodes) {
+            const firstNode = nodes[0];
+            const lastNode = nodes[nodes.length - 1];
+            const data = [];
+            if (!firstNode.canUpLevel()) {
+                return;
+            }
+            if (!lastNode.isLast()) {
+                const children = lastNode.parent.children.slice(lastNode.siblingIndex() + 1);
+                tools.addUpdateDataForParent(data, children, lastNode.getID());
+            }
+            if (firstNode.preSibling) {
+                tools.addUpdateDataForNextSibling(data, firstNode.preSibling, this.setting.rootId);
+            }
+            tools.addUpdateDataForNextSibling(data, firstNode.parent, firstNode.getID());
+            const updateData = nodes.map(node => {
+                const nextID = node === lastNode ? node.parent.getNextSiblingID() : node.getNextSiblingID();
+                const nodeData = this.getDataTemplate(node.getID(), node.parent.getParentID(), nextID);
+                return { type: 'update', data: nodeData };
+
+            });
+            data.push(...updateData);
+            return data;
+        };
+        Tree.prototype.getMultiDownLevelData = function (nodes) {
+            const firstNode = nodes[0];
+            const lastNode = nodes[nodes.length - 1];
+            const data = [];
+            if (!firstNode.canDownLevel()) {
+                return;
+            }
+            if (firstNode.preSibling.children.length) {
+                tools.addUpdateDataForNextSibling(data, firstNode.preSibling.lastChild(), firstNode.getID());
+            }
+            const preSibling = firstNode.preSibling;
+            const updatePreData = {
+                type: 'update',
+                data: this.getDataTemplate(preSibling.getID(), preSibling.getParentID(), lastNode.getNextSiblingID())
+            };
+            //如果设置了专项暂定,则需要清空
+            if (preSibling.data.specialProvisional) {
+                preSibling.data.specialProvisional = '';
+                updatePreData.specialProvisional = '';
+            }
+            data.push(updatePreData);
+            const updateData = nodes.map(node => {
+                const nextID = node === lastNode ? this.setting.rootId : node.getNextSiblingID();
+                return {
+                    type: 'update',
+                    data: this.getDataTemplate(node.getID(), preSibling.getID(), nextID)
+                };
+            });
+            data.push(...updateData);
+            return data;
+        };
+        Tree.prototype.getMultiUpMoveData = function (nodes) {
+            const firstNode = nodes[0];
+            const lastNode = nodes[nodes.length - 1];
+            const data = [];
+            if (!firstNode.canUpMove()) {
+                return;
+            }
+            if (firstNode.preSibling.preSibling) {
+                tools.addUpdateDataForNextSibling(data, firstNode.preSibling.preSibling, firstNode.getID());
+            }
+            tools.addUpdateDataForNextSibling(data, firstNode.preSibling, lastNode.getNextSiblingID());
+            tools.addUpdateDataForNextSibling(data, lastNode, firstNode.preSibling.getID());
+            return data;
+        };
+        Tree.prototype.getMultiDownMoveData = function (nodes) {
+            const firstNode = nodes[0];
+            const lastNode = nodes[nodes.length - 1];
+            const data = [];
+            if (!lastNode.canDownMove()) {
+                return;
+            }
+            if (firstNode.preSibling) {
+                tools.addUpdateDataForNextSibling(data, firstNode.preSibling, lastNode.getNextSiblingID());
+            }
+            tools.addUpdateDataForNextSibling(data, lastNode, lastNode.nextSibling.getNextSiblingID());
+            tools.addUpdateDataForNextSibling(data, lastNode.nextSibling, firstNode.getID());
+            return data;
+        };
         return new Tree(setting);
     },
     updateType: {update: 'update', new: 'new', delete: 'delete'}

+ 1 - 1
public/web/sheet/sheet_common.js

@@ -165,7 +165,7 @@ var sheetCommonObj = {
         let ch = GC.Spread.Sheets.SheetArea.viewport;
         for (var col = 0; col < setting.header.length; col++) {
             //var cell = sheet.getCell(row, col, GC.Spread.Sheets.SheetArea.viewport);
-            var val = data[row][setting.header[col].dataCode];
+            var val = _.get(data[row],setting.header[col].dataCode);
             if (val && setting.header[col].dataType === "Number") {
                 if (setting.header[col].hasOwnProperty('tofix')) {
                     val = scMathUtil.roundToString(val, setting.header[col].tofix);

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

@@ -150,6 +150,16 @@ var TREE_SHEET_CONTROLLER = {
                 }
             }
         };
+        controller.prototype.multiUpLevel = function (nodes) {
+            nodes.forEach(node => node.upLevel());
+            TREE_SHEET_HELPER.massOperationSheet(this.sheet, () => {
+                TREE_SHEET_HELPER.refreshNodesVisible(nodes, this.sheet, true);
+                this.sheet.showRow(nodes[0].serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                if (this.event.refreshBaseActn) {
+                    this.event.refreshBaseActn(this.tree);
+                }
+            });
+        };
         controller.prototype.downLevel = function () {
             var that = this;
             if (this.tree.selected) {
@@ -164,6 +174,17 @@ var TREE_SHEET_CONTROLLER = {
                 }
             }
         };
+        controller.prototype.multiDownLevel = function (nodes) {
+            nodes.forEach(node => node.downLevel());
+            const firstNode = nodes[0];
+            TREE_SHEET_HELPER.massOperationSheet(this.sheet, () => {
+                TREE_SHEET_HELPER.refreshNodesVisible([firstNode.parent], this.sheet, true);
+                this.sheet.showRow(firstNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                if (this.event.refreshBaseActn) {
+                    this.event.refreshBaseActn(this.tree);
+                }
+            });
+        };
         controller.prototype.upMove = function () {
             var that = this, sels = this.sheet.getSelections();
             if (this.tree.selected) {
@@ -182,6 +203,44 @@ var TREE_SHEET_CONTROLLER = {
                 });
             }
         };
+        controller.prototype.multiUpMove = function (nodes) {
+            TREE_SHEET_HELPER.massOperationSheet(this.sheet, () => {
+                const { row, col, rowCount, colCount } = this.sheet.getSelections()[0];
+                nodes.forEach(node => {
+                    TREE_SHEET_HELPER.refreshChildrenVisiable(this.sheet, this.tree, node, node.serialNo(), true); //为了处理移动前子项是隐藏的情况
+                });
+                const preNode = nodes[0].preSibling;
+                TREE_SHEET_HELPER.refreshChildrenVisiable(this.sheet, this.tree, preNode, preNode.serialNo(), true);
+                nodes.forEach(node => node.upMove());
+                TREE_SHEET_HELPER.refreshTreeNodeData(this.setting, this.sheet, [...nodes, preNode], true);
+                nodes.forEach(node => TREE_SHEET_HELPER.refreshChildrenVisiable(this.sheet, this.tree, node, node.serialNo()));
+                TREE_SHEET_HELPER.refreshChildrenVisiable(this.sheet, this.tree, preNode, preNode.serialNo());
+                this.sheet.setSelection(row - preNode.posterityCount() - 1, col, rowCount, colCount);
+                if (this.event.refreshBaseActn) {
+                    this.event.refreshBaseActn(this.tree);
+                }
+            });
+        };
+        controller.prototype.multiDownMove = function (nodes) {
+            TREE_SHEET_HELPER.massOperationSheet(this.sheet, () => {
+                const { row, col, rowCount, colCount } = this.sheet.getSelections()[0];
+                nodes.forEach(node => {
+                    TREE_SHEET_HELPER.refreshChildrenVisiable(this.sheet, this.tree, node, node.serialNo(), true); //为了处理移动前子项是隐藏的情况
+                });
+                const nextNode = nodes[nodes.length - 1].nextSibling;
+                TREE_SHEET_HELPER.refreshChildrenVisiable(this.sheet, this.tree, nextNode, nextNode.serialNo(), true);
+                for (let i = nodes.length - 1; i >= 0; i--) {
+                    nodes[i].downMove();
+                }
+                TREE_SHEET_HELPER.refreshTreeNodeData(this.setting, this.sheet, [...nodes, nextNode], true);
+                nodes.forEach(node => TREE_SHEET_HELPER.refreshChildrenVisiable(this.sheet, this.tree, node, node.serialNo()));
+                TREE_SHEET_HELPER.refreshChildrenVisiable(this.sheet, this.tree, nextNode, nextNode.serialNo());
+                this.sheet.setSelection(row + nextNode.posterityCount() + 1, col, rowCount, colCount);
+                if (this.event.refreshBaseActn) {
+                    this.event.refreshBaseActn(this.tree);
+                }
+            });
+        };
         controller.prototype.downMove = function () {
             var that = this, sels = this.sheet.getSelections();
             if (this.tree.selected) {
@@ -225,6 +284,38 @@ var TREE_SHEET_CONTROLLER = {
             this.event[eventName] = eventFun;
         };
 
+        // 获取有效的选中同层节点
+        // 如果选中的节点内,有比第一个选中节点深度小的节点,则此选中范围内无有效节点
+        // 如果没用上述的情况,则有效选中节点为,跟第一个选中节点深度相同的节点
+        controller.prototype.getValidNodesWithinSelection = function () {
+            const selection = this.sheet.getSelections()[0];
+            if (!selection || !commonUtil.isDef(selection.row)) {
+                return [];
+            }
+            const nodes = [];
+            let firstNode;
+            let firstNodeDepth;
+            const maxRow = selection.row + selection.rowCount;
+            for (let row = selection.row; row < maxRow; row++) {
+                const node = this.tree.items[row];
+                if (!node) {
+                    return [];
+                }
+                const depth = node.depth();
+                if (!firstNode) {
+                    firstNode = node;
+                    firstNodeDepth = firstNode.depth();
+                }
+                if (depth < firstNodeDepth) {
+                    return [];
+                }
+                if (depth === firstNodeDepth) {
+                    nodes.push(node);
+                }
+            }
+            return nodes;
+        };
+
         return new controller();
     },
     eventName: {

+ 6 - 6
web/building_saas/complementary_glj_lib/html/tools-gongliaoji.html

@@ -69,7 +69,7 @@
                             <!--<input type="radio" class="glj-radio" name="glj" value="allGljs">所有&nbsp;-->&nbsp;
                             <input type="radio" class="glj-radio" name="glj" value="stdGljs">标准&nbsp;&nbsp;
                             <input type="radio" class="glj-radio" name="glj" value="complementaryGljs">补充&nbsp;&nbsp;
-                            <div  class="modal-auto-height" id="componentTreeDiv" style="overflow: hidden">
+                            <div  class="modal-auto-height" id="componentTreeDiv" style="height: 435px; overflow: hidden">
                                 <!--<div class="print-list">-->
                                 <div style="width: 100%; height: 100%; overflow: auto">
                                     <ul id="componentTree" class="ztree"></ul>
@@ -91,7 +91,7 @@
                                         </div>
                                     </div>
                                 </div>
-                                <div class="modal-auto-height col-12" style="overflow: hidden" id="componentSheet">
+                                <div class="modal-auto-height col-12" style="height: 420px; overflow: hidden" id="componentSheet">
                                 </div>
                             </div>
                         </div>
@@ -253,19 +253,19 @@
         };
         $(document).ready(function(){
             //解决spreadjs sheet初始化没高度宽度
-            $('#modalCon').width($(window).width()*0.5);
+           /*  $('#modalCon').width($(window).width()*0.5);
             $('#componentTreeDiv').height($(window).height() - 300);
             $("#componentSheet").height($("#componentTreeDiv").height() - 15);
-            $("#componentSheet").width($('#modalCon').width() * 0.63);
+            $("#componentSheet").width($('#modalCon').width() * 0.63); */
             pageOprObj.initPage($("#GLJListSheet")[0], $('#gljComponentSheet')[0], $("#componentSheet")[0]);
         });
         //组成物弹出窗大小设置
-        $(window).resize(function () {
+        /* $(window).resize(function () {
             $('#modalCon').width($(window).width()*0.5);
             $('#componentTreeDiv').height($(window).height() - 300);
             $("#componentSheet").height($("#componentTreeDiv").height()-15);
             $("#componentSheet").width($('#modalCon').width()* 0.63);
-        });
+        }); */
   	</SCRIPT>
 </body>
 <script type="text/javascript">

+ 5 - 0
web/building_saas/complementary_glj_lib/js/glj.js

@@ -3,6 +3,11 @@
  */
 
 $(document).ready(function () {
+    $('#component').on('shown.bs.modal', function () {
+        if (componentOprObj.workBook) {
+            componentOprObj.workBook.refresh();
+        }
+    });
     let moduleName = 'compleGLj';
     SlideResize.loadHorizonWidth(moduleName, [$('#rightResize'), $('#leftResize')], [$('#leftContent'), $('#midContent'), $('#rightContent')], function () {
         refreshALlWorkBook();

+ 2 - 2
web/building_saas/complementary_ration_lib/html/dinge.html

@@ -530,7 +530,7 @@
                     </select>
 <!--                     <input type="radio" class="glj-radio" name="glj" value="stdGljs">标准&nbsp;&nbsp;
                     <input type="radio" class="glj-radio" name="glj" value="complementaryGljs">补充&nbsp;&nbsp; -->
-                    <div  class="modal-auto-height" id="gljSelTreeDiv" style="overflow: hidden">
+                    <div  class="modal-auto-height" id="gljSelTreeDiv" style="height: 435px; overflow: hidden;">
                         <div style="width: 100%; height: 100%; overflow: auto">
                             <ul id="selGljTree" class="ztree"></ul>
                         </div>
@@ -550,7 +550,7 @@
                                 </div>
                             </div>
                         </div>
-                        <div class="modal-auto-height col-12" style="overflow: hidden" id="gljSelSheet">
+                        <div class="modal-auto-height col-12" style="overflow: hidden; height: 420px;" id="gljSelSheet">
                         </div>
                     </div>
                 </div>

+ 2 - 2
web/building_saas/complementary_ration_lib/js/init.js

@@ -66,7 +66,7 @@ const initialization = (() => {
             $.bootstrapLoading.end();
         });
         //解决spreadjs sheet初始化没高度宽度
-        $('#modalCon').width($(window).width()*0.5);
+        /* $('#modalCon').width($(window).width()*0.5);
         $('#gljSelTreeDiv').height($(window).height() - 300);
         $("#gljSelSheet").height($("#gljSelTreeDiv").height()-21.6);
         $("#gljSelSheet").width($('#modalCon').width() * 0.63);
@@ -75,6 +75,6 @@ const initialization = (() => {
             $('#gljSelTreeDiv').height($(window).height() - 300);
             $("#gljSelSheet").height($("#gljSelTreeDiv").height()-21.6);
             $("#gljSelSheet").width($('#modalCon').width()* 0.63);
-        });
+        }); */
     });
 })();

+ 5 - 0
web/building_saas/css/custom.css

@@ -443,4 +443,9 @@ input.text-right{
 }
 .default-cursor {
     cursor: default !important;
+}
+
+.material_link.active{
+  border:2px solid #ff6501 !important;
+  border-right: 1px solid #fff !important;
 }

+ 6 - 3
web/building_saas/glj/html/project_glj.html

@@ -47,7 +47,10 @@
                         <a class="nav-link " id="mixRatio-nav" data-toggle="tab" href="#ph_div" role="tab" aria-selected="false">组成物计算</a>
                     </li>
                     <li class="nav-item">
-                         <a class="btn btn-sm ml-1" href="#" data-toggle="modal" data-target="#calcCoeDiv"></i> 计算系数</a>
+                      <a class="nav-link " id="ration-nav" data-toggle="tab" href="#ph_div" role="tab" aria-selected="true">相关定额</a>
+                  </li>
+                    <li class="nav-item">
+                         <a class="nav-link" href="#" data-toggle="modal" data-target="#calcCoeDiv"></i> 计算系数</a>
                     </li>
                 </ul>
                 <!-- Tab panes -->
@@ -65,8 +68,8 @@
                                 <div class=" left full-h" style="width: 30px" >
                                     <div class="rn-nav cn-nav d-flex align-items-start flex-column"id="calTab">
                                         <ul class="nav nav-tabs">
-                                            <li class="nav-item"><a data-toggle="tab" href="#rnc-yf" role="tab" class="nav-link active">运费计算</a></li>
-                                            <li class="nav-item"><a data-toggle="tab" id="priceTab" href="#rnc-yj" role="tab" class="nav-link">原价计算</a></li>
+                                            <li class="nav-item"><a data-toggle="tab" href="#rnc-yf" role="tab" class="nav-link material_link active">运费计算</a></li>
+                                            <li class="nav-item"><a data-toggle="tab" id="priceTab" href="#rnc-yj" role="tab" class="nav-link material_link">原价计算</a></li>
                                         </ul>
                                     </div>
                                 </div>

+ 1 - 1
web/building_saas/js/global.js

@@ -17,7 +17,6 @@ function autoFlashHeight(){
     $('.main-content').width($(window).width()-$('.main-nav').width()-$('.main-side').width()-5);
     $('#glj_tree_div .modal-content').width($(window).width() < 1020 + 20 ? $(window).width() - 20 : 1020);
     //$("#main .main-data-top").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);
-    typeof(loadMainSize)== 'function' ?loadMainSize():'';//zhang 2018-06-04  统一加载高度方法
     $(".main-data-full").height($(window).height()-headerHeight-toolsbarHeight-1);
     $(".main-data-full-fl").height($(window).height()-headerHeight-toolsbarHeight-37);
     $(".main-data-full-feeRate").height($(window).height()-headerHeight-78);
@@ -34,6 +33,7 @@ function autoFlashHeight(){
     $('#project-glj-main').width($(window).width()-($('.main-nav').width()+ 2));//-($('.filterType').width()+12)-5); //2、12是padding宽度,width 是不算padding宽度的
     $('#project_glj_sheet').width($('#project-glj-main').width()-($('.filterType').width())-1)//1是border宽度,width 是不算padding和border宽度的
     typeof(loadProjectGljSize)== 'function'?loadProjectGljSize():'';
+    typeof(loadMainSize)== 'function' ?loadMainSize():'';//zhang 2018-06-04  统一加载高度方法
     //typeof zmhs_obj === 'object' ? zmhs_obj.loadSideResize() : '';
 };
 

+ 9 - 8
web/building_saas/main/html/main.html

@@ -42,8 +42,8 @@
         let projectReadOnly = JSON.parse('<%- projectReadOnly %>');
         let projectCooperate = JSON.parse('<%- projectCooperate %>');
         let projectOptins =  JSON.parse('<%- options %>');
-        const G_SHOW_BLOCK_LIB = true;
-//        const G_SHOW_BLOCK_LIB = false;
+        // const G_SHOW_BLOCK_LIB = true;
+       const G_SHOW_BLOCK_LIB = false;
     </script>
 </head>
 
@@ -114,12 +114,12 @@
                                   <a class="dropdown-item btn-sm" href="javascript:void(0);"  id="displayDE">定额</a>
                               </div>
                               <!--<a href="javascript:void(0);" id="ZLFB_btn" class="dropdown-item" data-placement="bottom"><i class="fa fa-retweet" aria-hidden="true"></i> 整理分部</a>
-                              <% if (projectData.property.lockBills == true) { %>
-                              <a href="javascript:void(0)"  class="dropdown-item" name="lockBills"> <i class="fa fa-unlock-alt" aria-hidden="true"></i> 解锁清单</a>
-                              <% } else { %>
-                              <a href="javascript:void(0)"  class="dropdown-item" name="lockBills"> <i class="fa fa-lock" aria-hidden="true"></i> 锁定清单</a>
-                              <% } %>
-                              <a id="switchTznr" href="javascript:void(0);"  class="dropdown-item"><i class="fa fa-eye" aria-hidden="true"></i> 显示特征</a>-->
+                                <a id="switchTznr" href="javascript:void(0);"  class="dropdown-item"><i class="fa fa-eye" aria-hidden="true"></i> 显示特征</a>-->
+                            <% if (projectData.property.lockBills == true) { %>
+                            <a href="javascript:void(0)"  class="dropdown-item" name="lockBills"> <i class="fa fa-unlock-alt" aria-hidden="true"></i> 解锁清单</a>
+                            <% } else { %>
+                            <a href="javascript:void(0)"  class="dropdown-item" name="lockBills"> <i class="fa fa-lock" aria-hidden="true"></i> 锁定清单</a>
+                            <% } %>
                               <a id = "menu_calc_program_manage"  href="javascript:void(0);" class="dropdown-item"><i class="fa fa-calculator" aria-hidden="true"></i> 总计算程序</a>
                           </div>
                       </div>
@@ -143,6 +143,7 @@
                       <a href="javascript:void(0)"  class="btn btn-light btn-sm" name="lockBills"> <i class="fa fa-lock" aria-hidden="true"></i> 锁定清单</a>
                       <% } %>
                       <a id="switchTznr" href="javascript:void(0);"  class="btn btn-light btn-sm"><i class="fa fa-eye" aria-hidden="true"></i> 显示特征</a>-->
+                      <span class="ml-3" id="total-price-span"></span>
                   </div>
                   <div class="side-tabs">
                       <ul class="nav nav-tabs" role="tablist">

+ 2 - 2
web/building_saas/main/js/main.js

@@ -24,7 +24,7 @@ $(function () {
         billsLibObj.refreshBillsRelaSpread();
         rationLibObj.refreshSpread();
         subObj.initGljSubTab();
-        refreshSubSpread();
+        //autoFlashHeight 里已经包含了 refreshSubSpread();
     });
 
     $('#tab_report').on('shown.bs.tab', function(e){
@@ -79,7 +79,7 @@ function loadMainSize() {//加载造价书页面各高度
     let mainResizeEles = getMainResizeEles();
     SlideResize.loadVerticalHeight(mainResizeEles.eleObj.module, mainResizeEles.eleObj, mainResizeEles.limit, function () {
         refreshSubSpread();
-        zmhs_obj.refresh();
+        //zmhs_obj.refresh();
     });
 }
 

+ 24 - 0
web/building_saas/main/js/models/bills.js

@@ -334,18 +334,35 @@ var Bills = {
 
             return node.upMove();
         };
+        bills.prototype.multiUpMoveBills = function (tree, nodes) {
+            const upMoveData = tree.getMultiUpMoveData(nodes);;
+            project.pushNow('upMoveBills', this.getSourceType(), tools.coverseTreeUpdateData(upMoveData, this.project.ID()));
+            nodes.forEach(node => node.upMove());
+        };
         bills.prototype.downMoveBills = function (node) {
             var downMoveData = node.getDownMoveData();
             project.pushNow('downMoveBills', this.getSourceType(), tools.coverseTreeUpdateData(downMoveData, this.project.ID()));
 
             return node.downMove();
         };
+        bills.prototype.multiDownMoveBills = function (tree, nodes) {
+            const downMoveData = tree.getMultiDownMoveData(nodes);
+            project.pushNow('downMoveBills', this.getSourceType(), tools.coverseTreeUpdateData(downMoveData, this.project.ID()));
+            for (let i = nodes.length - 1; i >= 0; i--) {
+                nodes[i].downMove();
+            }
+        };
         bills.prototype.upLevelBills = function (node) {
             var upLevelData = node.getUpLevelData();
             project.pushNow('upLevelBills', this.getSourceType(), tools.coverseTreeUpdateData(upLevelData, this.project.ID()));
 
             return node.upLevel();
         };
+        bills.prototype.multiUpLevelBills = function (tree, nodes) {
+            const upLevelData = tree.getMultiUpLevelData(nodes);
+            project.pushNow('upLevelBills', this.getSourceType(), tools.coverseTreeUpdateData(upLevelData, this.project.ID()));
+            nodes.forEach(node => node.upLevel());
+        };
         bills.prototype.downLevelBills = function (node) {
             var downLevelData = node.getDownLevelData();
             this.setQuantityAfterDownLevel(node,downLevelData);
@@ -353,6 +370,13 @@ var Bills = {
 
             return node.downLevel();
         };
+        bills.prototype.multiDownLevelBills = function (tree, nodes) {
+            const downLevelData = tree.getMultiDownLevelData(nodes);
+            const firstNode = nodes[0];
+            this.setQuantityAfterDownLevel(firstNode, downLevelData);
+            project.pushNow('downLevelBills', [this.getSourceType()], [tools.coverseTreeUpdateData(downLevelData, this.project.ID())]);
+            nodes.forEach(node => node.downLevel());
+        };
         bills.prototype.setQuantityAfterDownLevel = function (node,downLevelData) {
             if(projectObj.project.projectInfo.property && projectObj.project.projectInfo.property.valuationType == "ration"){//工程量清单项目中,将B降级为A的子项后应清空A的工程量
                 let preNode = node.preSibling;

+ 1 - 1
web/building_saas/main/js/models/cache_tree.js

@@ -231,7 +231,7 @@ var cacheTree = {
         Node.prototype.upLevel = function () {
             var success = false,
                 iIndex = this.parent.children.indexOf(this), orgParent = this.parent, newNextSibling = this.parent.nextSibling;
-            if (this.canUpLevel) {
+            if (this.canUpLevel()) {
                 // NextSiblings become child
                 tools.addNodes(this.tree, this, this.parent.children.slice(iIndex + 1));
                 // Orginal Parent remove node and nextSiblings

+ 2 - 1
web/building_saas/main/js/models/calc_base.js

@@ -1400,7 +1400,8 @@ let calcBase = {
             node.updateData.calcBase = exp;
             node.updateData.calcBaseValue = parseFloat(calcBaseValue).toDecimal(decimalObj.decimal('totalPrice', node));
             node.updateData.tenderCalcBaseValue = parseFloat(tenderCalcBaseValue).toDecimal(decimalObj.decimal('totalPrice', node));
-            if (calculateUtil.isProgressive(exp, progression)) {
+            // progression来自overwrite里配置的全局变量
+            if (typeof progression !== 'undefined' && calculateUtil.isProgressive(exp, progression)) {
                 node.updateData.baseProgressiveFee = me.baseProgressiveFee;
             }
             node.changed = true;

+ 1 - 0
web/building_saas/main/js/models/calc_program.js

@@ -1914,6 +1914,7 @@ class CalcProgram {
             // 批量树结点计算后,计算程序早已物是人非,所以这里要重新计算一下。警告:第二个参数千万不能改成3,否则死循环!
             if (activeSubSheetIsCalcProgram())
                 calcProgramObj.refreshCalcProgram(projectObj.project.mainTree.selected, 2);
+            projectInfoObj.refreshTotalPriceSpan();
             $.bootstrapLoading.end();
         });
     };

+ 2 - 14
web/building_saas/main/js/models/project.js

@@ -374,21 +374,9 @@ var PROJECT = {
             }
             return false;
         };
-        //清单是否属于锁定范围(分部分项、措施项目)
+        // 清单是否属于锁定范围(所有清单)
         project.prototype.withinBillsLocked = function (node) {
-            const lockedFixFlag = [fixedFlag.SUB_ENGINERRING, fixedFlag.MEASURE];
-            while(node){
-                if(!node.parent){
-                    if(node.data.flagsIndex && node.data.flagsIndex.fixed && lockedFixFlag.includes(node.data.flagsIndex.fixed.flag)){
-                        return true;
-                    }
-                    else {
-                        return false;
-                    }
-                }
-                node = node.parent;
-            }
-            return true;
+            return node && node.sourceType === commonConstants.SourceType.BILLS;
         };
         project.prototype.updateNodes = function (datas,callback) {
           /*  let datas = [

+ 1 - 0
web/building_saas/main/js/models/project_glj.js

@@ -956,6 +956,7 @@ ProjectGLJ.prototype.calcEachFreightOrPrice = function (temp,type,priceMap) {//
           let ndoc = {};
           if(temp.unitFreight != sum) ndoc['unitFreight'] = sum;
           if(temp.exp != exp) ndoc['exp'] = exp;
+          if(temp.heightFee != heightFee) ndoc['heightFee'] = heightFee;
           if(!_.isEmpty(ndoc)) return {ID:temp.ID,doc:ndoc};
         }
         if(type == "price" && temp.supplyPrice !=sum) return {ID:temp.ID,doc:{supplyPrice:sum,heightFee:heightFee}}

+ 4 - 1
web/building_saas/main/js/models/quantity_detail.js

@@ -747,7 +747,10 @@ var quantity_detail = {
                             if(isNaN(times)){
                                 times = 1;
                             }
-                            rationNode.updateData.quantity = scMathUtil.roundForObj(ration_value / times,getDecimal("quantity",rationNode));
+                            let unitTimes = 1;//清单单位转定额单位的倍数,如 kg 转 t 时是1000
+                            if(gljUtil.isKGtoT(node.data.unit,rationNode.data.unit)) unitTimes = 1000;
+
+                            rationNode.updateData.quantity = scMathUtil.roundForObj(ration_value / (times * unitTimes),getDecimal("quantity",rationNode));
                             rationNode.updateData.contain = value?scMathUtil.roundForObj(rationNode.updateData.quantity/value,getDecimal("process")):0;
                             rationNode.changed = true;
                             needUpdateChildren.push(rationNode);

+ 25 - 3
web/building_saas/main/js/models/ration.js

@@ -318,6 +318,25 @@ var Ration = {
             ration1.serialNo = ration2.serialNo;
             ration2.serialNo = preSerialNo;
         };
+        ration.prototype.changeMultiPos = function (baseRation, rations) {
+            const updateData = [];
+            let tempSerialNo = baseRation.serialNo;
+            rations.forEach(ration => {
+                updateData.push({
+                    updateType: 'ut_update',
+                    updateData: this.getTempRationData(ration.ID, ration.billsItemID, tempSerialNo)
+                });
+                let orgSerialNo = ration.serialNo;
+                ration.serialNo = tempSerialNo;
+                tempSerialNo = orgSerialNo;
+            });
+            updateData.push({
+                updateType: 'ut_update',
+                updateData: this.getTempRationData(baseRation.ID, baseRation.billsItemID, tempSerialNo)
+            });
+            baseRation.serialNo = tempSerialNo;
+            this.project.pushNow('insertRation', [this.getSourceType()], [updateData]);
+        };
 
         ration.prototype.updateField = function (ration, field, newValue) {
             calcFees.setFee(ration, field, newValue);
@@ -796,9 +815,12 @@ var Ration = {
             node.updateData.contain = contain;
             node.updateData.quantityEXP="QDL*"+contain;
             node.updateData.quantity=scMathUtil.roundForObj(billQuantity*contain,getDecimal("quantity",node));
-            let times = parseInt(node.data.unit);
-            if (!isNaN(times)) {
-                node.updateData.quantityEXP+='*'+times;
+            if(!gljUtil.isKGtoT(billNode.data.unit,node.data.unit)){
+              console.log('hehe')
+              let times = parseInt(node.data.unit);
+              if (!isNaN(times)) {
+                  node.updateData.quantityEXP+='*'+times;
+              }
             }
             //  node.data.quantity = projectObj.project.quantity_detail.autoTransformQuantity(node.data.quantity,node);//按单位做转换
             node.changed = true;

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

@@ -446,6 +446,7 @@ function getActionUrl(actionType) {
     switch (actionType) {
         case 'add':
         case 'addMix':
+        case 'insert':  
         case 'unitPriceAddMix':
         case 'insertEquipment':
             return `${rootUrl}/0/true`;

+ 19 - 2
web/building_saas/main/js/views/importBills.js

@@ -75,7 +75,15 @@ const importBills = (function(){
                 let name = rootRow[0].value;
                 let existsRoot = findLast(rst, x => x.name === name && x.depth === 0);
                 if (!existsRoot) {
-                    let root = {ID: uuid.v1(), NextSiblingID: -1, ParentID: -1, name: name, depth: 0, parent: null};
+                    let root = {
+                        ID: uuid.v1(), 
+                        NextSiblingID: -1, 
+                        ParentID: -1, 
+                        name: name, 
+                        depth: 0, 
+                        parent: null,
+                        unitPriceAnalysis: 1
+                    };
                     let preData = findLast(rst, x => x.depth === root.depth);
                     if (preData) {
                         preData.NextSiblingID = root.ID;
@@ -167,7 +175,15 @@ const importBills = (function(){
                 quantity = dataTable[row][colMapping.quantity] ? dataTable[row][colMapping.quantity].value : null;
             if (!code) {    //没有编号的数据,名称必须为:清单 第xx章,认为新的表根节点
                 if (name && /清单 第\d+章/.test(name)) {
-                    curRoot = {code: null, name: name, ID: uuid.v1(), ParentID: -1, NextSiblingID: -1, parent: null};
+                    curRoot = {
+                        code: null, 
+                        name: name, 
+                        ID: uuid.v1(), 
+                        ParentID: -1, 
+                        NextSiblingID: -1, 
+                        parent: null,
+                        unitPriceAnalysis: 1
+                    };
                     rst.push(curRoot);
                 } else {
                     curRoot = null;
@@ -184,6 +200,7 @@ const importBills = (function(){
                     quantity: quantity,
                     ID: uuid.v1(),
                     NextSiblingID: -1,
+                    unitPriceAnalysis: 1
                 };
                 let lastData = rst[rst.length - 1];
                 let parents = getParents(lastData);

+ 18 - 22
web/building_saas/main/js/views/locate_view.js

@@ -358,6 +358,7 @@ let locateObject={
         }
         setBgColour(datas,priceMap);
         datas =  _.sortByAll(datas,['code']);
+        
         return datas;
 
 
@@ -365,31 +366,26 @@ let locateObject={
             let outStd = $("#outstanding").prop("checked");
             let outInp = $("#outInp").val();
             if(outStd == true && outInp && outInp!=""){
-                for(let b of bills){
-                    if(b.code && b.code.length >= 9){
-                        let key = b.code.substr(0,9);
-                        if(map[key] && map[key].count > 1){
-                            let avg = map[key].total/map[key].count;
-                            let unitPrice = b.unitPrice?parseFloat(b.unitPrice):0;
-                            if(unitPrice ==0 ) continue;
-                            if(Math.abs(unitPrice - avg)/avg * 100  >= parseFloat(outInp)) b.bgColour = "#FFFACD"
-                        }
-                    }
+              let key = "smartcost";// 2020-06-02  养护与建筑不同,养护是把所有结果相加取平均
+              if(map[key] && map[key].count > 1){
+                let avg = map[key].total/map[key].count;
+                for(let b of bills){ 
+                  let unitPrice = b.unitPrice?parseFloat(b.unitPrice):0;
+                  if(unitPrice ==0 ) continue;
+                  if(Math.abs(unitPrice - avg)/avg * 100  >= parseFloat(outInp)) b.bgColour = "#FFFACD"
                 }
+              }
             }
         }
-        function setPriceMap (bills,map) {
-            if(bills.code && bills.code.length >= 9){
-                let key = bills.code.substr(0,9);
-                let unitPrice = bills.unitPrice?parseFloat(bills.unitPrice):0;
-                if(map[key]){
-                    map[key].total += unitPrice;
-                    map[key].count ++;
-                }else {
-                    map[key] = {total:unitPrice,count:1}
-                }
-
-            }
+        function setPriceMap (bills,map) { // 2020-06-02  养护与建筑不同,养护是把所有结果相加取平均
+          let key = "smartcost";
+          let unitPrice = bills.unitPrice?parseFloat(bills.unitPrice):0;
+          if(map[key]){
+              map[key].total += unitPrice;
+              map[key].count ++;
+          }else {
+              map[key] = {total:unitPrice,count:1}
+          }
 
             return map;
         }

+ 6 - 1
web/building_saas/main/js/views/material_calc_view.js

@@ -231,8 +231,12 @@ materialCalcObj = {
         this.materialDatas = this.getMaterialCalcDatas();
         sheetCommonObj.showData(this.materialSheet, this.materialSetting,this.materialDatas);
         this.materialSheet.setRowCount(this.materialDatas.length);
-        sel.row = oldData?_.findIndex(this.materialDatas,{'id':oldData.id}):-1;
+        let pglj = projectGljObject.getProjectGLJSelected()
+        sel.row = pglj?_.findIndex(this.materialDatas,{'id':pglj.id}):-1;
+        if(sel.row == -1) sel.row = oldData?_.findIndex(this.materialDatas,{'id':oldData.id}):-1;
+      
         this.materialSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
+        this.materialSheet.showRow(sel.row==-1?0:sel.row, GC.Spread.Sheets.VerticalPosition.center);
     },
     showPriceDatas:function () {
         if(!$('#priceSheet').is(':visible')) return;
@@ -317,6 +321,7 @@ materialCalcObj = {
         if(newSel.row != oldSel.row){
             me.showPriceDatas();
             me.showFreightDatas();
+            projectGljObject.setSelectionWhenMaterialChange(me.getMaterialSelected())
         }
     },
     onFreightSelectionChange:function (sender,args) {

+ 84 - 6
web/building_saas/main/js/views/project_glj_view.js

@@ -13,6 +13,19 @@ projectGljObject={
     materialTreeSheet:null,
     projectGljSheetData:[],
     mixRatioSetting:{},
+    relatedRationSetting:{
+      header:[
+        {headerName: "编码", headerWidth: 100, dataCode: "code", dataType: "String"},
+        {headerName: "名称", headerWidth: 180, dataCode: "name", dataType: "String"},
+        {headerName: "单位", headerWidth: 50, dataCode: "unit", dataType: "String",hAlign: "center"},
+        {headerName: "工程量", headerWidth: 65, dataCode: "quantity", dataType: "Number", hAlign: "right",decimalField: "ration.quantity"},
+        {headerName: "单价", headerWidth: 65, dataCode: "feesIndex.common.unitFee", dataType: "Number", hAlign: "right",decimalField: "ration.unitPrice"}
+    ],
+    view: {
+        lockColumns: [0,1,2,3,4]//,
+        //colHeaderHeight:30
+      }
+    },
     materialTreeSetting:{
         "emptyRows":0,
         "headRows":1,
@@ -90,13 +103,15 @@ projectGljObject={
         }
     },
     initMixRatioSpread:function () {
-        this.mixRatioSpread = SheetDataHelper.createNewSpread($("#mix_ratio_sheet")[0]);
+        this.mixRatioSpread = SheetDataHelper.createNewSpread($("#mix_ratio_sheet")[0],2);
         sheetCommonObj.spreadDefaultStyle(this.mixRatioSpread);
-        this.mixRatioSheet = this.mixRatioSpread .getSheet(0);
+        this.mixRatioSheet = this.mixRatioSpread.getSheet(0);
         this.initSheet(this.mixRatioSheet,this.mixRatioSetting);
         this.mixRatioSheet.name('mixRatioSheet');
         this.mixRatioSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onMixRatioEditStarting);
         this.mixRatioSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMixRatioRangeChange);
+
+        this.initRelatedRationSheet();
         if(projectReadOnly){
             if(this.mixRatioSetting.view.lockColumns){
                 this.mixRatioSetting.view.lockColumns = null;
@@ -104,6 +119,14 @@ projectGljObject={
             disableSpread(this.mixRatioSpread);
         }
     },
+    initRelatedRationSheet:function(){
+      this.relatedRationSheet = this.mixRatioSpread.getSheet(1); 
+      sheetCommonObj.initSheet(this.relatedRationSheet, this.relatedRationSetting, 30);
+      this.relatedRationSheet.name('relatedRation');
+      this.relatedRationSheet.bind(GC.Spread.Sheets.Events.CellDoubleClick, this.onRelatedRationDoubleClick);
+      //this.mixRatioSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMixRatioRangeChange);
+    },
+
     initMaterialTreeSheet:function () {
         this.materialTreeSheet = this.projectGljSpread.getSheet(1);
         this.materialTreeSetting = this.createMaterialTreeSheetSetting();
@@ -265,6 +288,8 @@ projectGljObject={
 
     showMixRatioData:function () {
         let me = this,gljId = null,gljType = null;
+        if(!$('#mixRatio-nav').hasClass('active')) return;
+        me.mixRatioSpread.setActiveSheetIndex(0);
         let oldSel = me.mixRatioSheet.getSelections()[0];
         let projectGLJData = me.getSelectedProjectGLJ();
         if(projectGLJData){
@@ -290,6 +315,28 @@ projectGljObject={
             me.mixRatioSheet.setSelection(oldSel.row==-1?0:oldSel.row,oldSel.col,oldSel.rowCount,oldSel.colCount);
         })
     },
+    showRelatedRationDatas:function(){
+      let me = this,gljId = null,gljType = null;
+      if(!$('#ration-nav').hasClass('active')) return;
+      me.mixRatioSpread.setActiveSheetIndex(1);
+      let projectGLJData = me.getSelectedProjectGLJ();
+      let rationIDMap = {};
+      let rations = [];
+      if(projectGLJData){
+         for(let rg of projectObj.project.ration_glj.datas){
+            if(rg.projectGLJID == projectGLJData.id) rationIDMap[rg.rationID] = true;
+         } 
+         for(let r of projectObj.project.Ration.datas){
+            if(rationIDMap[r.ID] || (r.subType == rationType.gljRation && r.projectGLJID== projectGLJData.id)){
+              rations.push(r);
+            }
+         } 
+      }
+      this.relatedRationSheetData = rations;
+      sheetCommonObj.showData(me.relatedRationSheet, me.relatedRationSetting,rations);
+      me.relatedRationSheet.setRowCount(rations.length);
+    },
+
     getMixRatioSheetData:function (glj) {
         let data ={
             id:glj.id,
@@ -377,8 +424,29 @@ projectGljObject={
         let dataCode = me.projectGljSetting.header[args.col].dataCode;
         if(dataCode=='name'&& recode && gljUtil.isMaterialType(recode.type)) projectObj.project.projectGLJ.updateCalcMaterial(recode,'calcMaterial',1);
     },
-    onProjectGljSelectionChange:function (sender, args) {
+    onRelatedRationDoubleClick:function (sender,args) {
+      let me = projectGljObject;
+      let record = me.relatedRationSheetData[args.row];
+      $("#tab_zaojiashu").click();
+      locateObject.locateNode(record.ID);
+    },
+    setSelectionWhenMaterialChange:function(material){
+      if(material){
+        let i = _.findIndex(this.projectGljSheetData,{id:material.id})
+        if(i != -1){
+          let os = this.projectGljSheet.getSelections();
+          let ns = [{col:os[0].col,colCount:1,row:i,rowCount:1}]
+          this.projectGljSheet.setSelection(ns[0].row,ns[0].col,ns[0].rowCount,ns[0].colCount);
+          this.projectGljSheet.showRow(i, GC.Spread.Sheets.VerticalPosition.center);
+          this.onProjectGljSelectionChange({},{newSelections:ns,oldSelections:os},true);
+        }
+
+
+      }
+    },
+    onProjectGljSelectionChange:function (sender, args,fromMaterial=false) {
         let me = projectGljObject;
+        console.log(args)
         let newSel = args.newSelections[0];
         let oldSel = args.oldSelections?args.oldSelections[0]:{};
         me.projectGljSheet.suspendPaint();
@@ -390,7 +458,7 @@ projectGljObject={
             if(me.projectGljSheetData[orow]){
               let tstyle = gljOprObj.getSelStyle(false,{},me.projectGljSheetData[orow].bgColour);
               me.projectGljSheet.setStyle(orow, -1, tstyle);
-              me.projectGljRowChang();
+              me.projectGljRowChang(fromMaterial);
             }
         }else{
           me.projectGljSheet.repaint();
@@ -398,7 +466,7 @@ projectGljObject={
         me.projectGljSheet.resumeEvent();
         me.projectGljSheet.resumePaint();
     },
-    projectGljRowChang:function(row){
+    projectGljRowChang:function(fromMaterial){
         let me = projectGljObject;
         let sel = me.mixRatioSheet.getSelections()[0];
         sel.row = -1;
@@ -406,6 +474,8 @@ projectGljObject={
         sel.rowCount = 1;
         sel.colCount = 1;
         me.showMixRatioData();
+        me.showRelatedRationDatas();
+        if(fromMaterial != true) materialCalcObj.showDatas();
     },
     rightClickCallback:function (row) {
         let me = projectGljObject;
@@ -622,7 +692,7 @@ projectGljObject={
         this.projectGljSheet.setRowCount(this.projectGljSheetData.length);
         sheetCommonObj.showData(this.projectGljSheet, this.projectGljSetting,this.projectGljSheetData);
         //this.projectGljSheet.setRowCount(this.projectGljSheetData.length);
-        sel.row = oldData?_.findIndex(this.projectGljSheetData,{'id':oldData.id}):'';
+        sel.row = oldData?_.findIndex(this.projectGljSheetData,{'id':oldData.id}):0;
         this.projectGljSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
     },
     showMaterialTreeData:function () {
@@ -659,6 +729,7 @@ projectGljObject={
         }else {
             me.showProjectGljData();
             me.showMixRatioData();
+            me.showRelatedRationDatas();
         }
     },
     createMaterialTree:function (gljList) {
@@ -850,6 +921,7 @@ projectGljObject={
             me.projectGljSheetData.splice(row,1);
             me.projectGljSheet.deleteRows(row,1);
             me.showMixRatioData();
+            me.showRelatedRationDatas();
         }
         //me.projectGljSheetData[row] = me.getSheetDataByGLJ(glj);
     },
@@ -1504,7 +1576,13 @@ $(function () {
 
     $("#mixRatio-nav").on('shown.bs.tab', function () {
         projectGljObject.mixRatioSpread.refresh();
+        projectGljObject.showMixRatioData();
     });
+    $("#ration-nav").on('shown.bs.tab', function () {
+      projectGljObject.mixRatioSpread.refresh();
+      projectGljObject.showRelatedRationDatas();
+      console.log('hehe');
+  });
 });
 
 

+ 12 - 1
web/building_saas/main/js/views/project_info.js

@@ -81,7 +81,10 @@ var projectInfoObj = {
             projFeatureView.orgDatas = data.property.projectFeature ? projFeatureView.toViewDatas(data.property.projectFeature) : [];
             $('#fullpath').html(this.getFullPathHtml(data));
             // 分享给
-            $('#init-share').click(() => SHARE_TO.initModal(projectObj.project.ID()));
+            $('#init-share').click(() => {
+                SHARE_TO.initModal(projectObj.project.ID());
+                $('#share-tip').tooltip('hide');
+            });
             SHARE_TO.handleEventListener();
             $("[data-toggle='tooltip']").tooltip();
             if (data.property.valuationType == 'bill') {
@@ -90,5 +93,13 @@ var projectInfoObj = {
                 $("#about-calc").css('display', 'none');
             };
         }
+    },
+    // 刷新总造价显示span
+    refreshTotalPriceSpan: function () {
+        const totalNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.TOTAL_COST);
+        const price = totalNode ? calcTools.getFee(totalNode, 'common.tenderTotalFee') : '0';
+        const standardPrice = commonUtil.standardNumber(price);
+        const text = `总造价:${standardPrice} 元`;
+        $('#total-price-span').text(text);
     }
 };

+ 128 - 100
web/building_saas/main/js/views/project_view.js

@@ -69,78 +69,66 @@ var projectObj = {
             }
         };
         let selected = tree.selected, that = projectObj;
-
-        let canUpLevel = function (node) {
-            if(!node){
-                return false;
-            }
-            if(projectObj.project.isBillsLocked()== true && projectObj.project.withinBillsLocked(node)){
+        const validNodes = projectObj.mainController.getValidNodesWithinSelection();
+        const canUpLevel = function (nodes) {
+            if (!nodes.length || projectObj.project.isBillsLocked()) {
                 return false;
             }
-            if(node.depth()<=1){//焦点行是树结构的第一/二层节点,灰显。
+            const firstNode = nodes[0];
+            const lastNode = nodes[nodes.length - 1];
+            if (firstNode.depth() <= 1) { // 首节点是树结构的第一/二层节点,灰显。
                 return false;
             }
-            if(node.sourceType !== that.project.Bills.getSourceType()){//焦点行是定额/量价/工料机,灰显。
+            if (firstNode.sourceType !== commonConstants.SourceType.BILLS) { // 首节点是定额/量价/工料机,灰显。
                 return false;
-            }else {
-                if(node.data.type == billType.FX || node.data.type == billType.BX){//是分项,或者补项灰显。
-                    return false;
-                }
-                if(node.data.type == billType.FB&&node.nextSibling&&node.children.length>0){//焦点行是分部有后兄弟,有子项.
-                     if(node.children[0].data.type==billType.FX || node.children[0].data.type==billType.BX){ //焦点行子项是分项
-                         return false;
-                     }
-                }
-                if(node.data.type == billType.BILL &&node.nextSibling){//焦点行是清单有后兄弟
-                    if(node.data.calcBase&&node.data.calcBase!=""){//有基数计算
+            } else {
+                if (lastNode.data.type == billType.BILL && lastNode.nextSibling) { // 末节点是清单有后兄弟
+                    if (lastNode.data.calcBase) { // 有基数计算
                         return false;
                     }
-                    if(node.children.length>0&&node.children[0].sourceType !== that.project.Bills.getSourceType()){//有子项,并且子项不是清单
+                    if (lastNode.children.length > 0 && lastNode.children[0].sourceType !== commonConstants.SourceType.BILLS) { // 有子项,并且子项不是清单
                         return false;
                     }
                 }
             }
             return true;
         };
-        let canDownLevel = function (node) {//
-            if(!node){
-                return false;
-            }
-            if(projectObj.project.isBillsLocked()== true && projectObj.project.withinBillsLocked(node)){
+        const canDownLevel = function (nodes) {
+            if (!nodes.length || projectObj.project.isBillsLocked()) {
                 return false;
             }
-            if(node.depth()==0){//焦点行是树结构的第一层节点,灰显。
+            const firstNode = nodes[0];
+            if (firstNode.depth() === 0) {// 首节点是树结构的第一层节点,灰显。
                 return false;
             }
-            if(node.sourceType !== that.project.Bills.getSourceType()) {//焦点行是定额/量价/工料机,灰显。
+            if (firstNode.sourceType !== commonConstants.SourceType.BILLS) { // 首节点是定额/量价/工料机,灰显。
                 return false;
-            }else {
-                if(node.data.type == billType.FX || node.data.type == billType.BX){//是分项,灰显。
-                    return false;
-                }
-                if(!node.preSibling){//无前兄弟,灰显
+            } else {
+                const preNode = firstNode.preSibling;
+                if (!preNode) { // 首节点无前兄弟,灰显
                     return false;
-                }else if(node.preSibling.data.calcBase&&node.preSibling.data.calcBase!=""){//前兄弟有基数计算
+                } else if (preNode.data.calcBase) { // 首节点前兄弟有基数计算
                     return false
                 }
-                if(node.preSibling.children.length>0){//前兄弟有子项,子项是分项,灰显。
-                    if(node.data.type==billType.FB&&(node.preSibling.children[0].data.type==billType.FX||node.preSibling.children[0].data.type==billType.BX)){//焦点行是分部前兄弟有子项,子项是分项,灰显。
-                        return false;
-                    }
-                    if(node.data.type==billType.BILL&&node.preSibling.children[0].sourceType !== that.project.Bills.getSourceType()){//焦点行是清单,子项不是清单
+                if (preNode.children.length > 0) {//前兄弟有子项,子项是分项,灰显。
+                    if (firstNode.data.type == billType.BILL && preNode.children[0].sourceType !== commonConstants.SourceType.BILLS) { // 首节点是清单,首节点前兄弟子项不是清单
                         return false
                     }
                 }
             }
             return true;
         };
-        let canUpMove = function (node) {
-            if(node&&node.preSibling){//有前兄弟
-                if(node.sourceType==that.project.Bills.getSourceType()){
-                    if(projectObj.project.isBillsLocked()== true && projectObj.project.withinBillsLocked(node)){
+        const canUpMove = function (nodes) {
+            if (!nodes.length) {
+                return false;
+            }
+            const firstNode = nodes[0];
+            if (firstNode && firstNode.preSibling) {
+                if (firstNode.sourceType == commonConstants.SourceType.BILLS) {
+                    if (projectObj.project.isBillsLocked()) {
                         return false;
                     }
-                    if(node.data.type == billType.DXFY&&node.data.isAdd!==1){
+                    if (firstNode.data.type == billType.DXFY && firstNode.data.isAdd !== 1) {
                         return false;
                     }
                 }
@@ -148,13 +136,17 @@ var projectObj = {
             }
             return false
         };
-        let canDownMove = function (node) {
-            if(node&&node.nextSibling){
-                if(node.sourceType==that.project.Bills.getSourceType()){
-                    if(projectObj.project.isBillsLocked()== true && projectObj.project.withinBillsLocked(node)){
+        const canDownMove = function (nodes) {
+            if (!nodes.length) {
+                return false;
+            }
+            const lastNode = nodes[nodes.length - 1];
+            if (lastNode && lastNode.nextSibling) {
+                if (lastNode.sourceType == commonConstants.SourceType.BILLS) {
+                    if (projectObj.project.isBillsLocked()) {
                         return false;
                     }
-                    if(node.data.type == billType.DXFY&&node.data.isAdd!==1){
+                    if (lastNode.data.type == billType.DXFY && lastNode.data.isAdd !== 1) {
                         return false;
                     }
                 }
@@ -165,10 +157,10 @@ var projectObj = {
 
         setButtonValid(projectObj.project.Ration.canAdd(selected), $('#insertRation'));
         setButtonValid(ifCanDelete(), $('#delete'));
-        setButtonValid(canUpLevel(selected), $('#upLevel'));
-        setButtonValid(canDownLevel(selected), $('#downLevel'));
-        setButtonValid(canUpMove(selected) , $('#upMove'));
-        setButtonValid(canDownMove(selected), $('#downMove'));
+        setButtonValid(canUpLevel(validNodes), $('#upLevel'));
+        setButtonValid(canDownLevel(validNodes), $('#downLevel'));
+        setButtonValid(canUpMove(validNodes), $('#upMove'));
+        setButtonValid(canDownMove(validNodes), $('#downMove'));
         setButtonValid(!projectObj.project.isBillsLocked(), $('#ZLFB_btn'));
 
     },
@@ -883,6 +875,7 @@ var projectObj = {
         let startTime = +new Date();
         $.bootstrapLoading.start();
         this.project.loadDatas(function (err) {
+            projectInfoObj.refreshTotalPriceSpan(); // 工具栏中的总造价信息
             let mTime = +new Date();
             projectInfoObj.showProjectInfo(that.project.projectInfo);
             //快速列设置
@@ -1321,6 +1314,26 @@ var projectObj = {
                         return canInsertRationNode(selected);
                     }*/
                 },
+                "insertGLJ": {
+                  name: "插入人材机",
+                  icon: 'fa-sign-in',
+                  disabled: function () {
+                      if (projectReadOnly) {
+                          return true;
+                      }
+                      // var selected = project.mainTree.selected;
+                      // return project.Ration.addRationChecking(selected);  // Vincent, 2018-01-02
+                      return !project.Ration.canAdd(project.mainTree.selected);
+                  },
+                  callback: function (key, opt) {
+                    let selected = project.mainTree.selected;
+                    if(selected.data.calcBase&&selected.data.calcBase!=""){
+                        alert("当前有基数计算,不能插入定额/量价/工料机。");
+                        return;
+                    }
+                    getGLJData('insert');// ProjectController.addRation(project, controller, rationType.volumePrice);
+                  }
+                },
                 "insertLJ": {
                     name: "插入量价",//插入量价不需要自动定位到编号列
                     icon: 'fa-sign-in',
@@ -1359,7 +1372,7 @@ var projectObj = {
                         }
                     }
                 },
-                "insertGLJ": {
+                "insertEquipment": {
                     name: "插入设备",
                     icon: 'fa-sign-in',
                     disabled: function () {
@@ -2127,26 +2140,34 @@ $('#delete').click(function () {
     }
 });
 
-$('#upLevel').click(function () {
-    var controller = projectObj.mainController, project = projectObj.project;
-    var selected = controller.tree.selected, orgParent = selected.parent;
-    if (selected && selected.sourceType === project.Bills.getSourceType()) {
-        project.Bills.upLevelBills(selected.source);
-        controller.upLevel();
-        controller.refreshTreeNode([orgParent, selected]);
-        projectObj.project.calcProgram.calcNodesAndSave([selected,orgParent]);
-    }
-});
-$('#downLevel').click(function () {
-    var controller = projectObj.mainController, project = projectObj.project;
-    var selected = controller.tree.selected;
-    if (selected && selected.sourceType === project.Bills.getSourceType()) {
-        project.Bills.downLevelBills(selected.source);
-        controller.downLevel();
-        controller.refreshTreeNode([selected.parent]);
-        projectObj.converseCalculateBills(selected.parent);
-    }
-});
+// TODO 造价书节点的升降级、上下移都是异步的,不等服务器响应直接进行前端更新的。有风险,后续可能需要改。
+// 节流,防止快速触发
+const throttleTime = 400;
+const throttleUpLevel = _.throttle(() => {
+    const controller = projectObj.mainController;
+    const project = projectObj.project;
+    const mainTreeNodes = controller.getValidNodesWithinSelection();
+    const billsNodes = mainTreeNodes.map(node => node.source);
+    const orgParent = mainTreeNodes[0].parent;
+    project.Bills.multiUpLevelBills(project.Bills.tree, billsNodes);
+    controller.multiUpLevel(mainTreeNodes);
+    const refreshNodes = [orgParent, ...mainTreeNodes];
+    controller.refreshTreeNode(refreshNodes);
+    projectObj.project.calcProgram.calcNodesAndSave(refreshNodes);
+}, throttleTime);
+$('#upLevel').click(throttleUpLevel);
+const throttleDownLevel = _.throttle(() => {
+    const controller = projectObj.mainController
+    const project = projectObj.project;
+    const mainTreeNodes = controller.getValidNodesWithinSelection();
+    const billsNodes = mainTreeNodes.map(node => node.source);
+    const orgParent = mainTreeNodes[0].parent;
+    project.Bills.multiDownLevelBills(project.Bills.tree, billsNodes);
+    controller.multiDownLevel(mainTreeNodes);
+    controller.refreshTreeNode([orgParent, ...mainTreeNodes]);
+    projectObj.converseCalculateBills(orgParent);
+}, throttleTime);
+$('#downLevel').click(throttleDownLevel);
 $('#insertRation').click(function () {
     // projectObj.project.Ration.addNewRation(null,rationType.ration);
     // 连续点工具栏的插入定额按钮,显示树结构画线有问题。
@@ -2154,32 +2175,39 @@ $('#insertRation').click(function () {
     //2020-01-08  要限制定额数量,所以还是要用等回传信息的方式插入定额
     projectObj.project.Ration.addNewRation(null,rationType.ration,projectObj.selectColAndFocus,false);
 });
-$('#upMove').click(function () {
-    var controller = projectObj.mainController, project = projectObj.project;
-    var selected = controller.tree.selected, pre = selected.preSibling, preSerialNo;
-
-    if (selected.sourceType === project.Bills.getSourceType()) {
-        project.Bills.upMoveBills(selected.source);
-        controller.upMove();
-    } else if (selected.sourceType === project.Ration.getSourceType()) {
-        project.Ration.changePos(selected.source, selected.preSibling.source);
-        controller.upMove();
+const throttleUpMove = _.throttle(() => {
+    const controller = projectObj.mainController
+    const project = projectObj.project;
+    const mainTreeNodes = controller.getValidNodesWithinSelection();
+    const sourceNodes = mainTreeNodes.map(node => node.source);
+    const firstNode = mainTreeNodes[0];
+    if (firstNode.sourceType === commonConstants.SourceType.BILLS) {
+        project.Bills.multiUpMoveBills(project.Bills.tree, sourceNodes);
+        controller.multiUpMove(mainTreeNodes);
+    } else if (firstNode.sourceType === commonConstants.SourceType.RATION) {
+        //project.Ration.changePos(selected.source, selected.preSibling.source);
+        project.Ration.changeMultiPos(mainTreeNodes[0].preSibling.source, sourceNodes);
+        controller.multiUpMove(mainTreeNodes);
     };
-});
-$('#downMove').click(function () {
-    var controller = projectObj.mainController, project = projectObj.project;
-    var selected = controller.tree.selected, next, nextSerialNo;
-
-    if (selected) {
-        if (selected.sourceType === project.Bills.getSourceType()) {
-            project.Bills.downMoveBills(selected.source);
-            controller.downMove();
-        } else if (selected.sourceType === project.Ration.getSourceType()) {
-            project.Ration.changePos(selected.source, selected.nextSibling.source);
-            controller.downMove();
-        };
-    }
-});
+}, throttleTime);
+$('#upMove').click(throttleUpMove);
+const throttleDownMove = _.throttle(() => {
+    const controller = projectObj.mainController
+    const project = projectObj.project;
+    const mainTreeNodes = controller.getValidNodesWithinSelection();
+    const sourceNodes = mainTreeNodes.map(node => node.source);
+    const firstNode = mainTreeNodes[0];
+    if (firstNode.sourceType === commonConstants.SourceType.BILLS) {
+        project.Bills.multiDownMoveBills(project.Bills.tree, sourceNodes);
+        controller.multiDownMove(mainTreeNodes);
+    } else if (firstNode.sourceType === commonConstants.SourceType.RATION) {
+        const nextSource = mainTreeNodes[mainTreeNodes.length - 1].nextSibling.source;
+        const reverseSource = [...sourceNodes].reverse();
+        project.Ration.changeMultiPos(nextSource, reverseSource);
+        controller.multiDownMove(mainTreeNodes);
+    };
+}, throttleTime);
+$('#downMove').click(throttleDownMove);
 $("a[name='lockBills']").click(function () {//点击锁定/解锁清单
     let lockBills = projectObj.project.projectInfo.property.lockBills;
     lockBills = !lockBills;
@@ -2999,9 +3027,9 @@ function doAfterImport(resData){
             doAfterImportPosition(data);
         }
         //如果清单未锁定,导入后锁定清单
-        /*if(!projectObj.project.projectInfo.property.lockBills){
+        if(!projectObj.project.projectInfo.property.lockBills){
             $("a[name='lockBills']").click();
-        }*/
+        }
         $.bootstrapLoading.end();
         //重算
         projectObj.project.calcProgram.calcAllNodesAndSave(calcAllType.catAll, function () {

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

@@ -281,7 +281,6 @@ function refreshSubSpread(){
     if(subSpread) subSpread.refresh();
     if(MaterialController.spread) MaterialController.spread.refresh();
     BillsElf.refreshWorkBook();
-    //if($('#linkZMHS').hasClass('active')) zmhs_obj.refresh();
     if($('#rnc-zm').is(':visible')|| $('#rnc-fz').is(':visible') || $('#rnc-cus') || $('#rnc-stable').is(':visible')) zmhs_obj.refresh();
     if($('#linkMBZM').hasClass('active')) mbzm_obj.refresh();
 }

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

@@ -297,7 +297,6 @@ let zmhs_obj = {
     refresh:function () {
         $('#coeSpread').is(':visible')&&this.coeSpread?this.coeSpread.refresh():'';
         $('#coeSpread').is(':visible')&&this.coeSpread?this.showDatas():'';//这里combobox下拉框要重新加载一下
-        $('#coeSpread').is(':visible')&&this.coeSpread?this.coeSpread.refresh():'';
         $('#cusSpread').is(':visible')&&this.cusSpread?this.cusSpread.refresh():'';
         $('#assSpread').is(':visible')&&this.assSpread?this.assSpread.refresh():'';
         $('#stableSpread').is(':visible')&&this.stableSpread?this.stableSpread.refresh():'';

+ 10 - 5
web/building_saas/pm/js/pm_newMain.js

@@ -304,7 +304,7 @@ const projTreeObj = {
         },
         saveAs: {
             name: "另存为",
-            icon: 'fa-copy',
+            icon: 'fa-paste',
             disabled: function () {
                 const node = projTreeObj.tree.selected;
                 return !(node && node.data.projType === projectType.tender);
@@ -2069,7 +2069,7 @@ $(document).ready(function() {
         $('#save-as-name').val(name);
         setTimeout(() => $('#save-as-name')[0].focus(), 300);
     });
-    $('#save-as-confirm').click(async function () {
+    $('#save-as-confirm').click(_.throttle(async function () {
         try {
             const name = $('#save-as-name').val().trim();
             if (!name) {
@@ -2092,15 +2092,20 @@ $(document).ready(function() {
             projectData['shareInfo'] = [];
             projectData['name'] = name;
             projectMap['copy'] = { document: projectData };
-            $("#save-as-dialog").modal('hide');
+            //$("#save-as-dialog").modal('hide');
             $.bootstrapLoading.progressStart('拷贝项目', true);
             $("#progress_modal_body").text('正在拷贝项目,请稍候……');
             await ajaxPost('/pm/api/copyProjects', {projectMap:projectMap,user_id: userID, tenderCount: 1});
-            await importProcessChecking(null, null, (newProjectData) => handleTenderAfterChecking(newProjectData, projectData));
+            await importProcessChecking(null, null, (newProjectData) => {
+                handleTenderAfterChecking(newProjectData, projectData);
+                if (newProjectData) {
+                    $('#save-as-dialog').modal('hide');
+                }
+            });
         } catch (err) {
             alert(err);
         }
-    });
+    }, 2000));
 
     $('#selectSameTypeProject').click(function(){
         let value = $(this).prop('checked') == true?1:0;

+ 18 - 0
web/over_write/js/nongcun_2020.js

@@ -89,3 +89,21 @@
 
     overwrite();
 })();
+
+// 清单基数(仅能使用行引用)
+if (typeof baseFigureMap !== 'undefined') {
+    baseFigureMap.budget = {};
+    baseFigureMap.boq = {};
+}
+if (typeof baseFigureTemplate !== 'undefined') {
+    baseFigureTemplate.budget = {};
+    baseFigureTemplate.boq = {};
+}
+
+
+if (typeof module !== 'undefined') {
+    module.exports = {
+        progression: [],
+        deficiency: {}
+    };
+}

+ 7 - 0
web/over_write/js/shandong_2016.js

@@ -0,0 +1,7 @@
+if (typeof module !== 'undefined') {
+  module.exports = { 
+      getDefalutAssistProductionFeeRate: function () {
+          return 5
+      }
+  };
+}

+ 7 - 0
web/over_write/js/sichuan_2013.js

@@ -0,0 +1,7 @@
+if (typeof module !== 'undefined') {
+  module.exports = { 
+      getDefalutAssistProductionFeeRate: function () {
+          return 5
+      }
+  };
+}