浏览代码

Merge branch 'master' of http://192.168.1.12:3000/SmartCost/ConstructionCost

TonyKang 7 年之前
父节点
当前提交
a0db376efc
共有 50 个文件被更改,包括 2247 次插入262 次删除
  1. 2 0
      config/gulpConfig.js
  2. 2 0
      modules/complementary_glj_lib/models/gljModel.js
  3. 4 1
      modules/glj/models/glj_list_model.js
  4. 37 1
      modules/main/controllers/installation_controller.js
  5. 15 0
      modules/main/controllers/project_controller.js
  6. 62 38
      modules/main/facade/installation_facade.js
  7. 107 1
      modules/main/facade/project_facade.js
  8. 8 5
      modules/main/facade/ration_facade.js
  9. 12 0
      modules/main/facade/ration_installation_facade.js
  10. 2 1
      modules/main/models/bills.js
  11. 1 0
      modules/main/models/ration.js
  12. 2 1
      modules/main/routes/installation_route.js
  13. 1 0
      modules/main/routes/project_route.js
  14. 6 0
      modules/options/models/optionTypes.js
  15. 1 1
      modules/pm/controllers/pm_controller.js
  16. 35 10
      modules/ration_glj/facade/glj_calculate_facade.js
  17. 2 2
      modules/ration_glj/facade/ration_glj_facade.js
  18. 3 1
      modules/ration_glj/models/ration_glj_temp.js
  19. 27 0
      public/web/common_ajax.js
  20. 38 36
      public/web/sheet/sheet_common.js
  21. 3 1
      public/web/tree_sheet/tree_sheet_helper.js
  22. 1 1
      server.js
  23. 122 0
      web/building_saas/glj/html/project_glj.html
  24. 3 57
      web/building_saas/glj/js/project_glj.js
  25. 19 2
      web/building_saas/glj/js/project_glj_spread.js
  26. 24 7
      web/building_saas/main/html/main.html
  27. 92 7
      web/building_saas/main/js/models/bills.js
  28. 15 0
      web/building_saas/main/js/models/cache_tree.js
  29. 1 1
      web/building_saas/main/js/models/calc_program.js
  30. 492 0
      web/building_saas/main/js/models/installation_fee.js
  31. 9 4
      web/building_saas/main/js/models/main_consts.js
  32. 1 1
      web/building_saas/main/js/models/project.js
  33. 74 8
      web/building_saas/main/js/models/project_glj.js
  34. 23 4
      web/building_saas/main/js/models/quantity_detail.js
  35. 53 4
      web/building_saas/main/js/models/ration.js
  36. 10 1
      web/building_saas/main/js/models/ration_glj.js
  37. 47 0
      web/building_saas/main/js/models/ration_installation.js
  38. 36 6
      web/building_saas/main/js/views/glj_view.js
  39. 71 26
      web/building_saas/main/js/views/glj_view_contextMenu.js
  40. 175 15
      web/building_saas/main/js/views/installation_fee_view.js
  41. 2 0
      web/building_saas/main/js/views/main_tree_col.js
  42. 262 0
      web/building_saas/main/js/views/project_glj_view.js
  43. 7 6
      web/building_saas/main/js/views/project_property_display_view.js
  44. 177 0
      web/building_saas/main/js/views/project_property_indicativeInfo.js
  45. 15 2
      web/building_saas/main/js/views/project_property_projFeature.js
  46. 102 2
      web/building_saas/main/js/views/project_view.js
  47. 16 0
      web/building_saas/main/js/views/std_bills_lib.js
  48. 19 0
      web/building_saas/main/js/views/std_ration_lib.js
  49. 7 6
      web/building_saas/main/js/views/zlfb_view.js
  50. 2 3
      web/users/html/login.html

+ 2 - 0
config/gulpConfig.js

@@ -100,6 +100,7 @@ module.exports = {
         'web/building_saas/main/js/views/project_property_decimal_view.js',
         'web/building_saas/main/js/views/project_property_decimal_view.js',
         'web/building_saas/main/js/views/project_property_basicInfo.js',
         'web/building_saas/main/js/views/project_property_basicInfo.js',
         'web/building_saas/main/js/views/project_property_projFeature.js',
         'web/building_saas/main/js/views/project_property_projFeature.js',
+        'web/building_saas/main/js/views/project_property_indicativeInfo.js',
         'web/building_saas/main/js/views/project_property_display_view.js',
         'web/building_saas/main/js/views/project_property_display_view.js',
         'web/building_saas/main/js/main_ajax.js',
         'web/building_saas/main/js/main_ajax.js',
         'web/building_saas/main/js/main.js',
         'web/building_saas/main/js/main.js',
@@ -113,6 +114,7 @@ module.exports = {
         'web/building_saas/main/js/views/confirm_modal.js',
         'web/building_saas/main/js/views/confirm_modal.js',
         'web/building_saas/main/js/views/zlfb_view.js',
         'web/building_saas/main/js/views/zlfb_view.js',
         'web/building_saas/main/js/views/installation_fee_view.js',
         'web/building_saas/main/js/views/installation_fee_view.js',
+        'web/building_saas/main/js/views/project_glj_view.js',
         'public/web/rpt_tpl_def.js',
         'public/web/rpt_tpl_def.js',
         'public/web/treeDataHelper.js',
         'public/web/treeDataHelper.js',
         'public/web/ztree_common.js',
         'public/web/ztree_common.js',

+ 2 - 0
modules/complementary_glj_lib/models/gljModel.js

@@ -372,6 +372,7 @@ class GljDao {
             for(let gljData of componentStdGljData) {
             for(let gljData of componentStdGljData) {
                 gljData.connectCode = libGljData.code;
                 gljData.connectCode = libGljData.code;
                 gljData.consumption = componentConsume[gljData.ID + '_std'];
                 gljData.consumption = componentConsume[gljData.ID + '_std'];
+                gljData.from='std';
                 result.push(gljData);
                 result.push(gljData);
             }
             }
         }
         }
@@ -382,6 +383,7 @@ class GljDao {
             for(let gljData of componentCptGljData) {
             for(let gljData of componentCptGljData) {
                 gljData.connectCode = libGljData.code;
                 gljData.connectCode = libGljData.code;
                 gljData.consumption = componentConsume[gljData.ID + '_cpt'];
                 gljData.consumption = componentConsume[gljData.ID + '_cpt'];
+                gljData.from='cpt';
                 result.push(gljData);
                 result.push(gljData);
             }
             }
         }
         }

+ 4 - 1
modules/glj/models/glj_list_model.js

@@ -654,8 +654,11 @@ class GLJListModel extends BaseModel {
                 glj_id: tmp.ID,
                 glj_id: tmp.ID,
                 specs: tmp.specs,
                 specs: tmp.specs,
                 unit: tmp.unit === undefined ? '' : tmp.unit,
                 unit: tmp.unit === undefined ? '' : tmp.unit,
-                original_code:tmp.code
+                original_code:tmp.code,
             };
             };
+            if(tmp.from=='cpt'){
+                unitPriceData.is_add = 1;
+            }
             unitPriceInsertData.push(unitPriceData);
             unitPriceInsertData.push(unitPriceData);
         }
         }
         // 整理完后开始插入数据
         // 整理完后开始插入数据

+ 37 - 1
modules/main/controllers/installation_controller.js

@@ -7,7 +7,9 @@ let ration_installation_facade = require('../facade/ration_installation_facade')
 let logger = require("../../../logs/log_helper").logger;
 let logger = require("../../../logs/log_helper").logger;
 module.exports={
 module.exports={
     updateInstallationFee:updateInstallationFee,
     updateInstallationFee:updateInstallationFee,
-    updateRationInstallation:updateRationInstallation
+    updateRationInstallation:updateRationInstallation,
+    applyRuleByIDs:applyRuleByIDs,
+    resetToDefault:resetToDefault
 }
 }
 
 
 async function updateRationInstallation(req, res) {
 async function updateRationInstallation(req, res) {
@@ -27,6 +29,23 @@ async function updateRationInstallation(req, res) {
     res.json(result);
     res.json(result);
 }
 }
 
 
+async function applyRuleByIDs(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let datas= await ration_installation_facade.applyRuleByIDs(data);
+        result.data=datas;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
 async function  updateInstallationFee(req, res) {
 async function  updateInstallationFee(req, res) {
     let result={
     let result={
         error:0
         error:0
@@ -45,4 +64,21 @@ async function  updateInstallationFee(req, res) {
         result.message = err.message;
         result.message = err.message;
     }
     }
     res.json(result);
     res.json(result);
+}
+
+async function  resetToDefault(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let returnData= await installation_facade.resetToDefault(data.projectID,data.installFees);
+        result.data=returnData;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
 }
 }

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

@@ -78,5 +78,20 @@ module.exports = {
                 callback(req, res, err, message, result);
                 callback(req, res, err, message, result);
             }
             }
         });
         });
+    },
+    calcInstallationFee:async function(req,res){
+        let result={
+            error:0
+        }
+        try {
+            let data =  JSON.parse(req.body.data);
+            let resultData= await project_facade.calcInstallationFee(data);
+            result.data=resultData;
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        res.json(result);
     }
     }
 };
 };

+ 62 - 38
modules/main/facade/installation_facade.js

@@ -5,11 +5,12 @@ import {installSectionModel,installFeeItemModel} from "../../complementary_ratio
 import installationFeeModel from "../models/installation_fee";
 import installationFeeModel from "../models/installation_fee";
 import engineeringModel from "../../users/models/schema/engineering_lib";
 import engineeringModel from "../../users/models/schema/engineering_lib";
 const uuidV1 = require('uuid/v1');
 const uuidV1 = require('uuid/v1');
-let consts = require('../../main/models/project_consts')
+let consts = require('../../main/models/project_consts');
 
 
 module.exports={
 module.exports={
     copyInstallationFeeFromLib:copyInstallationFeeFromLib,
     copyInstallationFeeFromLib:copyInstallationFeeFromLib,
     updateInstallationFee:updateInstallationFee,
     updateInstallationFee:updateInstallationFee,
+    resetToDefault:resetToDefault,
     getData:getData
     getData:getData
 };
 };
 async function updateInstallationFee(projectID,updateData) {
 async function updateInstallationFee(projectID,updateData) {
@@ -64,6 +65,22 @@ function createUpdateQuery(projectID,data) {
     return [query,udoc];
     return [query,udoc];
 }
 }
 
 
+/*[
+    {libID:56,ID:123558}
+]*/
+async function resetToDefault(projectID,installFees) {
+    let newInstallFees = [];
+    for(let inf of installFees){
+        let newInstallationFee = await getInstallationFeeFromLib(inf.libID);
+        if(newInstallationFee){
+          let updateResult =  await installationFeeModel.findOneAndUpdate({projectID:projectID,ID:inf.ID},newInstallationFee,{new: true});
+            newInstallFees.push(updateResult);
+        }
+    }
+    return newInstallFees;
+}
+
+
 async function copyInstallationFeeFromLib(projectID,engineering_id) {
 async function copyInstallationFeeFromLib(projectID,engineering_id) {
 
 
     //安装增加费用内嵌文档的方式
     //安装增加费用内嵌文档的方式
@@ -71,37 +88,47 @@ async function copyInstallationFeeFromLib(projectID,engineering_id) {
     let ration_lib = engineering.ration_lib;
     let ration_lib = engineering.ration_lib;
     let installationFeeList = [];
     let installationFeeList = [];
     for(let rl of ration_lib){
     for(let rl of ration_lib){
-       let installFeeItems = await installFeeItemModel.find({'rationRepId':rl.id});
-       let installSections = await installSectionModel.find({'rationRepId':rl.id});
-       let positionMap = {};
-       let newInstallationFee = {
-           libID:rl.id,
-           libName:rl.name,
-           projectID:projectID
-       };
-        newInstallationFee.ID = uuidV1();
-       let create = false;
-       if(installFeeItems && installFeeItems.length > 0) {//费用项
-           create = true;
-           let tem_installFeeItem = [];
-           for(let ifee of installFeeItems){
+        let newInstallationFee = await getInstallationFeeFromLib(rl.id);
+        if(newInstallationFee){
+            newInstallationFee.libID = rl.id;
+            newInstallationFee.libName = rl.name;
+            newInstallationFee.projectID = projectID;
+            newInstallationFee.ID = uuidV1();
+            installationFeeList.push(newInstallationFee);
+        }
+    }
+    if(installationFeeList.length > 0){
+        await installationFeeModel.insertMany(installationFeeList);
+    }
+}
+
+async function getInstallationFeeFromLib(libID) {
+        let installFeeItems = await installFeeItemModel.find({'rationRepId':libID});
+        let installSections = await installSectionModel.find({'rationRepId':libID});
+        let positionMap = {};
+        let create = false;
+        let newInstallationFee={};
+        if(installFeeItems && installFeeItems.length > 0) {//费用项
+            create = true;
+            let tem_installFeeItem = [];
+            for(let ifee of installFeeItems){
                 let tem_fee ={
                 let tem_fee ={
                     feeItem:ifee.feeItem,
                     feeItem:ifee.feeItem,
                     feeType:ifee.feeType,
                     feeType:ifee.feeType,
                     position:ifee.position,
                     position:ifee.position,
                     ID:ifee.ID
                     ID:ifee.ID
                 };
                 };
-               positionMap[ifee.ID] = ifee.position;//设置选取位置对应表,为给规项赋值
-               tem_installFeeItem.push(tem_fee);
-           }
-           newInstallationFee.installFeeItem = tem_installFeeItem;
-       }
+                positionMap[ifee.ID] = ifee.position;//设置选取位置对应表,为给规项赋值
+                tem_installFeeItem.push(tem_fee);
+            }
+            newInstallationFee.installFeeItem = tem_installFeeItem;
+        }
 
 
-       if(installSections && installSections.length > 0){//章节项
-           create = true;
-           let tem_installSections = [];
-           let tem_feeRules = [];
-           for(let isect of installSections){
+        if(installSections && installSections.length > 0){//章节项
+            create = true;
+            let tem_installSections = [];
+            let tem_feeRules = [];
+            for(let isect of installSections){
                 let tem_sec={
                 let tem_sec={
                     ID:isect.ID,
                     ID:isect.ID,
                     name:isect.name,
                     name:isect.name,
@@ -128,21 +155,18 @@ async function copyInstallationFeeFromLib(projectID,engineering_id) {
                 }else {
                 }else {
                     tem_sec.feeRuleId = "";
                     tem_sec.feeRuleId = "";
                 }
                 }
-               tem_installSections.push(tem_sec);
-           }
-           newInstallationFee.installSection = tem_installSections;
-           newInstallationFee.feeRule = tem_feeRules;
-       }
-       if(create==true){
-           installationFeeList.push(newInstallationFee);
-       }
-    }
-    console.log(installationFeeList);
-    if(installationFeeList.length > 0){
-        await installationFeeModel.insertMany(installationFeeList);
-    }
+                tem_installSections.push(tem_sec);
+            }
+            newInstallationFee.installSection = tem_installSections;
+            newInstallationFee.feeRule = tem_feeRules;
+        }
+        if(create == true){
+            return newInstallationFee;
+        }
+        return null;
 }
 }
 
 
+
 function getData(projectID, callback) {
 function getData(projectID, callback) {
     installationFeeModel.find({'projectID': projectID}, (err, datas) => {
     installationFeeModel.find({'projectID': projectID}, (err, datas) => {
         if (err) {
         if (err) {

+ 107 - 1
modules/main/facade/project_facade.js

@@ -1,19 +1,125 @@
 /**
 /**
  * Created by zhang on 2018/1/26.
  * Created by zhang on 2018/1/26.
  */
  */
+let mongoose = require('mongoose');
 let  projectsModel = require("../../pm/models/project_schema");
 let  projectsModel = require("../../pm/models/project_schema");
 let async_n = require("async");
 let async_n = require("async");
+let _ = require('lodash');
 let ration_model = require('../models/ration');
 let ration_model = require('../models/ration');
 let bill_model = require('../models/bills');
 let bill_model = require('../models/bills');
 let consts = require('../models/project_consts');
 let consts = require('../models/project_consts');
 let projectConsts = consts.projectConst;
 let projectConsts = consts.projectConst;
+let ration_glj_model = mongoose.model('ration_glj');
+let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
+const uuidV1 = require('uuid/v1');
 
 
 module.exports = {
 module.exports = {
     markUpdateProject:markUpdateProject,
     markUpdateProject:markUpdateProject,
     removeProjectMark:removeProjectMark,
     removeProjectMark:removeProjectMark,
-    updateNodes:updateNodes
+    updateNodes:updateNodes,
+    calcInstallationFee:calcInstallationFee
 };
 };
 
 
+async function calcInstallationFee(data) {
+    let result={};
+    let billTasks  = generateTasks(data.bills,data.useID);
+    let rationTasks = generateTasks(data.ration,data.useID);
+    if(billTasks.length>0){
+        await bill_model.model.bulkWrite(billTasks);
+    }
+    console.log(rationTasks);
+    if(rationTasks.length>0){
+        await ration_model.model.bulkWrite(rationTasks);
+    }
+    //如果删除定额,需要删除对应的工料机
+    if(data.ration.delete.length>0){
+        let rationIDS = _.map(data.ration.delete,'ID');
+        await ration_glj_model.deleteMany({projectID: data.ration.delete[0].projectID, rationID: {"$in": rationIDS}});//删除定额工料机
+    }
+
+    let rationGLJTasks = [];
+    let updateList = [];
+    if(data.ration.update.length>0){//如果有需要更新的定额工料机
+        for(let ur of data.ration.update){
+            for(let g of ur.glj){
+                let gTasks = {
+                    updateOne:{
+                        filter:{
+                            ID:g.ID,
+                            projectID:g.projectID
+                        },
+                        update :{
+                            quantity:g.quantity,
+                            rationItemQuantity:g.rationItemQuantity
+                        }
+                    }
+                };
+                rationGLJTasks.push(gTasks);
+                updateList.push(g);
+            }
+        }
+    }
+    if(rationGLJTasks.length>0){
+       await ration_glj_model.bulkWrite(rationGLJTasks);
+    }
+
+    let newGljList = [];
+    if(data.ration.add.length>0){//新增的安装子目要增加对应的工料机
+        for(let nr of data.ration.add){
+            for(let tkey in nr.glj){
+                newGljList.push(await addInstallationGLJ(nr.glj[tkey]));
+            }
+        }
+    }
+    if(newGljList.length>0){
+        await ration_glj_model.insertMany(newGljList);
+    }
+    result.update = updateList;
+    result.add = newGljList;
+    return result;
+}
+
+async function addInstallationGLJ(glj) {
+    glj.ID = uuidV1();
+    let info = await ration_glj_facade.getInfoFromProjectGLJ(glj);
+    let newRecode  = ration_glj_facade.createNewRecord(info);
+    return newRecode;
+}
+
+
+function generateTasks(data,userID) {
+    let tasks=[];
+    let deleteInfo={deleted: true, deleteDateTime: new Date(), deleteBy: userID};
+    if(data.delete && data.delete.length > 0){
+        for(let bd of data.delete){
+            let task={
+                updateOne:{
+                    filter:{
+                        ID:bd.ID,
+                        projectID:bd.projectID
+                    },
+                    update :{
+                        deleteInfo:deleteInfo
+                    }
+                }
+            };
+            tasks.push(task);
+        }
+    }
+    if(data.add && data.add.length > 0){
+        for(let n_data of data.add){
+            let task = {
+                insertOne :{
+                    document:n_data
+                }
+            };
+            tasks.push(task);
+        }
+    }
+    return tasks;
+}
+
+
 function updateNodes(datas,callback) {
 function updateNodes(datas,callback) {
     let tasks = [];
     let tasks = [];
     for(let node of datas){
     for(let node of datas){

+ 8 - 5
modules/main/facade/ration_facade.js

@@ -4,7 +4,7 @@
 let mongoose = require('mongoose');
 let mongoose = require('mongoose');
 import SearchDao from '../../complementary_ration_lib/models/searchModel';
 import SearchDao from '../../complementary_ration_lib/models/searchModel';
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
-let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade")
+let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
 let quantity_detail = require("../facade/quantity_detail_facade");
 let quantity_detail = require("../facade/quantity_detail_facade");
 let ration_glj = mongoose.model('ration_glj');
 let ration_glj = mongoose.model('ration_glj');
 let ration_coe = mongoose.model('ration_coe');
 let ration_coe = mongoose.model('ration_coe');
@@ -35,7 +35,7 @@ async function addNewRation(data) {
     }
     }
     let newRation =await insertNewRation(data.newData,stdRation,data.calQuantity);
     let newRation =await insertNewRation(data.newData,stdRation,data.calQuantity);
     if(stdRation){
     if(stdRation){
-        return await addRationSubList(stdRation,newRation);
+        return await addRationSubList(stdRation,newRation,data.needInstall);
     }else {
     }else {
         return {ration:newRation};
         return {ration:newRation};
     }
     }
@@ -105,16 +105,19 @@ async function replaceRation(nodeInfo,stdRation,projectID,calQuantity) {
     if(stdRation){
     if(stdRation){
         await deleRationSubRecode(projectID,nodeInfo.ID);
         await deleRationSubRecode(projectID,nodeInfo.ID);
         let newRation = await updateRation(stdRation,nodeInfo.ID,nodeInfo.billsItemID,projectID,calQuantity);//生成并插入新的定额
         let newRation = await updateRation(stdRation,nodeInfo.ID,nodeInfo.billsItemID,projectID,calQuantity);//生成并插入新的定额
-        return await addRationSubList(stdRation,newRation);
+        return await addRationSubList(stdRation,newRation,nodeInfo.needInstall);
     }else {
     }else {
         return null;
         return null;
     }
     }
 }
 }
 
 
-async function addRationSubList(stdRation,newRation) {
+async function addRationSubList(stdRation,newRation,needInstall) {
     let ration_gljs = await addRationGLJ(stdRation,newRation);
     let ration_gljs = await addRationGLJ(stdRation,newRation);
     let ration_coes = await addRationCoe(stdRation,newRation);
     let ration_coes = await addRationCoe(stdRation,newRation);
-    let ration_installs =  await addRationInstallFee(stdRation,newRation);
+    let ration_installs = [];
+    if(needInstall){
+        ration_installs =  await addRationInstallFee(stdRation,newRation);
+    }
     return {ration:newRation,ration_gljs:ration_gljs,ration_coes:ration_coes,ration_installs:ration_installs};
     return {ration:newRation,ration_gljs:ration_gljs,ration_coes:ration_coes,ration_installs:ration_installs};
 }
 }
 
 

+ 12 - 0
modules/main/facade/ration_installation_facade.js

@@ -8,6 +8,7 @@ let projectConsts = consts.projectConst;
 
 
 module.exports={
 module.exports={
     updateRationInstallation:updateRationInstallation,
     updateRationInstallation:updateRationInstallation,
+    applyRuleByIDs:applyRuleByIDs,
     updateFromInstallationFee:updateFromInstallationFee,
     updateFromInstallationFee:updateFromInstallationFee,
     getData:getData,
     getData:getData,
     deleteByRation:deleteByRation
     deleteByRation:deleteByRation
@@ -22,6 +23,17 @@ async function updateRationInstallation(data){
     }
     }
 }
 }
 
 
+async function applyRuleByIDs(data){
+    console.log(data);
+    if(data.projectID&&data.IDs){
+        return rationInstallationModel.update({projectID: data.projectID, ID:{'$in':data.IDs}},{ruleId:data.ruleId,unifiedSetting:0},{multi: true});
+    }else {
+        throw  new Error('项目ID或者ID为空,更新失败!');
+    }
+    //ration.update({projectID: doc.updateData.projectID, ID: doc.updateData.ID}, doc.updateData,{multi: true},cb);
+
+}
+
 async function updateFromInstallationFee(projectID,rationInstallations) {
 async function updateFromInstallationFee(projectID,rationInstallations) {
     let tasks = [];
     let tasks = [];
     for (let ri of rationInstallations){
     for (let ri of rationInstallations){

+ 2 - 1
modules/main/models/bills.js

@@ -25,7 +25,7 @@ let billsSchema = new Schema({
     billsLibId: Number,
     billsLibId: Number,
     code: String,
     code: String,
     fullCode: String,
     fullCode: String,
-    type:{type: Number,default:4},//1 :大项费用 2:分部 3分项 4清单
+    type:{type: Number,default:4},//1 :大项费用 2:分部 3分项 4清单;5补项
     isAdd:{type: Number,default:0},//1 true 0 false是否新增
     isAdd:{type: Number,default:0},//1 true 0 false是否新增
     name: String,
     name: String,
     unit: String,
     unit: String,
@@ -65,6 +65,7 @@ let billsSchema = new Schema({
     fees: [subSchema.feesSchema],
     fees: [subSchema.feesSchema],
     // 标记字段
     // 标记字段
     flags: [subSchema.flagsSchema],
     flags: [subSchema.flagsSchema],
+    installationKey:String,//用来记录安装增加费的关联字段
     deleteInfo: deleteSchema,
     deleteInfo: deleteSchema,
 });
 });
 
 

+ 1 - 0
modules/main/models/ration.js

@@ -48,6 +48,7 @@ let rationSchema = new Schema({
     subType: Number,                            // 子类型:1人工、201材料、301机械、4主材、5设备
     subType: Number,                            // 子类型:1人工、201材料、301机械、4主材、5设备
     from:{type: String,default:'std'},          //std, cpt  来自标准、补充
     from:{type: String,default:'std'},          //std, cpt  来自标准、补充
     isSubcontract: Boolean,                     // 是否分包
     isSubcontract: Boolean,                     // 是否分包
+    installationKey:String,                   //用来记录安装增加费的关联字段
 
 
     // 定额特有属性:
     // 定额特有属性:
     libID: Number,
     libID: Number,

+ 2 - 1
modules/main/routes/installation_route.js

@@ -10,6 +10,7 @@ module.exports = function (app) {
 
 
     installationRouter.post('/updateInstallationFee', installationController.updateInstallationFee);
     installationRouter.post('/updateInstallationFee', installationController.updateInstallationFee);
     installationRouter.post('/updateRationInstallation', installationController.updateRationInstallation);
     installationRouter.post('/updateRationInstallation', installationController.updateRationInstallation);
-
+    installationRouter.post('/applyRuleByIDs', installationController.applyRuleByIDs);
+    installationRouter.post('/resetToDefault', installationController.resetToDefault);
     app.use('/installation',installationRouter);
     app.use('/installation',installationRouter);
 };
 };

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

@@ -12,6 +12,7 @@ module.exports = function (app) {
     projectRouter.post('/markUpdateProject', projectController.markUpdateProject);
     projectRouter.post('/markUpdateProject', projectController.markUpdateProject);
     projectRouter.post('/removeProjectMark', projectController.removeProjectMark);
     projectRouter.post('/removeProjectMark', projectController.removeProjectMark);
     projectRouter.post('/updateNodes', projectController.updateNodes);
     projectRouter.post('/updateNodes', projectController.updateNodes);
+    projectRouter.post('/calcInstallationFee', projectController.calcInstallationFee);
 
 
     app.use('/project',projectRouter);
     app.use('/project',projectRouter);
 };
 };

+ 6 - 0
modules/options/models/optionTypes.js

@@ -42,6 +42,12 @@ const optionSetting = {
             stringFont: 'default',
             stringFont: 'default',
             numFont: 'default'
             numFont: 'default'
         },
         },
+        BX: {
+            backColor: '#EEF8FA',
+            foreColor: 'default',
+            stringFont: 'default',
+            numFont: 'default'
+        },
         UNCBBILL: {
         UNCBBILL: {
             backColor: '#DFE8F9',
             backColor: '#DFE8F9',
             foreColor: 'default',
             foreColor: 'default',

+ 1 - 1
modules/pm/controllers/pm_controller.js

@@ -87,7 +87,7 @@ module.exports = {
         };
         };
 
 
         // 人工系数
         // 人工系数
-        if (datas.labourCoes.updateData){
+        if (datas.labourCoes&&datas.labourCoes.updateData){
             functions.push(updateLC());
             functions.push(updateLC());
         };
         };
 
 

+ 35 - 10
modules/ration_glj/facade/glj_calculate_facade.js

@@ -9,6 +9,7 @@ let ration_glj = mongoose.model('ration_glj');
 let ration = mongoose.model('ration');
 let ration = mongoose.model('ration');
 let ration_coe = mongoose.model('ration_coe');
 let ration_coe = mongoose.model('ration_coe');
 let std_ration_lib_ration_items = mongoose.model('std_ration_lib_ration_items');
 let std_ration_lib_ration_items = mongoose.model('std_ration_lib_ration_items');
+let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
 let glj_type_util = require('../../../public/cache/std_glj_type_util');
 let glj_type_util = require('../../../public/cache/std_glj_type_util');
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
 let decimal_facade = require('../../main/facade/decimal_facade');
 let decimal_facade = require('../../main/facade/decimal_facade');
@@ -26,7 +27,7 @@ let stateSeq ={
     cusQuantity:5,
     cusQuantity:5,
     cusCoe:6,
     cusCoe:6,
     adjMak:7
     adjMak:7
-}
+};
 
 
 
 
 async function calculateQuantity(query,noNeedCal){
 async function calculateQuantity(query,noNeedCal){
@@ -49,7 +50,7 @@ async function calculateQuantity(query,noNeedCal){
                  let times = calculateTimes(impactRation.rationAssList[i]);
                  let times = calculateTimes(impactRation.rationAssList[i]);
                  if(times!=0){
                  if(times!=0){
                      assRation = await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:impactRation.rationAssList[i].assistCode});
                      assRation = await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:impactRation.rationAssList[i].assistCode});
-                     assList.push({times:times,assRation:assRation})
+                     assList.push({times:times,assRation:assRation});
                      adjustState.push({index:stateSeq.ass,content:impactRation.rationAssList[i].name+" "+impactRation.rationAssList[i].actualValue+" : +"+impactRation.rationAssList[i].assistCode+"x"+times});
                      adjustState.push({index:stateSeq.ass,content:impactRation.rationAssList[i].name+" "+impactRation.rationAssList[i].actualValue+" : +"+impactRation.rationAssList[i].assistCode+"x"+times});
                  }
                  }
              }
              }
@@ -106,7 +107,7 @@ async function calculateQuantityPerGLJ(glj,index,coeList,assList,adjustState,noN
         if(noNeedCal==null){
         if(noNeedCal==null){
             if(!glj._doc.hasOwnProperty('customQuantity')||glj.customQuantity==null||glj.customQuantity==""){
             if(!glj._doc.hasOwnProperty('customQuantity')||glj.customQuantity==null||glj.customQuantity==""){
                 quantity =scMathUtil.roundTo(parseFloat(glj.rationItemQuantity),-decimal);
                 quantity =scMathUtil.roundTo(parseFloat(glj.rationItemQuantity),-decimal);
-                quantity =scMathUtil.roundTo(calculateAss(quantity,assList,glj),-decimal);
+                quantity =scMathUtil.roundTo(await calculateAss(quantity,assList,glj),-decimal);
                 quantity = calculateQuantityByCoes(quantity,coeList,glj);
                 quantity = calculateQuantityByCoes(quantity,coeList,glj);
             }else {
             }else {
                 quantity = glj.customQuantity;
                 quantity = glj.customQuantity;
@@ -126,12 +127,22 @@ async function calculateQuantityPerGLJ(glj,index,coeList,assList,adjustState,noN
     }
     }
 }
 }
 
 
-function calculateAss(quantity,assList,glj) {
+async function calculateAss(quantity,assList,glj) {
     for(let i=0;i<assList.length;i++){
     for(let i=0;i<assList.length;i++){
         if(assList[i].assRation){
         if(assList[i].assRation){
-            let assglj = _.find(assList[i].assRation.rationGljList,function (aglj) {
-                return aglj.gljId == glj.GLJID
-            })
+            let assglj = null;
+            for(let aglj of assList[i].assRation.rationGljList){
+                if(glj.createType == 'replace'){//如果工料机是替换过的,要用原始的编码来匹配
+                    let std_glj = await std_glj_lib_gljList_model.findOne({'ID':aglj.gljId});
+                    if(glj.rcode == std_glj.code){
+                        assglj = aglj;
+                        break;
+                    }
+                }else if(aglj.gljId == glj.GLJID){
+                    assglj = aglj;
+                    break;
+                }
+            }
             if(assglj){
             if(assglj){
                 let calQuantity = assglj.consumeAmt*assList[i].times;
                 let calQuantity = assglj.consumeAmt*assList[i].times;
                 quantity += calQuantity
                 quantity += calQuantity
@@ -155,9 +166,9 @@ function generateAdjustState(glj,coeList,adjustState,index,quantity) {
         for(let i=0;i<coeList.length;i++){
         for(let i=0;i<coeList.length;i++){
             if(coeList[i].isAdjust==1){
             if(coeList[i].isAdjust==1){
                 if(i==coeList.length-1){
                 if(i==coeList.length-1){
-                    adjustState.push({index:stateSeq.cusCoe,content:coeList[i].content});
+                    adjustState.push({index:stateSeq.cusCoe,content:getContent(coeList[i].coes)});//自定义乘系数要去掉倍数为1的
                 }else {
                 }else {
-                    adjustState.push({index:stateSeq.coe,content:"调 : "+coeList[i].content});
+                    adjustState.push({index:stateSeq.coe,content:"调 : "+coeList[i].content});//coeList[i].content
                 }
                 }
             }
             }
         }
         }
@@ -178,6 +189,20 @@ function generateAdjustState(glj,coeList,adjustState,index,quantity) {
     return adjustState;
     return adjustState;
 }
 }
 
 
+function getContent(coes) {
+    let stringList=[];
+    for(let c of coes){
+        if( c.amount&&c.amount!=1){
+            let operator = c.operator;
+            if(c.operator =="*"){
+                operator = "X";
+            }
+            stringList.push(c.coeType+operator+c.amount);
+        }
+    }
+    return stringList.join(",");
+
+}
 
 
 function calculateTimes(ass){
 function calculateTimes(ass){
     let times =(ass.actualValue-ass.stdValue)/ass.stepValue;
     let times =(ass.actualValue-ass.stdValue)/ass.stepValue;
@@ -211,7 +236,7 @@ function everyCoe(quantity,coe,glj) {
     let coeQuantity = quantity;
     let coeQuantity = quantity;
     if(coe.isAdjust==1){
     if(coe.isAdjust==1){
         for(let i=0;i<coe.coes.length;i++){
         for(let i=0;i<coe.coes.length;i++){
-            if(coe.coes[i].coeType=='单个'&&coe.coes[i].gljCode==glj.code){
+            if(coe.coes[i].gljCode==glj.code){//if(coe.coes[i].coeType=='单个工料机'&&coe.coes[i].gljCode==glj.code)
                 coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
                 coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
             } else if(coe.coes[i].coeType=='定额'){
             } else if(coe.coes[i].coeType=='定额'){
                 coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
                 coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);

+ 2 - 2
modules/ration_glj/facade/ration_glj_facade.js

@@ -166,8 +166,8 @@ function createNewRecord(ration_glj) {
     newRecoed.from = ration_glj.from ? ration_glj.from : undefined;
     newRecoed.from = ration_glj.from ? ration_glj.from : undefined;
     newRecoed.createType = ration_glj.createType ? ration_glj.createType : undefined;
     newRecoed.createType = ration_glj.createType ? ration_glj.createType : undefined;
     newRecoed.shortName = ration_glj.shortName;
     newRecoed.shortName = ration_glj.shortName;
-    newRecoed.billsItemID = ration_glj.billsItemID,
-        newRecoed.type = ration_glj.type;
+    newRecoed.billsItemID = ration_glj.billsItemID;
+    newRecoed.type = ration_glj.type;
     newRecoed.repositoryId = ration_glj.repositoryId;
     newRecoed.repositoryId = ration_glj.repositoryId;
     newRecoed.projectGLJID = ration_glj.projectGLJID;
     newRecoed.projectGLJID = ration_glj.projectGLJID;
     newRecoed.adjCoe = ration_glj.adjCoe
     newRecoed.adjCoe = ration_glj.adjCoe

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

@@ -58,6 +58,7 @@ let rationSchema = new Schema({
     deleteInfo: deleteSchema,
     deleteInfo: deleteSchema,
     type: Number,                               // 1 定额、2 量价、3 工料机定额
     type: Number,                               // 1 定额、2 量价、3 工料机定额
     subType: Number,                            // 子类型:1人工、201材料、301机械、4主材、5设备
     subType: Number,                            // 子类型:1人工、201材料、301机械、4主材、5设备
+    installationKey:String,//用来记录安装增加费的关联字段
 
 
     // 定额特有属性:
     // 定额特有属性:
     libID: Number,
     libID: Number,
@@ -185,7 +186,8 @@ let billsSchema = new Schema({
     fees: [subSchema.feesSchema],
     fees: [subSchema.feesSchema],
     // 标记字段
     // 标记字段
     flags: [subSchema.flagsSchema],
     flags: [subSchema.flagsSchema],
-    deleteInfo: deleteSchema
+    deleteInfo: deleteSchema,
+    installationKey:String//用来记录安装增加费的关联字段
 });
 });
 
 
 mongoose.model("bills", billsSchema);
 mongoose.model("bills", billsSchema);

+ 27 - 0
public/web/common_ajax.js

@@ -90,5 +90,32 @@ var CommonAjax = {
                 }
                 }
             }
             }
         });
         });
+    },
+    specialPost:function (url, data,successCallback, errorCallback) {
+        $.ajax({
+            url: url,
+            type: 'post',
+            data: data,
+            dataType: 'json',
+            error: function() {
+                alert('数据传输有误!');
+                if (errorCallback) {
+                    errorCallback();
+                }
+            },
+            success: function(response) {
+                // 修改失败则恢复原值
+                if (response.err !== 0) {
+                    alert('更改数据失败!');
+                    if (errorCallback) {
+                        errorCallback();
+                    }
+                } else {
+                    if (successCallback) {
+                        successCallback(response);
+                    }
+                }
+            }
+        });
     }
     }
 };
 };

+ 38 - 36
public/web/sheet/sheet_common.js

@@ -166,7 +166,7 @@ var sheetCommonObj = {
                 this.setCheckBoxCell(row,col,sheet,val)
                 this.setCheckBoxCell(row,col,sheet,val)
             }
             }
             if(setting.header[col].cellType === "comboBox"){
             if(setting.header[col].cellType === "comboBox"){
-                this.setComboBox(row,col,sheet,setting.header[col].options);
+                this.setComboBox(row,col,sheet,setting.header[col].options,setting.header[col].editorValueType);
             }
             }
             if(setting.header[col].cellType === "selectButton"){
             if(setting.header[col].cellType === "selectButton"){
                 this.setSelectButton(row,col,sheet,setting.header[col]);
                 this.setSelectButton(row,col,sheet,setting.header[col]);
@@ -186,6 +186,7 @@ var sheetCommonObj = {
             }
             }
             sheet.setValue(row, col, val, ch);
             sheet.setValue(row, col, val, ch);
         }
         }
+        this.setRowStyle(row,sheet,data[row].bgColour);
         if(setting.autoFit==true){
         if(setting.autoFit==true){
             sheet.getRange(row, -1, 1, -1, GC.Spread.Sheets.SheetArea.viewport).wordWrap(true);
             sheet.getRange(row, -1, 1, -1, GC.Spread.Sheets.SheetArea.viewport).wordWrap(true);
             sheet.autoFitRow(row);
             sheet.autoFitRow(row);
@@ -247,12 +248,29 @@ var sheetCommonObj = {
         sheet.getCell(row, col).hAlign(GC.Spread.Sheets.HorizontalAlign.center);
         sheet.getCell(row, col).hAlign(GC.Spread.Sheets.HorizontalAlign.center);
 
 
     },
     },
-    setComboBox(row,col,sheet,options){
+    setComboBox(row,col,sheet,options,editorValueType){
         //let combo = new GC.Spread.Sheets.CellTypes.ComboBox();
         //let combo = new GC.Spread.Sheets.CellTypes.ComboBox();
         let dynamicCombo = sheetCommonObj.getDynamicCombo(true);
         let dynamicCombo = sheetCommonObj.getDynamicCombo(true);
-        dynamicCombo.itemHeight(options.length).items(options);
+        if(options){
+            dynamicCombo.itemHeight(options.length).items(options);
+            if(editorValueType==true){
+                dynamicCombo.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.value);
+            }
+        }
         sheet.setCellType(row, col,dynamicCombo,GC.Spread.Sheets.SheetArea.viewport);
         sheet.setCellType(row, col,dynamicCombo,GC.Spread.Sheets.SheetArea.viewport);
     },
     },
+    setRowStyle(row,sheet,bgColour) {
+        if(bgColour){
+            let style = new GC.Spread.Sheets.Style();
+            style.backColor = bgColour;
+            style.borderLeft = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+            style.borderTop = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+            style.borderRight = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+            style.borderBottom = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+            sheet.setStyle(row, -1, style);
+        }
+    },
+
     setSelectButton(row,col,sheet,header){
     setSelectButton(row,col,sheet,header){
         let getSelectButton = function (cellWidth=100) {
         let getSelectButton = function (cellWidth=100) {
             function moreButton() {
             function moreButton() {
@@ -395,7 +413,7 @@ var sheetCommonObj = {
     },
     },
     //设置系统粘贴板数据,需要用户触发事件,直接调用会失败
     //设置系统粘贴板数据,需要用户触发事件,直接调用会失败
     copyTextToClipboard: function(text) {
     copyTextToClipboard: function(text) {
-        var textArea = document.createElement("textarea");
+        let textArea = document.createElement("textarea");
         textArea.style.position = 'fixed';
         textArea.style.position = 'fixed';
         textArea.style.top = 0;
         textArea.style.top = 0;
         textArea.style.left = 0;
         textArea.style.left = 0;
@@ -410,8 +428,8 @@ var sheetCommonObj = {
         document.body.appendChild(textArea);
         document.body.appendChild(textArea);
         textArea.select();
         textArea.select();
         try {
         try {
-            var successful = document.execCommand('copy');
-            var msg = successful ? 'successful' : 'unsuccessful';
+            let successful = document.execCommand('copy');
+            let msg = successful ? 'successful' : 'unsuccessful';
             console.log('Copying text command was ' + msg);
             console.log('Copying text command was ' + msg);
         } catch (err) {
         } catch (err) {
             console.log('Oops, unable to copy');
             console.log('Oops, unable to copy');
@@ -422,38 +440,22 @@ var sheetCommonObj = {
     getTableData: function (sheet, colSettings = null) {
     getTableData: function (sheet, colSettings = null) {
         let rst = '';
         let rst = '';
         let sel = sheet.getSelections()[0];
         let sel = sheet.getSelections()[0];
-        let vRows = [];
-        for(let i = sel.row, len = sel.row + sel.rowCount; i < len; i++){
-            if(sheet.getCell(i, -1).visible()){
-                vRows.push(i);
-            }
-        }
-        for(let row of vRows){
-            rst += '\n';
-            for(let j = 0, jLen = sel.colCount; j <jLen; j++){
+        let pasteText = [];
+        for(let row = sel.row; row < sel.row + sel.rowCount; row++){
+            if(!sheet.getCell(row, -1).visible())
+                continue;
+            let rowText = [];
+            for(let j = 0; j < sel.colCount; j++){
                 let col = sel.col + j;
                 let col = sel.col + j;
-                if(sheet.getCell(-1, col).visible()){
-                    let v = '';
-                    if(colSettings && (colSettings[col]['data']['field'] === 'itemCharacterText' || colSettings[col]['data']['field'] === 'jobContentText')){
-                       // v += sheet.getText(row, col) ? sheet.getText(row, col).replace(new RegExp('\n', 'g'), '\v') : '';
-                        v += sheet.getText(row, col) ? `"${sheet.getText(row, col)}"` : '';
-                        if(j !== jLen - 1){
-                            v += '\t';
-                        }
-                    }
-                    else {
-                        if(j === jLen - 1){
-                            v += sheet.getText(row, col) ? sheet.getText(row, col).replace('\n', '') : '';
-                        }
-                        else {
-                            v += sheet.getText(row, col) ? sheet.getText(row, col).replace('\n', '') + '\t' : '\t';
-                        }
-                    }
-                    rst += v;
-                }
+                if(!sheet.getCell(-1, col).visible())
+                    continue;
+                if(colSettings && (colSettings[col]['data']['field'] === 'itemCharacterText' || colSettings[col]['data']['field'] === 'jobContentText'))
+                    rowText.push(sheet.getText(row, col) ? `"${sheet.getText(row, col)}"` : '');
+                else
+                    rowText.push(sheet.getText(row, col) ? sheet.getText(row, col): '');
             }
             }
+            pasteText.push(rowText.join('\t'));
         }
         }
-        rst = rst.replace('\n', '');
-        return rst;
+        return pasteText.join('\n');
     }
     }
 }
 }

+ 3 - 1
public/web/tree_sheet/tree_sheet_helper.js

@@ -156,7 +156,9 @@ var TREE_SHEET_HELPER = {
                 if (colSetting.data.cellType && Object.prototype.toString.apply(colSetting.data.cellType) !== "[object String]") {
                 if (colSetting.data.cellType && Object.prototype.toString.apply(colSetting.data.cellType) !== "[object String]") {
                     cell.cellType(colSetting.data.cellType(node));
                     cell.cellType(colSetting.data.cellType(node));
                 }
                 }
-                if (colSetting.readOnly) {
+                if(sheet.name()=='mainSheet'&&gljOprObj.isInstallationNode(node)){//如果是通过安装增加费自动生成的,都是只读类型
+                    cell.locked(true);
+                }else if (colSetting.readOnly) {
                     if (Object.prototype.toString.apply(colSetting.readOnly) === "[object Function]") {
                     if (Object.prototype.toString.apply(colSetting.readOnly) === "[object Function]") {
                         cell.locked(colSetting.readOnly(node));
                         cell.locked(colSetting.readOnly(node));
                     } else {
                     } else {

+ 1 - 1
server.js

@@ -91,7 +91,7 @@ app.use(function (req, res, next) {
 //加载路由文件
 //加载路由文件
 fileUtils.getGlobbedFiles('./modules/**/routes/*.js').forEach(function(modelPath) {
 fileUtils.getGlobbedFiles('./modules/**/routes/*.js').forEach(function(modelPath) {
     require(path.resolve(modelPath))(app);
     require(path.resolve(modelPath))(app);
-})
+});
 
 
 //app.use(express.static(_rootDir+"/web"));
 //app.use(express.static(_rootDir+"/web"));
 //app.use(express.static(_rootDir+"/lib"));
 //app.use(express.static(_rootDir+"/lib"));

+ 122 - 0
web/building_saas/glj/html/project_glj.html

@@ -0,0 +1,122 @@
+<style type="text/css">
+    .copy,#save-as-tips{
+        display: none;
+    }
+</style>
+<div class="toolsbar px-1">
+    <div class="form-inline py-1">
+        <label class="mx-2">当前使用:<span id="used-name"></span>(<a href="#" id="pop-dj_2" data-original-title="" title=""><span id="used-count_2">0</span> 单位工程使用</a>)
+            <a class="btn btn-sm ml-1" href="#" data-toggle="modal" data-target="#change-dj_2"><i class="fa fa-exchange"></i> 选择其他</a>
+            <a class="btn btn-sm ml-1" href="#" data-toggle="modal" data-target="#file-save-as-dialog_2"><i class="fa fa-files-o"></i> 另存单独用</a></label>
+    </div>
+</div>
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-lg-12 p-0" id="project-glj-main">
+            <div class="top-content">
+                <div class="main-data-top" style="width: 100%" id="project_glj_sheet">
+                </div>
+            </div>
+            <div class="resize"></div>
+            <div class="bottom-content">
+                <ul class="nav nav-tabs" role="tablist">
+                    <li class="nav-item">
+                        <a class="nav-link active" data-toggle="tab" data-name="ration_sheet" id="ration_link" href="#glj_de_div" role="tab">相关定额</a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link" data-toggle="tab" data-name="mix_ratio_sheet" id="mix_ratio_link" href="#ph_div" role="tab">配合比表</a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link" data-toggle="tab" data-name="machine_sheet" id="machine_ratio_link" href="#ph_div" role="tab">机械单价</a>
+                    </li>
+                </ul>
+                <!-- Tab panes -->
+                <div class="tab-content">
+                    <div class="tab-pane active" id="glj_de_div" role="tabpanel">
+                        <div class="main-data-bottom ovf-hidden">
+                            相关定额
+                        </div>
+                    </div>
+                    <div class="tab-pane" id="ph_div" role="tabpanel">
+                        <div class="main-data-bottom" id="mix_ratio_sheet">
+                            test
+                        </div>
+                    </div>
+             <!--       <div class="tab-pane" id="jx_div" role="tabpanel">
+                        <div class="main-data-bottom" id="machine_sheet">
+                        </div>
+                    </div>-->
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<!--弹出更换-->
+<!--<div class="modal fade" id="change-dj" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">更换单价文件</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label class="custom-control custom-radio">
+                        <input name="change-type" type="radio" class="custom-control-input" checked="checked" value="0">
+                        <span class="custom-control-indicator"></span>
+                        <span class="custom-control-description">从本建设项目中选择</span>
+                    </label>
+                    <label class="custom-control custom-radio">
+                        <input name="change-type" type="radio" class="custom-control-input" value="1">
+                        <span class="custom-control-indicator"></span>
+                        <span class="custom-control-description">从其他建设项目中复制</span>
+                    </label>
+                </div>
+                &lt;!&ndash;从本建设项目中选择&ndash;&gt;
+                <div class="form-group select option">
+                    <label id="current-project-name"></label>
+                    <select class="form-control" id="self-file"></select>
+                </div>
+                &lt;!&ndash;从其他建设项目中复制&ndash;&gt;
+                <div class="form-group copy option">
+                    <label>选择建设项目</label>
+                    <select class="form-control" id="other-project"></select>
+                </div>
+                <div class="form-group copy option">
+                    <select class="form-control" id="other-file"></select>
+                    <small class="form-text text-muted">你选择的单价文件将复制一份至新项目,不会影响原建设项目的单价文件。</small>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a href="javascript:void(0);" class="btn btn-primary" id="change-file-confirm">确定</a>
+            </div>
+        </div>
+    </div>
+</div>
+&lt;!&ndash;弹出 另存新文件&ndash;&gt;
+<div class="modal fade" id="file-save-as-dialog" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">另存新费率文件</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>单价文件名称</label>
+                    <input class="form-control" id="save-as-name" value="">
+                    <small class="form-text text-danger" id="save-as-tips">已存在同名单价文件。</small>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a href="javascript:void(0);" class="btn btn-primary" id="save-as-confirm">确定</a>
+            </div>
+        </div>
+    </div>
+</div>-->

+ 3 - 57
web/building_saas/glj/js/project_glj.js

@@ -264,9 +264,9 @@ function init() {
             jsonData = sortProjectGLJ(jsonData);
             jsonData = sortProjectGLJ(jsonData);
             mixRatioConnectData = data.mixRatioConnectData !== undefined ? data.mixRatioConnectData : mixRatioConnectData;
             mixRatioConnectData = data.mixRatioConnectData !== undefined ? data.mixRatioConnectData : mixRatioConnectData;
             mixRatioMap = data.mixRatioMap !== undefined ? data.mixRatioMap : mixRatioMap;
             mixRatioMap = data.mixRatioMap !== undefined ? data.mixRatioMap : mixRatioMap;
-            host = data.constData.hostname !== undefined ? data.constData.hostname : '';
+           // host = data.constData.hostname !== undefined ? data.constData.hostname : '';
             materialIdList = data.constData.materialIdList !== undefined ? data.constData.materialIdList : materialIdList;
             materialIdList = data.constData.materialIdList !== undefined ? data.constData.materialIdList : materialIdList;
-            roomId = data.constData.roomId !== undefined ? data.constData.roomId : roomId;
+            //roomId = data.constData.roomId !== undefined ? data.constData.roomId : roomId;
             canNotChangeTypeId = data.constData.ownCompositionTypes !== undefined ?
             canNotChangeTypeId = data.constData.ownCompositionTypes !== undefined ?
                 data.constData.ownCompositionTypes : canNotChangeTypeId;
                 data.constData.ownCompositionTypes : canNotChangeTypeId;
             GLJTypeConst = data.constData.GLJTypeConst !== undefined ? JSON.parse(data.constData.GLJTypeConst) : GLJTypeConst;
             GLJTypeConst = data.constData.GLJTypeConst !== undefined ? JSON.parse(data.constData.GLJTypeConst) : GLJTypeConst;
@@ -391,7 +391,7 @@ function successTrigger(field, info,id) {
             projectGLJSpread.changeSupplyType(info);
             projectGLJSpread.changeSupplyType(info);
             break;
             break;
         case 'is_evaluate':
         case 'is_evaluate':
-            changeIsEvaluate(id);
+            projectObj.project.projectGLJ.changeIsEvaluate(id);
             break;
             break;
     }
     }
     // 重新加载数据到缓存
     // 重新加载数据到缓存
@@ -404,60 +404,6 @@ function successTrigger(field, info,id) {
     gljOprObj.refreshView();
     gljOprObj.refreshView();
 }
 }
 
 
-//更新是否暂估
-function changeIsEvaluate (id){
-    let projectGLJ = projectObj.project.projectGLJ;
-    let datas = projectGLJ.datas;
-    let gljList = datas.gljList;
-    let glj = _.find(gljList, {'id': id});
-    if(glj){
-        let con_key = gljOprObj.getIndex(glj,gljKeyArray);
-        let pratioM =datas.mixRatioConnectData[con_key];//找到父key
-        let conditions = [];
-        if(pratioM&&pratioM.length>0){
-            for(let p_key of pratioM ){
-                conditions.push(gljOprObj.getConditionByKey(p_key));
-            }
-        }
-        let gljs = projectGLJ.getProjectGLJs(conditions,false);
-        gljs.push(glj);
-        let nodes = projectGLJ.getImpactRationNodes(gljs);//取到因为改变工料机价格而受影响的定额
-        //更新对应的工料机类型的定额
-        let ration =_.find(projectObj.project.Ration.datas,{'type':rationType.gljRation,'projectGLJID':glj.id});
-        if(ration){
-            ration.isEstimate =glj.is_evaluate?1:0;
-            let ration_node = projectObj.project.mainTree.getNodeByID(ration.ID);
-            ration_node?projectObj.mainController.refreshTreeNode([ration_node]):"";
-        }
-        projectObj.project.calcProgram.calcRationsAndSave(nodes);//触发计算程序
-    }
-}
-
-/**
- * socket.io相关初始化
- *
- * @return {void}
- */
-function socketInit() {
-    if (socket === null) {
-        socket = io('http://' + host + ':3300');
-        socket.on('connect', function () {
-            socket.emit('join', roomId);
-            console.log('单价文件同步连接成功');
-        });
-    }
-
-    // 接收到改变
-    socket.on('dataChange', function (data) {
-        data = JSON.parse(data);
-        if (data.newValue === undefined) {
-            return false;
-        }
-        $("#message").html('市场单位已被修改,<a href="javascript:void(0);" id="load-data">点击加载</a>');
-        $("#notify").slideDown('fast');
-    });
-}
-
 //过滤消耗量为0的项目工料机
 //过滤消耗量为0的项目工料机
 function filterProjectGLJ(jsonData) {
 function filterProjectGLJ(jsonData) {
     if (jsonData.length > 0) {
     if (jsonData.length > 0) {

+ 19 - 2
web/building_saas/glj/js/project_glj_spread.js

@@ -18,7 +18,7 @@ function ProjectGLJSpread() {
     this.firstMixRatioRow = -1;
     this.firstMixRatioRow = -1;
     this.successCallback = null;
     this.successCallback = null;
     this.supplyType = ['自行采购', '部分甲供', '完全甲供', '甲定乙供'];
     this.supplyType = ['自行采购', '部分甲供', '完全甲供', '甲定乙供'];
-    this.supplyComboMap = [{text:"自行采购",value:0},{text:"完全甲供",value:2},{text:"部分甲供",value:1},{text:"甲定乙供",value:3}];//后来调整了下拉选项的顺序,为了不改之前的业务逻辑,这里的值对换了一下
+    this.supplyComboMap = supplyComboMap
     // 工料机类型是混凝土、砂浆、配合比、机械(不包括机械组成物)时,供货方式列只读。
     // 工料机类型是混凝土、砂浆、配合比、机械(不包括机械组成物)时,供货方式列只读。
     this.supplyReadonlyType = notEditType;
     this.supplyReadonlyType = notEditType;
 }
 }
@@ -294,8 +294,8 @@ ProjectGLJSpread.prototype.specialColumn = function (sourceData) {
     let supplyQuantity = this.sheetObj.getFieldColumn('supply_quantity');
     let supplyQuantity = this.sheetObj.getFieldColumn('supply_quantity');
     let activeSheet = this.sheetObj.getSheet();
     let activeSheet = this.sheetObj.getSheet();
 
 
-
     for (let data of sourceData) {
     for (let data of sourceData) {
+        let rowStyle = null;
         //设置类型名称:
         //设置类型名称:
         activeSheet.setValue(rowCounter, shortNameColumn,projectObj.project.projectGLJ.getShortNameByID(data.unit_price.type));
         activeSheet.setValue(rowCounter, shortNameColumn,projectObj.project.projectGLJ.getShortNameByID(data.unit_price.type));
         // 只有材料才显示是否暂估
         // 只有材料才显示是否暂估
@@ -343,6 +343,8 @@ ProjectGLJSpread.prototype.specialColumn = function (sourceData) {
                 activeSheet.getCell(rowCounter, marketPriceColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
                 activeSheet.getCell(rowCounter, marketPriceColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
                 activeSheet.getCell(rowCounter, basePriceColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
                 activeSheet.getCell(rowCounter, basePriceColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
                 activeSheet.getCell(rowCounter, supplyColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
                 activeSheet.getCell(rowCounter, supplyColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
+                //设置底色
+                rowStyle = this.getRowStyle("#E0E0E0");
             }
             }
         }
         }
         if(data.unit_price.is_add!=1){//如果不是新增,定额价不可修改。
         if(data.unit_price.is_add!=1){//如果不是新增,定额价不可修改。
@@ -365,10 +367,25 @@ ProjectGLJSpread.prototype.specialColumn = function (sourceData) {
         data=this.sheetObj.setProjectGLJDiffPrice(data);
         data=this.sheetObj.setProjectGLJDiffPrice(data);
         activeSheet.setValue(rowCounter,basePriceColumn,data.base_price);
         activeSheet.setValue(rowCounter,basePriceColumn,data.base_price);
         activeSheet.setValue(rowCounter,adjustPriceColumn,data.adjust_price);
         activeSheet.setValue(rowCounter,adjustPriceColumn,data.adjust_price);
+        if(rowStyle==null&&data.base_price == data.unit_price.market_price){//如果定额价等于市场价时,改底色。 优先度低于有组成物时的底色
+            rowStyle = this.getRowStyle("#C4CAFB");
+        }
+        activeSheet.setStyle(rowCounter, -1, rowStyle);
+
         rowCounter++;
         rowCounter++;
     }
     }
 };
 };
 
 
+ProjectGLJSpread.prototype.getRowStyle = function (bgColour) {
+    let style = new GC.Spread.Sheets.Style();
+    style.backColor = bgColour;
+    style.borderLeft = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+    style.borderTop = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+    style.borderRight = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+    style.borderBottom = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+    return style;
+};
+
 /**
 /**
  * 计算当前行对应组成物的市场以及基价单价价格
  * 计算当前行对应组成物的市场以及基价单价价格
  *
  *

+ 24 - 7
web/building_saas/main/html/main.html

@@ -43,6 +43,7 @@
             <ul class="nav nav-tabs flex-column" role="tablist">
             <ul class="nav nav-tabs flex-column" role="tablist">
                 <li class="nav-item"><a class="active" data-toggle="tab" href="#zaojiashu" id="tab_zaojiashu" role="tab">造价书</a></li>
                 <li class="nav-item"><a class="active" data-toggle="tab" href="#zaojiashu" id="tab_zaojiashu" role="tab">造价书</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#gongliaoji" id="tab_gongliaoji" data-name="tab_gongliaoji" role="tab">工料机</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#gongliaoji" id="tab_gongliaoji" data-name="tab_gongliaoji" role="tab">工料机</a></li>
+                <li class="nav-item"><a data-toggle="tab" href="#project_glj" id="tab_project_glj" data-name="tab_project_glj" role="tab">工料机新</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#fee_rates" id="tab_fee_rate" role="tab" >费率</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#fee_rates" id="tab_fee_rate" role="tab" >费率</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#calc_program_manage" id="tab_calc_program_manage" role="tab">计算程序</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#calc_program_manage" id="tab_calc_program_manage" role="tab">计算程序</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#reports" role="tab" id="tab_report" onclick="rptTplObj.iniPage();">报表</a></li>
                 <li class="nav-item"><a data-toggle="tab" href="#reports" role="tab" id="tab_report" onclick="rptTplObj.iniPage();">报表</a></li>
@@ -63,6 +64,19 @@
                     <a href="javascript:void(0)" class="btn btn-sm" id="downLevel" title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
                     <a href="javascript:void(0)" class="btn btn-sm" id="downLevel" title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
                     <a href="javascript:void(0)" class="btn btn-sm" id="downMove" title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
                     <a href="javascript:void(0)" class="btn btn-sm" id="downMove" title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
                     <a href="javascript:void(0)" class="btn btn-sm" id="upMove" title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
                     <a href="javascript:void(0)" class="btn btn-sm" id="upMove" title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                      <span>
+                  <a href="" class="btn btn-sm" data-toggle="dropdown"><b data-toggle="tooltip" data-placement="bottom">显示至...</b></a>
+                  <div class="dropdown-menu dropdown-menu-left" style="min-width: 6.5rem">
+                      <a class="dropdown-item" href="javascript:void(0);" style="padding: 0rem 1.5rem" id="displayDXFY">大项费用</a>
+                      <a class="dropdown-item" href="javascript:void(0);" style="padding: 0rem 1.5rem" id="displayFB1">一级分部</a>
+                      <a class="dropdown-item" href="javascript:void(0);" style="padding: 0rem 1.5rem" id="displayFB2">二级分部</a>
+                      <a class="dropdown-item" href="javascript:void(0);" style="padding: 0rem 1.5rem" id="displayFB3">三级分部</a>
+                      <a class="dropdown-item" href="javascript:void(0);" style="padding: 0rem 1.5rem" id="displayFB4">四级分部</a>
+                      <a class="dropdown-item" href="javascript:void(0);" style="padding: 0rem 1.5rem" id="displayFX">分项</a>
+                      <a class="dropdown-item" href="javascript:void(0);" style="padding: 0rem 1.5rem" id="displayZM">子目</a>
+                      <a class="dropdown-item" href="javascript:void(0);" style="padding: 0rem 1.5rem" id="displayZD">最底层</a>
+                  </div>
+                </span>
                   </div>
                   </div>
                   <div class="tools-btn">
                   <div class="tools-btn">
                       <a href="javacript:void(0);" data-toggle="modal" data-target="#column" class="btn btn-sm"><i class="fa fa-table" aria-hidden="true"></i> 列设置</a>
                       <a href="javacript:void(0);" data-toggle="modal" data-target="#column" class="btn btn-sm"><i class="fa fa-table" aria-hidden="true"></i> 列设置</a>
@@ -259,6 +273,9 @@
             <div class="tab-pane" id="gongliaoji" role="tabpanel">
             <div class="tab-pane" id="gongliaoji" role="tabpanel">
                 <%include ../../glj/html/glj_index.html %>
                 <%include ../../glj/html/glj_index.html %>
             </div>
             </div>
+            <div class="tab-pane" id="project_glj" role="tabpanel">
+              <%include ../../glj/html/project_glj.html %>
+            </div>
             <div class="tab-pane" id="reports" role="tabpanel">
             <div class="tab-pane" id="reports" role="tabpanel">
                 <%include ../../report/html/rpt_main.html %>
                 <%include ../../report/html/rpt_main.html %>
             </div>
             </div>
@@ -289,7 +306,7 @@
                             <ul class="nav flex-column nav-pills" role="tablist">
                             <ul class="nav flex-column nav-pills" role="tablist">
                                 <li class="nav-item"><a class="nav-link active" data-toggle="pill" href="#poj-settings-basicInfo" role="tab" id="tab_poj-settings-basicInfo">基本信息</a></li>
                                 <li class="nav-item"><a class="nav-link active" data-toggle="pill" href="#poj-settings-basicInfo" role="tab" id="tab_poj-settings-basicInfo">基本信息</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-projFeature" id="tab_poj-settings-projFeature" role="tab">工程特征</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-projFeature" id="tab_poj-settings-projFeature" role="tab">工程特征</a></li>
-                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-3" role="tab">指标信息</a></li>
+                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-indicativeInfo" id="tab_poj-settings-indicativeInfo" role="tab">指标信息</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-4" id="about-calc" role="tab">关于计算</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-4" id="about-calc" role="tab">关于计算</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-billsQuanDecimal" id="tab_poj-settings-bqDecimal" role="tab">清单工程量精度</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-billsQuanDecimal" id="tab_poj-settings-bqDecimal" role="tab">清单工程量精度</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-decimal" role="tab" id="tab_poj-settings-decimal">小数位数</a></li>
                                 <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-decimal" role="tab" id="tab_poj-settings-decimal">小数位数</a></li>
@@ -307,13 +324,11 @@
                                 <!--工程特征-->
                                 <!--工程特征-->
                                 <div class="tab-pane fade" id="poj-settings-projFeature" role="tabpanel">
                                 <div class="tab-pane fade" id="poj-settings-projFeature" role="tabpanel">
                                     <div class="modal-auto-height" style="overflow: hidden" id="projFeatureSpread">
                                     <div class="modal-auto-height" style="overflow: hidden" id="projFeatureSpread">
-                                        工程特征
                                     </div>
                                     </div>
                                 </div>
                                 </div>
                                 <!--指标信息-->
                                 <!--指标信息-->
-                                <div class="tab-pane fade" id="poj-settings-3" role="tabpanel">
-                                    <div class="modal-auto-height">
-                                        指标信息
+                                <div class="tab-pane fade" id="poj-settings-indicativeInfo" role="tabpanel">
+                                    <div class="modal-auto-height" style="overflow:hidden" id="indicativeInfoSpread">
                                     </div>
                                     </div>
                                 </div>
                                 </div>
                                 <!--关于计算-->
                                 <!--关于计算-->
@@ -926,7 +941,7 @@
                                     <legend class="legend" >分项费用:</legend>
                                     <legend class="legend" >分项费用:</legend>
                                     <div class="form-check">
                                     <div class="form-check">
                                         <label class="form-check-label">
                                         <label class="form-check-label">
-                                            <input class="form-check-input" name="install_setting_radios" id="all_project_calc" value="0" checked type="radio">
+                                            <input class="form-check-input" name="install_setting_radios" id="all_project_calc" value="0" type="radio">
                                             整个项目统一计取
                                             整个项目统一计取
                                         </label>
                                         </label>
                                     </div>
                                     </div>
@@ -946,7 +961,7 @@
                     </div>
                     </div>
                 </div>
                 </div>
                 <div class="modal-footer">
                 <div class="modal-footer">
-                    <button type="button" class="btn btn-link" >恢复默认值</button>
+                    <button type="button" class="btn btn-link" id="btn_reset_to_default">恢复默认值</button>
                   <!--  <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>-->
                   <!--  <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>-->
                     <button  class="btn btn-primary" id="calc_installation_fee_confirm">确定</button>
                     <button  class="btn btn-primary" id="calc_installation_fee_confirm">确定</button>
                 </div>
                 </div>
@@ -1128,6 +1143,7 @@
         <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_decimal_view.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_decimal_view.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_basicInfo.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_basicInfo.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_projFeature.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_projFeature.js"></script>
+        <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_indicativeInfo.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_display_view.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_display_view.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/main_ajax.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/main_ajax.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/main.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/main.js"></script>
@@ -1141,6 +1157,7 @@
         <script type="text/javascript" src='/web/building_saas/main/js/views/confirm_modal.js'></script>
         <script type="text/javascript" src='/web/building_saas/main/js/views/confirm_modal.js'></script>
         <script type="text/javascript" src='/web/building_saas/main/js/views/zlfb_view.js'></script>
         <script type="text/javascript" src='/web/building_saas/main/js/views/zlfb_view.js'></script>
         <script type="text/javascript" src='/web/building_saas/main/js/views/installation_fee_view.js'></script>
         <script type="text/javascript" src='/web/building_saas/main/js/views/installation_fee_view.js'></script>
+        <script type="text/javascript" src='/web/building_saas/main/js/views/project_glj_view.js'></script>
         <!--报表-->
         <!--报表-->
         <script type="text/javascript" src="/public/web/rpt_tpl_def.js"></script>
         <script type="text/javascript" src="/public/web/rpt_tpl_def.js"></script>
         <script type="text/javascript" src="/public/web/treeDataHelper.js"></script>
         <script type="text/javascript" src="/public/web/treeDataHelper.js"></script>

+ 92 - 7
web/building_saas/main/js/models/bills.js

@@ -124,7 +124,16 @@ var Bills = {
                 this.refreshDatas(data,'quantity');
                 this.refreshDatas(data,'quantity');
             }
             }
         };
         };
-
+        bills.prototype.getBillByCode = function(code){
+            let sortData = _.sortBy(projectObj.project.Bills.datas,'code');
+            return _.find(sortData, function(b) {
+                if(b.code&&b.code.indexOf(code)!=-1){
+                    return true;
+                }else {
+                    return false;
+                }
+            });
+        };
         bills.prototype.refreshDatas = function(data,fieldName){
         bills.prototype.refreshDatas = function(data,fieldName){
             var dataIndex = _.findIndex(this.datas,function(item) {
             var dataIndex = _.findIndex(this.datas,function(item) {
                 return item.ID ==data.billID;
                 return item.ID ==data.billID;
@@ -238,6 +247,10 @@ var Bills = {
             return this.tree.delete(node);
             return this.tree.delete(node);
         };
         };
 
 
+        bills.prototype.removeByID = function(ID){
+            _.remove(this.datas,{'ID':ID});
+        };
+
         bills.prototype.singleDeleteBills=function(node,controller){//只删除选中的分部,不删除其子项
         bills.prototype.singleDeleteBills=function(node,controller){//只删除选中的分部,不删除其子项
             let updateData = {};
             let updateData = {};
             let updateNode={};
             let updateNode={};
@@ -547,6 +560,18 @@ var Bills = {
                 }
                 }
             }
             }
         };
         };
+        bills.prototype.getTechNode=function () {//取技术措施项目节点
+            let items = projectObj.project.mainTree.items;//所有节点;
+            let techNode = null;
+            for(let item of items){
+                if(isFlag(item.data)&&item.data.flagsIndex.fixed.flag==fixedFlag.CONSTRUCTION_TECH){
+                    techNode = item;
+                    break;
+                }
+            }
+           return techNode;
+        };
+
         bills.prototype.deleteSelectedNode=function(){//删除选中单行时的节点
         bills.prototype.deleteSelectedNode=function(){//删除选中单行时的节点
             let controller = projectObj.mainController, project = projectObj.project;
             let controller = projectObj.mainController, project = projectObj.project;
             let selected = controller.tree.selected, parent = selected.parent;
             let selected = controller.tree.selected, parent = selected.parent;
@@ -564,10 +589,21 @@ var Bills = {
                 }else if(selected.sourceType==ModuleNames.ration_glj){
                 }else if(selected.sourceType==ModuleNames.ration_glj){
                     project.ration_glj.updataOrdelete(selected.source);
                     project.ration_glj.updataOrdelete(selected.source);
                 }
                 }
-                if(parent){
-                    projectObj.converseCalculateBills(parent);
-                }else { //删除的是大项费用要重新计算工程造价节点
-                    project.Bills.calcEngineeringCostNode(controller);
+                if(project.Bills.isFBFX(selected)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
+                    project.installation_fee.calcInstallationFee(function (isChange) {
+                        if(isChange){
+                            project.calcProgram.calcAllNodesAndSave();
+                        }else {
+                            if(parent){
+                                projectObj.converseCalculateBills(parent);
+                            }else { //删除的是大项费用要重新计算工程造价节点
+                                project.Bills.calcEngineeringCostNode(controller);
+                            }
+                            project.projectGLJ.loadData();
+                        }
+                    });
+                }else {
+                    project.projectGLJ.loadData();
                 }
                 }
             }
             }
         };
         };
@@ -669,10 +705,18 @@ var Bills = {
                 }
                 }
                 controller.m_delete(mainNodes);//删除树节点
                 controller.m_delete(mainNodes);//删除树节点
                 me.tree.m_delete(idTreeNodes);
                 me.tree.m_delete(idTreeNodes);
+                $.bootstrapLoading.end();
                 //重新计算
                 //重新计算
-                project.calcProgram.calcBillsAndSave(parentNodes,function () {
-                    project.projectGLJ.loadData();
+                project.installation_fee.calcInstallationFee(function (isChange) {
+                    project.calcProgram.calcAllNodesAndSave();
+                    if(!isChange) {
+                        project.projectGLJ.loadData();
+                    }
                 });
                 });
+
+               /* project.calcProgram.calcBillsAndSave(parentNodes,function () {
+                    project.projectGLJ.loadData();
+                });*/
             }, function () {
             }, function () {
                 $.bootstrapLoading.end();
                 $.bootstrapLoading.end();
             });
             });
@@ -715,6 +759,47 @@ var Bills = {
             });
             });
             cbTools.refreshFormulaNodes();
             cbTools.refreshFormulaNodes();
         };
         };
+        bills.prototype.getAllBXs = function () {
+          return _.filter(this.datas,{"type":billType.BX});
+        };
+        bills.prototype.getNewInstallBillData = function (code,billID,feeType) {
+            let controller = projectObj.mainController;
+            let parentNode;
+            if(feeType == '措施费用'){
+                parentNode = this.getTechNode();
+            }else {
+                let rootNode = this.getFBFXNode(controller);
+                   parentNode =getLeaveBill(rootNode.source);
+                if(parentNode.data.type == billType.FX){//如果是分项的话,取父节点
+                    parentNode = parentNode.parent;
+                }
+            }
+            if(!billID){
+                billID = uuid.v1();
+            }
+            let data = {
+                ID:billID,
+                projectID: parseInt(projectObj.project.ID()),
+                ParentID:parentNode.data.ID,
+                NextSiblingID:-1,
+                code : this.newFormatCode(code),
+                name:'安装增加费',
+                unit:'元',
+                quantity:'1'
+            };
+            return data;
+
+            function getLeaveBill(node) {
+                if(node.children.length>0){
+                    return getLeaveBill(node.children[node.children.length-1]);
+                }else {
+                    return node;
+                }
+            }
+
+
+        };
+
         return new bills(project);
         return new bills(project);
     }
     }
 };
 };

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

@@ -445,6 +445,21 @@ var cacheTree = {
               this.getAllSubNode(c,nodeArray);
               this.getAllSubNode(c,nodeArray);
           }
           }
         };
         };
+        Tree.prototype.getLeavesNodes = function (node) {//取该节点下的所有叶子节点
+            let leaves = [];
+            getLeaves(node,leaves);
+            return leaves;
+
+            function getLeaves(node,nodeArr) {
+                if(node.children.length>0){
+                    for(let ch of node.children){
+                        getLeaves(ch,nodeArr);
+                    }
+                }else {
+                    nodeArr.push(node);
+                }
+            }
+        };
         Tree.prototype.getNodeByID = function (ID) {
         Tree.prototype.getNodeByID = function (ID) {
           let node = this.nodes[this.prefix+ID];
           let node = this.nodes[this.prefix+ID];
           return node;
           return node;

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

@@ -1074,7 +1074,7 @@ class CalcProgram {
             $.bootstrapLoading.end();
             $.bootstrapLoading.end();
             return;
             return;
         };
         };
-
+        $.bootstrapLoading.start();
         me.project.updateNodes(dataArr, function (data) {
         me.project.updateNodes(dataArr, function (data) {
             if(callback){
             if(callback){
                 callback(data);
                 callback(data);

+ 492 - 0
web/building_saas/main/js/models/installation_fee.js

@@ -189,7 +189,499 @@ var installation_fee = {
                 })
                 })
             }
             }
         };
         };
+        installation_fee.prototype.calcInstallationFee=function(callback){
+            let project = projectObj.project,me = this;
+            let engineering = projectInfoObj.projectInfo.property.engineering;
+            let installSetting = projectInfoObj.projectInfo.property.installSetting;
+            let rationInstallation  = project.ration_installation;
+            let BXs =  project.Bills.getAllBXs();//取所有补项
+            let allBillsDatas = _.sortBy(_.cloneDeep(project.Bills.datas),'code');//取所有清单信息,用来查找清单信息和存放中间过程产生的清单
+            let rationKeyMap={};//安装子目关联表
+            let newBills = [];
+            let billSerialMap = {};
+            let FBMap = {};//保存分部下对应的补项
+            let usedBXMap = {};//有使用到的补项
+            if(engineering!=engineeringType.BUILD_IN){//如果不是安装工程,则不用计算
+                if(callback) callback(false);
+                return;
+            }
+            for(let bx of BXs){//把补项放入映射表中
+                FBMap[bx.ParentID] = bx;
+            }
+            for(let d of me.datas){
+                for(let item of d.installFeeItem){
+                    if(item.isCal == 1){ //勾选了记取的费用项
+                        let rule_ration_map = {};//费用规则定额映射表;
+                        let ra_installs = rationInstallation.getCalcRIByItemID(d.libID,item.ID);//取所有有效的定额安装增加费
+                        for(let ri of ra_installs){
+                            let rationNode = project.mainTree.getNodeByID(ri.rationID);
+                            if(rationNode){
+                                if(rule_ration_map[ri.ruleId]){
+                                    rule_ration_map[ri.ruleId].push(rationNode.data);
+                                }else {
+                                    rule_ration_map[ri.ruleId] = [rationNode.data];
+                                }
+                            }
+                        }
+                        for(let ruleIDKey in rule_ration_map){
+                            calcEachRule(item,d.libID,ruleIDKey,rule_ration_map[ruleIDKey],rationKeyMap,newBills);
+                        }
+                    }
+                }
+            }
+            let updateData = {
+                bills:{
+                    delete:[],
+                    add:newBills
+                },
+                ration:{//定额更新只有更新对应的工料机数据
+                    delete:[],
+                    update:[],
+                    add:[]
+                },
+                userID: userID
+            };
+            let oldITypeRations = _.cloneDeep(project.Ration.getAllInstallTypeRation())//取所有旧的安装增加费定额-没有用的要删除
+            let oldRationMap = {}, deleteRationNodes = [], deleteBillsNodes = [];
+            let isChange = newBills.length>0;//记录数据是否发生了改变;
+            for(let o of oldITypeRations){//过滤出要删除的定额
+                if(rationKeyMap[o.installationKey]==undefined){
+                    updateData.ration.delete.push(o);
+                    let d_node =  project.mainTree.getNodeByID(o.ID);
+                    if(d_node){
+                        deleteRationNodes.push(d_node);
+                        isChange = true;
+                    }
+                }
+                oldRationMap[o.installationKey] = o;
+            }
+
+            for(let inKey in rationKeyMap){
+                if(oldRationMap[inKey]){//存在,则更新就可以了
+                    if(checkRation(oldRationMap[inKey],rationKeyMap[inKey])){//检查是否需要更新
+                        updateData.ration.update.push(oldRationMap[inKey]);
+                        isChange = true;
+                    }
+                }else {
+                    updateData.ration.add.push(rationKeyMap[inKey]);
+                    isChange = true;
+                }
+            }
+
+            for(let tem_bx of BXs){//过滤要删除的补项
+                if(usedBXMap[tem_bx.ParentID]==undefined){
+                    updateData.bills.delete.push(tem_bx);
+                    let b_node =  project.mainTree.getNodeByID(tem_bx.ID);
+                    if(b_node){
+                        deleteBillsNodes.push(b_node);
+                        isChange = true;
+                    }
+                }
+            }
+
+            if(isChange == true){
+                $.bootstrapLoading.start();
+                CommonAjax.post("/project/calcInstallationFee",updateData,function (data) {
+                    //提交后台成功后所做的操作,删除要先删除定额,再删除清单,添加要先添加清单再添加定额
+                    console.log(data);
+                    project.ration_glj.addDatasToList(data.add);//添加插入的定额
+                    for(let ur of data.update){
+                        let glj = project.ration_glj.getDataByID(ur.ID);
+                        glj.quantity = ur.quantity;
+                        glj.rationItemQuantity = ur.rationItemQuantity;
+                    }
+
+                    //对树节点的操作并删除、添加清单、删除添加定额、删除对应的定额工料机缓存
+                    TREE_SHEET_HELPER.massOperationSheet(projectObj.mainController.sheet, function () {
+                        deleteOldNodes(deleteRationNodes,deleteBillsNodes);
+                        addNewNodes(updateData);
+                    });
+                    projectObj.project.projectGLJ.loadData(function () {
+                        cbTools.refreshFormulaNodes();
+                        if(callback){
+                            callback(true);
+                        }
+                        $.bootstrapLoading.end();
+                    });
+                });
+            }else {
+                if(callback) callback(false);
+            }
+            function addNewNodes(updateData) {
+                let controller = projectObj.mainController;
+                let Bill = project.Bills;
+                let newAddNode = [];
+                for(let nb of updateData.bills.add){
+                    let newSource = Bill.tree.insertByData(nb, nb.ParentID, -1, true);
+                    let newNode = project.mainTree.insert(nb.ParentID, -1, newSource.data.ID);
+                    newNode.source = newSource;
+                    newNode.sourceType = Bill.getSourceType();
+                    newNode.data = newSource.data;
+                    controller.sheet.addRows(newNode.serialNo(), 1);
+                    controller.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                    newAddNode.push(newNode);
+                    Bill.datas.push(nb);
+                }
+                for(let nr of updateData.ration.add){
+                   let newNode = project.mainTree.insert(nr.billsItemID, -1, nr.ID);
+                    newNode.source = nr;
+                    newNode.sourceType = project.Ration.getSourceType();
+                    newNode.data = nr;
+                    controller.sheet.addRows(newNode.serialNo(), 1);
+                    controller.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                    newAddNode.push(newNode);
+                    project.Ration.datas.push(nr);
+                }
+                console.log("add nodes");
+                TREE_SHEET_HELPER.refreshTreeNodeData(controller.setting, controller.sheet, newAddNode, false);
+            }
+
+            function deleteOldNodes(deleteRationNodes,deleteBillsNodes) {
+                let controller = projectObj.mainController, project = projectObj.project;
+                let Bill = project.Bills, Ration = project.Ration,ration_glj = project.ration_glj;
+                for(let rd of deleteRationNodes){
+                    controller.sheet.deleteRows(rd.serialNo(),1);
+                    controller.tree.delete(rd);
+                    Ration.removeByID(rd.getID());
+                    ration_glj.deleteByRation(rd.data);
+                }
+                for(let bd of deleteBillsNodes){
+                    controller.sheet.deleteRows(bd.serialNo(),1);
+                    controller.tree.delete(bd);
+                    Bill.tree.delete(bd.source);
+                    Bill.removeByID(bd.getID());
+                }
+                let sels = controller.sheet.getSelections();
+                controller.setTreeSelected(controller.tree.items[sels[0].row]);
+            }
+
+            
+            function checkRation(oldRation,newRation) {//检查定额是否需要更新
+                let gljs = project.ration_glj.getGljByRationID(oldRation.ID);
+                let modify = false;
+                let gljList =[];
+                for(let g of gljs){
+                    if(g.quantity != newRation.glj[g.code].quantity){//消耗量不一样,需重新修改
+                        let tem ={
+                            ID:g.ID,
+                            projectID:g.projectID,
+                            quantity :newRation.glj[g.code].quantity,
+                            rationItemQuantity:newRation.glj[g.code].rationItemQuantity
+                        };
+                        gljList.push(tem);
+                        modify = true;
+                    }
+                }
+                oldRation.glj = gljList;
+                return modify;
+            }
 
 
+            function calcEachRule(item,libID,ruleID,rations,rationKeyMap,newBills) {
+                let rule = me.getFeeRuleByID(libID,ruleID);
+                let pre_key = libID+item.ID+item.feeType+ruleID;
+                if(item.feeType == '子目费用'){
+                    for(let r of rations){//在定额的同级新增一条
+                        let billItemID = r.billsItemID;
+                        let nextID = -1;
+                        let newRationData = createNewRationData(billItemID,nextID,rule);
+                        let [labourQuantity,materialQuantity,machineQuantity] = calcQuantity(rule,r);
+                        newRationData = setGljQuantity(newRationData,labourQuantity,materialQuantity,machineQuantity);
+                        let installationKey = pre_key+billItemID;
+                        newRationData['installationKey'] = installationKey;
+                        if(rationKeyMap[installationKey]){//如果已经存在,则工料机消耗量累加起来
+                            sumGLJquantity(rationKeyMap[installationKey],labourQuantity,materialQuantity,machineQuantity);
+                        }else {
+                            rationKeyMap[installationKey] = newRationData;//在映射表中添加
+                        }
+                    }
+                }else if(item.feeType == '措施费用'){//措施费用时,则在记取位置选择的清单下新增安装子目。
+                    allInOne(item,rule,rations,newBills,pre_key,rationKeyMap);
+                }else if(item.feeType=='分项费用'){
+                    if(installSetting==undefined||installSetting=="0"){//选择了“整个项目统一计取”,则在记取位置选择的分项下新增安装子目
+                        allInOne(item,rule,rations,newBills,pre_key,rationKeyMap);
+                    }else {//选择了每个分部单独记取
+                        calcEveryFB(item,rule,rations,newBills,pre_key,rationKeyMap);
+                    }
+                }
+            }
+
+
+            function sumGLJquantity(ration,labourQuantity,materialQuantity,machineQuantity) {
+                let gljDecimal = getDecimal('glj.quantity');
+                let sumLabour = scMathUtil.roundForObj(ration.glj['RGFTZ'].quantity,gljDecimal)+labourQuantity;
+                let sumMaterial = scMathUtil.roundForObj(ration.glj['CLFTZ'].quantity,gljDecimal)+materialQuantity;
+                let sumMachine = scMathUtil.roundForObj(ration.glj['JXFTZ'].quantity,gljDecimal)+machineQuantity;
+                ration.glj['RGFTZ'].quantity =scMathUtil.roundToString(sumLabour,gljDecimal);
+                ration.glj['RGFTZ'].rationItemQuantity = scMathUtil.roundToString(sumLabour,gljDecimal);
+                ration.glj['CLFTZ'].quantity = scMathUtil.roundToString(sumMaterial,gljDecimal);
+                ration.glj['CLFTZ'].rationItemQuantity = scMathUtil.roundToString(sumMaterial,gljDecimal);
+                ration.glj['JXFTZ'].quantity = scMathUtil.roundToString(sumMachine,gljDecimal);
+                ration.glj['JXFTZ'].rationItemQuantity = scMathUtil.roundToString(sumMachine,gljDecimal);
+            }
+
+            function calcEveryFB(item,rule,rations,newBills,pre_key,rationKeyMap) {
+                let parentMap = {};
+                for(let r of rations){//先归类
+                    let rationNode = project.mainTree.getNodeByID(r.ID);
+                    if(rationNode){
+                        if(parentMap[rationNode.parent.parent.getID()]){
+                            parentMap[rationNode.parent.parent.getID()].push(r)
+                        }else {
+                            parentMap[rationNode.parent.parent.getID()] = [r];
+                        }
+                    }
+                }
+                for(let billID_key in parentMap){
+                    let gljDecimal = getDecimal('glj.quantity');
+                    let tem_rations = parentMap[billID_key];
+                    let BXNodeData;
+                    if(FBMap[billID_key]){//查看有没有对应的补项,如果没有,新增一个
+                        BXNodeData = FBMap[billID_key];
+                    }else {//新增一个
+                        BXNodeData = {
+                            projectID: parseInt(project.ID()),
+                            ParentID:billID_key,
+                            NextSiblingID:-1,
+                            code : 'BAZF',
+                            name:'安装增加费',
+                            unit:'元',
+                            quantity:'1',
+                            type:billType.BX
+                        };
+                        BXNodeData.ID =  uuid.v1();
+                        FBMap[billID_key] = BXNodeData;
+                        newBills.push(BXNodeData);
+                    }
+                    usedBXMap[billID_key] = BXNodeData;//记录有用到的补项,最后没有用到的要删除
+                    let newRationData = createNewRationData(BXNodeData.ID,-1,rule);
+                    let labourSum = 0,materialSum =0,machineSum = 0;
+                    for(let ra of tem_rations){//措施费用的情况下,多条定额生成一条安装子目
+                        let [tem_labourQuantity,tem_materialQuantity,tem_machineQuantity] = calcQuantity(rule,ra);
+                        labourSum =scMathUtil.roundForObj(labourSum+tem_labourQuantity,gljDecimal);
+                        materialSum= scMathUtil.roundForObj(materialSum+tem_materialQuantity,gljDecimal);
+                        machineSum = scMathUtil.roundForObj(machineSum+tem_machineQuantity,gljDecimal);
+                    }
+                    newRationData = setGljQuantity(newRationData,labourSum,materialSum,machineSum);
+                    let installationKey = pre_key+BXNodeData.ID;
+                    newRationData['installationKey'] = installationKey;
+                    rationKeyMap[installationKey] = newRationData;//在映射表中添加
+                }
+            }
+
+
+            function allInOne(item,rule,rations,newBills,pre_key,rationKeyMap) {//统一设置
+                let billData = getBillNodeData(item,rule,newBills);//取对应的清单或生成一个新的清单数据
+                let newRationData = createNewRationData(billData.ID,-1,rule);
+                let gljDecimal = getDecimal('glj.quantity');
+                let labourSum = 0,materialSum =0,machineSum = 0;
+                for(let r of rations){//措施费用的情况下,多条定额生成一条安装子目
+                    let [tem_labourQuantity,tem_materialQuantity,tem_machineQuantity] = calcQuantity(rule,r);
+                    labourSum =scMathUtil.roundForObj(labourSum+tem_labourQuantity,gljDecimal);
+                    materialSum= scMathUtil.roundForObj(materialSum+tem_materialQuantity,gljDecimal);
+                    machineSum = scMathUtil.roundForObj(machineSum+tem_machineQuantity,gljDecimal);
+                }
+                newRationData = setGljQuantity(newRationData,labourSum,materialSum,machineSum);
+                let installationKey = pre_key+billData.ID;
+                newRationData['installationKey'] = installationKey;
+                rationKeyMap[installationKey] = newRationData;//在映射表中添加
+            }
+
+            function setGljQuantity(rationData,labourQuantity,materialQuantity,machineQuantity) {
+                let gljDecimal = getDecimal('glj.quantity');
+                rationData.glj['RGFTZ'].quantity = scMathUtil.roundToString(labourQuantity,gljDecimal);
+                rationData.glj['RGFTZ'].rationItemQuantity = scMathUtil.roundToString(labourQuantity,gljDecimal);
+                rationData.glj['CLFTZ'].quantity = scMathUtil.roundToString(materialQuantity,gljDecimal);
+                rationData.glj['CLFTZ'].rationItemQuantity = scMathUtil.roundToString(materialQuantity,gljDecimal);
+                rationData.glj['JXFTZ'].quantity = scMathUtil.roundToString(machineQuantity,gljDecimal);
+                rationData.glj['JXFTZ'].rationItemQuantity = scMathUtil.roundToString(machineQuantity,gljDecimal);
+                return rationData;
+            }
+
+            function createNewRationData(billItemID,nextID,rule) {
+                let br = project.Ration.getBillsSortRation(billItemID);
+                let serialNo = 0;
+                if(billSerialMap[billItemID]){
+                    serialNo = billSerialMap[billItemID]+1
+                }else {
+                    serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
+                    billSerialMap[billItemID] = serialNo;
+                }
+                serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
+                let newRationData = project.Ration.getTempRationData(project.Ration.getNewRationID(), billItemID, serialNo, rationType.install);
+                newRationData = setNewRationProperty(newRationData,nextID,rule);
+                return newRationData;
+            }
+
+
+            function getBillNodeData(item,rule,newBills) {
+                let billData = null;
+                let billID = null;
+                if(rule.billID&&rule.billID!=""){
+                    billData = getBillsByID(rule.billID);
+                    billID = rule.billID;
+                }
+                if(!billData){
+                    billData = getBillsByCode(rule.position);
+                    if(!billData){//如果按ID和按code都找不到清单的话,自动生成一个
+                        let newBillData = project.Bills.getNewInstallBillData(rule.position,billID,item.feeType);
+                        if(item.feeType == '措施费用'){
+                            newBillData.type = billType.BILL;
+                        }else if(item.feeType == '分项费用'){
+                            newBillData.type = billType.FX;
+                        }
+                        newBills.push(newBillData);
+                        allBillsDatas.push(newBillData);
+                        return newBillData;
+                    }
+                }
+                return billData;
+            }
+            function getBillsByID(billID){
+                return _.find(allBillsDatas,{"ID":billID});
+            }
+
+            function getBillsByCode(code){
+                return _.find(allBillsDatas, function(b) {
+                    if(b.code&&b.code.indexOf(code)!=-1){
+                        return true;
+                    }else {
+                        return false;
+                    }
+                })
+            }
+
+
+            function calcQuantity(rule,ration) {//计算单条定额的三个消耗量
+                let gljDecimal = getDecimal('glj.quantity');
+                let labourQuantity = 0, materialQuantity = 0, machineQuantity = 0;
+                let labour = rule.labour?rule.labour*0.01:0;
+                let material = rule.material?rule.material*0.01:0;
+                let machine = rule.machine?rule.machine*0.01:0;
+                let feeRate =  rule.feeRate?rule.feeRate*0.01:0;
+                if(rule.base=='分别按人材机乘系数'){//'分别按人材机乘系数','人工','材料','机械'
+                    labourQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getLabourTotalFee(ration))*parseFloat(labour),gljDecimal);
+                    materialQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getMaterialTotalFee(ration))*parseFloat(material),gljDecimal);
+                    machineQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getMachineTotalFee(ration))*parseFloat(machine),gljDecimal);
+                }else if(rule.base=='人工'){
+                    labourQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getLabourTotalFee(ration))*parseFloat(feeRate)*parseFloat(labour),gljDecimal);
+                }else if(rule.base=='材料'){
+                    materialQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getMaterialTotalFee(ration))*parseFloat(feeRate)*parseFloat(material),gljDecimal);
+                }else if(rule.base=='机械'){
+                    machineQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getMachineTotalFee(ration))*parseFloat(feeRate)*parseFloat(machine),gljDecimal);
+                }
+                return [labourQuantity,materialQuantity,machineQuantity];
+            }
+
+            function setNewRationProperty(data,nextID,rule) {
+                data.code = rule.code;
+                data.name = rule.rule;
+                data.unit = '元';
+                data.quantity = '1';
+                data.contain ='1';
+                data.nextID = nextID;
+                data.glj = {
+                    'RGFTZ':{
+                        rationID:data.ID,
+                        billsItemID:data.billsItemID,
+                        shortName:project.projectGLJ.getShortNameByID(gljType.LABOUR),
+                        GLJID:-1,
+                        projectID:data.projectID,
+                        code:'RGFTZ',
+                        original_code:'RGFTZ',
+                        name:'人工费调整',
+                        specs:'',
+                        unit:'元',
+                        type:gljType.LABOUR,
+                        basePrice:1,
+                        adjCoe:null,
+                        from:'std',
+                        repositoryId:-1,
+                        quantity:'0',
+                        rationItemQuantity:'0'
+                    },
+                    'CLFTZ':{
+                        rationID:data.ID,
+                        billsItemID:data.billsItemID,
+                        shortName:project.projectGLJ.getShortNameByID(gljType.GENERAL_MATERIAL),
+                        GLJID:-1,
+                        projectID:data.projectID,
+                        code:'CLFTZ',
+                        original_code:'CLFTZ',
+                        name:'材料费调整',
+                        specs:'',
+                        unit:'元',
+                        type:gljType.GENERAL_MATERIAL,
+                        basePrice:1,
+                        adjCoe:null,
+                        from:'std',
+                        repositoryId:-1,
+                        quantity:'0',
+                        rationItemQuantity:'0'
+                    },
+                    'JXFTZ':{
+                        rationID:data.ID,
+                        billsItemID:data.billsItemID,
+                        shortName:project.projectGLJ.getShortNameByID(gljType.MACHINE_COMPOSITION),
+                        GLJID:-1,
+                        projectID:data.projectID,
+                        code:'JXFTZ',
+                        original_code:'JXFTZ',
+                        name:'机械费调整',
+                        specs:'',
+                        unit:'元',
+                        type:gljType.MACHINE_COMPOSITION,
+                        basePrice:1,
+                        adjCoe:null,
+                        from:'std',
+                        repositoryId:-1,
+                        quantity:'0',
+                        rationItemQuantity:'0'
+                    }
+                };
+                return data;
+            }
+        };
+
+        installation_fee.prototype.updateInstallSetting = function (newValue,callback) {
+           let mixDatas = {
+                projectID: projectObj.project.ID(),
+                updateType: 'update',
+                properties: {
+                    "property.installSetting":newValue
+                },
+                labourCoes: {},
+                rations: [],
+                bills: []
+            };
+            CommonAjax.post('/pm/api/updateMixDatas', {user_id: userID, mixDataArr: mixDatas}, function (rstData) {
+                projectInfoObj.projectInfo.property.installSetting = newValue;
+                if(callback){
+                    callback();
+                }
+            });
+
+        };
+        installation_fee.prototype.resetToDefault = function (callback) {
+            let me = this;
+            let installFees = [];
+            for(let d of me.datas){
+                let ins ={
+                    libID:d.libID,
+                    ID:d.ID
+                };
+                installFees.push(ins);
+            }
+            //data.projectID,data.installFees
+            $.bootstrapLoading.start();
+            CommonAjax.post("/installation/resetToDefault",{projectID:project.ID(),installFees:installFees},function (result) {
+                console.log(result)
+                me.datas = result;
+                if(callback){
+                    callback();
+                }
+                $.bootstrapLoading.end();
+            })
+        };
         // 提交数据后返回数据处理
         // 提交数据后返回数据处理
         installation_fee.prototype.doAfterUpdate = function(err, data){
         installation_fee.prototype.doAfterUpdate = function(err, data){
 
 

+ 9 - 4
web/building_saas/main/js/models/main_consts.js

@@ -155,7 +155,8 @@ const volumePriceMaps = {
 const rationType = {
 const rationType = {
     ration: 1,
     ration: 1,
     volumePrice: 2,
     volumePrice: 2,
-    gljRation: 3
+    gljRation: 3,
+    install:4
 };
 };
 const leafBillGetFeeType = {
 const leafBillGetFeeType = {
     rationContent: 0,
     rationContent: 0,
@@ -240,13 +241,15 @@ const billType ={
     DXFY:1,//大项费用
     DXFY:1,//大项费用
     FB:2,//分部
     FB:2,//分部
     FX:3,//分项
     FX:3,//分项
-    BILL:4//清单
+    BILL:4,//清单
+    BX:5//补项
 };
 };
 const billText = {
 const billText = {
     1:'费用',
     1:'费用',
     2:'分部',
     2:'分部',
     3:'分项',
     3:'分项',
-    4:'清单'
+    4:'清单',
+    5:'补项'
 };
 };
 
 
 const cpFeeTypes = [
 const cpFeeTypes = [
@@ -300,4 +303,6 @@ const engineeringType = {
 };
 };
 
 
 const installFeeType = ['子目费用','分项费用','措施费用'];
 const installFeeType = ['子目费用','分项费用','措施费用'];
-const installSectionBase = ['分别按人材机乘系数','人工','材料','机械'];
+const installSectionBase = ['分别按人材机乘系数','人工','材料','机械'];
+const supplyComboMap = [{text:"自行采购",value:0},{text:"完全甲供",value:2},{text:"部分甲供",value:1},{text:"甲定乙供",value:3}];//后来调整了下拉选项的顺序,为了不改之前的业务逻辑,这里的值对换了一下
+

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

@@ -6,7 +6,7 @@ var PROJECT = {
         // 定义private方法
         // 定义private方法
         var tools = {
         var tools = {
             _project: null,
             _project: null,
-            _ID: projectID,
+            _ID: parseInt(projectID),
             _userID: userID,
             _userID: userID,
             updateLock: 0,
             updateLock: 0,
             updateData: [],
             updateData: [],

+ 74 - 8
web/building_saas/main/js/models/project_glj.js

@@ -252,7 +252,7 @@ ProjectGLJ.prototype.updateGLJProperty = function (node, updateField, newval) {
 
 
 }
 }
 
 
-ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from) {
+ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from,cb) {
     let me = this;
     let me = this;
     let projectGljs = this.datas.gljList;
     let projectGljs = this.datas.gljList;
     let pgljID = from=="rg"?recode.projectGLJID:recode.id;//和定额工料机统一接口,项目工料机ID取值不一样
     let pgljID = from=="rg"?recode.projectGLJID:recode.id;//和定额工料机统一接口,项目工料机ID取值不一样
@@ -277,6 +277,9 @@ ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from) {
             projectObj.project.calcProgram.calcRationsAndSave(nodes);//触发计算程序
             projectObj.project.calcProgram.calcRationsAndSave(nodes);//触发计算程序
             socket.emit('unitFileChangeNotify', JSON.stringify(data));
             socket.emit('unitFileChangeNotify', JSON.stringify(data));
             projectObj.project.markUpdateProject({projectID:projectObj.project.ID(),'unitFileID':socketObject.getUnitFileRoomID()},"unitFile");
             projectObj.project.markUpdateProject({projectID:projectObj.project.ID(),'unitFileID':socketObject.getUnitFileRoomID()},"unitFile");
+            if(cb){
+                cb(gljs);
+            }
             $.bootstrapLoading.end();
             $.bootstrapLoading.end();
         }
         }
         $.bootstrapLoading.start();
         $.bootstrapLoading.start();
@@ -286,8 +289,64 @@ ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from) {
     } else {
     } else {
         gljOprObj.showRationGLJSheetData();
         gljOprObj.showRationGLJSheetData();
     }
     }
+};
+
+ProjectGLJ.prototype.pGljUpdate= function (data,callback) {
+    let me = this;
+    $.bootstrapLoading.start();
+    CommonAjax.specialPost( '/glj/update',data,function (result) {
+        let glj = me.getByID(data.id);//更新缓存
+        let impactList = [];
+        glj[data.field] = data.value;
+        if(data.extend&&data.extend!=""){
+            let extend = JSON.parse(data.extend);
+            for (let key in extend) {
+                glj[key] = extend[key];
+            }
+        }
+        if(data.field == 'is_evaluate'){
+            impactList =  me.changeIsEvaluate(data.id);
+        }
+        if(callback){
+            callback(impactList);
+        }
+        $.bootstrapLoading.end();
+    });
+};
+
+//更新是否暂估
+ProjectGLJ.prototype.changeIsEvaluate=function (id){
+    let projectGLJ = projectObj.project.projectGLJ;
+    let datas = projectGLJ.datas;
+    let gljList = datas.gljList;
+    let glj = _.find(gljList, {'id': id});
+    if(glj){
+        let con_key = gljOprObj.getIndex(glj,gljKeyArray);
+        let pratioM =datas.mixRatioConnectData[con_key];//找到父key
+        let conditions = [];
+        if(pratioM&&pratioM.length>0){
+            for(let p_key of pratioM ){
+                conditions.push(gljOprObj.getConditionByKey(p_key));
+            }
+        }
+        let gljs = projectGLJ.getProjectGLJs(conditions,false);
+        gljs.push(glj);
+        let nodes = projectGLJ.getImpactRationNodes(gljs);//取到因为改变工料机价格而受影响的定额
+        //更新对应的工料机类型的定额
+        let ration =_.find(projectObj.project.Ration.datas,{'type':rationType.gljRation,'projectGLJID':glj.id});
+        if(ration){
+            ration.isEstimate =glj.is_evaluate?1:0;
+            let ration_node = projectObj.project.mainTree.getNodeByID(ration.ID);
+            ration_node?projectObj.mainController.refreshTreeNode([ration_node]):"";
+        }
+        projectObj.project.calcProgram.calcRationsAndSave(nodes);//触发计算程序
+        return gljs;
+    }
 }
 }
 
 
+ProjectGLJ.prototype.getByID = function (ID) {
+    return _.find(this.datas.gljList,{'id':ID});
+};
 
 
 ProjectGLJ.prototype.refreshTreeNodePriceIfNeed = function (data) {
 ProjectGLJ.prototype.refreshTreeNodePriceIfNeed = function (data) {
     if ((data.unit_price.type == gljType.MAIN_MATERIAL || data.unit_price.type == gljType.EQUIPMENT) && projectInfoObj.projectInfo.property.displaySetting.disPlayMainMaterial == true) {
     if ((data.unit_price.type == gljType.MAIN_MATERIAL || data.unit_price.type == gljType.EQUIPMENT) && projectInfoObj.projectInfo.property.displaySetting.disPlayMainMaterial == true) {
@@ -399,7 +458,7 @@ ProjectGLJ.prototype.getAdjustPrice = function (glj) {
         //let labour=1;
         //let labour=1;
         let coe = labour && labour.coe ? labour.coe : 1;
         let coe = labour && labour.coe ? labour.coe : 1;
         return scMathUtil.roundTo(parseFloat(coe * scMathUtil.roundForObj(glj.unit_price.base_price,decimal)), -decimal);
         return scMathUtil.roundTo(parseFloat(coe * scMathUtil.roundForObj(glj.unit_price.base_price,decimal)), -decimal);
-    } else if (notEditType.indexOf(glj.unit_price.type)>0&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班,调整价根据组成物计算得出。
+    } else if (notEditType.indexOf(glj.unit_price.type)!=-1&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班,调整价根据组成物计算得出。
         let p =0;
         let p =0;
         for(let ratio of glj.ratio_data){
         for(let ratio of glj.ratio_data){
            let tem =  _.find( projectObj.project.projectGLJ.datas.gljList,{
            let tem =  _.find( projectObj.project.projectGLJ.datas.gljList,{
@@ -410,7 +469,9 @@ ProjectGLJ.prototype.getAdjustPrice = function (glj) {
                'unit': ratio.unit
                'unit': ratio.unit
            })
            })
             if(tem){
             if(tem){
-                p+=scMathUtil.roundForObj(this.getAdjustPrice(tem)*scMathUtil.roundForObj(ratio.consumption,quantity_decimal),decimal);
+                let priceData={};
+                gljOprObj.setGLJPrice(priceData,tem);
+                p+=scMathUtil.roundForObj(priceData.adjustPrice*scMathUtil.roundForObj(ratio.consumption,quantity_decimal),decimal);
             }
             }
         }
         }
         return scMathUtil.roundForObj(p,decimal);
         return scMathUtil.roundForObj(p,decimal);
@@ -422,7 +483,7 @@ ProjectGLJ.prototype.getAdjustPrice = function (glj) {
 ProjectGLJ.prototype.getBasePrice = function(glj){
 ProjectGLJ.prototype.getBasePrice = function(glj){
     let price_decimal = getDecimal("glj.unitPrice");
     let price_decimal = getDecimal("glj.unitPrice");
     let quantity_decimal = getDecimal("glj.quantity");
     let quantity_decimal = getDecimal("glj.quantity");
-    if (notEditType.indexOf(glj.unit_price.type)>0&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班等有组成物的材料,价格需根据组成物计算得出。
+    if (notEditType.indexOf(glj.unit_price.type)!=-1&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班等有组成物的材料,价格需根据组成物计算得出。
         let p =0;
         let p =0;
         for(let ratio of glj.ratio_data){
         for(let ratio of glj.ratio_data){
             let tem =  _.find( projectObj.project.projectGLJ.datas.gljList,{
             let tem =  _.find( projectObj.project.projectGLJ.datas.gljList,{
@@ -433,7 +494,9 @@ ProjectGLJ.prototype.getBasePrice = function(glj){
                 'unit': ratio.unit
                 'unit': ratio.unit
             });
             });
             if(tem){
             if(tem){
-                p+=scMathUtil.roundForObj(tem.unit_price.base_price*scMathUtil.roundForObj(ratio.consumption,quantity_decimal),price_decimal);
+                let priceData={};
+                gljOprObj.setGLJPrice(priceData,tem);
+                p+=scMathUtil.roundForObj(priceData.basePrice*scMathUtil.roundForObj(ratio.consumption,quantity_decimal),price_decimal);
             }
             }
         }
         }
         return scMathUtil.roundForObj(p,price_decimal);
         return scMathUtil.roundForObj(p,price_decimal);
@@ -442,10 +505,11 @@ ProjectGLJ.prototype.getBasePrice = function(glj){
     }
     }
 };
 };
 
 
+
 ProjectGLJ.prototype.getMarketPrice = function (glj) {
 ProjectGLJ.prototype.getMarketPrice = function (glj) {
     let price_decimal = getDecimal("glj.unitPrice");
     let price_decimal = getDecimal("glj.unitPrice");
     let quantity_decimal = getDecimal("glj.quantity");
     let quantity_decimal = getDecimal("glj.quantity");
-    if (notEditType.indexOf(glj.unit_price.type)>0&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班等有组成物的材料,价格需根据组成物计算得出。
+    if (notEditType.indexOf(glj.unit_price.type)!=-1&&glj.ratio_data.length>0) {//对于混凝土、配合比、砂浆、机械台班等有组成物的材料,价格需根据组成物计算得出。
         let p =0;
         let p =0;
         for(let ratio of glj.ratio_data){
         for(let ratio of glj.ratio_data){
             let tem =  _.find( projectObj.project.projectGLJ.datas.gljList,{
             let tem =  _.find( projectObj.project.projectGLJ.datas.gljList,{
@@ -456,7 +520,9 @@ ProjectGLJ.prototype.getMarketPrice = function (glj) {
                 'unit': ratio.unit
                 'unit': ratio.unit
             });
             });
             if(tem){
             if(tem){
-                p+=scMathUtil.roundForObj(tem.unit_price.market_price*scMathUtil.roundForObj(ratio.consumption,quantity_decimal),price_decimal);
+                let priceData={};
+                gljOprObj.setGLJPrice(priceData,tem);
+                p+=scMathUtil.roundForObj(priceData.marketPrice*scMathUtil.roundForObj(ratio.consumption,quantity_decimal),price_decimal);
             }
             }
         }
         }
         return scMathUtil.roundForObj(p,price_decimal);
         return scMathUtil.roundForObj(p,price_decimal);
@@ -500,7 +566,7 @@ ProjectGLJ.prototype.calcQuantity  = function (){
 
 
 }
 }
 
 
-ProjectGLJ.prototype.getQuantityPerGLJ =function (pglj,mixRatioSubdivisionMap,mixRatioTechMap) {
+ProjectGLJ.prototype.getQuantityPerGLJ = function (pglj,mixRatioSubdivisionMap,mixRatioTechMap) {
     let billIDs =   projectObj.project.Bills.getSubdivisionProjectLeavesID();//取分部分项上的所有叶子清单ID
     let billIDs =   projectObj.project.Bills.getSubdivisionProjectLeavesID();//取分部分项上的所有叶子清单ID
     let tech_billIDS =  projectObj.project.Bills.getTechLeavesID();//取所有技术措施项目叶子清单ID
     let tech_billIDS =  projectObj.project.Bills.getTechLeavesID();//取所有技术措施项目叶子清单ID
     let ration_glj_list = projectObj.project.ration_glj.datas;
     let ration_glj_list = projectObj.project.ration_glj.datas;

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

@@ -553,7 +553,6 @@ var quantity_detail = {
                     if(project.quantity_detail.quantityEditChecking(value,node,fieldName)){
                     if(project.quantity_detail.quantityEditChecking(value,node,fieldName)){
                         node.data.isFromDetail=0;
                         node.data.isFromDetail=0;
                         project.quantity_detail.cleanQuantityDetail(node,true);
                         project.quantity_detail.cleanQuantityDetail(node,true);
-                        $.bootstrapLoading.start();
                         if(node.sourceType === project.Bills.getSourceType()){
                         if(node.sourceType === project.Bills.getSourceType()){
                             me.updateBillQuantity(value,node,null,editingText);
                             me.updateBillQuantity(value,node,null,editingText);
                         }else {
                         }else {
@@ -606,11 +605,23 @@ var quantity_detail = {
                     }
                     }
                 }
                 }
             }
             }
-            if(needUpdateChildren.length>0){
+            if(needUpdateChildren.length>0){//清单下的定额工程量发生了改变
                 node.changed = true;//本身发生了改变,需要存储。
                 node.changed = true;//本身发生了改变,需要存储。
-                project.calcProgram.calcRationsAndSave(needUpdateChildren, function () {
+                /*project.calcProgram.calcRationsAndSave(needUpdateChildren, function () {
                     project.projectGLJ.loadData();
                     project.projectGLJ.loadData();
+                });*/
+                project.calcProgram.calcRationsAndSave(needUpdateChildren, function () {
+                    if(project.Bills.isFBFX(node)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
+                        project.installation_fee.calcInstallationFee(function (isChange) {
+                            if(isChange){
+                                project.calcProgram.calcAllNodesAndSave();
+                            }
+                        });
+                    }else {
+                        project.projectGLJ.loadData();
+                    }
                 });
                 });
+
             }else {
             }else {
                 node.changed = true;
                 node.changed = true;
                 project.calcProgram.calcAndSave(node, function () {
                 project.calcProgram.calcAndSave(node, function () {
@@ -635,7 +646,15 @@ var quantity_detail = {
             }
             }
             node.changed = true;
             node.changed = true;
             project.calcProgram.calcAndSave(node, function () {
             project.calcProgram.calcAndSave(node, function () {
-                project.projectGLJ.loadData();
+                if(project.Bills.isFBFX(node)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
+                    project.installation_fee.calcInstallationFee(function (isChange) {
+                        if(isChange){
+                            project.calcProgram.calcAllNodesAndSave();
+                        }
+                    });
+                }else {
+                    project.projectGLJ.loadData();
+                }
             });
             });
             projectObj.mainController.refreshTreeNode(node.children);//刷新子工料机总消耗量
             projectObj.mainController.refreshTreeNode(node.children);//刷新子工料机总消耗量
             gljOprObj.showRationGLJSheetData();
             gljOprObj.showRationGLJSheetData();

+ 53 - 4
web/building_saas/main/js/models/ration.js

@@ -110,6 +110,9 @@ var Ration = {
                 newData['subType'] = gljType.GENERAL_MATERIAL;   // 默认的量价类型为材料
                 newData['subType'] = gljType.GENERAL_MATERIAL;   // 默认的量价类型为材料
                 newData['programID'] = projectInfoObj.projectInfo.property.engineering;
                 newData['programID'] = projectInfoObj.projectInfo.property.engineering;
             };
             };
+            if(rType == rationType.install){//是安装增加费生成的定额
+                newData['programID'] = projectInfoObj.projectInfo.property.engineering;
+            }
             return newData;
             return newData;
         };
         };
 
 
@@ -265,6 +268,9 @@ var Ration = {
             project.ration_installation.deleteByRation(ration);
             project.ration_installation.deleteByRation(ration);
             this.datas.splice(this.datas.indexOf(ration), 1);
             this.datas.splice(this.datas.indexOf(ration), 1);
         };
         };
+        ration.prototype.removeByID = function(ID){
+            _.remove(this.datas,{'ID':ID});
+        };
         ration.prototype.getDeleteDataByBill = function (nodes) {
         ration.prototype.getDeleteDataByBill = function (nodes) {
             let updateData = [];
             let updateData = [];
             for (let node of nodes) {
             for (let node of nodes) {
@@ -369,13 +375,18 @@ var Ration = {
         };
         };
         ration.prototype.updateRationCodes = function (recodes) {
         ration.prototype.updateRationCodes = function (recodes) {
             let libID = projectInfoObj.projectInfo.engineeringInfo.ration_lib[0].id;
             let libID = projectInfoObj.projectInfo.engineeringInfo.ration_lib[0].id;
+            let engineering = projectInfoObj.projectInfo.property.engineering;
             let projectID = projectInfoObj.projectInfo.ID;
             let projectID = projectInfoObj.projectInfo.ID;
             let project = projectObj.project;
             let project = projectObj.project;
             let mainTree = project.mainTree;
             let mainTree = project.mainTree;
             let nodeInfo =[];
             let nodeInfo =[];
             let refershNodes = [];
             let refershNodes = [];
             for(let r of recodes){
             for(let r of recodes){
-                nodeInfo.push({ID:r.node.data.ID,billsItemID:r.node.data.billsItemID,newCode:r.value});
+                let needInstall = false;
+                if(engineering==engineeringType.BUILD_IN) {//如果是安装工程,要看需不需要生成安装增加费
+                    needInstall = project.Bills.isFBFX(r.node);
+                }
+                nodeInfo.push({ID:r.node.data.ID,billsItemID:r.node.data.billsItemID,newCode:r.value,needInstall:needInstall});
                 refershNodes.push(r.node);
                 refershNodes.push(r.node);
             }
             }
             let calQuantity = optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan');
             let calQuantity = optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan');
@@ -403,15 +414,17 @@ var Ration = {
                 });
                 });
 
 
                 if(data.length<recodes.length){//说明有部分定额编号没找到记录
                 if(data.length<recodes.length){//说明有部分定额编号没找到记录
-                    alert('当前库中找不到定额"' + recodes[data.length-1].value + '"');
+                    alert('当前库中找不到定额"' + recodes[data.length].value + '"');
                 }
                 }
             })
             })
         };
         };
         ration.prototype.addNewRation = function (itemQuery,rationType) {
         ration.prototype.addNewRation = function (itemQuery,rationType) {
             let me = this;
             let me = this;
             let project = projectObj.project, sheetController = projectObj.mainController;
             let project = projectObj.project, sheetController = projectObj.mainController;
+            let engineering = projectInfoObj.projectInfo.property.engineering;
             let selected = project.mainTree.selected, newSource = null, newNode = null,pre=null,br=null;
             let selected = project.mainTree.selected, newSource = null, newNode = null,pre=null,br=null;
             let billItemID = null,serialNo=1,nextID=null;
             let billItemID = null,serialNo=1,nextID=null;
+            let needInstall = false;
             if (selected === null) { return; }
             if (selected === null) { return; }
             if (selected.sourceType === project.Bills.getSourceType() && selected.depth() > 0) {
             if (selected.sourceType === project.Bills.getSourceType() && selected.depth() > 0) {
                 if (selected.source.children.length > 0) {
                 if (selected.source.children.length > 0) {
@@ -446,8 +459,12 @@ var Ration = {
                         brUpdate.push({projectID:newData.projectID,ID:br[i].ID,serialNo:br[i].serialNo});
                         brUpdate.push({projectID:newData.projectID,ID:br[i].ID,serialNo:br[i].serialNo});
                     }
                     }
                 }
                 }
+                if(engineering==engineeringType.BUILD_IN) {//如果是安装工程,要看需不需要生成安装增加费
+                    let billsNode = project.mainTree.getNodeByID(billItemID);
+                    needInstall = project.Bills.isFBFX(billsNode);//在分部分项插入的定额才需要定额安装增加费
+                }
                 $.bootstrapLoading.start();
                 $.bootstrapLoading.start();
-                CommonAjax.post("/ration/addNewRation",{itemQuery:itemQuery,newData:newData,calQuantity:calQuantity,brUpdate:brUpdate},function (data) {
+                CommonAjax.post("/ration/addNewRation",{itemQuery:itemQuery,newData:newData,calQuantity:calQuantity,brUpdate:brUpdate,needInstall:needInstall},function (data) {
                     //更新缓存
                     //更新缓存
                     console.log(data);
                     console.log(data);
                     me.datas.push(data.ration);
                     me.datas.push(data.ration);
@@ -464,8 +481,16 @@ var Ration = {
                     ProjectController.syncDisplayNewNode(sheetController, newNode);
                     ProjectController.syncDisplayNewNode(sheetController, newNode);
                     project.projectGLJ.loadData(function () {
                     project.projectGLJ.loadData(function () {
                         project.ration_glj.addToMainTree(data.ration_gljs);
                         project.ration_glj.addToMainTree(data.ration_gljs);
-                        project.calcProgram.calcAndSave(newNode);
                         projectObj.mainController.refreshTreeNode([newNode], false);
                         projectObj.mainController.refreshTreeNode([newNode], false);
+                        project.calcProgram.calcAndSave(newNode,function () {
+                            if(project.Bills.isFBFX(newNode)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
+                                project.installation_fee.calcInstallationFee(function (isChange) {
+                                    if(isChange){
+                                        project.calcProgram.calcAllNodesAndSave();
+                                    }
+                                });
+                            }
+                        });
                         $.bootstrapLoading.end();
                         $.bootstrapLoading.end();
                     });
                     });
                     console.log(data);
                     console.log(data);
@@ -559,7 +584,31 @@ var Ration = {
             }
             }
             return true;
             return true;
         };
         };
+        ration.prototype.getAllInstallTypeRation = function () {//取所有计取安装增加费生成的定额
+            return _.filter(this.datas,{'type':rationType.install});
+        };
 
 
+        ration.prototype.getLabourTotalFee=function(ration){//feesIndex.labour.totalFee  取定额的人工费合价
+            if(ration.feesIndex&&ration.feesIndex.labour&&ration.feesIndex.labour.totalFee){
+                return ration.feesIndex.labour.totalFee;
+            }else {
+                return 0;
+            }
+        };
+        ration.prototype.getMaterialTotalFee=function(ration){//feesIndex.material.totalFee 取定额的材料费合价
+            if(ration.feesIndex&&ration.feesIndex.material&&ration.feesIndex.material.totalFee){
+                return ration.feesIndex.material.totalFee;
+            }else {
+                return 0;
+            }
+        } ;
+        ration.prototype.getMachineTotalFee=function(ration){//feesIndex.machine.totalFee 取定额的机械费合价
+            if(ration.feesIndex&&ration.feesIndex.machine&&ration.feesIndex.machine.totalFee){
+                return ration.feesIndex.machine.totalFee;
+            }else {
+                return 0;
+            }
+        } ;
         return new ration(project);
         return new ration(project);
     }
     }
 };
 };

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

@@ -104,6 +104,10 @@ var ration_glj = {
             }
             }
             projectObj.project.projectGLJ.loadData();
             projectObj.project.projectGLJ.loadData();
         };
         };
+        ration_glj.prototype.getDataByID = function (ID) {
+           return _.find(this.datas,{'ID':ID});
+        };
+
         ration_glj.prototype.refreshAfterSave = function (data) {
         ration_glj.prototype.refreshAfterSave = function (data) {
             let me = projectObj.project.ration_glj;
             let me = projectObj.project.ration_glj;
             let neRecodes = [];
             let neRecodes = [];
@@ -127,6 +131,9 @@ var ration_glj = {
                 }
                 }
             });
             });
         };
         };
+        ration_glj.prototype.getGljByRationID = function(rationID){
+            return  _.filter(this.datas, {'rationID': rationID});
+        };
         ration_glj.prototype.addDatasToList = function (datas) {
         ration_glj.prototype.addDatasToList = function (datas) {
             let  me = projectObj.project.ration_glj;
             let  me = projectObj.project.ration_glj;
             if(datas&&datas.length>0){
             if(datas&&datas.length>0){
@@ -141,6 +148,7 @@ var ration_glj = {
             datas = sortRationGLJ(datas);
             datas = sortRationGLJ(datas);
             for (let data of datas) {
             for (let data of datas) {
                 if (this.needShowToTree(data)) {
                 if (this.needShowToTree(data)) {
+                    gljOprObj.setGLJPrice(data);
                     this.transferToNodeData(data);
                     this.transferToNodeData(data);
                     let parentNode = _.find(projectObj.project.mainTree.items, function (n) {//找父节点
                     let parentNode = _.find(projectObj.project.mainTree.items, function (n) {//找父节点
                         return n.sourceType == ModuleNames.ration && n.data.ID == data.rationID;
                         return n.sourceType == ModuleNames.ration && n.data.ID == data.rationID;
@@ -397,7 +405,7 @@ var ration_glj = {
             var doc = {};
             var doc = {};
             doc[updateField] = newval;
             doc[updateField] = newval;
             if (updateField == "type") {
             if (updateField == "type") {
-                doc.shortName = projectObj.project.projectGLJ.getShortNameByID[newval];
+                doc.shortName = projectObj.project.projectGLJ.getShortNameByID(newval);
             }
             }
             CommonAjax.post("/rationGlj/updateRationGLJByEdit", {
             CommonAjax.post("/rationGlj/updateRationGLJByEdit", {
                 query: query,
                 query: query,
@@ -705,6 +713,7 @@ var ration_glj = {
                     fieldName = "marketPrice";
                     fieldName = "marketPrice";
                     projectObj.project.projectGLJ.updatePriceFromRG(node.data, fieldName, newval);
                     projectObj.project.projectGLJ.updatePriceFromRG(node.data, fieldName, newval);
                     return;
                     return;
+
                 }
                 }
             } else {
             } else {
                 if(fieldName == "contain"){
                 if(fieldName == "contain"){

+ 47 - 0
web/building_saas/main/js/models/ration_installation.js

@@ -45,6 +45,53 @@ let ration_installation = {
             let ri = _.find(me.datas,{'ID':ID})
             let ri = _.find(me.datas,{'ID':ID})
             return ri;
             return ri;
         };
         };
+        ration_installation.prototype.getCalcRIByItemID = function (libID,itemID) {//按费用项ID取费用规则不为空的定额安装增加费
+            return _.filter(this.datas,function (item) {
+                if(item.libID == libID && item.feeItemId == itemID && item.ruleId && item.ruleId !=""){
+                    return true;
+                }
+                return false;
+            })
+        };
+        ration_installation.prototype.getDataByConditions = function (conditions) {
+            return _.filter(this.datas,function (item) {
+                let match = true;
+                for(let ckey in conditions){
+                    if( Array.isArray(conditions[ckey])){
+                       let isContain =  _.includes(conditions[ckey],item[ckey]);
+                       if(!isContain){//不包含
+                           match = false;
+                           break;
+                       }
+                    }else {
+                        if(conditions[ckey]!=item[ckey]){
+                            match = false;
+                            break;
+                        }
+                    }
+                }
+                return match;
+            })
+        };
+        ration_installation.prototype.applyRuleByIDs = function(projectID,IDs,ruleId,callback){
+            let me = this;
+            $.bootstrapLoading.start();
+            CommonAjax.post('/installation/applyRuleByIDs',{projectID:projectID,IDs:IDs,ruleId:ruleId},function (data) {
+                //更新缓存
+                for(let ID of IDs){
+                    let ri = _.find(me.datas,{'ID':ID});
+                    ri.ruleId = ruleId;
+                    ri.unifiedSetting = 0;
+                }
+                if(callback){
+                    callback();
+                }
+                $.bootstrapLoading.end();
+            },function () {
+                $.bootstrapLoading.end();
+            })
+
+        };
         ration_installation.prototype.update = function (updateData,callback) {
         ration_installation.prototype.update = function (updateData,callback) {
             let  me = this;
             let  me = this;
             $.bootstrapLoading.start();
             $.bootstrapLoading.start();

+ 36 - 6
web/building_saas/main/js/views/glj_view.js

@@ -300,8 +300,7 @@ var gljOprObj = {
         sheet.name('quantity_detail');
         sheet.name('quantity_detail');
         me.bindSheetEvent(sheet);
         me.bindSheetEvent(sheet);
         sheet.bind(GC.Spread.Sheets.Events.EditStarting, function (sender, args) {
         sheet.bind(GC.Spread.Sheets.Events.EditStarting, function (sender, args) {
-             let selected = projectObj.project.mainTree.selected;
-            if(selected&&selected.sourceType == ModuleNames.ration_glj){//是主材或者是设备时只读
+            if(me.detailSheetReadonly()){
                 args.cancel = true;
                 args.cancel = true;
             }else {
             }else {
                 if(args.sheet.getValue(args.row,args.col)==null){//这里是为了解决当单元格里的值是null的时候,在单元格里输入数据,按键盘箭头移动光标的时候,会直接结束编辑,跳到另外的单元格。
                 if(args.sheet.getValue(args.row,args.col)==null){//这里是为了解决当单元格里的值是null的时候,在单元格里输入数据,按键盘箭头移动光标的时候,会直接结束编辑,跳到另外的单元格。
@@ -310,6 +309,18 @@ var gljOprObj = {
             }
             }
         });
         });
     },
     },
+    detailSheetReadonly:function () {
+        let selected = projectObj.project.mainTree.selected;
+        if(selected) {//是主材或者是设备时只读
+            if(selected.sourceType == ModuleNames.ration_glj){
+                return true;
+            }else if(gljOprObj.isInstallationNode(selected)){//是补项或者是安装类型的定额时只读
+                return true;
+            }
+            return false;
+        }
+        return true;
+    },
     showCoeData: function (sheet, setting, datas) {
     showCoeData: function (sheet, setting, datas) {
         sheet.floatingObjects.remove("customerCoe");
         sheet.floatingObjects.remove("customerCoe");
         sheetCommonObj.showData(sheet, setting, datas);
         sheetCommonObj.showData(sheet, setting, datas);
@@ -329,6 +340,7 @@ var gljOprObj = {
         sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
         sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
         sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
         sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
         sheet.bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
         sheet.bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
+        sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.startEditChecking);
         // sheet.bind(GC.Spread.Sheets.Events.CellClick, me.onCellClick);
         // sheet.bind(GC.Spread.Sheets.Events.CellClick, me.onCellClick);
     },
     },
 
 
@@ -345,7 +357,23 @@ var gljOprObj = {
         //  if (!me.ration) {return;};
         //  if (!me.ration) {return;};
         // your code...
         // your code...
     },
     },
-
+    startEditChecking:function (sender,args) {
+        let me = gljOprObj;
+        let selected = projectObj.project.mainTree.selected;
+        if(selected){
+            if(me.isInstallationNode(selected)==true){
+                args.cancel = true;
+            }
+        }else {
+            args.cancel = true;
+        }
+    },
+    isInstallationNode:function(node){
+        if((node.sourceType == ModuleNames.ration&&node.data.type == rationType.install)||(node.sourceType == ModuleNames.bills&&node.data.type==billType.BX)){//是定额安装费类型或者补项
+            return true;
+        }
+        return false
+    },
     onEditEnded: function (sender, args) {
     onEditEnded: function (sender, args) {
         var me = gljOprObj;
         var me = gljOprObj;
         if (args.sheetName == 'ration_glj') {
         if (args.sheetName == 'ration_glj') {
@@ -424,6 +452,9 @@ var gljOprObj = {
         if(args.sheetName == 'rationInstallSheet' && checkboxValue){
         if(args.sheetName == 'rationInstallSheet' && checkboxValue){
             return;
             return;
         }
         }
+        if(gljOprObj.isInstallationNode(selected)==true){
+            return;
+        }
         let newval = 0;
         let newval = 0;
         if (checkboxValue) {
         if (checkboxValue) {
             newval = 0;
             newval = 0;
@@ -921,13 +952,12 @@ var gljOprObj = {
     setGLJPrice:function (data,glj) {
     setGLJPrice:function (data,glj) {
         let proGLJ =  projectObj.project.projectGLJ;
         let proGLJ =  projectObj.project.projectGLJ;
         glj = glj?glj:_.find(proGLJ.datas.gljList, {'id': data.projectGLJID});
         glj = glj?glj:_.find(proGLJ.datas.gljList, {'id': data.projectGLJID});
+        data.marketPrice = proGLJ.getMarketPrice(glj);
         if(this.calcPriceDiff(glj)==true) {//计取价差
         if(this.calcPriceDiff(glj)==true) {//计取价差
             data.basePrice = proGLJ.getBasePrice(glj);
             data.basePrice = proGLJ.getBasePrice(glj);
-            data.marketPrice = proGLJ.getMarketPrice(glj);
             data.adjustPrice = proGLJ.getAdjustPrice(glj);
             data.adjustPrice = proGLJ.getAdjustPrice(glj);
         }else {//不计价差
         }else {//不计价差
             data.basePrice = proGLJ.getMarketPrice(glj);
             data.basePrice = proGLJ.getMarketPrice(glj);
-            data.marketPrice = proGLJ.getMarketPrice(glj);
             data.adjustPrice = proGLJ.getMarketPrice(glj);
             data.adjustPrice = proGLJ.getMarketPrice(glj);
         }
         }
         return data;
         return data;
@@ -1386,8 +1416,8 @@ var gljOprObj = {
                     //project.ration_glj.datas = project.ration_glj.datas.concat(result.newRecodes);//显示和缓存统一,这样的话就不用更新两个位置了
                     //project.ration_glj.datas = project.ration_glj.datas.concat(result.newRecodes);//显示和缓存统一,这样的话就不用更新两个位置了
                     project.ration_glj.datas = project.ration_glj.datas.concat(result.showData);
                     project.ration_glj.datas = project.ration_glj.datas.concat(result.showData);
                     gljOprObj.sheetData = gljOprObj.sheetData.concat(result.showData);
                     gljOprObj.sheetData = gljOprObj.sheetData.concat(result.showData);
-                    project.ration_glj.addToMainTree(result.showData);
                     project.projectGLJ.loadData(function () {
                     project.projectGLJ.loadData(function () {
+                        project.ration_glj.addToMainTree(result.showData);
                         gljOprObj.showRationGLJSheetData();
                         gljOprObj.showRationGLJSheetData();
                         project.calcProgram.calcAndSave(selected);
                         project.calcProgram.calcAndSave(selected);
                         projectObj.mainController.refreshTreeNode([selected]);
                         projectObj.mainController.refreshTreeNode([selected]);

+ 71 - 26
web/building_saas/main/js/views/glj_view_contextMenu.js

@@ -16,11 +16,15 @@ var gljContextMenu = {
                     icon: 'fa-remove',
                     icon: 'fa-remove',
                     disabled: function () {
                     disabled: function () {
                         var sheetData = gljOprObj.sheetData;
                         var sheetData = gljOprObj.sheetData;
-                        var disable = true;
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
-                            disable=  sheetData[gljContextMenu.selectedRow].isMixRatio==true?true:false;
+                            if( sheetData[gljContextMenu.selectedRow].isMixRatio==true){
+                                return true;
+                            }
+                        }
+                        if(gljOprObj.isInstallationNode(projectObj.project.mainTree.selected)){
+                            return true;
                         }
                         }
-                        return disable;
+                        return false;
                     },
                     },
                     callback: function () {
                     callback: function () {
                         var sheetData = gljOprObj.sheetData;
                         var sheetData = gljOprObj.sheetData;
@@ -35,16 +39,21 @@ var gljContextMenu = {
                     name: '添加工料机',
                     name: '添加工料机',
                     icon: 'fa-sign-in',
                     icon: 'fa-sign-in',
                     disabled: function () {
                     disabled: function () {
-                        var disable = true;
                         var selected = projectObj.project.mainTree.selected;
                         var selected = projectObj.project.mainTree.selected;
                         var sheetData = gljOprObj.sheetData;
                         var sheetData = gljOprObj.sheetData;
-                        if(selected&&selected.sourceType==ModuleNames.ration&&selected.data.type==rationType.ration){
-                            disable=false;
+                        if(selected){
+                            if(selected.sourceType!=ModuleNames.ration){
+                                return true;
+                            }else if(selected.data.type!=rationType.ration){
+                                return true;
+                            }
                         }
                         }
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
-                            disable=  sheetData[gljContextMenu.selectedRow].isMixRatio==true?true:false;
+                            if(sheetData[gljContextMenu.selectedRow].isMixRatio==true){
+                                return true;
+                            }
                         }
                         }
-                        return disable;
+                        return false;
                     },
                     },
                     callback:function () {
                     callback:function () {
                         getGLJData('add');
                         getGLJData('add');
@@ -58,11 +67,15 @@ var gljContextMenu = {
                     icon: 'fa-sign-in',
                     icon: 'fa-sign-in',
                     disabled: function () {
                     disabled: function () {
                         var sheetData = gljOprObj.sheetData;
                         var sheetData = gljOprObj.sheetData;
-                        var disable = true;
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
-                            disable=  sheetData[gljContextMenu.selectedRow].isMixRatio==true?true:false;
+                            if(sheetData[gljContextMenu.selectedRow].isMixRatio==true){
+                                return true;
+                            }
                         }
                         }
-                        return disable;
+                        if(gljOprObj.isInstallationNode(projectObj.project.mainTree.selected)){
+                            return true;
+                        }
+                        return false;
                     },
                     },
                     callback: function () {
                     callback: function () {
                         getGLJData('replace');
                         getGLJData('replace');
@@ -78,9 +91,14 @@ var gljContextMenu = {
                         var sheetData = gljOprObj.sheetData;
                         var sheetData = gljOprObj.sheetData;
                         var disable = true;
                         var disable = true;
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
-                            disable=  sheetData[gljContextMenu.selectedRow].isMixRatio==true?true:false;
+                            if(sheetData[gljContextMenu.selectedRow].isMixRatio==true){
+                                return true;
+                            }
                         }
                         }
-                        return disable;
+                        if(gljOprObj.isInstallationNode(projectObj.project.mainTree.selected)){
+                            return true;
+                        }
+                        return false;
                     },
                     },
                     callback: function () {
                     callback: function () {
                         getGLJData('m_replace');
                         getGLJData('m_replace');
@@ -94,12 +112,17 @@ var gljContextMenu = {
                     icon: 'fa-sign-in',
                     icon: 'fa-sign-in',
                     disabled: function () {
                     disabled: function () {
                         var sheetData = gljOprObj.sheetData;
                         var sheetData = gljOprObj.sheetData;
-                        var disable = true;
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
                         if(subSpread.getActiveSheetIndex()==0&&sheetData!=null&&sheetData.length>0&&gljContextMenu.selectedRow<sheetData.length){
                             var recode = sheetData[gljContextMenu.selectedRow];
                             var recode = sheetData[gljContextMenu.selectedRow];
-                            disable= recode.isMixRatio!=true&&recode.isAdd==true?false:true
+                            if(!(recode.isMixRatio!=true&&recode.isAdd==true)){
+                                return true
+                            }
+                          //  disable= recode.isMixRatio!=true&&recode.isAdd==true?false:true
+                        }
+                        if(gljOprObj.isInstallationNode(projectObj.project.mainTree.selected)){
+                            return true;
                         }
                         }
-                        return disable;
+                        return false;
                     },
                     },
                     callback: function () {
                     callback: function () {
                         var sheetData = gljOprObj.sheetData;
                         var sheetData = gljOprObj.sheetData;
@@ -115,7 +138,11 @@ var gljContextMenu = {
                     icon: 'fa-sign-in',
                     icon: 'fa-sign-in',
                     disabled: function () {
                     disabled: function () {
                         var sheetData = gljOprObj.detailData;
                         var sheetData = gljOprObj.detailData;
-                        return gljContextMenu.selectedRow>sheetData.length;
+                        if(gljOprObj.detailSheetReadonly()){
+                            return true
+                        }else {
+                            return  gljContextMenu.selectedRow>sheetData.length;
+                        }
                     },
                     },
                     callback: function () {
                     callback: function () {
                         projectObj.project.quantity_detail.insertQuantityDetail(gljContextMenu.selectedRow);
                         projectObj.project.quantity_detail.insertQuantityDetail(gljContextMenu.selectedRow);
@@ -232,11 +259,17 @@ var gljContextMenu = {
                     name: '应用到当前分项',
                     name: '应用到当前分项',
                     icon: 'fa-sign-in',
                     icon: 'fa-sign-in',
                     disabled: function () {
                     disabled: function () {
-                        /* var sheetData = gljOprObj.detailData;
-                         return gljContextMenu.selectedRow>sheetData.length-2;*/
+                        let sheetData = installationFeeObj.rationInstallData;
+                        if(gljContextMenu.selectedRow>sheetData.length-1){
+                            return true;
+                        }
+                        if(sheetData[gljContextMenu.selectedRow].unifiedSetting == 1){
+                            return true;
+                        }
+                        return false;
                     },
                     },
                     callback: function () {
                     callback: function () {
-                        //projectObj.project.quantity_detail.moveDown(gljContextMenu.selectedRow);
+                        installationFeeObj.applyRuleTo('FX',gljContextMenu.selectedRow);
                     },
                     },
                     visible: function(key, opt){
                     visible: function(key, opt){
                         return subSpread.getActiveSheet().name()=='rationInstallSheet';
                         return subSpread.getActiveSheet().name()=='rationInstallSheet';
@@ -246,11 +279,17 @@ var gljContextMenu = {
                     name: '应用到当前分部',
                     name: '应用到当前分部',
                     icon: 'fa-sign-in',
                     icon: 'fa-sign-in',
                     disabled: function () {
                     disabled: function () {
-                        /* var sheetData = gljOprObj.detailData;
-                         return gljContextMenu.selectedRow>sheetData.length-2;*/
+                        let sheetData = installationFeeObj.rationInstallData;
+                        if(gljContextMenu.selectedRow>sheetData.length-1){
+                            return true;
+                        }
+                        if(sheetData[gljContextMenu.selectedRow].unifiedSetting == 1){
+                            return true;
+                        }
+                        return false;
                     },
                     },
                     callback: function () {
                     callback: function () {
-                        //projectObj.project.quantity_detail.moveDown(gljContextMenu.selectedRow);
+                        installationFeeObj.applyRuleTo('FB',gljContextMenu.selectedRow);
                     },
                     },
                     visible: function(key, opt){
                     visible: function(key, opt){
                         return subSpread.getActiveSheet().name()=='rationInstallSheet';
                         return subSpread.getActiveSheet().name()=='rationInstallSheet';
@@ -260,11 +299,17 @@ var gljContextMenu = {
                     name: '应用到当前项目',
                     name: '应用到当前项目',
                     icon: 'fa-sign-in',
                     icon: 'fa-sign-in',
                     disabled: function () {
                     disabled: function () {
-                        /* var sheetData = gljOprObj.detailData;
-                         return gljContextMenu.selectedRow>sheetData.length-2;*/
+                        let sheetData = installationFeeObj.rationInstallData;
+                        if(gljContextMenu.selectedRow>sheetData.length-1){
+                            return true;
+                        }
+                        if(sheetData[gljContextMenu.selectedRow].unifiedSetting == 1){
+                            return true;
+                        }
+                        return false;
                     },
                     },
                     callback: function () {
                     callback: function () {
-                        //projectObj.project.quantity_detail.moveDown(gljContextMenu.selectedRow);
+                        installationFeeObj.applyRuleTo('PJ',gljContextMenu.selectedRow);
                     },
                     },
                     visible: function(key, opt){
                     visible: function(key, opt){
                         return subSpread.getActiveSheet().name()=='rationInstallSheet';
                         return subSpread.getActiveSheet().name()=='rationInstallSheet';

+ 175 - 15
web/building_saas/main/js/views/installation_fee_view.js

@@ -26,9 +26,15 @@ let installationFeeObj={
                return installationFeeObj.getDisplayText(item);
                return installationFeeObj.getDisplayText(item);
             },
             },
             forRule:function (item,val) {//
             forRule:function (item,val) {//
-                let feeRule = projectObj.project.installation_fee.getFeeRuleByID(item.libID,val);
-                if(feeRule){
-                    return feeRule.rule;
+                let install_fee = projectObj.project.installation_fee;
+                let impactRules =install_fee.getFeeRuleBySection({libID:item.libID,ID:item.sectionId});
+                if(_.find(impactRules,{ID:val})){
+                    return val;
+                }else {
+                    let feeRule = projectObj.project.installation_fee.getFeeRuleByID(item.libID,val);
+                    if(feeRule){
+                        return feeRule.rule;
+                    }
                 }
                 }
                 return val;
                 return val;
             }
             }
@@ -506,7 +512,6 @@ let installationFeeObj={
         return feeRules;
         return feeRules;
     },
     },
 
 
-
     getDetailRowDataBySection(is,libID){
     getDetailRowDataBySection(is,libID){
         let me = this;
         let me = this;
         let tem_detail = {
         let tem_detail = {
@@ -813,6 +818,9 @@ let installationFeeObj={
         }
         }
         installation_fee.updateFeeRule({position:recode.code,billID:recode.ID},rationInstall.libID,rationInstall.ruleId,function (){
         installation_fee.updateFeeRule({position:recode.code,billID:recode.ID},rationInstall.libID,rationInstall.ruleId,function (){
             me.refreshRationInstallationRow(riselection.row);
             me.refreshRationInstallationRow(riselection.row);
+            installation_fee.calcInstallationFee(function () {
+                projectObj.project.calcProgram.calcAllNodesAndSave();
+            });
         });
         });
     },
     },
     updateFeeRulePosition:function (recode) {
     updateFeeRulePosition:function (recode) {
@@ -867,6 +875,9 @@ let installationFeeObj={
         };
         };
         projectObj.project.ration_installation.update(updateData,function (data) {
         projectObj.project.ration_installation.update(updateData,function (data) {
             me.refreshRationInstallationRow(ri_row);
             me.refreshRationInstallationRow(ri_row);
+            projectObj.project.installation_fee.calcInstallationFee(function () {
+                projectObj.project.calcProgram.calcAllNodesAndSave();
+            });
         });
         });
     },
     },
     updateFeeItemPosition:function(recode){
     updateFeeItemPosition:function(recode){
@@ -884,7 +895,7 @@ let installationFeeObj={
             //更新缓存
             //更新缓存
             feeItem.position =recode.code;
             feeItem.position =recode.code;
             feeItem.billID = recode.ID;
             feeItem.billID = recode.ID;
-            feeItem.displayPosition = recode.code + ' '+recode.name;
+            feeItem.displayPosition = me.getDisplayText(feeItem);
             me.feeItemSheet.getCell(selection.row, selection.col).value(feeItem.displayPosition);
             me.feeItemSheet.getCell(selection.row, selection.col).value(feeItem.displayPosition);
             for(let ir of impacRules){
             for(let ir of impacRules){
                 ir.position = recode.code;
                 ir.position = recode.code;
@@ -934,6 +945,7 @@ let installationFeeObj={
     },
     },
     onRationInstallValueChange:function (e,info) {
     onRationInstallValueChange:function (e,info) {
         let me = installationFeeObj;
         let me = installationFeeObj;
+        let installation_fee = projectObj.project.installation_fee
         if(info.newValue==info.oldValue){
         if(info.newValue==info.oldValue){
             return;
             return;
         }
         }
@@ -959,8 +971,8 @@ let installationFeeObj={
         }
         }
         if(fieldID=='unifiedSetting'){//勾选统一设置
         if(fieldID=='unifiedSetting'){//勾选统一设置
             updateData.ruleId = '';
             updateData.ruleId = '';
-            let feeItem =  projectObj.project.installation_fee.getFeeItemByID(raInstallation.libID,raInstallation.feeItemId);
-            let section = projectObj.project.installation_fee.getInstallSectionByID(raInstallation.libID,raInstallation.sectionId);
+            let feeItem =  installation_fee.getFeeItemByID(raInstallation.libID,raInstallation.feeItemId);
+            let section = installation_fee.getInstallSectionByID(raInstallation.libID,raInstallation.sectionId);
             if(section&&feeItem&&feeItem.isCal == 1){
             if(section&&feeItem&&feeItem.isCal == 1){
                 updateData.ruleId = section.feeRuleId;
                 updateData.ruleId = section.feeRuleId;
             }
             }
@@ -968,6 +980,9 @@ let installationFeeObj={
         updateData[fieldID] = info.newValue;
         updateData[fieldID] = info.newValue;
         projectObj.project.ration_installation.update(updateData,function (data) {
         projectObj.project.ration_installation.update(updateData,function (data) {
             me.refreshRationInstallationRow(info.row);
             me.refreshRationInstallationRow(info.row);
+            installation_fee.calcInstallationFee(function () {
+                projectObj.project.calcProgram.calcAllNodesAndSave();
+            });
         });
         });
     },
     },
     modifyFeeRuleValueChange:function (e,info) {
     modifyFeeRuleValueChange:function (e,info) {
@@ -1140,12 +1155,128 @@ let installationFeeObj={
         }
         }
         return data;
         return data;
     },
     },
-    calcInstallationFee:function(){//计算定额安装费
-
-
-
-
+    calcInstallationFee:function(callback){//计算安装增加费
+        let engineering = projectInfoObj.projectInfo.property.engineering;
+        let installSetting = projectInfoObj.projectInfo.property.installSetting;
+        let install_fee = projectObj.project.installation_fee;
+        let autoCreate = false;
+        if(engineering!=engineeringType.BUILD_IN){//如果不是安装工程,则不用计算
+            return;
+        }
+        //可执行检查
+        let install_datas = install_fee.datas;
+        for(let d of install_datas){
+            for(let item of d.installFeeItem){
+                if(item.isCal == 1){ //勾选了记取的费用项
+                    let positionCheck = false;//是否做记取位置检查的开关
+                    if(item.feeType=='措施费用'){//如果是措施费用,检查是否选取了记取位置或者清单编码是否存在
+                        positionCheck = true;
+                    }else if(item.feeType=='分项费用'&&(installSetting==undefined||installSetting=="0")){//当费用项是分项费用时,且选择了“整个项目统一计取”
+                        positionCheck = true;
+                    }
+                    if(positionCheck == true){
+                        let sections = install_fee.getInstallSectionsByfeeItemID(d.libID,item.ID);
+                        for(let s of sections){
+                            if(s.feeRuleId&&s.feeRuleId!=""){//有选中规则项
+                                let feeRule = install_fee.getFeeRuleByID(d.libID,s.feeRuleId);
+                                if(feeRule){
+                                    if((!feeRule.billID||feeRule.billID=="")&&(!feeRule.position||feeRule.position=="")){//清单ID和position都为空的时候
+                                         alert("计取位置不能为空!");
+                                         return
+                                    }
+                                    if (autoCreate == false){//不自动生成的时候才做检查
+                                        if(feeRule.billID&&feeRule.billID!=""){//先检查清单ID
+                                            let node = projectObj.project.mainTree.getNodeByID(item.billID);
+                                            if(!node){
+                                                let c = confirm("所选清单没有找到,需要自动生成吗?");
+                                                if(c){
+                                                    autoCreate = true;
+                                                }else {
+                                                    return;
+                                                }
+                                            }
+                                        }else if(feeRule.position && feeRule.position!=""){//再检查code
+                                            let bill = projectObj.project.Bills.getBillByCode(feeRule.position);
+                                            if(!bill){
+                                                let c = confirm("所选清单没有找到,需要自动生成吗?");
+                                                if(c){
+                                                    autoCreate = true;
+                                                }else {
+                                                    return;
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        $('#calc_installation_fee').modal('hide');
+        install_fee.calcInstallationFee(function (isChange) {
+            if(isChange){
+                projectObj.project.calcProgram.calcAllNodesAndSave();
+                installationFeeObj.showRationInstallationData(projectObj.project.mainTree.selected);
+            }
+            console.log("cal end");
+        });
     },
     },
+    initSettingRadio:function () {
+        let installSetting = projectInfoObj.projectInfo.property.installSetting;
+        //radio 值设置
+        if(installSetting==undefined||installSetting=="0"){
+            $("#all_project_calc").prop("checked",true);
+            $("#FB_calc").prop("checked",false);
+        }else {
+            $("#all_project_calc").prop("checked",false);
+            $("#FB_calc").prop("checked",true);
+        }
+    },
+    applyRuleTo:function(level,row){//level:FX/FB/PJ
+        let selectRecord = this.rationInstallData[row];
+        let ration_installation = projectObj.project.ration_installation;
+        let rationID = selectRecord.rationID;
+        let condition = {'libID':selectRecord.libID,'feeItemId':selectRecord.feeItemId,'sectionId':selectRecord.sectionId};
+        let rationList = [];
+        let rationNode = projectObj.project.mainTree.getNodeByID(rationID);
+        if(!rationNode){
+            return;
+        }
+        if(level == 'FX'){//应用到分项
+            let children = rationNode.parent.children;//兄弟节点
+            for(let c of children){
+                if(c.data.type == rationType.ration){
+                    rationList.push(c.data.ID);
+                }
+            }
+            condition.rationID = rationList;
+        }else if(level == 'FB'){//应用到分部
+            let FBNode = rationNode.parent.parent;//分部节点
+            let rationNodeList =  projectObj.project.mainTree.getLeavesNodes(FBNode);
+            for(let r of rationNodeList){
+                if(r.data.type == rationType.ration){
+                    rationList.push(r.data.ID);
+                }
+            }
+            condition.rationID = rationList;
+        }
+        //应用到项目的时候就不用加入rationList做判断
+        let riList = ration_installation.getDataByConditions(condition);
+        let IDList = _.map(riList,'ID');
+        ration_installation.applyRuleByIDs(selectRecord.projectID,IDList,selectRecord.ruleId,function () {
+            //计算安装增加费
+            projectObj.project.installation_fee.calcInstallationFee(function (isChange) {
+                if(isChange){
+                    projectObj.project.calcProgram.calcAllNodesAndSave();
+                }
+            });
+        })
+    },
+    getRationByParentID:function () {
+
+    }
 };
 };
 
 
 
 
@@ -1157,6 +1288,9 @@ $(function () {
             installationFeeObj.showFeeItemData();
             installationFeeObj.showFeeItemData();
             installationFeeObj.showFeeDetailData();
             installationFeeObj.showFeeDetailData();
         }
         }
+        //radio 值设置
+        installationFeeObj.initSettingRadio();
+
     });
     });
     $('#calc_position').on('shown.bs.modal',function () {
     $('#calc_position').on('shown.bs.modal',function () {
         installationFeeObj.positionSelectedObject = null;
         installationFeeObj.positionSelectedObject = null;
@@ -1206,10 +1340,36 @@ $(function () {
         if(canChange==false){
         if(canChange==false){
             return;
             return;
         }
         }
-        let val = $('input[name="install_setting_radios"]:checked').val();
-        console.log(val);
+        me.calcInstallationFee();
+    });
+    $('#btn_reset_to_default').click(function (){
+        let ifModel =  projectObj.project.installation_fee;
+        let c = confirm("确定恢复系统默认值吗?");
+        if(c){
+            ifModel.resetToDefault(function () {
+                installationFeeObj.showFeeItemData();
+                installationFeeObj.showFeeDetailData();
+            });
+            ifModel.updateInstallSetting("0",function () {
+                installationFeeObj.initSettingRadio();
+            });
+        }
+      /*  installationFeeObj.showFeeItemData();
+        installationFeeObj.showFeeDetailData();*/
+    });
 
 
+    $("input[name='install_setting_radios']").each(function(){
+        $(this).click(function(){
+            var settingVal = $(this).val();
+            let installSetting = projectInfoObj.projectInfo.property.installSetting;
+            if(installSetting==settingVal){
+                return;
+            }
+            projectObj.project.installation_fee.updateInstallSetting(settingVal);
+        });
     });
     });
+
+
     $('#calc_installation_fee_close').click(function (){
     $('#calc_installation_fee_close').click(function (){
         let me = installationFeeObj;
         let me = installationFeeObj;
         let info = {
         let info = {
@@ -1221,7 +1381,7 @@ $(function () {
         if(canChange==false){
         if(canChange==false){
             return;
             return;
         }
         }
-        $('#calc_installation_fee').modal('hide');
+        me.calcInstallationFee();
     });
     });
 
 
     $('#more_feeRule_confirm').click(function (){
     $('#more_feeRule_confirm').click(function (){

+ 2 - 0
web/building_saas/main/js/views/main_tree_col.js

@@ -16,6 +16,8 @@ let MainTreeCol = {
                 }
                 }
                 else if (node.data.type == 3) {    // 工料机定额
                 else if (node.data.type == 3) {    // 工料机定额
                     return projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写
                     return projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写
+                }else if(node.data.type == 4){//安装增加费生成的定额
+                    return '安';
                 }
                 }
             } else if (node.sourceType === projectObj.project.ration_glj.getSourceType()) {
             } else if (node.sourceType === projectObj.project.ration_glj.getSourceType()) {
                 return projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写
                 return projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写

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

@@ -0,0 +1,262 @@
+/**
+ * Created by zhang on 2018/3/13.
+ */
+projectGljObject={
+    projectGljSetting:{
+        header: [
+            {headerName: "编码", headerWidth: 80, dataCode: "code", dataType: "String"},
+            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
+            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", hAlign: "left", dataType: "String"},
+            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
+            {headerName: "类型", headerWidth: 45, dataCode: "short_name", hAlign: "center", dataType: "String"},
+            {headerName: "总消耗量", headerWidth: 100, dataCode: "quantity", hAlign: "right", dataType: "Number",decimalField:'glj.quantity'},
+            {headerName: "定额价", headerWidth: 70, dataCode: "basePrice", hAlign: "right", dataType: "Number",decimalField:'glj.quantity',validator:"number"},
+            {headerName: "调整价", headerWidth: 70, dataCode: "adjustPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice"},
+            {headerName: "市场价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice",validator:"number"},
+            {headerName: "是否暂估", headerWidth: 60, dataCode: "is_evaluate", hAlign: "center", dataType: "String",cellType:'checkBox'},
+            {headerName: "供货方式", headerWidth: 80, dataCode: "supply", hAlign: "center", dataType: "String",cellType:'comboBox',editorValueType:true,options:supplyComboMap},
+            {headerName: "甲供数量", headerWidth: 100, dataCode: "supply_quantity", hAlign: "right", dataType: "String",validator:"number"},
+            {headerName: "交货方式", headerWidth: 90, dataCode: "delivery", hAlign: "left", dataType: "String"},
+            {headerName: "送达地点", headerWidth: 100, dataCode: "delivery_address", hAlign: "left", dataType: "String"},
+            {headerName: "不调价", headerWidth: 55, dataCode: "is_adjust_price", dataType: "String",cellType: "checkBox"}
+        ],
+        view: {
+            lockColumns: [0,1,2,3,4,5,7,12,13]
+        }
+    },
+    projectGljSpread:null,
+    projectGljSheet:null,
+    projectGljSheetData:[],
+    mixRatioSetting:{
+        header:[
+            {headerName: "编码", headerWidth: 80, dataCode: "code", dataType: "String"},
+            {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
+            {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
+            {headerName: "类型", headerWidth: 45, dataCode: "short_name", hAlign: "center", dataType: "String"},
+            {headerName: "定额价", headerWidth: 70, dataCode: "basePrice", hAlign: "right", dataType: "Number",decimalField:'glj.quantity',validator:"number"},
+            {headerName: "调整价", headerWidth: 70, dataCode: "adjustPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice"},
+            {headerName: "市场价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",decimalField:"glj.unitPrice",validator:"number"}
+        ],
+        view: {
+            lockColumns: [0,1]
+        }
+    },
+    mixRatioSpread:null,
+    mixRatioSheet:null,
+    mixRatioData:[],
+    initProjectGljSpread:function () {
+        this.projectGljSpread = SheetDataHelper.createNewSpread($("#project_glj_sheet")[0]);
+        this.projectGljSheet = this.projectGljSpread .getSheet(0);
+        this.initSheet(this.projectGljSheet,this.projectGljSetting);
+        this.projectGljSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onProjectGljSelectionChange);
+        this.projectGljSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onProjectGljEditStarting);
+        this.projectGljSheet.name('projectGljSheet');
+    },
+    onProjectGljEditStarting:function (sender, args) {
+        let me = projectGljObject;
+        let row = args.row;
+        let col = args.col;
+        let dataCode = me.projectGljSetting.header[col].dataCode;
+        if(dataCode=='is_adjust_price'||dataCode=='is_evaluate'){
+            args.cancel = true;
+        }
+    },
+    onProjectGljSelectionChange:function (sender, args) {
+        let me = projectGljObject;
+        let row = args.newSelections[0].row;
+        let col = args.newSelections[0].col;
+        let data = me.projectGljSheetData[row];
+        let dataCode = me.projectGljSetting.header[col].dataCode;
+        if(dataCode=='basePrice'||dataCode=='marketPrice'||dataCode=='supply'){//有组成物时,市场单价、定额价、供货方式不能修改
+            let priceCell = false;
+            if (data.ratio_data  && data.ratio_data.length > 0){
+                priceCell = true;
+            }
+            if(priceCell==false&&dataCode=='basePrice'&&data.is_add!=1){//如果不是新增,定额价不可修改。
+                priceCell = true;
+            }
+            me.projectGljSheet.getCell(row, col,  GC.Spread.Sheets.SheetArea.viewport).locked(priceCell);
+        }
+        if(dataCode == 'supply_quantity'){
+            if (data.supply == 1) {// 如果为部分甲供则甲供数量需要可编辑
+                me.projectGljSheet.getCell(row, col,  GC.Spread.Sheets.SheetArea.viewport).locked(false);
+            }else {
+                me.projectGljSheet.getCell(row, col,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
+            }
+        }
+        me.projectGljSheet.repaint();
+    },
+
+
+    showProjectGljData:function () {
+        let projectGljSheetData = [];
+        let gljList = projectObj.project.projectGLJ.datas.gljList;
+        gljList = filterProjectGLJ(gljList);
+        gljList = sortProjectGLJ(gljList);
+        for(let glj of gljList){
+            projectGljSheetData.push(this.getSheetDataByGLJ(glj));
+        }
+        this.projectGljSheetData = projectGljSheetData;
+        this.projectGljSheet.setRowCount(0);
+        sheetCommonObj.showData(this.projectGljSheet, this.projectGljSetting,this.projectGljSheetData);
+        this.projectGljSheet.setRowCount(this.projectGljSheetData.length);
+    },
+    getSheetDataByGLJ:function (glj) {
+        let projectGLJ = projectObj.project.projectGLJ;
+        let materialIdList = projectGLJ.datas.constData.materialIdList;
+        let data ={
+            id:glj.id,
+            code:glj.code,
+            name:glj.name,
+            specs:glj.specs,
+            unit:glj.unit,
+            type:glj.type,
+            short_name:projectGLJ.getShortNameByID(glj.type),
+            quantity:glj.quantity,
+            supply:glj.supply,
+            supply_quantity:glj.supply_quantity,
+            delivery:glj.delivery,
+            delivery_address:glj.delivery_address,
+            is_adjust_price:glj.is_adjust_price,
+            ratio_data:glj.ratio_data,
+            is_add:glj.unit_price.is_add,
+            bgColour:'white'
+        };
+        gljOprObj.setGLJPrice(data,glj);
+
+        //供货方式为完全甲供时设置甲供数量为总消耗量
+        if (data.supply == 2) {
+            data.supply_quantity = glj.quantity;
+        }
+        // 只有材料才显示是否暂估
+        if (materialIdList.indexOf(glj.type) >= 0) {
+            data.is_evaluate = glj.is_evaluate;
+        }
+        //bgColour
+        if(data.basePrice == data.marketPrice){//如果定额价等于市场价时,改底色。 优先度低于有组成物时的底色
+            data.bgColour = "#C4CAFB";
+        }
+        if (notEditType.indexOf(glj.type) >= 0) {
+            if (data.ratio_data  && data.ratio_data.length > 0){//有组成物时
+                //设置底色
+                data.bgColour = "#E0E0E0";
+            }
+        }
+        return data;
+    },
+    refreshProjectGljRow:function (row) {
+        let me = projectGljObject;
+        let rowData = me.projectGljSheetData[row];
+        let glj = projectObj.project.projectGLJ.getByID(rowData.id);
+        if(glj){
+            me.projectGljSheetData[row] = me.getSheetDataByGLJ(glj);
+        }
+        sheetCommonObj.showRowData(this.projectGljSheet, this.projectGljSetting,row,this.projectGljSheetData);
+    },
+    initSheet: function (sheet,setting) {
+        var me = this;
+        sheetCommonObj.initSheet(sheet, setting, 30);
+        sheet.bind(GC.Spread.Sheets.Events.ValueChanged, me.onSheetValueChange);
+    },
+    onSheetValueChange:function (e,info) {
+        let me = projectGljObject;
+        if(info.sheetName=='projectGljSheet'){
+            me.onProjectGLJValueChange(e,info);
+        }
+    },
+    onProjectGLJValueChange:function (e,info) {
+        let projectGLJ = projectObj.project.projectGLJ;
+        let me = projectGljObject,row = info.row, col = info.col;
+        let dataCode = me.projectGljSetting.header[col].dataCode;
+        let recode = me.projectGljSheetData[row];
+        let value = info.newValue;
+        if (!me.checkData(col,me.projectGljSetting,value)) {
+            alert('输入的数据类型不对,请重新输入!');
+            return ;
+        }
+        let callback=function (impactList) {
+            info.sheet.suspendPaint();
+            info.sheet.suspendEvent();
+            me.refreshProjectGljRow(row);
+            for(let g of impactList){
+                let index = _.findIndex(me.projectGljSheetData, { 'id': g.id });
+                if(index>=0&&index != row){
+                    me.refreshProjectGljRow(index);
+                }
+            }
+            info.sheet.resumeEvent();
+            info.sheet.resumePaint();
+        };
+        if(dataCode=='basePrice'||dataCode=='marketPrice'){
+            value= scMathUtil.roundForObj(value,getDecimal('glj.unitPrice'));//修改市场价和修改定额价时需要重新记算很多受影响的树节点,现在改成与定字额工料机那里调相同的方法。
+            let editField = dataCode === 'basePrice'?"base_price":"market_price";
+            projectObj.project.projectGLJ.updatePrice(recode,editField,value,'pg',callback);
+
+        }else {
+            let extend = {};
+            // 如果是供货方式则需要处理数据
+            if (dataCode === 'supply') {
+                extend.supply_quantity = me.getSupplyQuantity(value, recode.quantity);
+            }
+            if(dataCode === 'supply_quantity'){//修改数量需做4舍5入
+                value= value.toDecimal(getDecimal('glj.quantity'));
+            }
+            if(dataCode === 'is_evaluate'||dataCode === 'is_adjust_price'){
+                if(value == true){
+                    value = 1;
+                }else if(value == false){
+                    value = 0;
+                }
+            }
+            extend = Object.keys(extend).length > 0 ?  JSON.stringify(extend) : '';
+            let updateData = {id: recode.id, field: dataCode, value: value, extend: extend};
+            projectGLJ.pGljUpdate(updateData,callback);
+        }
+    },
+    getSupplyQuantity : function(supplyType, quantity) {
+        // 自行采购和甲定乙供则把甲供数量设置为0,其余情况则设置为当前总消耗量
+        let supplyQuantity = supplyType == 0 || supplyType == 3 ? 0 : quantity;
+        supplyQuantity = parseFloat(supplyQuantity);
+        return supplyQuantity;
+    },
+    checkData : function(col,setting, value) {
+        let result = true;
+        let validator = setting.header[col].validator !== undefined ? setting.header[col].validator : null;
+        if (validator === null) {
+            return result;
+        }
+        switch (validator) {
+            case 'number':
+                let regular = /^\d+(\.\d+)?$/;
+                result = regular.test(value);
+                break;
+            case 'boolean':
+                let booleanValue = [true, false];
+                result = booleanValue.indexOf(value) >= 0;
+                break;
+        }
+        return result;
+    }
+};
+
+
+$(function () {
+    $('#tab_project_glj').on('show.bs.tab', function (e) {
+        let me = projectGljObject;
+        $(e.relatedTarget.hash).removeClass('active');
+        setTimeout(function () {
+            if(me.projectGljSpread==null){
+                me.initProjectGljSpread();
+            }
+            me.showProjectGljData();
+            loadSize("project-glj-main", function () {
+                me.projectGljSpread.refresh();
+            });
+        },1)
+    });
+    slideResize($("#project-glj-main"), function () {
+        projectGljObject.projectGljSpread.refresh();
+    });
+});
+
+

+ 7 - 6
web/building_saas/main/js/views/project_property_display_view.js

@@ -6,8 +6,8 @@ let projDisplayView = {
     init: function () {
     init: function () {
         this.datas = projectInfoObj.projectInfo.property.displaySetting;
         this.datas = projectInfoObj.projectInfo.property.displaySetting;
         this.datas = this.datas === undefined ? {autoHeight: true, disPlayMainMaterial: true} : this.datas;
         this.datas = this.datas === undefined ? {autoHeight: true, disPlayMainMaterial: true} : this.datas;
-        $("#autoHeight").attr("checked", this.datas.autoHeight);
-        $("#disPlayMainMaterial").attr("checked", this.datas.disPlayMainMaterial);
+        $("#autoHeight").prop("checked", this.datas.autoHeight);
+        $("#disPlayMainMaterial").prop("checked", this.datas.disPlayMainMaterial);
         //$('#disPlayMainMateria').prop('checked')
         //$('#disPlayMainMateria').prop('checked')
     },
     },
 
 
@@ -37,9 +37,9 @@ let calcOptions = {
     datas: null,//just for view
     datas: null,//just for view
     init: function () {
     init: function () {
         this.datas = projectInfoObj.projectInfo.property.calcOptions;
         this.datas = projectInfoObj.projectInfo.property.calcOptions;
-        $("#calc_main").attr("checked", this.datas.calc_main);
-        $("#calc_add").attr("checked", this.datas.calc_add);
-        $("#calc_est").attr("checked", this.datas.calc_est);
+        $("#calc_main").prop("checked", this.datas.calc_main);
+        $("#calc_add").prop("checked", this.datas.calc_add);
+        $("#calc_est").prop("checked", this.datas.calc_est);
     },
     },
     updateChecking: function (properties) {
     updateChecking: function (properties) {
         if (this.datas == null) {
         if (this.datas == null) {
@@ -60,6 +60,7 @@ let calcOptions = {
 }
 }
 
 
 
 
+/*
 $(document).ready(function () {
 $(document).ready(function () {
     $('#tab_display_setting').on('shown.bs.tab', function () {
     $('#tab_display_setting').on('shown.bs.tab', function () {
         projDisplayView.init();
         projDisplayView.init();
@@ -67,4 +68,4 @@ $(document).ready(function () {
     $('#about-calc').on('shown.bs.tab', function () {
     $('#about-calc').on('shown.bs.tab', function () {
         calcOptions.init();
         calcOptions.init();
     });
     });
-});
+});*/

+ 177 - 0
web/building_saas/main/js/views/project_property_indicativeInfo.js

@@ -0,0 +1,177 @@
+/**
+ * Created by Zhong on 2018/3/7.
+ */
+let indicativeInfoObj = {
+    feeType: {common: 'common', labour: 'labour', material: 'material', machine: 'machine', mainMaterial: 'mainMaterial', equipment: 'equipment',
+        labourDiff: 'labourDiff', materialDiff: 'materialDiff', machineDiff: 'machineDiff', manage: 'manage', profit: 'profit'},
+    workBook: null,
+    setting:{
+        header: [
+            {name: '名称', dataCode: 'name', width: 200, vAlign: 'center', hAlign: 'left'},
+            {name: '金额', dataCode: 'price', width: 120, vAlign: 'center', hAlign: 'right'},
+            {name: '占造价比例(%)', dataCode: 'rate', width: 100, vAlign: 'center', hAlign: 'right'},
+            {name: '单方造价', dataCode: 'perCentiare', width: 80, vAlign: 'center', hAlign: 'right'}
+        ],
+        options: {
+            tabStripVisible:  false,
+            allowCopyPasteExcelStyle : false,
+            allowExtendPasteRange: false,
+            allowUserDragDrop : false,
+            allowUserDragFill: false,
+            scrollbarMaxAlign : true
+        }
+    },
+
+    renderSheetFuc: function (sheet, fuc) {
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        fuc();
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
+
+    setOptions: function (workbook, opts) {
+        for(let opt in opts){
+            workbook.options[opt] = opts[opt];
+        }
+    },
+
+    buildHeader: function (sheet, headers) {
+        let me = projFeatureView;
+        let fuc = function () {
+            sheet.setColumnCount(headers.length);
+            sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
+            for(let i = 0, len = headers.length; i < len; i++){
+                sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
+                sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
+            }
+        };
+        me.renderSheetFuc(sheet, fuc);
+    },
+
+    buildSheet: function () {
+        if(!this.workBook){
+            this.workBook = new GC.Spread.Sheets.Workbook($('#indicativeInfoSpread')[0], {sheetCount: 1});
+            this.setOptions(this.workBook, this.setting.options);
+            this.workBook.getSheet(0).options.isProtected = true;
+            this.buildHeader(this.workBook.getActiveSheet(), this.setting.header);
+        }
+    },
+    showData(datas){
+        let sheet = this.workBook.getActiveSheet();
+        let cols = this.setting.header;
+        let fuc = function () {
+            sheet.setRowCount(datas.length);
+            for(let col = 0, cLen = cols.length; col < cLen; col++){
+                sheet.getRange(-1, col, -1, 1, GC.Spread.Sheets.SheetArea.viewport).hAlign(GC.Spread.Sheets.HorizontalAlign[cols[col]['hAlign']]);
+                sheet.getRange(-1, col, -1, 1, GC.Spread.Sheets.SheetArea.viewport).vAlign(GC.Spread.Sheets.VerticalAlign[cols[col]['vAlign']]);
+                for(let row = 0, rLen = datas.length; row < rLen; row++){
+                    sheet.setValue(row, col, datas[row][cols[col]['dataCode']]);
+                }
+            }
+        };
+        this.renderSheetFuc(sheet, fuc);
+    },
+    //是清单
+    isBills: function (node) {
+        return node && node.sourceType === projectObj.project.Bills.getSourceType();
+    },
+    //是大项费用
+    isDXFY: function (node) {
+        return this.isBills(node) && node.data.type === billType.DXFY;
+    },
+    //是分部分项工程
+    isFBFX: function (node) {
+        return this.isDXFY(node) && node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === fixedFlag.SUB_ENGINERRING;
+    },
+    //是措施项目
+    isCSXM: function (node) {
+        return this.isDXFY(node) && node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === fixedFlag.MEASURE;
+    },
+    //是工程造价
+    isEngieeringCost: function (node) {
+        return this.isDXFY(node) && node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === fixedFlag.ENGINEERINGCOST;
+    },
+    //存在某个费用
+    fee: function (node, feeType) {
+        return node && node.data.feesIndex && node.data.feesIndex[feeType] ? node.data.feesIndex[feeType].totalFee : 0;
+    },
+    //根据固定行ID获取固定行清单节点
+    getFixedBill: function (flag) {
+        for(let node of projectObj.project.mainTree.items){
+            if(node && node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === flag){
+                return node;
+            }
+        }
+        return null;
+    },
+    getDXFY: function (node) {
+        if(!node) return null;
+        let dxfy = Object.create(null);
+        let engCostFee = this.fee(this.getFixedBill(fixedFlag.ENGINEERINGCOST), this.feeType.common);
+        let commonFee = this.fee(node, this.feeType.common);
+        let buildingArea = projFeatureView.getFeature('projFeature', 'buildingArea');
+        let areaNum = !buildingArea.value || buildingArea.value == '' || isNaN(buildingArea.value) ? 0 : buildingArea.value;
+        dxfy.name = node.data.name;
+        dxfy.price = commonFee ? parseFloat(commonFee).toDecimal(decimalObj.bills.totalPrice) : 0;
+        dxfy.rate = engCostFee == 0 || this.isEngieeringCost(node) ? '' : parseFloat(dxfy.price/engCostFee*100).toDecimal(2);
+        dxfy.perCentiare = areaNum == 0 ? '' : parseFloat(dxfy.price/areaNum).toDecimal(decimalObj.bills.totalPrice);
+        return dxfy;
+    },
+    getIndicativeInfo: function () {
+        let rst = [];
+        for(let node of projectObj.project.mainTree.items){
+            if(this.isDXFY(node)){
+                let dxfy = this.getDXFY(node);
+                if(!dxfy) continue;
+                if(this.isFBFX(node)){
+                    rst.push(dxfy);
+                    rst.push({name: '其中:', price: '', rate: '', perCentiare: ''});
+                    rst.push({name: '       人工费', price: parseFloat(this.fee(node, this.feeType.labour)).toDecimal(decimalObj.bills.totalPrice), rate: '', perCentiare: ''});
+                    rst.push({name: '       材料费', price: parseFloat(this.fee(node, this.feeType.material)).toDecimal(decimalObj.bills.totalPrice), rate: '', perCentiare: ''});
+                    rst.push({name: '       机械费', price: parseFloat(this.fee(node, this.feeType.machine)).toDecimal(decimalObj.bills.totalPrice), rate: '', perCentiare: ''});
+                    rst.push({name: '       主材费', price: parseFloat(this.fee(node, this.feeType.mainMaterial)).toDecimal(decimalObj.bills.totalPrice), rate: '', perCentiare: ''});
+                    rst.push({name: '       设备费', price: parseFloat(this.fee(node, this.feeType.equipment)).toDecimal(decimalObj.bills.totalPrice), rate: '', perCentiare: ''});
+                    let labourDiff = this.fee(node, this.feeType.labourDiff),
+                        materialDiff = this.fee(node, this.feeType.materialDiff),
+                        machineDiff = this.fee(node, this.feeType.machineDiff),
+                        rcjDiff = labourDiff + materialDiff + machineDiff;
+                    rst.push({name: '人材机价差', price: parseFloat(rcjDiff).toDecimal(decimalObj.bills.totalPrice), rate: '', perCentiare: ''});
+                    rst.push({name: '企业管理费', price: parseFloat(this.fee(node, this.feeType.manage)).toDecimal(decimalObj.bills.totalPrice), rate: '', perCentiare: ''});
+                    rst.push({name: '利润', price: parseFloat(this.fee(node, this.feeType.profit)).toDecimal(decimalObj.bills.totalPrice), rate: '', perCentiare: ''});
+                }
+                else if(this.isCSXM(node)){
+                    rst.push(dxfy);
+                    rst.push({name: '其中:', price: '', rate: '', perCentiare: ''});
+                    let safeConst = this.getDXFY(this.getFixedBill(fixedFlag.SAFETY_CONSTRUCTION));
+                    if(safeConst){
+                        safeConst.name = `      ${safeConst.name}`;
+                        rst.push(safeConst);
+                    }
+                }
+                else{
+                    rst.push(dxfy);
+                }
+            }
+        }
+        return rst;
+    }
+};
+
+$(document).ready(function () {
+    $('#poj-set').on('shown.bs.modal', function () {
+        indicativeInfoObj.buildSheet();
+        indicativeInfoObj.showData(indicativeInfoObj.getIndicativeInfo());
+    });
+
+    $('#poj-set').on('hidden.bs.modal', function () {
+       if(indicativeInfoObj.workBook){
+           indicativeInfoObj.workBook.destroy();
+           indicativeInfoObj.workBook = null;
+       }
+    });
+
+    $('#tab_poj-settings-indicativeInfo').on('shown.bs.tab', function () {
+        indicativeInfoObj.workBook.refresh();
+    });
+});

+ 15 - 2
web/building_saas/main/js/views/project_property_projFeature.js

@@ -9,7 +9,7 @@ let projFeatureView = {
     setting:{
     setting:{
         header: [
         header: [
             {name: '属性', dataCode: 'dispName', width: 200, vAlign: 'center', hAlign: 'left'},
             {name: '属性', dataCode: 'dispName', width: 200, vAlign: 'center', hAlign: 'left'},
-            {name: '值', dataCode: 'value', width: 120, vAlign: 'center', hAlign: 'left'}
+            {name: '值', dataCode: 'value', width: 120, vAlign: 'center', hAlign: 'center'}
         ],
         ],
         options: {
         options: {
             tabStripVisible:  false,
             tabStripVisible:  false,
@@ -110,7 +110,7 @@ let projFeatureView = {
             }
             }
             for(let col = 0, cLen = cols.length; col < cLen; col++){
             for(let col = 0, cLen = cols.length; col < cLen; col++){
                 sheet.getRange(-1, col, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[cols[col]['hAlign']]);
                 sheet.getRange(-1, col, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[cols[col]['hAlign']]);
-                sheet.getRange(-1, col, -1, 1).hAlign(GC.Spread.Sheets.VerticalAlign[cols[col]['vAlign']]);
+                sheet.getRange(-1, col, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[cols[col]['vAlign']]);
                 for(let row = 0, rLen = datas.length; row < rLen; row++){
                 for(let row = 0, rLen = datas.length; row < rLen; row++){
                     sheet.setValue(row, col, datas[row][cols[col]['dataCode']]);
                     sheet.setValue(row, col, datas[row][cols[col]['dataCode']]);
                 }
                 }
@@ -188,6 +188,19 @@ let projFeatureView = {
         }
         }
     },
     },
 
 
+    getFeature: function (featureType, eigenKey) {
+        for(let feature of this.orgDatas){
+            if(feature.key === featureType){
+                for(let eigen of feature.items){
+                    if(eigen.key === eigenKey){
+                        return eigen;
+                    }
+                }
+            }
+        }
+        return null;
+    },
+
     isDef: function (v) {
     isDef: function (v) {
         return v !== undefined && v !== null;
         return v !== undefined && v !== null;
     },
     },

+ 102 - 2
web/building_saas/main/js/views/project_view.js

@@ -437,6 +437,18 @@ var projectObj = {
             info.sheet.setValue(info.row, info.col, newV);
             info.sheet.setValue(info.row, info.col, newV);
         }
         }
     },
     },
+    onCellDoubleClick: function (sender, info){
+        let project = projectObj.project;
+        let node = project.mainTree.items[info.row];
+        let fieldName = projectObj.mainController.setting.cols[info.col].data.field;
+        if(fieldName == 'marketUnitFee'){
+            if(gljOprObj.hasComposition(node.data,true)){
+                alert("当前工料机的市场价由组成物计算得出,不可直接修改。");
+                return;
+            }
+        }
+
+    },
     mainSpreadEditEnded: function (sender, info) {
     mainSpreadEditEnded: function (sender, info) {
         let project = projectObj.project;
         let project = projectObj.project;
         let node = project.mainTree.items[info.row];
         let node = project.mainTree.items[info.row];
@@ -489,6 +501,7 @@ var projectObj = {
         if (!this.mainSpread) {
         if (!this.mainSpread) {
             this.mainSpread = SheetDataHelper.createNewSpread($('#billsSpread')[0]);
             this.mainSpread = SheetDataHelper.createNewSpread($('#billsSpread')[0]);
             this.mainSpread.getActiveSheet().selectionPolicy(GC.Spread.Sheets.SelectionPolicy.muliRange);
             this.mainSpread.getActiveSheet().selectionPolicy(GC.Spread.Sheets.SelectionPolicy.muliRange);
+            this.mainSpread.getActiveSheet().name('mainSheet');
         }
         }
     },
     },
     refreshMainSpread: function () {
     refreshMainSpread: function () {
@@ -573,6 +586,7 @@ var projectObj = {
                 that.mainSpread.bind(GC.Spread.Sheets.Events.RangeChanged, that.mainSpreadRangeChanged);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.RangeChanged, that.mainSpreadRangeChanged);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.ClipboardChanged, that.msClipboardChanged);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.ClipboardChanged, that.msClipboardChanged);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.ButtonClicked, that.onButtonClick);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.ButtonClicked, that.onButtonClick);
+                that.mainSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, that.onCellDoubleClick);
                 that.loadMainSpreadContextMenu();
                 that.loadMainSpreadContextMenu();
                 that.loadFocusLocation();
                 that.loadFocusLocation();
                 let endTime = +new Date();
                 let endTime = +new Date();
@@ -961,7 +975,7 @@ var projectObj = {
     getNodeColorStyle: function (node, colSetting) {
     getNodeColorStyle: function (node, colSetting) {
         let colorSetting = optionsOprObj.getOption(optionsOprObj.optionsTypes.COLOROPTS);
         let colorSetting = optionsOprObj.getOption(optionsOprObj.optionsTypes.COLOROPTS);
         let mapping = {DEFAULT: 'DEFAULT', DXFY: 'DXFY', FB: 'FB', UNLEAFBILL: 'UNLEAFBILL',
         let mapping = {DEFAULT: 'DEFAULT', DXFY: 'DXFY', FB: 'FB', UNLEAFBILL: 'UNLEAFBILL',
-            FX: 'FX', UNCBBILL: 'UNCBBILL', CBBILL: 'CBBILL', ZCSB: 'ZCSB'};
+            FX: 'FX', BX: 'BX', UNCBBILL: 'UNCBBILL', CBBILL: 'CBBILL', ZCSB: 'ZCSB'};
         let styleMap = null;
         let styleMap = null;
         //中文字段名,由于同一节点中,中文字体大小和数字字体大小不同
         //中文字段名,由于同一节点中,中文字体大小和数字字体大小不同
         let stringFields = [
         let stringFields = [
@@ -994,6 +1008,10 @@ var projectObj = {
             else if(node.data.type === billType.FX){
             else if(node.data.type === billType.FX){
                 styleMap = mapping.FX;
                 styleMap = mapping.FX;
             }
             }
+            //补项
+            else if(node.data.type === billType.BX){
+                styleMap = mapping.BX;
+            }
             //清单
             //清单
             else if(node.data.type === billType.BILL){
             else if(node.data.type === billType.BILL){
                 //非叶子节点的清单
                 //非叶子节点的清单
@@ -1157,6 +1175,86 @@ $('#downMove').click(function () {
         };
         };
     }
     }
 });
 });
+//显示至..
+let displayLevel = function(nodes, depth, type){
+    let refreshNodes = [];
+    function getExpandedController(){
+        if(type === 'DXFY' || type === 'FB'){
+            if(type === 'FB'){
+                projectObj.project.mainTree.items[0].setExpanded(true);
+                refreshNodes.push(projectObj.project.mainTree.items[0]);
+            }
+            return  function expandedControl(nodes, depth){
+                let bType = type === 'FB' ? billType.FB : billType.DXFY;
+                for(let node of nodes){
+                    let nodeDepth = node.depth();
+                    if(nodeDepth <= depth){
+                        let expanded = nodeDepth === depth && !node.children[0] || nodeDepth < depth && node.children[0] && node.children[0].data.type === bType ? true : false;
+                        node.setExpanded(expanded);
+                        refreshNodes.push(node);
+                        if(nodeDepth < depth){
+                            expandedControl(node.children, depth);
+                        }
+                    }
+                }
+            }
+        }
+        else if(type === 'FX' || type === 'ZM' || type === 'ZD'){
+            return  function expandedControl(nodes){
+                for(let node of nodes){
+                    if(type !== 'FX' || node.sourceType === projectObj.project.Bills.getSourceType()){
+                        let expanded = true;
+                        if(type === 'FX'){
+                            expanded =  !node.children[0] || node.children[0] && node.children[0].sourceType === projectObj.project.Bills.getSourceType() ? true : false;
+                        }
+                        else if(type === 'ZM'){
+                            expanded =  !node.children[0] || node.children[0] && node.children[0].sourceType !== projectObj.project.ration_glj.getSourceType() ? true : false;
+                        }
+                        node.setExpanded(expanded);
+                        refreshNodes.push(node);
+                        expandedControl(node.children);
+                    }
+                }
+            }
+        }
+    }
+    getExpandedController()(nodes, depth);
+    let sheet = projectObj.mainSpread.getActiveSheet();
+    TREE_SHEET_HELPER.massOperationSheet(sheet, function () {
+        TREE_SHEET_HELPER.refreshNodesVisible(refreshNodes, projectObj.mainSpread.getActiveSheet(), true)
+    });
+};
+$('#displayDXFY').click(function () {
+   displayLevel(projectObj.project.mainTree.items, 0, 'DXFY')
+});
+//显示至一级分部
+$('#displayFB1').click(function () {
+   displayLevel(projectObj.project.mainTree.items[0].children, 1, 'FB');
+});
+//二级分部
+$('#displayFB2').click(function () {
+    displayLevel(projectObj.project.mainTree.items[0].children, 2, 'FB');
+});
+//三级分部
+$('#displayFB3').click(function () {
+    displayLevel(projectObj.project.mainTree.items[0].children, 3, 'FB');
+});
+//四级分部
+$('#displayFB4').click(function () {
+    displayLevel(projectObj.project.mainTree.items[0].children, 4, 'FB');
+});
+//分项
+$('#displayFX').click(function () {
+    displayLevel(projectObj.project.mainTree.items, null, 'FX');
+});
+//子目
+$('#displayZM').click(function () {
+    displayLevel(projectObj.project.mainTree.items, null, 'ZM');
+});
+//最底层
+$('#displayZD').click(function () {
+   displayLevel(projectObj.project.mainTree.roots, null, 'ZD');
+});
 
 
 $('#poj-set').on('show.bs.modal', function () {
 $('#poj-set').on('show.bs.modal', function () {
     let setCalcFlag = function (obj, val, curFlag) {
     let setCalcFlag = function (obj, val, curFlag) {
@@ -1169,7 +1267,7 @@ $('#poj-set').on('show.bs.modal', function () {
     }
     }
     if (projectObj.project) {
     if (projectObj.project) {
         // let mode = projectObj.project.projSetting.billsCalcMode;
         // let mode = projectObj.project.projSetting.billsCalcMode;
-        // let settingConst = projectObj.project.projSetting.settingConst;
+        // let settingConst = projectObj.project.projSetting.settingConst;
         let ft = projectObj.project.property.billsCalcMode ? projectObj.project.property.billsCalcMode : leafBillGetFeeType.rationContent;
         let ft = projectObj.project.property.billsCalcMode ? projectObj.project.property.billsCalcMode : leafBillGetFeeType.rationContent;
         setCalcFlag($('#rationContent'), leafBillGetFeeType.rationContent, ft);
         setCalcFlag($('#rationContent'), leafBillGetFeeType.rationContent, ft);
         setCalcFlag($('#rationPriceConverse'), leafBillGetFeeType.rationPriceConverse, ft);
         setCalcFlag($('#rationPriceConverse'), leafBillGetFeeType.rationPriceConverse, ft);
@@ -1180,6 +1278,8 @@ $('#poj-set').on('show.bs.modal', function () {
         let zg = projectObj.project.property.zanguCalcMode ? projectObj.project.property.zanguCalcMode : zanguCalcType.common;
         let zg = projectObj.project.property.zanguCalcMode ? projectObj.project.property.zanguCalcMode : zanguCalcType.common;
         setCalcFlag($('#zangu_common'), zanguCalcType.common, zg);
         setCalcFlag($('#zangu_common'), zanguCalcType.common, zg);
         setCalcFlag($('#zangu_gatherMaterial'), zanguCalcType.gatherMaterial, zg);
         setCalcFlag($('#zangu_gatherMaterial'), zanguCalcType.gatherMaterial, zg);
+        projDisplayView.init();
+        calcOptions.init();
     }
     }
 });
 });
 $('#property_ok').click(function () {
 $('#property_ok').click(function () {

+ 16 - 0
web/building_saas/main/js/views/std_bills_lib.js

@@ -192,6 +192,22 @@ var billsLibObj = {
                         ProjectController.addBills(projectObj.project, projectObj.mainController, selectNode.data);
                         ProjectController.addBills(projectObj.project, projectObj.mainController, selectNode.data);
                     }
                     }
                 }
                 }
+                else{
+                    let me = billsLibObj;
+                    let node = stdBillsTree.items[args.row];
+                    if (!node || node.children.length === 0)
+                        return;
+                    node.setExpanded(!node.expanded);
+                    TREE_SHEET_HELPER.massOperationSheet(args.sheet, function () {
+                        let iCount = node.posterityCount(), i, child;
+                        for (i = 0; i < iCount; i++) {
+                            child = stdBillsTree.items[args.row + i + 1];
+                            args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
+                        }
+                        args.sheet.invalidateLayout();
+                    });
+                    args.sheet.repaint();
+                }
             });
             });
         }, function () {
         }, function () {
             that.stdBillsSpread.unbind(GC.Spread.Sheets.Events.CellDoubleClick);
             that.stdBillsSpread.unbind(GC.Spread.Sheets.Events.CellDoubleClick);

+ 19 - 0
web/building_saas/main/js/views/std_ration_lib.js

@@ -14,6 +14,7 @@ var rationLibObj = {
     checkSpread: function () {
     checkSpread: function () {
         if (!this.rationChapterSpread) {
         if (!this.rationChapterSpread) {
             this.rationChapterSpread = SheetDataHelper.createNewSpread($('#stdRationChapter')[0]);
             this.rationChapterSpread = SheetDataHelper.createNewSpread($('#stdRationChapter')[0]);
+            this.rationChapterSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, this.onChapterSpreadCellDoubleClick);
         }
         }
         if (!this.sectionRationsSpread) {
         if (!this.sectionRationsSpread) {
             this.sectionRationsSpread = SheetDataHelper.createNewSpread($('#stdSectionRations')[0]);
             this.sectionRationsSpread = SheetDataHelper.createNewSpread($('#stdSectionRations')[0]);
@@ -46,6 +47,7 @@ var rationLibObj = {
         var that = this;
         var that = this;
         var showRationChapterTree = function (datas) {
         var showRationChapterTree = function (datas) {
             var rationChapterTree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: false});
             var rationChapterTree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: false});
+            that.tree = rationChapterTree;
             var rationChapterTreeController = TREE_SHEET_CONTROLLER.createNew(rationChapterTree, that.rationChapterSpread.getActiveSheet(), that.rationChapterTreeSetting);
             var rationChapterTreeController = TREE_SHEET_CONTROLLER.createNew(rationChapterTree, that.rationChapterSpread.getActiveSheet(), that.rationChapterTreeSetting);
             rationChapterTree.loadDatas(datas);
             rationChapterTree.loadDatas(datas);
             rationChapterTreeController.showTreeData();
             rationChapterTreeController.showTreeData();
@@ -67,6 +69,23 @@ var rationLibObj = {
             showRationChapterTree([]);
             showRationChapterTree([]);
         });
         });
     },
     },
+    //双击隐藏显示
+    onChapterSpreadCellDoubleClick: function (sender, args) {
+        let me = rationLibObj;
+        let node = me.tree.items[args.row];
+        if (!node || node.children.length === 0)
+            return;
+        node.setExpanded(!node.expanded);
+        TREE_SHEET_HELPER.massOperationSheet(args.sheet, function () {
+            let iCount = node.posterityCount(), i, child;
+            for (i = 0; i < iCount; i++) {
+                child = me.tree.items[args.row + i + 1];
+                args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
+            }
+            args.sheet.invalidateLayout();
+        });
+        args.sheet.repaint();
+    },
     setTagForHint: function (datas) {
     setTagForHint: function (datas) {
         let sheet = this.sectionRationsSpread.getActiveSheet();
         let sheet = this.sectionRationsSpread.getActiveSheet();
         sheet.suspendPaint();
         sheet.suspendPaint();

+ 7 - 6
web/building_saas/main/js/views/zlfb_view.js

@@ -68,7 +68,6 @@ let zlfb_object={
         let resort = $('#bill_resort').prop('checked'),recode=$('#bill_recode').prop('checked'),first=$('#bill_first').prop('checked');
         let resort = $('#bill_resort').prop('checked'),recode=$('#bill_recode').prop('checked'),first=$('#bill_first').prop('checked');
         let second =$('#bill_second').prop('checked'), third =$('#bill_third').prop('checked');
         let second =$('#bill_second').prop('checked'), third =$('#bill_third').prop('checked');
         let needSelf = first==true||second==true||third==true;//需要补充分部节点;
         let needSelf = first==true||second==true||third==true;//需要补充分部节点;
-        $.bootstrapLoading.start();
         if(me.sectionInfo){
         if(me.sectionInfo){
             let FX_nodes =me.sectionInfo.FX_nodes,fxMap = me.sectionInfo.fxMap,FB_nodes =me.sectionInfo.FB_nodes;
             let FX_nodes =me.sectionInfo.FX_nodes,fxMap = me.sectionInfo.fxMap,FB_nodes =me.sectionInfo.FB_nodes;
             let codeMap = {},sectionNodeMap={},allNewNode=[],updateData={},newDataMap={};
             let codeMap = {},sectionNodeMap={},allNewNode=[],updateData={},newDataMap={};
@@ -145,8 +144,6 @@ let zlfb_object={
                 }
                 }
             };
             };
             me.submitRequest(newDataMap,allNewNode,updateData,FBFX,controller);
             me.submitRequest(newDataMap,allNewNode,updateData,FBFX,controller);
-        }else {
-            $.bootstrapLoading.end();
         }
         }
     },
     },
     addSubNode:function (parentNode,oldChildren,allNewNode,controller) {
     addSubNode:function (parentNode,oldChildren,allNewNode,controller) {
@@ -243,7 +240,9 @@ let zlfb_object={
         }
         }
         updateData.projectID = FBFX.data.projectID;
         updateData.projectID = FBFX.data.projectID;
         updateData.user_id = userID;
         updateData.user_id = userID;
+        $.bootstrapLoading.start();
         CommonAjax.post('/bills/reorganizeFBFX',updateData,function (data) {
         CommonAjax.post('/bills/reorganizeFBFX',updateData,function (data) {
+            $.bootstrapLoading.end();
             //更新前端缓存
             //更新前端缓存
             let billDatas = projectObj.project.Bills.datas;
             let billDatas = projectObj.project.Bills.datas;
             let quantity_detail_datas = projectObj.project.quantity_detail.datas;
             let quantity_detail_datas = projectObj.project.quantity_detail.datas;
@@ -278,9 +277,11 @@ let zlfb_object={
                 });
                 });
             }
             }
             cbTools.refreshFormulaNodes();
             cbTools.refreshFormulaNodes();
-            //重新计算
-            projectObj.project.Bills.getEngineeringCostNode(controller).changed = true;
-            projectObj.project.calcProgram.calcAllNodesAndSave();
+            projectObj.project.installation_fee.calcInstallationFee(function () {
+                //重新计算
+                projectObj.project.Bills.getEngineeringCostNode(controller).changed = true;
+                projectObj.project.calcProgram.calcAllNodesAndSave();
+            });
         },function () {
         },function () {
             //errorCallback
             //errorCallback
         });
         });

+ 2 - 3
web/users/html/login.html

@@ -17,15 +17,14 @@
             <h1 class="d-flex justify-content-center">Smartcost</h1>
             <h1 class="d-flex justify-content-center">Smartcost</h1>
             <h4 class="d-flex justify-content-center mb-2">用户登录</h4>
             <h4 class="d-flex justify-content-center mb-2">用户登录</h4>
             <div class="form-group">
             <div class="form-group">
-                <input id="inputEmail" class="form-control " name="inputEmail" placeholder="通行账号 邮箱/手机" autofocus="" value="laiku123@qq.com
-" />
+                <input id="inputEmail" class="form-control " name="inputEmail" placeholder="通行账号 邮箱/手机" autofocus="" value="laiku123@qq.com" />
             </div>
             </div>
             <div class="form-group">
             <div class="form-group">
                 <input id="inputPassword" class="form-control " name="inputPassword" placeholder="输入密码" type="password" value="19930523" />
                 <input id="inputPassword" class="form-control " name="inputPassword" placeholder="输入密码" type="password" value="19930523" />
             </div>
             </div>
             <div class="form-group" id="error-tips" style="display: none;">
             <div class="form-group" id="error-tips" style="display: none;">
                 <div class="alert alert-danger" role="alert">
                 <div class="alert alert-danger" role="alert">
-                    <strong>登录失败</strong> <span id="message"</span>
+                    <strong>登录失败</strong> <span id="message"></span>
                 </div>
                 </div>
             </div>
             </div>
             <div class="form-group">
             <div class="form-group">