Explorar el Código

超高降效相关

vian hace 5 años
padre
commit
fcfdd3b9a2
Se han modificado 29 ficheros con 1346 adiciones y 100 borrados
  1. 1 0
      .gitignore
  2. 1 0
      config/gulpConfig.js
  3. 2 1
      modules/all_models/ration.js
  4. 22 1
      modules/bills_lib/models/bills_lib_interfaces.js
  5. 10 0
      modules/main/controllers/project_controller.js
  6. 109 0
      modules/main/facade/project_facade.js
  7. 1 0
      modules/main/routes/project_route.js
  8. 18 3
      public/common_util.js
  9. 2 2
      public/web/common_ajax.js
  10. 33 0
      public/web/sheet/sheet_common.js
  11. 6 0
      web/building_saas/css/custom.css
  12. 12 12
      web/building_saas/main/html/main.html
  13. 4 0
      web/building_saas/main/js/controllers/block_controller.js
  14. 1 0
      web/building_saas/main/js/controllers/material_controller.js
  15. 21 0
      web/building_saas/main/js/models/bills.js
  16. 968 59
      web/building_saas/main/js/models/overHeight.js
  17. 6 0
      web/building_saas/main/js/models/project.js
  18. 21 2
      web/building_saas/main/js/models/project_glj.js
  19. 2 0
      web/building_saas/main/js/models/quantity_detail.js
  20. 29 3
      web/building_saas/main/js/models/ration.js
  21. 5 1
      web/building_saas/main/js/models/ration_glj.js
  22. 9 5
      web/building_saas/main/js/views/glj_view.js
  23. 8 4
      web/building_saas/main/js/views/glj_view_contextMenu.js
  24. 6 4
      web/building_saas/main/js/views/main_tree_col.js
  25. 1 0
      web/building_saas/main/js/views/mbzm_view.js
  26. 1 0
      web/building_saas/main/js/views/project_glj_view.js
  27. 45 3
      web/building_saas/main/js/views/project_view.js
  28. 1 0
      web/building_saas/main/js/views/zlfb_view.js
  29. 1 0
      web/common/html/header.html

+ 1 - 0
.gitignore

@@ -2,6 +2,7 @@ node_modules/
 .git/
 dist/
 .idea/
+.vscode/
 tmp/*.xlsx
 tmp/*.pdf
 tmp/*.jsp

+ 1 - 0
config/gulpConfig.js

@@ -11,6 +11,7 @@ module.exports = {
         'lib/bootstrap/bootstrap.min.js',
         'lib/bootstrap/bootstrap-submenu.js',
         'web/building_saas/js/*.js',
+        'public/common_util.js',
         'public/web/scMathUtil.js',
         'public/web/gljUtil.js',
         'public/web/PerfectLoad.js',

+ 2 - 1
modules/all_models/ration.js

@@ -88,7 +88,8 @@ let rationSchema = new Schema({
     remark:String,
     bookmarkBackground:String,//书签背景色
     bookmarkAnnotation:String,//批注
-    overHeight: String // 超高降效
+    overHeight: String, // 超高降效
+    referenceRationList: {type: Array, default: []} // 关联的定额ID列表,如超高子目关联的定额ID列表
 });
 
 let ration = mongoose.model("ration", rationSchema, "ration");

+ 22 - 1
modules/bills_lib/models/bills_lib_interfaces.js

@@ -3030,7 +3030,28 @@ billsLibDao.prototype.edUpdateItem = function(data, callback){
         }
     });
 };
-//
+
+// 将标准清单的某些属性转换为项目清单的数据
+billsLibDao.prototype.getDataToProjectBills = function (stdBills) {
+    // 处理工作内容和项目特征
+    const jobContent = stdBills.jobContent
+        .map(({ serialNo, content }) => ({ serialNo, content, isChecked: true }));
+    const itemCharacter = stdBills
+        .itemCharacter.map(({ serialNo, content }) => ({ serialNo, character: content, eigenvalue: [], isChecked: false }));
+    const itemCharacterText = "[项目特征]\n[工作内容]\n" + stdBills.jobContentText;
+    const jobContentText = '';
+    return {
+        jobContent,
+        itemCharacter,
+        itemCharacterText,
+        jobContentText,
+        programID: stdBills.engineering, // 取费专业
+        comments: stdBills.recharge, // 说明
+        name: stdBills.name,
+        unit: stdBills.unit,
+        ruleText: stdBills.ruleText,
+    };
+}
 
 billsLibDao.prototype.getStdBillsByCode = async function (data, callback) {
     let findData = function (value, field, Array) {

+ 10 - 0
modules/main/controllers/project_controller.js

@@ -123,6 +123,16 @@ module.exports = {
         }
         res.json(result);
     },
+    async calcOverHeightFee (req, res) {
+        try {
+            const data = JSON.parse(req.body.data);
+            const rst = await project_facade.calcOverHeightFee(data);
+            res.json({ error: 0, data: rst, message: 'success' });
+        } catch (err) {
+            console.log(err);
+            res.json({ error: 1, data: null, message: err.message });
+        }
+    },
     saveProperty: function(req, res){
         let result = {error: 0, message: '', data: null};
         let data = JSON.parse(req.body.data);

+ 109 - 0
modules/main/facade/project_facade.js

@@ -7,6 +7,7 @@ module.exports = {
     removeProjectMark:removeProjectMark,
     updateNodes:updateNodes,
     calcInstallationFee:calcInstallationFee,
+    calcOverHeightFee: calcOverHeightFee,
     saveProperty: saveProperty,
     getDefaultColSetting: getDefaultColSetting,
     markProjectsToChange:markProjectsToChange,
@@ -40,6 +41,7 @@ let mainQuantityLib = mongoose.model('std_main_quantity_lib');
 let materialLib = mongoose.model('std_material_lib');
 import fixedFlag from '../../common/const/bills_fixed';
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
+const billsLibDao = require("../../bills_lib/models/bills_lib_interfaces");
 
 async function calcInstallationFee(data) {
     let result={};
@@ -149,6 +151,113 @@ function generateTasks(data,userID) {
     return tasks;
 }
 
+/**
+ * 计取超高降效费,可能包含更新清单、更新定额、新增清单、新增定额及其子数据、删除定额及其子数据
+ * @param {Object} data - {updateData: {ration: [],..}, addData: {ration: [],...}, deleteData: {ration: [],...}}
+ * @return {Object} - {bills: Array, rationGLJ: Array}
+ */
+async function calcOverHeightFee(data) {
+    // 更新数据
+    async function update({ project, bills, ration }) {
+        const tasks = [];
+        // 更新项目
+        if (project && project.ID) {
+            const projectTask = projectsModel.update({ ID: project.ID }, 
+                { 'property.overHeightOption': project.overHeightOption, 'property.overHeightSpecificID': project.overHeightSpecificID });
+            tasks.push(projectTask);
+        }
+        // 更新清单和定额的超高降效列
+        const models = [];
+        if (bills.length) {
+            models.push({ model: bill_model.model, items: bills });
+        }
+        if (ration.length) {
+            models.push({ model: ration_model.model, items: ration });
+        }
+        models.forEach(modelData => {
+            const bulkTask = modelData.items.map(item => (
+                {
+                    updateOne: {
+                        filter: { ID: item.ID },
+                        update: { overHeight: item.overHeight }
+                    }
+                }));
+            const task = modelData.model.bulkWrite(bulkTask);
+            tasks.push(task);;
+        });
+        if (!tasks.length) {
+            return;
+        }
+        await Promise.all(tasks);
+    }
+    // 插入数据
+    async function add({ bills, ration, rationGLJ}) {
+        const tasks = [];
+        // 匹配标准清单,加上工作内容等数据
+        for (const billsItem of bills) {
+            let stdBills = await billsLibDao.getStdBillsByCode(billsItem);
+            stdBills = stdBills ? stdBills._doc : null;
+            if (stdBills) {
+                // 获取项目清单所需要的数据
+                const projectBillsData = billsLibDao.getDataToProjectBills(stdBills);
+                Object.assign(billsItem, projectBillsData);
+            } else {
+                delete billsItem.billsLibId;
+            }
+            billsItem.code += '001';
+        }
+        // 新增清单
+        if (bills.length) {
+            tasks.push(bill_model.model.insertMany(bills));
+        }
+        // 新增定额
+        if (ration.length) {
+            tasks.push(ration_model.model.insertMany(ration));
+        }
+        // 完整的定额人材机数据
+        let completeRationGLJList = [];
+        if (rationGLJ.length) {
+            // 定额人材机需要新增项目人材机、单价文件、且返回完整的定额人材机数据
+            const rationGLJTasks = rationGLJ.map(glj => addInstallationGLJ(glj));
+            completeRationGLJList = await Promise.all(rationGLJTasks);
+            // 新增定额人材机
+            tasks.push(ration_glj_model.insertMany(completeRationGLJList));
+        }
+        // 返回新的清单和定额人材机数据
+        const rst = {
+            bills,
+            rationGLJ: completeRationGLJList,
+        }
+        if (!tasks.length) {
+            return rst;
+        }
+        await Promise.all(tasks);
+        return rst;
+    }
+    // 删除数据
+    async function del({ ration }) {
+        const tasks = [];
+        const rationIDList = ration.map(item => item.ID);
+        if (!rationIDList.length) {
+            return;
+        }
+        // 删除定额数据
+        const rationTask = ration_model.model.deleteMany({ ID: {$in: rationIDList} });
+        tasks.push(rationTask);
+        // 删除定额人材机数据
+        const rationGLJTask = ration_glj_model.deleteMany({ rationID: {$in: rationIDList} });
+        tasks.push(rationGLJTask);
+        await Promise.all(tasks);
+    }
+    // 处理任务
+    const { updateData, addData, deleteData } = data;
+    const updateTask = update(updateData);
+    const addTask = add(addData);
+    const delTask = del(deleteData);
+    const [updateRst, addRst, delRst] = await Promise.all([updateTask, addTask, delTask]);
+    return addRst;
+}
+
 async function updateNodes(datas){
     let nodeGroups = _.groupBy(datas,'type');
     let rationTasks = [];

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

@@ -13,6 +13,7 @@ module.exports = function (app) {
     projectRouter.post('/removeProjectMark', projectController.removeProjectMark);
     projectRouter.post('/updateNodes', projectController.updateNodes);
     projectRouter.post('/calcInstallationFee', projectController.calcInstallationFee);
+    projectRouter.post('/calcOverHeightFee', projectController.calcOverHeightFee);
     projectRouter.post('/saveProperty', projectController.saveProperty);
     projectRouter.post('/getDefaultColSetting', projectController.getDefaultColSetting);
     projectRouter.post('/getSEIProjects', projectController.getSEIProjects);

+ 18 - 3
public/common_util.js

@@ -26,16 +26,31 @@ function deleteEmptyObject(arr) {
         window.commonUtil = factory();
     }
 })(() => {
+    // 是否定义
     function isDef(val) {
         return typeof val !== 'undefined' && val !== null;
     }
-
+    // 是否空值
     function isEmptyVal(val) {
         return val === null || val === undefined || val === '';
     }
+    // 是否数值
+    function isNumber(val) {
+        return !isEmptyVal(val) && !isNaN(val);
+    }
+    // 是否近似相等(null = undefined = '', 1 = '1'...)
+    function similarEqual(a, b) {
+        // null == '' 为false,所以不能用非严等
+        if (isEmptyVal(a) && isEmptyVal(b)) {
+            return true;
+        }
+        return a == b;
+    }
 
     return {
         isDef,
-        isEmptyVal
+        isEmptyVal,
+        isNumber,
+        similarEqual,
     };
-});
+});

+ 2 - 2
public/web/common_ajax.js

@@ -163,12 +163,12 @@ $.ajaxSetup({
 
 
 
-async function ajaxPost(url, data) {
+async function ajaxPost(url, data, isPlainData = false) {
     return new Promise(function (resolve, reject) {
         $.ajax({
             type:"POST",
             url: url,
-            data: {'data': JSON.stringify(data)},
+            data: isPlainData ? data : {'data': JSON.stringify(data)},
             dataType: 'json',
             cache: false,
             timeout: 200000,

+ 33 - 0
public/web/sheet/sheet_common.js

@@ -72,6 +72,39 @@ var sheetCommonObj = {
             sheet.setColumnVisible(i,setting.header[i].visible === false ? false:true);
         }
     },
+    getHeadersFromTreeSetting: function (treeSetting) {
+        const vAlignMap = ['top', 'center', 'bottom'];
+        const hAlignMap = ['left', 'center', 'right'];
+        return treeSetting.cols.map(item => {
+            const vAlign = vAlignMap[item.data.vAlign];
+            const hAlign = hAlignMap[item.data.hAlign];
+            return {
+                name: item.head.titleNames[0],
+                dataCode: item.data.field,
+                width: item.width,
+                vAlign,
+                hAlign,
+            };
+        });
+
+    },
+    setHeader: function(sheet, headers) {
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        sheet.setColumnCount(headers.length);
+        sheet.setRowHeight(0, 30, GC.Spread.Sheets.SheetArea.colHeader);
+        headers.forEach((header, index) => {
+            sheet.setValue(0, index, header.name, GC.Spread.Sheets.SheetArea.colHeader);
+            sheet.setColumnWidth(index, header.width, GC.Spread.Sheets.SheetArea.colHeader);
+            if (header.formatter) {
+                sheet.setFormatter(-1, index, header.formatter);
+            }
+            sheet.getRange(-1, index, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[header.hAlign]);
+            sheet.getRange(-1, index, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[header.vAlign]);
+        });
+        sheet.resumeEvent();
+        sheet.resumePaint();
+    },
     cleanSheet: function(sheet, setting, rowCount) {
         sheet.suspendPaint();
         sheet.suspendEvent();

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

@@ -439,3 +439,9 @@ input.text-right{
     padding-left: 0;
     padding-right: 0;
 }
+.over-height {
+    max-width: 550px !important;
+}
+.hide-area {
+    display: none;
+}

+ 12 - 12
web/building_saas/main/html/main.html

@@ -2182,8 +2182,8 @@
     </div>
 </div>
 <!--超高降效-->
-<div class="modal fade" id="overHeight" data-backdrop="static">
-    <div class="modal-dialog" role="document">
+<div class="modal fade" id="overHeightOpt" data-backdrop="static">
+    <div class="modal-dialog over-height" role="document">
         <div class="modal-content">
             <div class="modal-header">
                 <h5 class="modal-title">超高降效选项设置</h5>
@@ -2194,20 +2194,20 @@
             <div class="modal-body">
                 <div class="mb-2">
                     <div class="form-check">
-                        <input class="form-check-input" type="radio" name="cgx" id="cgx1">
-                        <label class="form-check-label" for="cgx1">
+                        <input class="form-check-input" type="radio" name="cgx" value="1" id="separationOpt">
+                        <label class="form-check-label" for="separationOpt">
                             对应清单或分项下
                         </label>
                     </div>
                     <div class="form-check">
-                        <input class="form-check-input" type="radio" name="cgx" id="cgx2">
-                        <label class="form-check-label" for="cgx2">
+                        <input class="form-check-input" type="radio" name="cgx" value="2" id="measureOpt">
+                        <label class="form-check-label" for="measureOpt">
                             指定措施清单:“011704001”
                         </label>
                     </div>
                     <div class="form-check">
-                        <input class="form-check-input" type="radio" name="cgx" id="cgx3">
-                        <label class="form-check-label" for="cgx3">
+                        <input class="form-check-input" type="radio" name="cgx" value="3" id="specificOpt">
+                        <label class="form-check-label" for="specificOpt">
                             指定具体位置
                         </label>
                     </div>
@@ -2216,11 +2216,11 @@
                     软件自动默认13清单的超高清单下,如若与实际工程不一致,可以自行指定具体位置。
                 </div>
                 <!--指定具体位置-->
-                <div class="modal-fixed-height">
+                <div class="modal-fixed-height hide-area" id="specificArea">
                 </div>
             </div>
             <div class="modal-footer">
-                <a href="javascript:;" class="btn btn-primary">确定</a>
+                <a href="javascript:;" class="btn btn-primary" id="overHeightOptConfirmed">确定</a>
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
             </div>
         </div>
@@ -2238,7 +2238,7 @@
             </div>
             <div class="modal-body">
                 <div class="form-group">
-                    <p>未找到对应清单,是否需要自动生成?</p>
+                    <p>未找到指定措施清单“011704001”,是否需要自动生成</p>
                     <p>【是】:软件自动生成清单</p>
                     <p>【否】:取消本次操作</p>
                 </div>
@@ -2262,7 +2262,7 @@
             </div>
             <div class="modal-body">
                 <div class="form-group">
-                    <p>指定清单已不存在,请重新指定</p>
+                    <p>未找到指定的超高降效清单,请重新指定</p>
                     <p>【是】:指定清单</p>
                     <p>【否】:取消本次操作</p>
                 </div>

+ 4 - 0
web/building_saas/main/js/controllers/block_controller.js

@@ -10,6 +10,9 @@ let BlockController = {
         if(selected.sourceType == ModuleNames.ration && selected.data.type == rationType.install){
             return true;
         }
+        if (OVER_HEIGHT.isOverHeight(selected)) {
+            return true;
+        }
         if(projectObj.project.Bills.hasFlags(selected)){//所有固定清单项不能复制
             return true;
         }
@@ -332,6 +335,7 @@ let BlockController = {
              //更新计算程序模板,并进行重新计算
              project.calcProgram.calcNodesAndSave(rationNodes,function () {
                  installationFeeObj.calcInstallationFee();
+                 OVER_HEIGHT.reCalcOverHeightFee();
              });
         })
 

+ 1 - 0
web/building_saas/main/js/controllers/material_controller.js

@@ -65,6 +65,7 @@ let MaterialController = {
             projectObj.project.projectGLJ.loadData(function () {
                 projectObj.project.calcProgram.calcNodesAndSave(nodes,function(){
                     installationFeeObj.calcInstallationFee();
+                    OVER_HEIGHT.reCalcOverHeightFee();
                 });
                 gljOprObj.refreshView();
             })

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

@@ -228,6 +228,26 @@ var Bills = {
             this.datas.push(newData);
             return this.tree.insertByData(newData, parentId, nextSiblingId, true);
         };
+        // 已经有数据,更新前端缓存及节点,不进行通信
+        bills.prototype.addNewDataSimply = function (newData) {
+            const newNodes = [];
+            const controller = projectObj.mainController;
+            this.addDatasToList(newData);
+            newData.forEach(item => {
+                // 插入清单树
+                const newSource = projectObj.project.Bills.tree.insertByData(item, item.ParentID, item.NextSiblingID, true);
+                // 插入主树
+                const newNode = project.mainTree.insert(item.ParentID, item.NextSiblingID, newSource.data.ID);
+                newNode.source = newSource;
+                newNode.sourceType = projectObj.project.Bills.getSourceType();
+                newNode.data = newSource.data;
+                controller.sheet.addRows(newNode.serialNo(), 1);
+                // controller.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                newNodes.push(newNode);
+            });
+            TREE_SHEET_HELPER.refreshTreeNodeData(controller.setting, controller.sheet, newNodes, false);
+            return newNodes;
+        }
         bills.prototype.deleteBills = function (node) {
             let deleteNode = function (node) {
                 this.project.Ration.deleteByBills([node]);
@@ -826,6 +846,7 @@ var Bills = {
                     }
                     gljOprObj.refreshView();
                 });
+                OVER_HEIGHT.reCalcOverHeightFee();
                 //添加内容为定额子目时,根据特征及内容添加规则刷新清单
                 if(updateData['ration']){
                     let addRuleSetting = getAddRuleSetting();

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 968 - 59
web/building_saas/main/js/models/overHeight.js


+ 6 - 0
web/building_saas/main/js/models/project.js

@@ -571,6 +571,12 @@ var PROJECT = {
             return projectObj.project.projectInfo.property.isInstall?true:false;//如果是undefinded 就也返回false
         };
 
+        // 判断项目能否使用超高降效相关功能 (是否含有超高降效库数据)
+        project.prototype.isOverHeightProject = function () {
+            const overHeight = projectObj.project.projectInfo.property.overHeight;
+            return Array.isArray(overHeight) && overHeight.length;
+        }
+
         /*        project.prototype.setBillsCalcMode = function (calcMode) {
                     this.property.billsCalcMode = calcMode;
                     this.initCalcFields();

+ 21 - 2
web/building_saas/main/js/models/project_glj.js

@@ -55,6 +55,24 @@ ProjectGLJ.prototype.loadData = function (callback = null) {
     });
 };
 
+ProjectGLJ.prototype.loadDataSync = async function () {
+    if (this.isLoading) {
+        return false;
+    }
+    this.isLoading = true;
+    const project_id = projectObj.project.ID();
+    try {
+        const rst = await ajaxPost('/glj/getData', { project_id }, true);
+        this.isLoading = false;
+        this.refreshByDatas(rst);
+        projectObj.project.projectGLJ = this;
+    } catch (err) {
+        this.isLoading = false;
+        throw new Error('获取项目人材机数据错误');
+    }
+    
+}
+
 //更新项目工料机数据和缓存
 ProjectGLJ.prototype.refreshByDatas = function(datas){
     this.datas = datas;
@@ -66,7 +84,6 @@ ProjectGLJ.prototype.loadToCache = function (data) {
     this.datas = data;
 }
 
-
 /**
  * 获取对应工料机数据
  *
@@ -299,7 +316,9 @@ ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from,cb
             me.refreshTreeNodePriceIfNeed(glj);//刷新造价书中主树上的定额工料机;
             gljs.push(glj);
             let nodes = me.getImpactRationNodes(gljs);//取到因为改变工料机价格而受影响的定额
-            projectObj.project.calcProgram.calcNodesAndSave(nodes);//触发计算程序
+            projectObj.project.calcProgram.calcNodesAndSave(nodes, function () {
+                OVER_HEIGHT.reCalcOverHeightFee();
+            });//触发计算程序
             projectGljObject.onUnitFileChange(data);
             if(cb){
                 cb(gljs);

+ 2 - 0
web/building_saas/main/js/models/quantity_detail.js

@@ -773,6 +773,7 @@ var quantity_detail = {
                 });*/
                 project.calcProgram.calcNodesAndSave(needUpdateChildren, function () {
                     project.projectGLJ.calcQuantity();
+                    OVER_HEIGHT.reCalcOverHeightFee();
                     if(project.Bills.isFBFX(node)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
                         project.installation_fee.calcInstallationFee(function (isChange,rations) {
                             if(isChange){
@@ -831,6 +832,7 @@ var quantity_detail = {
                         }
                     });
                 }
+                OVER_HEIGHT.reCalcOverHeightFee();
             });
             let childrenNodes = [];
             for(let r of rationNodes){

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

@@ -440,7 +440,9 @@ var Ration = {
                 project.projectGLJ.loadData(function () {
                     mbzm_obj.nodeChanged = true;//子目模板关联刷新
                     gljOprObj.showDataIfRationSelect(projectObj.project.mainTree.selected,"-111111111");//这里第二个参数是为了使改前和改后selectedID不一样,删除了的话下方的定额工料机不会刷新
-                    project.calcProgram.calcNodesAndSave(refershNodes);
+                    project.calcProgram.calcNodesAndSave(refershNodes, function () {
+                        OVER_HEIGHT.reCalcOverHeightFee();
+                    });
                     projectObj.mainController.refreshTreeNode(refershNodes, true);
                     $.bootstrapLoading.end();
                 });
@@ -562,8 +564,32 @@ var Ration = {
                 projectObj.selectColAndFocus(newNode,null);
             },true,type);
         };
-
-
+        // 已经有数据,更新前端缓存及节点,不进行通信
+        ration.prototype.addNewDataSimply = function (newData) {
+            const newNodes = [];
+            const controller = projectObj.mainController;
+            this.addDatasToList(newData);
+            newData.forEach(item => {
+                const newNode = project.mainTree.insert(item.billsItemID, -1, item.ID);
+                newNode.source = item;
+                newNode.sourceType = project.Ration.getSourceType();
+                newNode.data = item;
+                controller.sheet.addRows(newNode.serialNo(), 1);
+                newNodes.push(newNode);
+            });
+            TREE_SHEET_HELPER.refreshTreeNodeData(controller.setting, controller.sheet, newNodes, false);
+        };
+        // 数据库的数据已删除,删除前端缓存及节点,不进行通信
+        ration.prototype.deleteDataSimply = function (IDList) {
+            const rationNodes = projectObj.project.mainTree.items.filter(node => IDList.includes(node.data.ID));
+            const controller = projectObj.mainController;
+            rationNodes.forEach(node => {
+                controller.sheet.deleteRows(node.serialNo(),1);
+                controller.tree.delete(node);
+                projectObj.project.Ration.removeByID(node.data.ID);
+                projectObj.project.ration_glj.deleteByRation(node.data);
+            });
+        };
         ration.prototype.addNewRation = function (itemQuery,rationType,callback=null,isEmpty=false,priceType,needCalcAndSave=true) {//priceType 是量价类型
             console.log('addNewRation');
             let me = this;

+ 5 - 1
web/building_saas/main/js/models/ration_glj.js

@@ -285,6 +285,7 @@ let ration_glj = {
             }
             project.calcProgram.calcAndSave(rationNode,function () {
                 installationFeeObj.calcInstallationFee();
+                OVER_HEIGHT.reCalcOverHeightFee();
             });
         };
         // CSL,2017.05.09
@@ -461,6 +462,7 @@ let ration_glj = {
                     me.reCalcWhenGLJChange(recode);//触发计算定额以及父节点
                     $.bootstrapLoading.end();
                     installationFeeObj.calcInstallationFee();
+                    OVER_HEIGHT.reCalcOverHeightFee();
                 });
             };
             $.bootstrapLoading.start();
@@ -1005,7 +1007,9 @@ let ration_glj = {
             let node = this.findRationNodeByID(ration_glj.rationID);
             if (node) {
                 node.changed = true;
-                project.calcProgram.calcAndSave(node);
+                project.calcProgram.calcAndSave(node, function () {
+                    OVER_HEIGHT.reCalcOverHeightFee();
+                });
             }
         };
         return new ration_glj(project);

+ 9 - 5
web/building_saas/main/js/views/glj_view.js

@@ -218,7 +218,7 @@ var gljOprObj = {
             //是主材或者是设备时只读
             if(selected.sourceType == ModuleNames.ration_glj){
                 return true;
-            }else if(gljOprObj.isInstallationNode(selected)){//是补项或者是安装类型的定额时只读
+            }else if(gljOprObj.isInstallationNode(selected) || OVER_HEIGHT.isOverHeight(selected)){//是补项或者是安装、超高类型的定额时只读
                 return true;
             }
             return false;
@@ -251,7 +251,7 @@ var gljOprObj = {
         let selected = projectObj.project.mainTree.selected;
         if($.bootstrapLoading.isLoading())  args.cancel = true;
         if(selected){
-            if(me.isInstallationNode(selected)==true){
+            if(me.isInstallationNode(selected)==true || OVER_HEIGHT.isOverHeight(selected)){
                 args.cancel = true;
             }else {
                 if(args.sheetName == 'quantity_detail'){//工程量明细表
@@ -394,7 +394,7 @@ var gljOprObj = {
         if(args.sheetName == 'rationInstallSheet' && checkboxValue){
             return;
         }
-        if(gljOprObj.isInstallationNode(selected)==true){
+        if(gljOprObj.isInstallationNode(selected)==true || OVER_HEIGHT.isOverHeight(selected)){
             return;
         }
         let newval = checkboxValue? 0:1;
@@ -1315,7 +1315,9 @@ var gljOprObj = {
                     selected.data.adjustState = result.adjustState;
                     selected.data.name = result.name;
                     projectObj.mainController.refreshTreeNode(nodes);
-                    project.calcProgram.calcAndSave(selected);
+                    project.calcProgram.calcAndSave(selected, function () {
+                        OVER_HEIGHT.reCalcOverHeightFee();
+                    });
                     $.bootstrapLoading.end();
                 });
             }
@@ -1349,7 +1351,9 @@ var gljOprObj = {
             project.projectGLJ.loadData(function () {
                 me.showRationGLJSheetData();
                 var rationNodes = me.refreshStateAfterMreplace(stateList, nodes);
-                project.calcProgram.calcNodesAndSave(rationNodes);
+                project.calcProgram.calcNodesAndSave(rationNodes, function () {
+                    OVER_HEIGHT.reCalcOverHeightFee();
+                });
                 $.bootstrapLoading.end();
             });
         })

+ 8 - 4
web/building_saas/main/js/views/glj_view_contextMenu.js

@@ -16,7 +16,8 @@ var gljContextMenu = {
                     icon: 'fa-sign-in',
                     disabled: function () {
                         var sheetData = gljOprObj.sheetData;
-                        if(gljOprObj.isInstallationNode(projectObj.project.mainTree.selected)){
+                        const selected = projectObj.project.mainTree.selected;
+                        if(gljOprObj.isInstallationNode(selected) || OVER_HEIGHT.isOverHeight(selected)){
                             return true;
                         }
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
@@ -66,7 +67,8 @@ var gljContextMenu = {
                     icon: 'fa-remove',
                     disabled: function () {
                         var sheetData = gljOprObj.sheetData;
-                        if(gljOprObj.isInstallationNode(projectObj.project.mainTree.selected)){
+                        const selected = projectObj.project.mainTree.selected;
+                        if(gljOprObj.isInstallationNode(selected) || OVER_HEIGHT.isOverHeight(selected)){
                             return true;
                         }
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
@@ -93,7 +95,8 @@ var gljContextMenu = {
                     icon: 'fa-sign-in',
                     disabled: function () {
                         let sheetData = gljOprObj.sheetData;
-                        if(gljOprObj.isInstallationNode(projectObj.project.mainTree.selected)){
+                        const selected = projectObj.project.mainTree.selected;
+                        if(gljOprObj.isInstallationNode(selected) || OVER_HEIGHT.isOverHeight(selected)){
                             return true;
                         }
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
@@ -116,7 +119,8 @@ var gljContextMenu = {
                     icon: 'fa-sign-in',
                     disabled: function () {
                         var sheetData = gljOprObj.sheetData;
-                        if(gljOprObj.isInstallationNode(projectObj.project.mainTree.selected)){
+                        const selected = projectObj.project.mainTree.selected;
+                        if(gljOprObj.isInstallationNode(selected) || OVER_HEIGHT.isOverHeight(selected)){
                             return true;
                         }
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){

+ 6 - 4
web/building_saas/main/js/views/main_tree_col.js

@@ -245,7 +245,7 @@ let MainTreeCol = {
                 if(node.data.type==billType.DXFY||node.data.type==billType.FB||(node.data.type==billType.BILL&&MainTreeCol.readOnly.billsParent(node))){//大项费用、分部、清单父项行,工程量只读。
                     return true;
                 }
-            }else if(MainTreeCol.readOnly.glj(node)){
+            }else if(MainTreeCol.readOnly.glj(node) || OVER_HEIGHT.isOverHeight(node)){
                 return true;
             }
             return false;
@@ -315,7 +315,8 @@ let MainTreeCol = {
             const isOverHeight = OVER_HEIGHT.isOverHeight(node);
             const notFBFXAndMeasure = !projectObj.project.Bills.isFBFX(node)
                 && !projectObj.project.Bills.isMeasure(node);
-            return isOverHeight || notFBFXAndMeasure;
+            const hasCalcBase = !!node.data.calcBase;    
+            return isOverHeight || notFBFXAndMeasure || hasCalcBase;
         }
     },
     cellType: {
@@ -432,7 +433,8 @@ let MainTreeCol = {
             const isOverHeight = OVER_HEIGHT.isOverHeight(node);
             const notFBFXAndMeasure = !projectObj.project.Bills.isFBFX(node)
                 && !projectObj.project.Bills.isMeasure(node);
-            if (isOverHeight || notFBFXAndMeasure) {
+            const hasCalcBase = node.data.calcBase;
+            if (isOverHeight || notFBFXAndMeasure || hasCalcBase) {
                 return;
             }
             const dynamicCombo = sheetCommonObj.getDynamicCombo();
@@ -451,7 +453,7 @@ let MainTreeCol = {
         if(node.sourceType==projectObj.project.Bills.getSourceType()){
             return MainTreeCol.lockBillChecking(node,field)
         }
-        if(gljOprObj.isInstallationNode(node)){//如果是通过安装增加费自动生成的,都是只读类型
+        if(gljOprObj.isInstallationNode(node) || OVER_HEIGHT.isOverHeight(node)){//如果是通过安装增加费、超高降效自动生成的,都是只读类型
             return true;
         }
         return false;

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

@@ -210,6 +210,7 @@ let mbzm_obj={
                 if(parentsNodes.length > 0) calRations = calRations.concat(parentsNodes);//计算被删除的子目关联定额的父节点
                 projectObj.project.calcProgram.calcNodesAndSave(calRations,function () {
                     installationFeeObj.calcInstallationFee();
+                    OVER_HEIGHT.reCalcOverHeightFee();
                 });
                 mbzm_obj.showApplySuccess();
             });

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

@@ -851,6 +851,7 @@ let projectGljObject={
             projectObj.project.calcProgram.calcNodesAndSave(updateNodes,function () {
                 projectObj.mainController.refreshTreeNode(projectObj.project.mainTree.roots);
                 installationFeeObj.calcInstallationFee();//计算安装增加费
+                OVER_HEIGHT.reCalcOverHeightFee();
             });
         }
         gljOprObj.refreshView();

+ 45 - 3
web/building_saas/main/js/views/project_view.js

@@ -460,7 +460,7 @@ var projectObj = {
             project.ration_glj.updateFromMainSpread(value,node,fieldName);
         }
         else if (fieldName === 'overHeight') {
-            debugger;
+            OVER_HEIGHT.handleValueChanged([{ node, value }]);
             return;
         }
         else if(fieldName === 'remark'){
@@ -870,7 +870,7 @@ var projectObj = {
         }
         let updateRationCodes = [];//更新定额编码时要用同步的方式
         // 超高降效的操作比较耗时,需要减少触发
-        const updateOverHeights = [];
+        const overHeightChangedData = [];
         if(changedObj.changedCells.length > 0){
             console.log(changedObj.changedCells);
             for (let changedCell of changedObj.changedCells) {
@@ -880,12 +880,15 @@ var projectObj = {
                 if(colSetting.data.field=='code' && node.sourceType == project.Ration.getSourceType()&&node.data.type==rationType.ration){//如果是更新定额的编码
                     updateRationCodes.push({'node':node,value:value});
                 } else if (colSetting.data.field === 'overHeight') {
-                    updateOverHeights.push({node, value});
+                    overHeightChangedData.push({ node, value });
                 } else {
                     projectObj.updateCellValue(node, value, colSetting,changedCell.text);
                 }
             }
         }
+        if (overHeightChangedData.length) {
+            OVER_HEIGHT.handleValueChanged(overHeightChangedData);
+        }
         if(updateRationCodes.length>0){
             project.Ration.updateRationCodes(updateRationCodes);
         }
@@ -1446,6 +1449,45 @@ var projectObj = {
                         return projectObj.project.isInstall();
                     }
                 },
+                "calcOverHeightFee": {
+                    name: '超高降效费用',
+                    icon: 'fa-sign-in',
+                    visible: function () {
+                        return projectObj.project.isOverHeightProject();
+                    },
+                    items: {
+                        'calcOverHeight': {
+                            name: '计取超高降效',
+                            icon: 'fa-sign-in',
+                            disabled: function () {
+                                return projectReadOnly;
+                            },
+                            callback: function (key, opt) {
+                                OVER_HEIGHT.switchVisible();
+                            }
+                        },
+                        'setOption': {
+                            name: '设置子目生成方式',
+                            icon: 'fa-sign-in',
+                            disabled: function () {
+                                return projectReadOnly;
+                            },
+                            callback: function (key, opt) {
+                                $('#overHeightOpt').modal('show');
+                            }
+                        },
+                        'cancelOverHeight': {
+                            name: '取消超高降效',
+                            icon: 'fa-sign-in',
+                            disabled: function () {
+                                return projectReadOnly;
+                            },
+                            callback: function (key, opt) {
+                                OVER_HEIGHT.cancelCalc();
+                            }
+                        },
+                    }
+                },
                 "cleanzmhs":{
                     name:'清空子目换算',
                     icon: 'fa-remove',

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

@@ -291,6 +291,7 @@ let zlfb_object={
                 projectObj.project.Bills.getEngineeringCostNode(controller).changed = true;
                 projectObj.project.calcProgram.calcAllNodesAndSave();
             });
+            OVER_HEIGHT.reCalcOverHeightFee();
         },function () {
             //errorCallback
         });

+ 1 - 0
web/common/html/header.html

@@ -285,6 +285,7 @@
 <script src="/lib/bootstrap/bootstrap-submenu.js"></script>
 <script type="text/javascript" src="/web/building_saas/js/moment.min.js"></script>
 <script type="text/javascript" src="/web/building_saas/js/message.js"></script>
+<script type="text/javascript" src="/public/common_util.js"></script>
 <script type="text/javascript" src="/public/web/scMathUtil.js"></script>
 <script type="text/javascript" src="/public/web/gljUtil.js"></script>
 <script type="text/javascript" src="/public/web/PerfectLoad.js"></script>