Kaynağa Gözat

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

TonyKang 7 yıl önce
ebeveyn
işleme
bd4a5a632c
63 değiştirilmiş dosya ile 1477 ekleme ve 3743 silme
  1. 19 0
      Dockerfile_test
  2. 1 0
      config/gulpConfig.js
  3. 6 0
      modules/bills_lib/controllers/bills_lib_controllers.js
  4. 3 0
      modules/bills_lib/controllers/bills_permissionController.js
  5. 88 0
      modules/bills_lib/models/bills_lib_interfaces.js
  6. 2 0
      modules/bills_lib/routes/bills_lib_routes.js
  7. 19 1
      modules/fee_rates/controllers/fee_rates_controller.js
  8. 9 3
      modules/fee_rates/facade/fee_rates_facade.js
  9. 1 6
      modules/fee_rates/routes/fee_rates_route.js
  10. 1 1
      modules/glj/controllers/glj_controller.js
  11. 6 4
      modules/glj/models/glj_list_model.js
  12. 2 0
      modules/glj/models/schemas/unit_price.js
  13. 1 0
      modules/glj/models/unit_price_model.js
  14. 2 2
      modules/main/controllers/labour_coe_controller.js
  15. 87 0
      modules/main/facade/calc_program_facade.js
  16. 29 11
      modules/main/facade/labour_coe_facade.js
  17. 2 0
      modules/main/models/bills.js
  18. 44 0
      modules/main/models/calc_program_model.js
  19. 0 0
      modules/main/models/labour_coe_model.js
  20. 7 2
      modules/main/models/proj_setting_model.js
  21. 4 2
      modules/main/models/project.js
  22. 3 2
      modules/main/models/project_consts.js
  23. 9 1
      modules/main/models/schemas/proj_setting.js
  24. 4 0
      modules/pm/models/project_model.js
  25. 4 4
      modules/ration_glj/controllers/ration_glj_controller.js
  26. 7 3
      modules/ration_glj/facade/glj_calculate_facade.js
  27. 47 7
      modules/ration_glj/facade/ration_glj_facade.js
  28. 1 0
      modules/ration_glj/models/ration_glj.js
  29. 2 0
      modules/ration_glj/models/ration_glj_temp.js
  30. 31 0
      modules/ration_repository/controllers/search_controller.js
  31. 13 2
      modules/ration_repository/models/ration_item.js
  32. 1 0
      modules/ration_repository/routes/ration_front_end_routes.js
  33. 1 2
      modules/ration_repository/routes/ration_rep_routes.js
  34. 3 3
      public/calc_util.js
  35. 2 1
      server.js
  36. 1 0
      web/building_saas/complementary_glj_lib/js/components.js
  37. 2 1
      web/building_saas/css/main.css
  38. 6 1
      web/building_saas/glj/js/common_spread.js
  39. 13 5
      web/building_saas/glj/js/project_glj_spread.js
  40. 3 0
      web/building_saas/main/html/calc_program_manage.html
  41. 49 5
      web/building_saas/main/html/main.html
  42. 21 4
      web/building_saas/main/js/controllers/project_controller.js
  43. 83 19
      web/building_saas/main/js/models/bills.js
  44. 24 3597
      web/building_saas/main/js/models/calc_program.js
  45. 27 3
      web/building_saas/main/js/models/fee_rate.js
  46. 2 1
      web/building_saas/main/js/models/main_consts.js
  47. 12 7
      web/building_saas/main/js/models/project.js
  48. 58 2
      web/building_saas/main/js/models/ration.js
  49. 15 4
      web/building_saas/main/js/models/ration_glj.js
  50. 7 5
      web/building_saas/main/js/views/calc_program_manage.js
  51. 3 2
      web/building_saas/main/js/views/character_content_view.js
  52. 110 0
      web/building_saas/main/js/views/confirm_modal.js
  53. 307 0
      web/building_saas/main/js/views/fee_rate_view.js
  54. 33 9
      web/building_saas/main/js/views/glj_view.js
  55. 5 2
      web/building_saas/main/js/views/main_tree_col.js
  56. 4 0
      web/building_saas/main/js/views/options_view.js
  57. 55 5
      web/building_saas/main/js/views/project_property_labour_coe_view.js
  58. 111 11
      web/building_saas/main/js/views/project_view.js
  59. 16 2
      web/building_saas/main/js/views/std_bills_lib.js
  60. 39 0
      web/building_saas/main/js/views/std_ration_lib.js
  61. 3 1
      web/building_saas/main/js/views/sub_view.js
  62. 7 0
      web/building_saas/pm/js/pm_main.js
  63. BIN
      web/dest/css/img/feeRate_btn.jpg

+ 19 - 0
Dockerfile_test

@@ -0,0 +1,19 @@
+FROM constructioncost:1.0
+
+WORKDIR home/ConstructionCost
+
+RUN git pull http://192.168.1.12:3000/SmartCost/ConstructionCost master
+
+RUN cnpm install -g gulp
+
+RUN cnpm install
+
+RUN gulp build
+
+EXPOSE 6060
+
+ENV NODE_ENV=qa
+
+ENTRYPOINT babel-node server.js
+
+

+ 1 - 0
config/gulpConfig.js

@@ -93,6 +93,7 @@ module.exports = {
         'web/building_saas/main/js/models/quantity_detail.js',
         'web/building_saas/main/js/views/glj_view_contextMenu.js',
         'web/building_saas/main/js/views/calc_program_view.js',
+        'web/building_saas/main/js/views/confirm_modal.js',
         'public/web/treeDataHelper.js',
         'public/web/ztree_common.js',
         'public/web/rpt_tpl_def.js',

+ 6 - 0
modules/bills_lib/controllers/bills_lib_controllers.js

@@ -239,6 +239,12 @@ module.exports = {
         billsLibDao.edUpdateItem(data, function(err, message, id){
             callback(req, res, err, message, id);
         })
+    },
+    getStdBillsByCode: function (req, res) {
+        let data = JSON.parse(req.body.data);
+        billsLibDao.getStdBillsByCode(data, function (err, message, data) {
+            callback(req, res, err, message, data)
+        });
     }
 }
 

+ 3 - 0
modules/bills_lib/controllers/bills_permissionController.js

@@ -53,6 +53,9 @@ class billsPermContr extends baseController{
     deleteBills(req, res){
         billsController.deleteBills(req, res);
     }
+    getStdBillsByCode(req, res) {
+        billsController.getStdBillsByCode(req, res);
+    }
 
 }
 

+ 88 - 0
modules/bills_lib/models/bills_lib_interfaces.js

@@ -3031,5 +3031,93 @@ billsLibDao.prototype.edUpdateItem = function(data, callback){
 };
 //
 
+billsLibDao.prototype.getStdBillsByCode = function (data, callback) {
+    let findData = function (value, field, Array) {
+        let i = 0;
+        for (i = 0; i < Array.length; i++) {
+            if (value[field] === Array[i][field]) {
+                return Array[i];
+            }
+        }
+        return null;
+    };
+    let MergeData = function (arr) {
+        let result = "", count = 0;
+        for(let i = 0; i < arr.length; i++){
+            if(arr[i].isChecked === true){
+                count += 1;
+                if (count === 1) {
+                    result += count + ". " + arr[i].content;
+                } else {
+                    result += "\n" + count + ". " + arr[i].content;
+                }
+            }
+        }
+        return result;
+    }
+    async.waterfall([
+        function (callback) {
+            Bills.findOne({'billsLibId': data.billsLibId, 'code': data.code, 'deleted': false}, "-_id", function (err, result) {
+                callback(err, JSON.parse(JSON.stringify(result)));
+            });
+        },
+        function (bills, callback) {
+            if (bills) {
+                ItemCharacter.find({'billsLibId': data.billsLibId, 'deleted': false}, '-_id', function (err, result) {
+                    if (err) {
+                        callback(err, bills);
+                    } else {
+                        bills.itemCharacter = [];
+                        if (result && bills && bills.items) {
+                            for (let item of bills.items) {
+                                let itemData = findData(item, 'id', result);
+                                if (itemData) {
+                                    bills.itemCharacter.push(JSON.parse(JSON.stringify(itemData)));
+                                }
+                            }
+                        }
+                        bills.itemCharacterText = MergeData(bills.itemCharacter);
+                        callback(err, bills);
+                    }
+                });
+            } else {
+                callback(null, bills);
+            }
+            
+        },
+        function (bills, callback) {
+            if (bills) {
+                JobContent.find({'billsLibId': data.billsLibId, 'deleted': false}, '-_id', function (err, result) {
+                    if (err) {
+                        callback(err, bills);
+                    } else {
+                        bills.jobContent = [];
+                        if (result && bills && bills.jobs) {
+                            for (let job of bills.jobs) {
+                                let jobData = findData(job, 'id', result);;
+                                if (jobData) {
+                                    jobData = JSON.parse(JSON.stringify(jobData));
+                                    jobData.isChecked = true;
+                                    bills.jobContent.push(jobData);
+                                }
+                            }
+                        }
+                        bills.jobContentText = MergeData(bills.jobContent);
+                        callback(err, bills);
+                    }
+                });
+            } else {
+                callback(null, bills);
+            }
+        }
+    ], function (err, result) {
+        if (err) {
+            callback(1, err, null);
+        } else {
+            callback(0, err, result);
+        }
+    });
+};
+
 
 module.exports = new billsLibDao();

+ 2 - 0
modules/bills_lib/routes/bills_lib_routes.js

@@ -65,6 +65,8 @@ module.exports =function (app) {
     billsRouter.post("/edCreateItem", itemsContr.init, itemsContr.edCreateItem);
     billsRouter.post("/edUpdateItem", itemsContr.init, itemsContr.edUpdateItem);
 
+    billsRouter.post('/getStdBillsByCode', billsContr.init, billsContr.getStdBillsByCode);
+
     app.use("/stdBillsEditor", billsRouter);
 
 }

+ 19 - 1
modules/fee_rates/controllers/fee_rates_controller.js

@@ -53,7 +53,8 @@ module.exports = {
     checkFeeRateName:checkFeeRateName,
     getChangeInfo:getChangeInfo,
     changeFeeRateFileFromCurrent:changeFeeRateFileFromCurrent,
-    changeFeeRateFileFromOthers:changeFeeRateFileFromOthers
+    changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
+    setFeeRateToBill:setFeeRateToBill
 }
 
 function libNames(req, res) {
@@ -175,4 +176,21 @@ async function changeFeeRateFileFromOthers(req, res) {
         result.message = err.message;
     }
     res.json(result);
+}
+
+
+async function setFeeRateToBill(req,res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        let uresult= await feeRateFacde.setFeeRateToBill(data);
+        console.log(uresult);
+    }catch (err){
+        console.log(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
 }

+ 9 - 3
modules/fee_rates/facade/fee_rates_facade.js

@@ -7,7 +7,7 @@ let mongoose = require('mongoose');
 let feeRateModel = mongoose.model('fee_rates');
 let feeRateFileModel = mongoose.model('fee_rate_file');
 let std_fee_rate_lib_model = mongoose.model('std_fee_rate_libs');
-let project_feerate_temp = mongoose.model('project_feerate_temp');
+let billModel=require('../../main/models/bills');//mongoose.model('bills');
 let projectsModel = require("../../pm/models/project_schema");
 let consts = require('../../main/models/project_consts');
 let _=require("lodash");
@@ -26,7 +26,8 @@ module.exports={
     changeFeeRateFileFromCurrent:changeFeeRateFileFromCurrent,
     changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
     newFeeRateFile:newFeeRateFile,
-    getFeeRatesByProject:getFeeRatesByProject
+    getFeeRatesByProject:getFeeRatesByProject,
+    setFeeRateToBill:setFeeRateToBill
 };
 let operationMap={
     'ut_create':create_fee_rate,
@@ -202,7 +203,6 @@ async function getFeeRateData(projectID) {
                 feeRateData._doc.rates = feeRate?feeRate.rates:[];
                 //
                 feeRateData._doc.usageProjects=await getUsageProjects(feeRateData.ID);
-                console.log(feeRateData._doc);
                 result.datas = feeRateData;
             }
         }else {
@@ -347,6 +347,12 @@ async function getFeeRatesByProject(rootProjectID) {
        return feeRates;
 }
 
+async function setFeeRateToBill(data){
+    data=JSON.parse(data);
+    let result  = await billModel.model.findOneAndUpdate(data.query,data.doc);
+    return result
+}
+
 async function changeFeeRateFileFromCurrent(jdata){
     let data = JSON.parse(jdata);
     let newFeeRateFile=data.newFeeRateFile;

+ 1 - 6
modules/fee_rates/routes/fee_rates_route.js

@@ -18,12 +18,7 @@ module.exports = function (app) {
     frRouter.post('/getChangeInfo', frController.getChangeInfo);
     frRouter.post('/changeFeeRateFileFromCurrent', frController.changeFeeRateFileFromCurrent);
     frRouter.post('/changeFeeRateFileFromOthers', frController.changeFeeRateFileFromOthers);
-
-    //
-/*    frRouter.post('/getLibNames', frController.libNames);
-    frRouter.post('/getLibFeeRates', frController.libFeeRates);
-    frRouter.post('/getProjectFeeRates', frController.projectFeeRates);
-    frRouter.post('/updateProjectFeeRate', frController.projectFeeUpdateRate);*/
+    frRouter.post('/setFeeRateToBill', frController.setFeeRateToBill);
 
     app.use('/feeRates',frRouter);
 }

+ 1 - 1
modules/glj/controllers/glj_controller.js

@@ -109,7 +109,7 @@ class GLJController extends BaseController {
         try {
             // 可编辑的字段
             let editableField = ['is_evaluate', 'unit_price.market_price', 'is_adjust_price', 'mix_ratio.consumption',
-                'supply'];
+                'supply', 'supply_quantity'];
             if (editableField.indexOf(field) < 0) {
                 throw '对应字段不能编辑';
             }

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

@@ -104,7 +104,7 @@ class GLJListModel extends BaseModel {
             let quantityList = {};
             // 整理数据
             for (let tmp of quantityData) {
-                let tmpNum = parseInt(tmp.rationQuantity);
+                let tmpNum = parseFloat(tmp.rationQuantity);
                 tmpNum = isNaN(tmpNum) ? 1 : tmpNum;
                 if (quantityList[tmp.projectGLJID] === undefined) {
                     quantityList[tmp.projectGLJID] = tmp.quantity * tmpNum;
@@ -204,6 +204,7 @@ class GLJListModel extends BaseModel {
             glj.quantity = quantityList[projectGljId] !== undefined ? quantityList[projectGljId] : 0;
             glj.quantity = totalComposition[glj.code] !== undefined ? totalComposition[glj.code] : glj.quantity;
             glj.quantity = compositionConsumption[gljId] !== undefined ?  glj.quantity + compositionConsumption[gljId] : glj.quantity;
+            glj.quantity = parseFloat(glj.quantity).toFixed(3);
 
             // 组成物数据
             gljList[index].ratio_data = mixRatioData[gljId] !== undefined ? mixRatioData[gljId] : [];
@@ -421,7 +422,7 @@ class GLJListModel extends BaseModel {
     async compositionInit(data, unitPriceFileId) {
         let gljId = data.glj_id === undefined ? 0 : data.glj_id;
         let projectId = data.project_id === undefined ? 0 : data.project_id;
-        if (code === 0 || projectId === 0) {
+        if (gljId === 0 || projectId === 0) {
             throw '参数错误';
         }
         let fromTable = data.from === undefined ? 'std' : data.from;
@@ -481,7 +482,8 @@ class GLJListModel extends BaseModel {
                 code: tmp.code,
                 name: tmp.name,
                 unit_price_file_id: unitPriceFileId,
-                type: tmp.gljType
+                type: tmp.gljType,
+                short_name: tmp.shortName === undefined ? '' : tmp.shortName,
             };
             unitPriceInsertData.push(unitPriceData);
         }
@@ -521,7 +523,7 @@ class GLJListModel extends BaseModel {
             }
 
             // 查找对应的项目工料机数据
-            let [gljData, compositionList] = await this.getCompositionGLJList(projectGLJData.code, projectGLJData.project_id);
+            let [gljData, compositionList] = await this.getCompositionGLJList(projectGLJData.glj_id, projectGLJData.project_id);
 
             if (gljData.length <= 0) {
                 throw '没有对应的组成物项目工料机';

+ 2 - 0
modules/glj/models/schemas/unit_price.js

@@ -28,6 +28,8 @@ let modelSchema = {
     },
     // 类型
     type: Number,
+    // 类型简称
+    short_name: String,
     // 单价文件表id
     unit_price_file_id: Number,
 };

+ 1 - 0
modules/glj/models/unit_price_model.js

@@ -115,6 +115,7 @@ class UnitPriceModel extends BaseModel {
             unit_price_file_id: unitPriceFileId,
             name: data.name,
             type: data.type,
+            short_name: data.shortName !== undefined ? data.shortName : ''
         };
 
         let addPriceResult = await this.add(insertData);

+ 2 - 2
modules/main/controllers/labour_coe_controller.js

@@ -26,10 +26,10 @@ async function getProjectLabourCoe(req, res) {
 };
 
 async function getStdLabourCoe(req, res) {
-    let result={error: 0};
+    let result = {error: 0, message: '', data: null};
 
     try {
-        let stdLC = await labourCoeFacade.getStdLabourCoe(req.body.data.libID);
+        let stdLC = await labourCoeFacade.getStdLabourCoe(req.body.ID);
         result.data= stdLC;
     }catch (err){
         console.log(err);

+ 87 - 0
modules/main/facade/calc_program_facade.js

@@ -0,0 +1,87 @@
+/**
+ * Created by CSL on 2017-10-22.
+ */
+
+const uuidV1 = require('uuid/v1');
+let logger = require("../../../logs/log_helper").logger;
+let mongoose = require('mongoose');
+let stdCalcProgramsModel = mongoose.model('std_calc_programs');
+let projectCalcProgramsModel = mongoose.model('calc_programs');
+let EngineeringLibModel = require("../../users/models/engineering_lib_model");
+let _=require("lodash");
+let consts = require('../models/project_consts');
+let projectConsts = consts.projectConst;
+
+module.exports = {
+    newProjectCalcProgramFile: newProjectCalcProgramFile,
+    getProjectCalcProgramFile: getProjectCalcProgramFile,
+    getStdCalcProgramFile: getStdCalcProgramFile,
+    getData: getData,
+    save: save
+};
+
+async function newProjectCalcProgramFile(data) {
+    logger.info(`Create new CalcProgram file for project : ${data.ID}`);
+    let rst = null;
+    let egnrModel = new EngineeringLibModel();
+    let egnr = await egnrModel.getEngineering(data.property.engineering_id);
+    if(!egnr) return rst;
+    let valid_CP_libs = egnr._doc.program_lib;
+    if (valid_CP_libs == undefined  || valid_CP_libs.length == 0) return rst;
+    // 绑定多个计算程序标准文件时,默认取第一个作为标准模板。
+    let stdCP = await getStdCalcProgramFile(valid_CP_libs[0].id);
+    let doc={
+        ID: uuidV1(),
+        projectID: data.ID,
+        name: data.name,
+        libID: stdCP.ID,
+        libName: stdCP.libName,
+        templates: stdCP.templates
+    };
+    await projectCalcProgramsModel.create(doc);
+    rst = {ID: doc.ID, name: doc.name};
+    return rst;
+};
+
+async function getProjectCalcProgramFile(ID) {
+    let projLC = await projectCalcProgramsModel.findOne({ID:ID});
+    return projLC;
+};
+
+async function getStdCalcProgramFile(libID) {
+    let stdLC = await stdCalcProgramsModel.findOne({ID:libID});
+    return stdLC;
+};
+
+// 统一的 getData() 方法供project调用
+function getData(projectID, callback) {
+    projectCalcProgramsModel.findOne({projectID: projectID}, '-_id', function (err, datas) {
+        if (!err) {
+            // 旧项目没有计算程序文件,默认给它生成一个。
+            if (!datas) {
+                logger.info(`Create a calcProgram file for old project : ${projectID}`);
+                getStdCalcProgramFile(1).then(function (stdCP) {
+                    let doc = {
+                        ID: uuidV1(),
+                        projectID: projectID,
+                        name: '[旧项目补计算程序文件]',
+                        libID: stdCP.ID,
+                        libName: stdCP.libName,
+                        templates: stdCP.templates
+                    };
+                    projectCalcProgramsModel.create(doc);
+                    callback(0, projectConsts.CALC_PROGRAM, stdCP);
+                });
+            } else {
+                callback(0, projectConsts.CALC_PROGRAM, datas);
+            };
+        } else {
+            callback(1, projectConsts.CALC_PROGRAM, null);
+        };
+    });
+};
+
+// 统一的 save() 方法供project调用
+function save (user_id, datas, callback) {
+    projectCalcProgramsModel.update({"projectID": 553}, {"libName":"goo—test"}, callback(null, {data: 'test'}));
+}

+ 29 - 11
modules/main/facade/labour_coe_facade.js

@@ -22,11 +22,12 @@ module.exports = {
 
 async function newProjectLabourCoe(data) {
     logger.info(`Create new LabourCoe file for project : ${data.ID}`);
-    let valid_LC_libs = [];
-    let egnrID = data.property.engineering_id;
+    let rst = null;
     let egnrModel = new EngineeringLibModel();
-    let egnr = await egnrModel.getEngineering(egnrID);
-    if(egnr){ valid_LC_libs = egnr._doc.artificial_lib };
+    let egnr = await egnrModel.getEngineering(data.property.engineering_id);
+    if(!egnr) return rst;
+    let valid_LC_libs = egnr._doc.artificial_lib;
+    if (valid_LC_libs == undefined  || valid_LC_libs.length == 0) return rst;
     // 绑定多个人工系数标准文件时,默认取第一个作为标准模板。
     let stdLC = await getStdLabourCoe(valid_LC_libs[0].id);
     let doc={
@@ -38,8 +39,8 @@ async function newProjectLabourCoe(data) {
         coes: stdLC.coes
     };
     await projectLabourCoesModel.create(doc);
-    let newLC = {ID: doc.ID, name: doc.name};
-    return newLC;
+    rst = {ID: doc.ID, name: doc.name};
+    return rst;
 };
 
 async function getProjectLabourCoe(ID) {
@@ -54,13 +55,30 @@ async function getStdLabourCoe(libID) {
 };
 
 // 统一的 getData() 方法供project调用
-function getData (projectID, callback) {
-    projectLabourCoesModel.findOne({projectID: projectID}, '-_id', function(err, datas) {
-            if (!err) {
-                callback(0, projectConsts.LABOUR_COE, datas);
+function getData(projectID, callback) {
+    projectLabourCoesModel.findOne({projectID: projectID}, '-_id', function (err, datas) {
+        if (!err) {
+            // 旧项目没有人工系数文件,默认给它生成一个。
+            if (!datas) {
+                logger.info(`Create a LabourCoe file for old project : ${projectID}`);
+                getStdLabourCoe(1).then(function (stdLC) {
+                    let doc = {
+                        ID: uuidV1(),
+                        projectID: projectID,
+                        name: '[旧项目补人工系数文件]',
+                        libID: stdLC.ID,
+                        libName: stdLC.libName,
+                        coes: stdLC.coes
+                    };
+                    projectLabourCoesModel.create(doc);
+                    callback(0, projectConsts.LABOUR_COE, stdLC);
+                });
             } else {
-                callback(1, projectConsts.LABOUR_COE, null);
+                callback(0, projectConsts.LABOUR_COE, datas);
             };
+        } else {
+            callback(1, projectConsts.LABOUR_COE, null);
+        };
     });
 };
 

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

@@ -26,6 +26,8 @@ let billsSchema = new Schema({
     name: String,
     unit: String,
     quantity: String, // Decimal
+    feeRateID:Number,
+    feeRate:String,
     isFromDetail:{type: Number,default:0},//1 true 0 false
     programID: Number,
     // 工程量计算规则

+ 44 - 0
modules/main/models/calc_program_model.js

@@ -0,0 +1,44 @@
+/**
+ * Created by CSL on 2017-10-22.
+ */
+let mongoose = require('mongoose');
+let Schema = mongoose.Schema;
+
+let calcItemSchema = new Schema({
+    ID: Number,
+    code: String,
+    name: String,
+    fieldName: String,
+    dispExpr: String,
+    expression: String,
+    compiledExpr: String,
+    statement: String,
+    feeRateID: Number,
+    feeRate: Number,
+    labourCoeID: Number
+},{versionKey:false, _id: false});
+
+let templateSchema = new Schema({
+    ID: Number,
+    name: String,
+    calcItems: [calcItemSchema]
+},{versionKey:false, _id: false});
+
+let stdCalcPrograms = new Schema({
+    ID: Number,
+    region: String,
+    libName: String,
+    templates: [templateSchema]
+},{versionKey:false, _id: false});
+
+let projectCalcPrograms = new Schema({
+    ID: String,
+    projectID: Number,
+    name: String,
+    libID: Number,
+    libName: String,
+    templates: [templateSchema]
+},{versionKey:false});
+
+mongoose.model('std_calc_programs', stdCalcPrograms, 'std_calc_programs');
+mongoose.model('calc_programs', projectCalcPrograms, 'calc_programs');

modules/main/models/labour_coe.js → modules/main/models/labour_coe_model.js


+ 7 - 2
modules/main/models/proj_setting_model.js

@@ -3,7 +3,7 @@
  */
 
 let baseModel = require('./base_model');
-import {default as projSettingSchema, collectionName as collectionName} from "./schemas/proj_setting";
+import {default as projSettingSchema, collectionName as collectionName, billsCalcModeConst as billsCalcModeConst} from "./schemas/proj_setting";
 
 class projSettingModel extends baseModel {
 
@@ -15,7 +15,12 @@ class projSettingModel extends baseModel {
     getData (projectID, callback) {
         this.model.findOne({"projectID": projectID}, '-_id', function (err, result) {
             if (!err) {
-                callback(0, collectionName, result);
+                let data = JSON.parse(JSON.stringify(result));
+                if (!data.billsCalcMode) {
+                    data.billsCalcMode = billsCalcModeConst.rationContent;
+                }
+                data.billsCalcModeConst = billsCalcModeConst;
+                callback(0, collectionName, data);
             } else {
                 callback(1, '查询数据失败。', null);
             }

+ 4 - 2
modules/main/models/project.js

@@ -12,7 +12,8 @@ var fee_rate_data = require('../../fee_rates/facade/fee_rates_facade');
 let projCounter = require('./proj_counter_model');
 let projSetting = require('./proj_setting_model');
 let volumePriceData = require('../../volume_price/models/volume_price_model');
-var labour_coe_data = require('../facade/labour_coe_facade');
+var labour_coe_facade = require('../facade/labour_coe_facade');
+var calc_program_facade = require('../facade/calc_program_facade');
 var consts = require('./project_consts');
 var projectConsts = consts.projectConst;
 var async = require("async");
@@ -30,7 +31,8 @@ moduleMap[projCounter.collectionName] = projCounter;
 moduleMap[projSetting.collectionName] = projSetting;
 moduleMap[volumePriceData.collectionName] = volumePriceData;
 moduleMap[projectConsts.FEERATE] = fee_rate_data;
-moduleMap[projectConsts.LABOUR_COE] = labour_coe_data;
+moduleMap[projectConsts.LABOUR_COE] = labour_coe_facade;
+moduleMap[projectConsts.CALC_PROGRAM] = calc_program_facade;
 
 var Project = function (){};
 

+ 3 - 2
modules/main/models/project_consts.js

@@ -15,7 +15,8 @@ let projectConst = {
     PROPERTIES: 'properties',
     VOLUMEPRICE: 'volume_price',
     FEERATE:'feeRate',
-    LABOUR_COE:'labour_coe'
+    LABOUR_COE:'labour_coe',
+    CALC_PROGRAM:'calc_program'
 };
 
 let projectConstList = [
@@ -41,4 +42,4 @@ let commonConst = {
     UT_DELETE: 'ut_delete'
 };
 
-module.exports = {projectConst: projectConst, commonConst: commonConst, projectConstList: projectConstList};
+module.exports = {projectConst: projectConst, commonConst: commonConst, projectConstList: projectConstList};

+ 9 - 1
modules/main/models/schemas/proj_setting.js

@@ -5,13 +5,21 @@
 let mongoose = require("mongoose");
 let Schema = mongoose.Schema;
 let collectionName = 'proj_setting';
+let billsCalcModeConst = {
+    rationContent: 0, rationPrice: 1, rationPriceConverse: 2, billsPrice: 3
+};
 let projSettingSchema = {
     projectID: Number,
     // 列设置
     main_tree_col: {
         type: Schema.Types.Mixed,
         default: {}
+    },
+    billsCalcMode: {
+        type: Number,
+        default: billsCalcModeConst.rationContent
+        // rationContent = 0, rationPrice = 1, rationPriceConverse = 2, billsPrice = 3
     }
 };
 let model = mongoose.model(collectionName, new Schema(projSettingSchema, {versionKey: false, collection: collectionName}));
-export {model as default, collectionName as collectionName};
+export {model as default, collectionName as collectionName, billsCalcModeConst as billsCalcModeConst};

+ 4 - 0
modules/pm/models/project_model.js

@@ -8,6 +8,7 @@ let newProjController = require('../controllers/new_proj_controller');
 let copyProjController = require('../controllers/copy_proj_controller');
 let feeRateFacade = require('../../fee_rates/facade/fee_rates_facade');
 let labourCoeFacade = require('../../main/facade/labour_coe_facade');
+let calcProgramFacade = require('../../main/facade/calc_program_facade');
 let logger = require("../../../logs/log_helper").logger;
 
 let Projects = require("./project_schema");
@@ -97,6 +98,9 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
                     // 新建人工系数文件 CSL, 2017.10.13
                     let lcFile = await labourCoeFacade.newProjectLabourCoe(data.updateData);
                     newProject.property.labourCoeFile = lcFile ? lcFile : null;
+                    // 新建计算程序文件 CSL, 2017.10.23
+                    let cpFile = await calcProgramFacade.newProjectCalcProgramFile(data.updateData);
+                    newProject.property.calcProgramFile = cpFile ? cpFile : null;
                 }
                 newProject.save(async function (err, result) {
                     if (!err && result._doc.projType === projectType.tender) {

+ 4 - 4
modules/ration_glj/controllers/ration_glj_controller.js

@@ -85,8 +85,8 @@ async function replaceGLJ(req, res){
         let data = req.body.data;
         data = JSON.parse(data);
         console.log(data);
-        let datas= await ration_glj_facade.replaceGLJ(data);
-        result.data=datas;
+        let rdata= await ration_glj_facade.replaceGLJ(data);
+        result.data=rdata;
     }catch (err){
         logger.err(err);
         result.error=1;
@@ -103,8 +103,8 @@ async function mReplaceGLJ(req, res){
         let data = req.body.data;
         data = JSON.parse(data);
         console.log(data);
-        let datas= await ration_glj_facade.mReplaceGLJ(data);
-        result.data=datas;
+        let mresult= await ration_glj_facade.mReplaceGLJ(data);
+        result.data=mresult;
     }catch (err){
         logger.err(err);
         result.error=1;

+ 7 - 3
modules/ration_glj/facade/glj_calculate_facade.js

@@ -135,8 +135,12 @@ function calculateAss(quantity,assList,glj) {
 }
 
 function generateAdjustState(glj,coeList,adjustState,index) {
-   //替换工料机 and  添加工料机
-
+   //替换工料机 and 添加工料机
+    if(glj._doc.createType=='replace'){
+        adjustState.push({index:stateSeq.replase,content:glj.rcode+'换'+glj.code});
+    }else if(glj._doc.createType=='add'){
+        adjustState.push({index:stateSeq.add,content:'添'+glj.code+'量'+glj.quantity});
+    }
     // to do
 
   //标准附注条件调整 + 自定义乘系数
@@ -153,7 +157,7 @@ function generateAdjustState(glj,coeList,adjustState,index) {
     }
 
     //自定义消耗量
-    if(glj._doc.hasOwnProperty('customQuantity')){
+    if(glj._doc.createType!='add'&&glj._doc.hasOwnProperty('customQuantity')){
         if(glj.customQuantity!==null){
             adjustState.push({index:stateSeq.cusQuantity,content:glj.code+'量'+glj.customQuantity});
         }

+ 47 - 7
modules/ration_glj/facade/ration_glj_facade.js

@@ -157,6 +157,7 @@ function createNewRecord(ration_glj) {
     newRecoed.from=ration_glj.from?ration_glj.from:undefined;
     newRecoed.createType=ration_glj.createType?ration_glj.createType:undefined;
     newRecoed.shortName = ration_glj.shortName;
+    newRecoed.billsItemID=ration_glj.billsItemID,
     newRecoed.type = ration_glj.type;
     newRecoed.repositoryId = ration_glj.repositoryId;
     newRecoed.projectGLJID=ration_glj.projectGLJID;
@@ -425,15 +426,16 @@ function deleteByBill(user_id,datas,callback) {
 
 
 function  deleteByID(datas,callback){
-    ration_glj.deleteOne(datas.query,(err,result)=>{
-        if(err){
-            callback(err,'');
+    deleteAndUpdateState(datas).then(function (result) {
+        if(result.err){
+            callback(result.err,'');
         }else {
             let returndata ={
                 moduleName:'ration_glj',
                 data:{
                     updateTpye:commonConsts.UT_DELETE,
                     query:datas.query,
+                    adjustState:result.adjustState
                 }
             }
             callback(null,returndata)
@@ -441,6 +443,20 @@ function  deleteByID(datas,callback){
     })
 }
 
+async  function deleteAndUpdateState(datas) {
+    let result={
+        err:null
+    }
+    try {
+        await ration_glj.deleteOne(datas.query);
+        let stateResult =  await glj_calculate_facade.calculateQuantity({projectID:datas.query.projectID,rationID:datas.doc.rationID});
+        result.adjustState=stateResult.adjustState;
+    }catch (err){
+        result.err=err;
+    }
+    return result;
+}
+
 function startingTask(processName){
     return function(asyncCallBack){
         var result = {
@@ -607,6 +623,7 @@ function getGLJSearchInfo(ration_glj) {
         project_id: ration_glj.projectID,
         code: ration_glj.code,
         name: ration_glj.name,
+        shortName:ration_glj.shortName,
         specs: ration_glj.specs,
         unit: ration_glj.unit,
         type: ration_glj.type,
@@ -634,14 +651,18 @@ async function addGLJ(rgList) {
        newRecodes.push(createNewRecord(g));
    }
     await ration_glj.insertMany(newRecodes);
+
+    let stateResult =  await glj_calculate_facade.calculateQuantity({projectID:rgList[0].projectID,rationID:rgList[0].rationID});
     let result={
         newRecodes:newRecodes,
-        showData:rgList
+        showData:rgList,
+        adjustState:stateResult.adjustState
     }
    return result;
 }
 
 async function replaceGLJ(data) {
+    let rdata={};
     let projectGljModel = new GLJListModel();
     let result = await projectGljModel.addList(getGLJSearchInfo(data));
     data.marketPrice=result.unit_price.market_price;
@@ -650,9 +671,13 @@ async function replaceGLJ(data) {
     data.projectGLJID=result.id;
     data.isEstimate=result.is_evaluate;
     let updateResult=await ration_glj.findOneAndUpdate({ID:data.ID,projectID:data.projectID},data);
-    return data
+    let stateResult =  await glj_calculate_facade.calculateQuantity({projectID:data.projectID,rationID:data.rationID});
+    rdata.data=data;
+    rdata.adjustState=stateResult.adjustState;
+    return rdata;
 }
 async function mReplaceGLJ(data) {
+    let mresult={};
     let projectGljModel = new GLJListModel();
     let result = await projectGljModel.addList(getGLJSearchInfo(data.doc));
     data.doc.marketPrice=result.unit_price.market_price;
@@ -660,11 +685,26 @@ async function mReplaceGLJ(data) {
     data.doc.basePrice=result.unit_price.base_price;
     data.doc.projectGLJID=result.id;
     data.doc.isEstimate=result.is_evaluate;
+    let rationList=await ration_glj.distinct('rationID',data.query);
     let updateResult=await ration_glj.update(data.query,data.doc,{multi: true});
-    console.log(updateResult);
-    return data
+    let stateList= await changAdjustState(data,rationList);
+    mresult.data=data;
+    mresult.stateList=stateList;
+    return mresult
 }
 
+async function changAdjustState(data,rationList) {
+    let stateList=[];
+    for(let r of rationList){
+      let stateResult = await glj_calculate_facade.calculateQuantity({projectID:data.query.projectID,rationID:r});
+      stateList.push({rationID:r,adjustState:stateResult.adjustState});
+    }
+    return stateList;
+}
+
+async function testError() {
+  throw  new Error('test Error');
+}
 
 function getData(projectID, callback) {
     ration_glj.find({'projectID':projectID},(err,datas)=>{

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

@@ -17,6 +17,7 @@ var ration_glj = new Schema({
     specs:String,
     unit:String,
     shortName:String,
+    billsItemID: Number,
     type:Number,
     quantity:Number,
     customQuantity:Number,

+ 2 - 0
modules/ration_glj/models/ration_glj_temp.js

@@ -132,6 +132,8 @@ let billsSchema = new Schema({
     name: String,
     unit: String,
     quantity: String, // Decimal
+    feeRateID:String,
+    feeRate:String,
     isFromDetail:{type: Number,default:0},//1 true 2 false
     programID: Number,
     comments: String,

+ 31 - 0
modules/ration_repository/controllers/search_controller.js

@@ -3,6 +3,7 @@
  */
 var rationItem = require('../models/ration_item');
 let rationChapter = require('../models/ration_section_tree');
+let asyncTool = require('async');
 var callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
 };
@@ -32,5 +33,35 @@ module.exports = {
                 callback(req, res, 0, '', rst);
             }
         });
+    },
+    matchRation: function (req, res) {
+        let rId = req.body.rationLibId, code = req.body.code;
+        asyncTool.waterfall([
+            function (callback) {
+                rationItem.matchRation(rId, code, callback);
+            },
+            function (ration, callback) {
+                if (ration) {
+                    rationChapter.getRationChapter(rId, ration.sectionId).then(function(result, err) {
+                        if (!err) {
+                            ration.chapter = JSON.parse(JSON.stringify(result));
+                            callback(err, ration);
+                        } else {
+                            callback(err, ration);
+                        }
+                    }).catch(
+
+                    );
+                } else {
+                    callback(null, ration);
+                }
+            }
+        ], function (err, result) {
+            if (err) {
+                callback(req, res, 1, err, null);
+            } else {
+                callback(req, res, 0, err, result);
+            }
+        });
     }
 };

+ 13 - 2
modules/ration_repository/models/ration_item.js

@@ -113,8 +113,19 @@ rationItemDAO.prototype.findRation = function (repId, keyword, callback) {
         } else {
             callback(false, '', data);
         }
-    })
-}
+    });
+};
+
+rationItemDAO.prototype.matchRation = function (repId, keyword, callback) {
+    let filter = {
+        'rationRepId': repId,
+        'code': keyword,
+        '$or': [{'isDeleted': {"$exists":false}}, {'isDeleted': null}, {'isDeleted': false}]
+    };
+    rationItemModel.findOne(filter, function (err, data) {
+        callback(err, JSON.parse(JSON.stringify(data)));
+    });
+};
 
 rationItemDAO.prototype.getRationItem = function (repId, code, callback) {
     if (callback) {

+ 1 - 0
modules/ration_repository/routes/ration_front_end_routes.js

@@ -31,6 +31,7 @@ module.exports = function (app) {
 
     apiRouter.post('/getRationItem', searchController.getRationItem);
     apiRouter.post('/findRation', searchController.findRation);
+    apiRouter.post('/matchRation', searchController.matchRation);
 
     app.use("/rationRepository/api", apiRouter);
 };

+ 1 - 2
modules/ration_repository/routes/ration_rep_routes.js

@@ -42,8 +42,7 @@ module.exports = function (app) {
 
     apiRouter.post('/getRationItem', searchController.getRationItem);
     apiRouter.post('/findRation', searchController.findRation);
-
-
+    apiRouter.post('/matchRation', searchController.matchRation);
 };
 
 

+ 3 - 3
public/calc_util.js

@@ -348,9 +348,9 @@ class Calculation {
             $CE.template = template;
             $CE.calcBase = me.compiledCalcBases;
 
-            if (!$treeNode.fees) {
-                $treeNode.fees = [];
-                $treeNode.feesIndex = {};
+            if (!$treeNode.data.fees) {
+                $treeNode.data.fees = [];
+                $treeNode.data.feesIndex = {};
             };
 
             for (let idx of template.compiledSeq) {

+ 2 - 1
server.js

@@ -29,7 +29,8 @@ fileUtils.getGlobbedFiles('./modules/reports/models/*.js').forEach(function(mode
 })
 
 // 引入人工系数模块
-require('./modules/main/models/labour_coe');
+require('./modules/main/models/labour_coe_model');
+require('./modules/main/models/calc_program_model');
 
 //config.setupCache();
 let cfgCacheUtil = require("./config/cacheCfg");

+ 1 - 0
web/building_saas/complementary_glj_lib/js/components.js

@@ -237,6 +237,7 @@ let componentOprObj = {
             }
             updateArr.push(re.currentGlj);
             that.updateComponent(updateArr);
+            $('#componentsCacnel').click();
         });
     }
 };

+ 2 - 1
web/building_saas/css/main.css

@@ -312,4 +312,5 @@ body {
 .gc-column-header-cell{
     text-align: center!important;
 }
-.modal-lg{max-width: 1000px}
+.modal-lg{max-width: 1000px}
+.modal-feeRate {max-width: 550px}

+ 6 - 1
web/building_saas/glj/js/common_spread.js

@@ -49,7 +49,12 @@ CommonSpreadJs.prototype.init = function(target) {
     this.sheet.autoGenerateColumns = false;
     // 设置表单不可编辑
     this.sheet.options.isProtected = true;
-
+    this.sheet.options.protectionOptions = {
+        allowSelectLockedCells: true,
+        allowSelectUnlockedCells: true,
+        allowResizeRows: true,
+        allowResizeColumns: true
+    };
     return this.spread;
 };
 

+ 13 - 5
web/building_saas/glj/js/project_glj_spread.js

@@ -44,6 +44,7 @@ ProjectGLJSpread.prototype.init = function () {
         {name: '名称', field: 'name', visible: true},
         {name: '规格型号', field: 'specs', visible: true},
         {name: '单位', field: 'unit', visible: true},
+        {name: '类型', field: 'unit_price.short_name', visible: true},
         {name: 'ID', field: 'id', visible: false},
         {name: '类型', field: 'unit_price.type', visible: false},
         {name: '总消耗量', field: 'quantity', visible: true},
@@ -88,12 +89,14 @@ ProjectGLJSpread.prototype.init = function () {
     let adjustPriceColumn = this.sheetObj.getFieldColumn('adjust_price');
     let marketPriceColumn = this.sheetObj.getFieldColumn('unit_price.market_price');
     let supplyColumn = this.sheetObj.getFieldColumn('supply');
+    let shortNameColumn = this.sheetObj.getFieldColumn('unit_price.short_name');
 
     // 居中样式
     let centerStyleSetting = {hAlign: 1};
     this.sheetObj.setStyle(-1, isEvaluateColumn, centerStyleSetting);
     this.sheetObj.setStyle(-1, isAdjustPriceColumn, centerStyleSetting);
     this.sheetObj.setStyle(-1, unitColumn, centerStyleSetting);
+    this.sheetObj.setStyle(-1, shortNameColumn, centerStyleSetting);
 
     // 向右对齐样式
     let rightStyleSetting = {hAlign: GC.Spread.Sheets.HorizontalAlign.right};
@@ -244,6 +247,7 @@ ProjectGLJSpread.prototype.specialColumn = function (sourceData) {
     let connectCodeColumn = this.sheetObj.getFieldColumn('connect_code');
     let consumptionColumn = this.sheetObj.getFieldColumn('consumption');
     let supplyColumn = this.sheetObj.getFieldColumn('supply');
+    let supplyQuantity = this.sheetObj.getFieldColumn('supply_quantity');
     let activeSheet = this.sheetObj.getSheet();
 
     for (let data of sourceData) {
@@ -256,16 +260,20 @@ ProjectGLJSpread.prototype.specialColumn = function (sourceData) {
             activeSheet.getCell(rowCounter, isEvaluateColumn, GC.Spread.Sheets.SheetArea.viewport).locked(true);
             activeSheet.setValue(rowCounter, isEvaluateColumn, '');
         }
-
+        // 设置供货方式列是否可选
+        if (this.supplyReadonlyType.indexOf(data.unit_price.type) >= 0) {
+            // 锁定该单元格
+            activeSheet.getCell(rowCounter, supplyColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
+        }
+        // 如果为部分甲供或者为全部甲供则甲供数量需要可编辑
+        if (data.supply === 1 || data.supply === 2) {
+            activeSheet.getCell(rowCounter, supplyQuantity,  GC.Spread.Sheets.SheetArea.viewport).locked(false);
+        }
         // 供货方式数据
         let supplyIndex = parseInt(data.supply);
         supplyIndex = isNaN(supplyIndex) ? 0 : supplyIndex;
         let supplyText = this.supplyType[supplyIndex] !== undefined ? this.supplyType[supplyIndex] : '自行采购';
         activeSheet.setValue(rowCounter, supplyColumn, supplyText);
-        if (this.supplyReadonlyType.indexOf(data.unit_price.type) >= 0) {
-            // 锁定该单元格
-            activeSheet.getCell(rowCounter, supplyColumn,  GC.Spread.Sheets.SheetArea.viewport).locked(true);
-        }
 
         // 如果类型为混凝土、砂浆、配合比、机械,则市场单价和供货方式不能修改
         if (canNotChangeTypeId.indexOf(data.unit_price.type) >= 0) {

+ 3 - 0
web/building_saas/main/html/calc_program_manage.html

@@ -8,6 +8,9 @@
 </head>
 
 <body>
+<div style="">
+    <img id="f_btn" src="/web/dest/css/img/feeRate_btn.jpg" alt="" />
+</div>
     <div class="toolsbar px-1">
     </div>
     <div class="container-fluid">

+ 49 - 5
web/building_saas/main/html/main.html

@@ -444,7 +444,7 @@
                                         <fieldset class="form-group">
                                             <div class="form-check">
                                                 <label class="form-check-label">
-                                                    <input class="form-check-input" name="calcFlag" id="rationContent" value="0" checked="" type="radio">
+                                                    <input class="form-check-input" name="calcFlag" id="rationContent" value="0" type="radio">
                                                     子目含量取费
                                                 </label>
                                             </div>
@@ -478,7 +478,7 @@
                                 <!--人工单价调整-->
                                 <div class="tab-pane fade" id="poj-settings-6" role="tabpanel">
                                     <div class="row px-3">
-                                        <select class="col-4 form-control form-control-sm"><option>渝建[2016]71号</option><option>渝建[2017]78号</option></select>
+                                        <select class="col-4 form-control form-control-sm" id="std_labour_coe_files"><option>渝建[2016]71号</option><option>渝建[2017]78号</option></select>
                                     </div>
                                     <div style="height:8px;"></div>
                                     <div class="modal-auto-height" id="labourCoeSpread"></div>
@@ -539,6 +539,25 @@
             </div>
         </div>
     </div>
+    <!--弹出清单单位选择设置-->
+    <div class="modal fade" id="std_bills_unit" data-backdrop="static">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title"><i class="fa fa-superscript"></i> 请选择清单计量单位</h5>
+                    <button type="button" class="close" id='std_bills_unit_close' aria-label="Close">
+                        <span aria-hidden="true">&times;</span>
+                    </button>
+                </div>
+                <div class="modal-body modal-auto-height" id="std_bills_unit_spread" style="height: 200px; width: 500px; overflow: hidden;">
+                </div>
+                <div class="modal-footer">
+                    <a href="javascript:void(0);" id="std_bills_unit_ok" class="btn btn-primary">确定</a>
+                    <button type="button" class="btn btn-secondary" id='std_bills_unit_cancel'>关闭</button>
+                </div>
+            </div>
+        </div>
+    </div>    
     <!--弹出列设置-->
     <div class="modal fade" id="column" data-backdrop="static">
         <div class="modal-dialog modal-lg" role="document">
@@ -562,7 +581,7 @@
         <div class="modal-dialog modal-lg" role="document" id="modalCon">
             <div class="modal-content" >
                 <div class="modal-header">
-                    <h5 class="modal-title">内容</h5>
+                    <h5 class="modal-title">请选择工料机</h5>
                     <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                         <span aria-hidden="true">&times;</span>
                     </button>
@@ -601,6 +620,29 @@
             </div>
         </div>
     </div>
+    <!--费率选择窗口-->
+    <div class="modal fade" id="fee_rate_tree" data-backdrop="static">
+        <div class="modal-dialog modal-feeRate" role="document" id="fee_rate_dialog">
+            <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">
+                    <input type="hidden" id="edit_from">
+                    <div class="row">
+                        <div class="modal-auto-height col-12" style="overflow: hidden" id="fee_rate_sheet">
+                    </div>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" id="frCacnel" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                    <a href="javascript:void(0);" id="fee_selected_conf" class="btn btn-primary">确定</a>
+                </div>
+            </div>
+        </div>
+    </div>
 
     <!-- JS. -->
     <script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
@@ -628,8 +670,7 @@
     <script src="/public/web/uuid.js"></script>
 
     <script type="text/javascript" src="/public/web/sheet/sheet_common.js"></script>
-    <script type="text/javascript" src="/web/building_saas/main/js/models/calc_program.js"></script>
-    <script type="text/javascript" src="/web/building_saas/main/js/views/calc_program_manage.js"></script>
+
 
     <!-- JS. -->
     <script src="/lib/popper/popper.min.js"></script>
@@ -668,6 +709,8 @@
     <script type="text/javascript" src="/web/building_saas/main/js/models/ration_ass.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/models/volume_price.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/models/labour_coe.js"></script>
+    <script type="text/javascript" src="/web/building_saas/main/js/models/calc_program.js"></script>
+    <script type="text/javascript" src="/web/building_saas/main/js/views/calc_program_manage.js"></script>
 
     <script type="text/javascript" src="/public/web/id_tree.js"></script>
     <script type="text/javascript" src="/test/tmp_data/test_ration_calc/ration_calc_base.js"></script>
@@ -695,6 +738,7 @@
     <script type="text/javascript" src="/web/building_saas/main/js/models/quantity_detail.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/glj_view_contextMenu.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/calc_program_view.js"></script>
+    <script type="text/javascript" src='/web/building_saas/main/js/views/confirm_modal.js'></script>
     <!-- reports -->
     <script type="text/javascript" src="/public/web/treeDataHelper.js"></script>
     <script type="text/javascript" src="/public/web/ztree_common.js"></script>

+ 21 - 4
web/building_saas/main/js/controllers/project_controller.js

@@ -17,13 +17,16 @@ ProjectController = {
     addBills: function (project, sheetController, std) {
         if (!project || !sheetController) { return null; }
 
-        var target = project.getParentTarget(project.mainTree.selected, 'sourceType', project.Bills.getSourceType());
-        var newSource = null, newNode = null;
+        let target = project.getParentTarget(project.mainTree.selected, 'sourceType', project.Bills.getSourceType());
+        let newSource = null, newNode = null;
+        let parentID = target ? target.source.getParentID() : project.Bills.tree.setting.rootId;
+        let nextSiblingID = target ? target.source.getNextSiblingID() : project.Bills.tree.setting.rootId;
 
         if (std) {
-            newSource = project.Bills.insertStdBills(target ? target.source.getParentID() : project.Bills.tree.setting.rootId, target ? target.source.getNextSiblingID() : project.Bills.tree.setting.rootId, std.data);
+            let newCode = project.Bills.newFormatCode(std.code);
+            newSource = project.Bills.insertStdBills(parentID, nextSiblingID, std, newCode);
         } else {
-            newSource = project.Bills.insertBills(target ? target.source.getParentID() : project.mainTree.setting.rootId, target ? target.source.getNextSiblingID() : project.mainTree.setting.rootId);
+            newSource = project.Bills.insertBills(parentID, nextSiblingID);
         }
         newNode = project.mainTree.insert(target.getParentID(), target.getNextSiblingID());
 
@@ -79,6 +82,20 @@ ProjectController = {
             this.syncDisplayNewNode(sheetController, newNode);
         }
     },
+    replaceRation: function (project, sheetController, std) {
+        if (!project || !sheetController) { return; }
+
+        let selected = project.mainTree.selected, newSource = null, newNode = null;
+        if (selected === null) { return; }
+
+        if (selected.sourceType === project.Ration.getSourceType()) {
+            project.Ration.replaceRation(selected.source, std);
+            project.ration_glj.addRationGLJ(selected.source, std);
+            sheetController.refreshTreeNode([selected], false);
+        } else {
+            alert('当前焦点行不是定额,无法替换。');
+        }
+    },
     addVolumePrice: function (project, sheetController) {
         if (!project || !sheetController) { return null; }
 

+ 83 - 19
web/building_saas/main/js/models/bills.js

@@ -37,6 +37,9 @@ var Bills = {
                 let uData = JSON.parse(JSON.stringify(data));
                 delete uData.feesIndex;
                 delete uData.flagsIndex;
+                if (uData.quantity) {
+                    uData.quantity = uData.quantity.toFixed(2);
+                }
                 if (uData.fees) {
                     for (let fee of uData.fees) {
                         fee.unitFee = fee.unitFee.toFixed(2);
@@ -85,6 +88,9 @@ var Bills = {
             this.datas = datas;
             // generate Fees & Flags Index, For View & Calculate
             this.datas.forEach(function (data) {
+                if (data.quantity) {
+                    data.quantity = parseFloat(data.quantity);
+                }
                 data.feesIndex = {};
                 if (data.fees) {
                     data.fees.forEach(function (fee) {
@@ -164,7 +170,7 @@ var Bills = {
             var newData = null, that = this;
             insertData.forEach(function (data) {
                 if (data.type === idTree.updateType.new) {
-                    data.data.code = stdBillsData.code;
+                    data.data.code = that.newFormatCode(stdBillsData.code);
                     data.data.name = stdBillsData.name;
                     data.data.unit = stdBillsData.unit;
                     // 工程量计算规则
@@ -203,6 +209,7 @@ var Bills = {
             project.quantity_detail.deleteByBills(deleteData);
             project.pushNow('deleteBills', modules, deleteDatas);
 
+            this.datas.splice(this.datas.indexOf(node.data), 1);
             return this.tree.delete(node);
         };
 
@@ -250,41 +257,98 @@ var Bills = {
             } else {
                 data[field] = newValue;
             }
-            updateData.push({'updateType': 'ut_update', 'updateData': data});
+            updateData.push({'updateType': 'ut_update', 'updateData': tools.formatBillsUpdateData(data)});
             this.project.pushNow('updateBills', this.getSourceType(), updateData);
         };
 
-        bills.prototype.updateAll = function () {
+        bills.prototype.getUpdateAllData = function () {
             let updateData = [];
             for (let data of this.datas) {
-                let uData = JSON.parse(JSON.stringify(data));
-                delete uData.feesIndex;
-                delete uData.flagsIndex;
-                if (uData.fees) {
-                    for (let fee of uData.fees) {
-                        fee.unitFee = fee.unitFee.toFixed(2);
-                        fee.totalFee = fee.totalFee.toFixed(2);
-                        fee.tenderUnitFee = fee.tenderUnitFee.toFixed(2);
-                        fee.tenderTotalFee = fee.tenderTotalFee.toFixed(2);
-                    }
-                }
-                updateData.push({'updateType': 'ut_update', 'updateData': uData});
+                updateData.push({'updateType': 'ut_update', 'updateData': tools.formatBillsUpdateData(data)});
             }
-            this.project.pushNow('updateAllBills', this.getSourceType(), updateData);
+            return updateData;
         };
 
-        bills.prototype.updateNodes = function (nodes, updateNow) {
+        bills.prototype.updateAll = function () {
+            this.project.pushNow('updateAllBills', this.getSourceType(), this.getUpdateAllData());
+        };
+
+        bills.prototype.getUpdateNodesData = function (nodes) {
             let updateData = [];
             for (let node of nodes) {
                 updateData.push({'updateType': 'ut_update', 'updateData': tools.formatBillsUpdateData(node.data)});
             }
+            return updateData;
+        }
+
+        bills.prototype.updateNodes = function (nodes, updateNow) {
             if (updateNow) {
-                this.project.pushNow('updateBills', this.getSourceType(), updateData);
+                this.project.pushNow('updateBills', this.getSourceType(), this.getUpdateNodesData(nodes));
             } else {
-                this.project.push(this.getSourceType(), updateData);
+                this.project.push(this.getSourceType(), this.getUpdateNodesData(nodes));
+            }
+        };
+
+        bills.prototype.sameStdCode = function (stdCode, filterCode) {
+            let reg = new RegExp('^' + stdCode), matchs= [];
+            for (let data of this.datas) {
+                if (data.code && data.code.length === 12 && reg.test(data.code) && data.code !== filterCode) {
+                    matchs.push(data.code);
+                }
+            }
+            return matchs;
+        }
+
+        bills.prototype.newFormatCode = function (stdCode, filterCode) {
+            let matchs = this.sameStdCode(stdCode, filterCode);
+            let format = function (Number) {
+                let s = Number + '';
+                while (s.length < 3) {
+                    s = '0' + s;
+                }
+                return s;
+            }
+            for (i = 0; i <= matchs.length; i++) {
+                let formatCode = stdCode + format(i+1);
+                if (matchs.indexOf(formatCode) === -1) {
+                    return formatCode;
+                }
+            }
+        };
+
+        bills.prototype.replaceBills = function (node, stdBillsData, code) {
+            let updateData = [];
+            node.data.code = code;
+            if (stdBillsData) {
+                node.data.name = stdBillsData.name;
+                node.data.unit = stdBillsData.unit;
+                // 工程量计算规则
+                node.data.ruleText = stdBillsData.ruleText;
+                // 说明(补注)
+                node.data.comments = stdBillsData.recharge;
+                // 工作内容
+                node.data.jobContent = stdBillsData.jobContent;
+                node.data.jobContentText = stdBillsData.jobContentText;
+                // 特征
+                node.data.itemCharacter = stdBillsData.itemCharacter;
+                node.data.itemCharacterText = stdBillsData.itemCharacterText;
             }
+            updateData.push({'updateType': 'ut_update', 'updateData': tools.formatBillsUpdateData(node.data)});
+
+            this.project.pushNow('replaceBills', this.getSourceType(), updateData);
+            return node;            
         };
 
+        bills.prototype.sameStdCodeBillsData = function (stdCode) {
+            let reg = new RegExp('^' + stdCode);
+            for (let data of this.datas) {
+                if (data.code && data.code.length === 12 && reg.test(data.code) && /^[\d]+$/.test(data.code)) {
+                    return data;
+                }
+            }
+            return null;            
+        }
+
         return new bills(project);
     }
 };

Dosya farkı çok büyük olduğundan ihmal edildi
+ 24 - 3597
web/building_saas/main/js/models/calc_program.js


+ 27 - 3
web/building_saas/main/js/models/fee_rate.js

@@ -34,14 +34,17 @@ var FeeRate = {
             return feeRate;
         };
         FeeRate.prototype.getActivateFeeRateID = function(){
-            var feeRate = this.getActivateFeeRate()
+            var feeRate = this.getActivateFeeRate();
             if(feeRate){
                 return feeRate.ID;
             }else {
                 return 0;
             }
         };
-
+        FeeRate.prototype.getFeeRateByID=function (ID) {
+            var rates = this.getActivateFeeRate().rates;
+            return _.find(rates,{'ID':ID})
+        };
         FeeRate.prototype.getSubViewData= function(item) {
             var datas = [];
             if(item.hasOwnProperty('subFeeRate')&&item.subFeeRate!=undefined){
@@ -213,7 +216,28 @@ var FeeRate = {
                 callback(data);
             });
         };
-
+        FeeRate.prototype.setFeeRateToBill=function (rate,bills,callback) {
+            var query={
+                ID:bills.ID,
+                projectID:bills.projectID,
+                deleteInfo:null
+            }
+            var doc={
+                feeRate:null,
+                feeRateID:rate.ID
+            }
+            CommonAjax.post('/feeRates/setFeeRateToBill', {query:query,doc:doc}, function (data) {
+                callback(data);
+            });
+        };
+        FeeRate.prototype.loadFeeRateToBill=function (node) {
+            if(node.data.feeRateID){
+                var feeRate = this.getFeeRateByID(node.data.feeRateID);
+                if(feeRate){
+                    node.data.feeRate=feeRate.rate.toString();
+                }
+            }
+        };
         FeeRate.prototype.changeFeeRateFileFromCurrent = function (newFeeRateFile,callback){
             var me=this;
             var projectID = projectInfoObj.projectInfo.ID;

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

@@ -13,5 +13,6 @@ const ModuleNames = {
     quantity_detail:'quantity_detail',
     volume_price: 'volume_price',
     projectGLJ: 'project_glj',
-    labour_coe: 'labour_coe'
+    labour_coe: 'labour_coe',
+    calc_program: 'calc_program'
 };

+ 12 - 7
web/building_saas/main/js/models/project.js

@@ -87,7 +87,8 @@ var PROJECT = {
                     totalFee: 2
                 }
             };
-            this.LabourCoe = new LabourCoe(this);
+            this.labourCoe = new LabourCoe(this);
+            this.calcProgram = new CalcProgram(this);
 
             this.masterField = {ration: 'billsItemID', volumePrice: 'billsItemID'};
         };
@@ -148,7 +149,7 @@ var PROJECT = {
                     newNode.source = nodes[i];
                     newNode.sourceType = that.Bills.getSourceType();
                     newNode.data = nodes[i].data;
-
+                    that.FeeRate.loadFeeRateToBill(newNode);
                     if (nodes[i].children.length === 0) {
                         loadRationNode(that.Ration.datas, newNode);
                         loadVolumePriceNode(newNode);
@@ -288,21 +289,25 @@ var PROJECT = {
             }
         };
 
-        project.prototype.setCalcFlag = function (calcFlag) {
-            this.calcFlag = calcFlag;
+        project.prototype.setBillsCalcMode = function (calcMode) {
+            this.projSetting.billsCalcMode = calcMode;
+            this.initCalcFields();
+        };
+
+        project.prototype.initCalcFields = function () {
             if (this.calcFields) {
                 for (let field of this.calcFields) {
                     // unitFeeCalcFlag
-                    if (this.calcFlag === rationContent) {
+                    if (this.projSetting.billsCalcMode === this.projSetting.billsCalcModeConst.rationContent) {
                         field.unitFeeFlag = rationContentUnitFeeFlag;
-                    } else if ( this.calcFlag === billsPrice) {
+                    } else if ( this.projSetting.billsCalcMode === this.projSetting.billsCalcModeConst.billsPrice) {
                         field.unitFeeFlag = billsPriceUnitFeeFlag;
                     } else {
                         field.unitFeeFlag = averageQtyUnitFeeFlag;
                     }
                     // totalFeeCalcFlag
                     if (field.type === 'common') {
-                        if (this.calcFlag === rationPriceConverse) {
+                        if (this.projSetting.billsCalcMode === this.projSetting.billsCalcModeConst.rationPriceConverse) {
                             field.totalFeeFlag = sumTotalFeeFlag;
                         } else {
                             field.totalFeeFlag = totalFeeFlag;

+ 58 - 2
web/building_saas/main/js/models/ration.js

@@ -160,7 +160,7 @@ var Ration = {
             return newRation;
         };
         ration.prototype.insertStdRation = function (billsID, preRation, std) {
-            var br = this.getBillsSortRation(billsID), updateData = this.getInsertRationData(billsID, preRation), newRation = null;
+            var br = this.getBillsSortRation(billsID), updateData = this.getInsertRationData(billsID, preRation), newRation = null, that = this;
             updateData.forEach(function (data) {
 
                 if (data.updateType === 'ut_create') {
@@ -175,6 +175,8 @@ var Ration = {
                         data.updateData.ruleText = std.chapter.ruleText;
                     }
                     data.updateData.rationAssList =  projectObj.project.ration_ass.CreateNewAss(std);
+                    // calculate ration Quantity
+                    that.CalculateQuantity(data.updateData);
                     newRation = data.updateData;
                 }
             });
@@ -280,8 +282,62 @@ var Ration = {
             } else {
                 this.project.push(this.getSourceType(), updateData);
             }
-        }
+        };
 
+        ration.prototype.FilterNumberFromUnit = function (unit) {
+            let reg = new RegExp('^[0-9]+');
+            if (reg.test(unit)) {
+                return parseInt(unit.match(reg)[0]);
+            } else {
+                return 1;
+            }
+        };
+
+        ration.prototype.CalculateQuantity = function (ration) {
+            // calculate ration Quantity
+            if (optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan')) {
+                let billsNode = this.project.Bills.tree.findNode(ration[this.project.masterField.ration]);
+                let billsQuantity = billsNode.data.quantity ? billsNode.data.quantity : 0;
+                if (optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToRationUnit')) {
+                    ration.quantity = (billsQuantity / this.FilterNumberFromUnit(ration.unit)).toDecimal(4);
+                } else {
+                    ration.quantity = billsQuantity.toDecimal(4);
+                }
+            }
+        };
+
+        ration.prototype.replaceRation = function (ration, std) {
+            this.project.beginUpdate('replaceRation');
+            
+            // delete
+            let ration_glj =projectObj.project.ration_glj;
+            this.project.push(this.project.ration_glj.getSourceType(), this.project.ration_glj.getDeleteDataByRation(ration));
+
+            this.project.ration_glj.deleteByRation(ration);
+            this.project.ration_coe.deleteByRation(ration);
+            this.project.quantity_detail.deleteByRation(ration);
+
+            // insertNewRation
+            let updateData = [];
+            ration.code = std.code;
+            ration.name = std.name;
+            ration.caption = std.caption;
+            ration.unit = std.unit;
+            ration.libID = std.rationRepId;
+            ration.content = std.jobContent;
+            if (std.chapter) {
+                ration.comments = std.chapter.explanation;
+                ration.ruleText = std.chapter.ruleText;
+            }
+            ration.rationAssList = projectObj.project.ration_ass.CreateNewAss(std);
+            // calculate ration Quantity
+            this.CalculateQuantity(ration);
+            updateData.push({updateType: 'ut_update', updateData: ration});
+            this.project.push(this.getSourceType(), updateData);
+
+            this.project.endUpdate();
+        };
+        
         return new ration(project);
     }
 };

+ 15 - 4
web/building_saas/main/js/models/ration_glj.js

@@ -139,6 +139,9 @@ var ration_glj = {
             _.remove(gljOprObj.sheetData,data.query);
             gljOprObj.showRationGLJSheetData();
             projectObj.project.projectGLJ.loadData();
+            var selected = projectObj.project.mainTree.selected;
+            selected.data.adjustState=data.adjustState;
+            projectObj.mainController.refreshTreeNode([selected]);
         };
         // CSL,2017.05.09
         ration_glj.prototype.modifyQuantity = function (data, newQuantity) {
@@ -179,6 +182,7 @@ var ration_glj = {
                     newGLJ.projectID = newRation.projectID;
                     newGLJ.GLJID = temdata.gljId;
                     newGLJ.rationID = newRation.ID;
+                    newGLJ.billsItemID=newRation.billsItemID,
                     newGLJ.rationItemQuantity= temdata.consumeAmt;
                     newGLJ.quantity=temdata.consumeAmt;
                     newGLJ.glj_repository_id=data.rationRepId;
@@ -243,7 +247,7 @@ var ration_glj = {
         ration_glj.prototype.updataOrdelete=function(row){
             var updateData = null;
             if(row.rationItemQuantity==0){
-                updateData=this.getUpdateData('ut_delete',{'ID': row.ID, 'projectID': row.projectID});
+                updateData=this.getUpdateData('ut_delete',{'ID': row.ID, 'projectID': row.projectID},{rationID:row.rationID});
                 project.pushNow('updateRationGLJ',[this.getSourceType()],updateData)
             }else {
                 this.customQuantityUpdate(row,0,0);//('ut_update',{'ID': row.ID, 'projectID': row.projectID},{'quantity':0,'customQuantity':0});
@@ -324,6 +328,7 @@ var ration_glj = {
                   projectID:ration.projectID,
                   GLJID:glj.ID,
                   rationID:ration.ID,
+                  billsItemID:ration.billsItemID,
                   rationItemQuantity:0,
                   quantity:0,
                   name:glj.name,
@@ -349,11 +354,13 @@ var ration_glj = {
             if(selectCode==oldData.code){
                 return callback(null);
             }
-            oldData.createType='replace';
+            if(oldData.createType!='replace'){
+                oldData.rcode=oldData.code;
+                oldData.createType='replace';
+            }
             oldData.GLJID=glj.ID;
             oldData.rationItemQuantity=0;
             oldData.name=glj.name;
-            oldData.rcode=oldData.code;
             oldData.code=glj.code;
             oldData.unit=glj.unit;
             oldData.specs=glj.specs;
@@ -383,7 +390,6 @@ var ration_glj = {
                 createType:'replace',
                 rationItemQuantity:0,
                 name:glj.name,
-                rcode:oldData.code,
                 code:glj.code,
                 unit:glj.unit,
                 specs:glj.specs,
@@ -392,6 +398,11 @@ var ration_glj = {
                 repositoryId:glj.repositoryId,
                 projectID:oldData.projectID
             }
+            if(oldData.createType=='replace'){
+                doc.rcode=oldData.rcode;
+            }else {
+                doc.rcode=oldData.code;
+            }
             if(glj.hasOwnProperty("compilationId")){
                 doc.from="cpt";
             }else {

+ 7 - 5
web/building_saas/main/js/views/calc_program_manage.js

@@ -25,19 +25,19 @@ let rationPM = {
             {headerName:"费用名称",headerWidth:200,dataCode:"name", dataType: "String"},
             {headerName:"计算基数",headerWidth:180,dataCode:"dispExpr", dataType: "String"},
             {headerName:"基数说明",headerWidth:300,dataCode:"statement", dataType: "String"},
-            {headerName:"费率",headerWidth:80,dataCode:"feeRate", dataType: "Number"},
+            {headerName:"费率",headerWidth:80,dataCode:"feeRate", dataType: "Number",hAlign: "left"},
             {headerName:"字段名称",headerWidth:140,dataCode:"displayFieldName", dataType: "String", hAlign: "center"},
             {headerName:"备注",headerWidth:100,dataCode:"memo", dataType: "String"}
         ],
         view:{
             comboBox:[],
-            lockColumns:[0,1,2,3,4,6]
+            lockColumns:[0,1,2,3,6]
         }
     },
 
     buildSheet: function (){
         let me = this;
-        me.datas = calcTemplates;
+        me.datas = projectObj.project.calcProgram.datas.templates;
         if (me.mainSpread) {
             me.mainSpread.destroy();
             me.mainSpread = null;
@@ -56,14 +56,16 @@ let rationPM = {
 
         me.mainSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EnterCell, me.onMainEnterCell);
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.CellChanged, me.onDetailCellChanged);
-
+        //me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.CellClick, me.onCellClick);
         let mSheet = me.mainSpread.getSheet(0);
         sheetCommonObj.showData(mSheet, me.mainSetting, me.datas);
 
         let dSheet = me.detailSpread.getSheet(0);
+        feeRateObject.setFeeRateCellCol(dSheet,4);
+        dSheet.name('calc_detail');
         sheetCommonObj.showData(dSheet, me.detailSetting, me.datas[0].calcItems);
-    },
 
+    },
     onMainEnterCell: function(sender, args) {
         var me = rationPM;
         var row = args.sheet.getActiveRowIndex();

+ 3 - 2
web/building_saas/main/js/views/character_content_view.js

@@ -661,8 +661,9 @@ let pageCCOprObj = {
         node.data.itemCharacter = itemCharacter;
         node.data.jobContentText = contentTxt ? contentTxt : '';
         node.data.itemCharacterText = characterTxt ? characterTxt : '';
-
-
+    },
+    safeItemCharater: function (itemCharater) {
+        return characterOprObj.buildItemCharactet(itemCharater);
     },
     //设置特征及内容currentCache
     setCacheAndShow: function (node) {

+ 110 - 0
web/building_saas/main/js/views/confirm_modal.js

@@ -0,0 +1,110 @@
+/**
+ * 
+ * Created by Mai on 2017/10/20.
+ */
+
+let ConfirmModal = {  
+    reBind: function (obj, eventName, fun) {
+         obj.unbind(eventName);
+         obj.bind(eventName, fun);
+    },
+    stdBillsUnit: {
+        modalObj: $('#std_bills_unit'),
+        okObj: $('#std_bills_unit_ok'),
+        cancelObj: $('#std_bills_unit_cancel'),
+        closeObj: $('#std_bills_unit_close'),
+        spread: null,
+        setting: {
+            "emptyRows":0,
+            "headRows":1,
+            "headRowHeight":[25],
+            "defaultRowHeight": 21,
+            "cols":[{
+                "width":120,
+                "readOnly":true,
+                "head":{
+                    "titleNames":["编码"],
+                    "spanCols":[1],
+                    "spanRows":[1],
+                    "vAlign":[1],
+                    "hAlign":[1],
+                    "font":["Arial"]
+                },
+                "data":{
+                    "field":"code",
+                    "vAlign":1,
+                    "hAlign":0,
+                    "font":"Arial"
+                }
+            }, {
+                "width":200,
+                "readOnly":true,
+                "head":{
+                    "titleNames":["名称"],
+                    "spanCols":[1],
+                    "spanRows":[1],
+                    "vAlign":[1],
+                    "hAlign":[1],
+                    "font":["Arial"]
+                },
+                "data":{
+                    "field":"name",
+                    "vAlign":1,
+                    "hAlign":0,
+                    "font":"Arial"
+                }
+            }, {
+                "width":50,
+                "readOnly":true,
+                "head":{
+                    "titleNames":["单位"],
+                    "spanCols":[1],
+                    "spanRows":[1],
+                    "vAlign":[1],
+                    "hAlign":[1],
+                    "font":["Arial"]
+                },
+                "data":{
+                    "field":"unit",
+                    "vAlign":1,
+                    "hAlign":1,
+                    "font":"Arial"
+                }
+            }]
+        },
+        check: function (std, okCallBack, cancelCallBack) {
+            if (!this.spread) {
+                this.spread = SheetDataHelper.createNewSpread($('#std_bills_unit_spread')[0], {sheetCount: 1});
+                this.spread.options.showScrollTip = GC.Spread.Sheets.ShowScrollTip.vertical;
+                SheetDataHelper.loadSheetHeader(this.setting, this.spread.getActiveSheet());
+            }
+            let sheet = ConfirmModal.stdBillsUnit.spread.getActiveSheet();
+            let modalObj = this.modalObj;
+            let okFun = function () {
+                modalObj.modal('toggle');
+                if (okCallBack) {
+                    let newStd = JSON.parse(JSON.stringify(std));
+                    newStd.unit = sheet.getText(sheet.getSelections()[0].row, 2);
+                    okCallBack(newStd);
+                }
+            };
+            let cancelFun = function () {
+                modalObj.modal('toggle');
+                if (cancelCallBack) {
+                    cancelCallBack();
+                }
+            };
+            ConfirmModal.reBind(this.okObj, 'click', okFun);
+            ConfirmModal.reBind(this.cancelObj, 'click', cancelFun);
+            ConfirmModal.reBind(this.closeObj, 'click', cancelFun);
+            let datas = [];
+            let units = std.unit.split('/');
+            for (let unit of units) {
+                datas.push({'code': std.code, 'name': std.name, 'unit': unit});
+            }
+            SheetDataHelper.loadSheetData(this.setting, sheet, datas);
+            this.modalObj.modal('show');  
+            ConfirmModal.stdBillsUnit.spread.refresh();  
+        }
+    }
+};

+ 307 - 0
web/building_saas/main/js/views/fee_rate_view.js

@@ -12,6 +12,20 @@ var feeRateObject={
     needCascadeSet:false,
     selectionLoad:false,
     changeInfo:null,
+    feeRateSpreads:null,
+    editingCell:null,
+    feeRateSelection:null,
+    sheetSetting: {
+        header: [
+            {headerName: "专业名称", headerWidth: 200, dataCode: "name", dataType: "String"},
+            {headerName: "值%", headerWidth: 150, dataCode: "rate", dataType: "String",hAlign: "right"},
+            {headerName: "备注", dataCode: "memo", dataType: "String"}
+        ],
+        view: {
+            comboBox: [],
+            lockColumns: [0, 1, 2]
+        }
+    },
     columns: [
         {
             id: 'name',
@@ -101,6 +115,236 @@ var feeRateObject={
 
         }
     },
+    createSheet:function(){
+        var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate();
+        feeRateObject.feeRateSpreads=sheetCommonObj.buildSheet($('#fee_rate_sheet')[0], feeRateObject.sheetSetting,feeRateFile.rates.length);
+        feeRateObject.feeRateSheet = feeRateObject.feeRateSpreads.getSheet(0);
+        feeRateObject.feeRateSheet.selectionUnit(1)//0 cell,1 row,2 col;
+        feeRateObject.feeRateSheet.options.isProtected = true;
+        feeRateObject.feeRateSheet.name('fee_rate');
+        feeRateObject.feeRateSheet.bind(GC.Spread.Sheets.Events.CellClick,feeRateObject.onCellClick);
+        feeRateObject.feeRateSheet.bind(GC.Spread.Sheets.Events.CellDoubleClick,feeRateObject.onCellDoubleClick);
+    },
+    showSelectTree:function () {
+        var sheet= feeRateObject.feeRateSheet;
+        var setting=feeRateObject.sheetSetting;
+        var data = projectObj.project.FeeRate.getActivateFeeRate().rates;
+        var ch = GC.Spread.Sheets.SheetArea.viewport;
+        var groups=[];
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        sheet.rowOutlines.direction(GC.Spread.Sheets.Outlines.OutlineDirection.backward);
+        sheet.getRange(-1, 0, -1, 1).cellType(feeRateObject.getTreeNodeCellType());
+        for (var col = 0; col < setting.header.length; col++) {
+            var hAlign = "left", vAlign = "center";
+            if (setting.header[col].hAlign) {
+                hAlign = setting.header[col].hAlign;
+            } else if (setting.header[col].dataType !== "String"){
+                hAlign = "right";
+            }
+            vAlign = setting.header[col].vAlign?setting.header[col].vAlign:vAlign;
+            sheetCommonObj.setAreaAlign(sheet.getRange(-1, col, -1, 1), hAlign, vAlign);
+            if (setting.header[col].formatter) {
+                sheet.setFormatter(-1, col, setting.header[col].formatter, GC.Spread.Sheets.SheetArea.viewport);
+            }
+            for (var row = 0; row < data.length; row++) {
+                var val = data[row][setting.header[col].dataCode];
+                if(val&&setting.header[col].dataType === "Number"){
+                    if(setting.header[col].hasOwnProperty('tofix')){
+                        val =parseFloat(val).toFixed(setting.header[col].tofix);
+                    }else {
+                        val =parseFloat(val).toFixed(2);
+                    }
+                }
+                sheet.setValue(row, col, val, ch);
+                if(col==0){
+                    feeRateObject.setSheetGroup(data[row],data,groups,row+1);
+                }
+            }
+        }
+        //this.lockCells(sheet,setting);
+        _.forEach(groups,function (g) {
+            for(var k in g){
+                sheet.rowOutlines.group(parseInt(k), g[k]);
+            }
+        })
+     /*   sheet.rowOutlines.group(1, 6);
+        sheet.rowOutlines.group(8, 6);
+        sheet.rowOutlines.group(15, 6);
+        sheet.rowOutlines.group(22, 6);*/
+       // sheet.getRange(-1, 0, -1, 1).width(300);
+        sheet.showRowOutline(false);
+        sheet.resumeEvent();
+        sheet.resumePaint(false);
+    },
+    getTreeNodeCellType:function () {
+        var ns = GC.Spread.Sheets;
+        function TreeNodeCellType() {
+        }
+        TreeNodeCellType.prototype = new ns.CellTypes.Text();
+        TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+            var level = options.sheet.rowOutlines.getLevel(options.row);
+            var nlevel = -1;
+            if (options.row < options.sheet.getRowCount() - 1) {
+                nlevel = options.sheet.rowOutlines.getLevel(options.row + 1);
+            }
+            var hoffset = (level + 2) * 12;
+            x += hoffset;
+            w -= hoffset;
+            GC.Spread.Sheets.CellTypes.Base.prototype.paint.apply(this, arguments);
+            if (options.row == options.sheet.getRowCount() - 1) return; //last row
+            if (nlevel > level) {
+                var collapsed = options.sheet.rowOutlines.isCollapsed(options.row + 1);
+                x--;
+                y += h / 2 - 3;
+                ctx.save();
+                ctx.fillStyle = "black";
+                ctx.beginPath();
+                if (collapsed) {
+                    ctx.moveTo(x - 5, y);
+                    ctx.lineTo(x, y + 3);
+                    ctx.lineTo(x - 5, y + 6);
+                } else {
+                    ctx.moveTo(x, y);
+                    ctx.lineTo(x, y + 5);
+                    ctx.lineTo(x - 5, y + 5);
+                }
+                ctx.fill();
+                ctx.restore();
+            }
+            else {
+                x--;
+                y += h / 2 - 3;
+                ctx.save();
+                ctx.restore();
+            }
+        };
+        // override getHitInfo to allow cell type get mouse messages
+        TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            return {
+                x: x,
+                y: y,
+                row: context.row,
+                col: context.col,
+                cellStyle: cellStyle,
+                cellRect: cellRect,
+                sheetArea: context.sheetArea
+            };
+        }
+        TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
+            var level = hitinfo.sheet.rowOutlines.getLevel(hitinfo.row);
+            var hoffset = (level + 2) * 12 + hitinfo.cellRect.x;
+            if (hitinfo.x < hoffset && hitinfo.x > hoffset - 10) {
+                var collapsed = hitinfo.sheet.rowOutlines.isCollapsed(hitinfo.row + 1);
+                hitinfo.sheet.rowOutlines.setCollapsed(hitinfo.row, !collapsed);
+                hitinfo.sheet.invalidateLayout();
+                hitinfo.sheet.repaint();
+            }
+        };
+        return new TreeNodeCellType()
+    },
+    getFeeRateEditCellType:function () {
+        var ns = GC.Spread.Sheets;
+        function FeeRateEditCellType() {
+            var init=false;
+        }
+        FeeRateEditCellType.prototype = new ns.CellTypes.Text();
+        FeeRateEditCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+            if(value!=null){
+                ctx.fillText(value,x+3+ctx.measureText(value).width,y+h-3);
+            }
+            if(feeRateObject.editingCell){
+                if(feeRateObject.editingCell.row==options.row&&feeRateObject.editingCell.col==options.col){
+                    var image = document.getElementById('f_btn'),imageMagin = 3;
+                    var imageHeight = h-2*imageMagin;
+                    var imageWidth = w*2/7;
+                    var imageX = x + w - imageWidth- imageMagin, imageY = y + h / 2 - imageHeight / 2;
+                    ctx.save();
+                    ctx.drawImage(image, imageX, imageY,imageWidth,imageHeight);
+                    ctx.beginPath();
+                    ctx.arc(imageX+imageWidth/2,imageY+imageHeight/2,1,0,360,false);
+                    ctx.arc(imageX+imageWidth/2-4,imageY+imageHeight/2,1,0,360,false);
+                    ctx.arc(imageX+imageWidth/2+4,imageY+imageHeight/2,1,0,360,false);
+                    ctx.fillStyle="black";//填充颜色,默认是黑色
+                    ctx.fill();//画实心圆
+                    ctx.closePath();
+                    ctx.restore();
+                }
+            }
+        };
+        FeeRateEditCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            return {
+                x: x,
+                y: y,
+                row: context.row,
+                col: context.col,
+                cellStyle: cellStyle,
+                cellRect: cellRect,
+                sheetArea: context.sheetArea
+            };
+        };
+        FeeRateEditCellType.prototype.processMouseDown = function (hitinfo) {
+            var me=feeRateObject;
+            if(me.editingCell==null){
+                var showSelectBtn = true;
+                if(hitinfo.sheet.name()!='calc_detail'){
+                    showSelectBtn=me.ifFeeRateEdit();
+                }
+                if(showSelectBtn){
+                    me.editingCell={
+                        row:hitinfo.row,
+                        col:hitinfo.col
+                    }
+                    hitinfo.sheet.invalidateLayout();
+                    hitinfo.sheet.repaint();
+                }
+            }else if(hitinfo.row==me.editingCell.row){
+                var offset=hitinfo.cellRect.x+hitinfo.cellRect.width-6;
+                var imageMagin=3;
+                var imageHeight = hitinfo.cellRect.height-2*imageMagin;
+                var imageWidth = hitinfo.cellRect.width*2/7;
+                if(hitinfo.x<offset&&hitinfo.x>offset-imageWidth){
+                    me.showSelectModal(hitinfo);
+                }
+            }
+        };
+        FeeRateEditCellType.prototype.processMouseLeave = function (hitinfo) {
+            feeRateObject.editingCell=null;
+            hitinfo.sheet.invalidateLayout();
+            hitinfo.sheet.repaint();
+        }
+        return new FeeRateEditCellType();
+    },
+    showSelectModal:function (hitinfo) {
+        $("#fee_rate_tree").modal({show:true});
+        $('#edit_from').val(hitinfo.sheet.name());
+    },
+    setSheetGroup:function (rate,data,groups,row) {
+        var me=this;
+        var group={};
+        var count=me.getChildrenCount(rate.ID,data);
+        if(count>0){
+            group[row]=count;
+            groups.push(group);
+        }
+        return groups;
+    },
+    getChildrenCount:function (id,data) {
+        var me=this;
+        var sum=0;
+        var children=_.filter(data,{'ParentID':id});
+        if(children&&children.length==0){
+            return 0;
+        }
+        for(var i=0;i<children.length;i++){
+            sum+=me.getChildrenCount(children[i].ID,data);
+        }
+        return children.length+sum;
+    },
+    ifFeeRateEdit:function () {
+        var selected = projectObj.project.mainTree.selected;
+        return MainTreeCol.readOnly.forCalcBase(selected)?false:true;
+    },
     createSpreadView:function () {
         if (this.mainViews) {
             this.mainViews.destroy();
@@ -369,6 +613,49 @@ var feeRateObject={
             projectObj.project.FeeRate.synchronizeFeeRate();
         }
         projectObj.project.FeeRate.changeFeeRateFileFromOthers(feeRateFileID,name,callback);
+    },
+    setFeeRateCellCol:function (sheet,col) {
+        sheet.getRange(-1, col, -1, 1).cellType(this.getFeeRateEditCellType());
+    },
+    onCellClick:function (sender,args) {
+       var data =projectObj.project.FeeRate.getActivateFeeRate().rates;
+       feeRateObject.feeRateSelection=data[args.row];
+    },
+    onCellDoubleClick:function (sender,args) {
+        var data =projectObj.project.FeeRate.getActivateFeeRate().rates;
+        feeRateObject.feeRateSelection=data[args.row];
+        feeRateObject.submitFeeRateBySelect();
+    },
+    checkSelectedFeeRate:function () {
+        var validate = false;
+        var data =projectObj.project.FeeRate.getActivateFeeRate().rates;
+        if(feeRateObject.feeRateSelection!=null){
+            var children=_.filter(data,{'ParentID':feeRateObject.feeRateSelection.ID});
+            validate=children&&children.length==0;
+        }
+        return validate;
+    },
+    setFeeRateToBill:function () {
+       var rate = feeRateObject.feeRateSelection;
+       var selected = projectObj.project.mainTree.selected;
+        projectObj.project.FeeRate.setFeeRateToBill(rate,selected.data,function (data) {
+            selected.data.feeRateID=rate.ID.toString();
+            selected.data.feeRate=rate.rate.toString();
+            projectObj.mainController.refreshTreeNode([selected]);
+            $("#fee_rate_tree").modal('hide');
+        });
+    },
+    submitFeeRateBySelect:function () {
+        var validate = this.checkSelectedFeeRate();
+        if(validate){
+            if($('#edit_from').val()=='calc_detail'){
+                //do calc_detail
+            }else {
+                this.setFeeRateToBill();
+            }
+        }else {
+            //$("#fee_rate_tree").modal('hide');
+        }
     }
 }
 
@@ -527,3 +814,23 @@ $('#inlineFormCustomSelect').change(function(){
     socket.emit('changeActivateFeeRate',{oldRoom:oldValue,newRoom:selectID});
 })
 
+$('#fee_rate_tree').on('shown.bs.modal', function (e) {
+    if(feeRateObject.feeRateSpreads==null){
+        feeRateObject.createSheet();
+    }
+    feeRateObject.feeRateSelection=null;
+    feeRateObject.showSelectTree();
+});
+
+$('#fee_rate_tree').on('hidden.bs.modal', function (e) {
+    if(feeRateObject.feeRateSpreads){
+        feeRateObject.feeRateSpreads.destroy();
+        feeRateObject.feeRateSpreads=null;
+        $('#edit_from').val('');
+        $('#edit_row').val('');
+    }
+});
+
+$('#fee_selected_conf').bind('click',function (){
+    feeRateObject.submitFeeRateBySelect();
+})

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

@@ -526,6 +526,7 @@ var gljOprObj = {
         }
     },
     showRationGLJSheetData:function () {
+        this.sheetData=_.sortBy(this.sheetData,'type');
         sheetCommonObj.showData(this.sheet,this.setting,this.sheetData);
     },
     filterGljByRation:function (ration,datas) {
@@ -536,9 +537,8 @@ var gljOprObj = {
         return gljList;
     },
     showInSheet:function(gljList){
-        gljList=this.combineWithProjectGlj(gljList);
-        sheetCommonObj.showData(this.sheet,this.setting,gljList);
-        this.sheetData=gljList;
+        this.sheetData=this.combineWithProjectGlj(gljList);
+        this.showRationGLJSheetData();
     },
     combineWithProjectGlj:function (ration_gljs) {
         var projectGljs = projectObj.project.projectGLJ.datas.gljList;
@@ -797,10 +797,12 @@ var gljOprObj = {
         if(gljOprObj.GLJSelection.length>0&&selected&&selected.sourceType==ModuleNames.ration){
             project.ration_glj.addGLJByLib(gljOprObj.GLJSelection,selected.data,function (result) {
                 if(result){
+                    selected.data.adjustState=result.adjustState;
                     project.ration_glj.datas = project.ration_glj.datas.concat(result.newRecodes);
                     gljOprObj.sheetData = gljOprObj.sheetData.concat(result.showData)
                     gljOprObj.showRationGLJSheetData();
                     project.projectGLJ.loadData();
+                    projectObj.mainController.refreshTreeNode([selected]);
                     $("#glj_tree_div").modal('hide');
                 }
             });//doc.rationID=selected.data.ID;
@@ -814,12 +816,17 @@ var gljOprObj = {
         var oldData=me.sheetData[gljContextMenu.selectedRow];
         var project= projectObj.project;
         var selectCode=gljOprObj.GLJSelection[0];
+        var selected = projectObj.project.mainTree.selected;
         project.ration_glj.replaceGLJ(selectCode,oldData,function (result) {
             if(result){
-                var index = _.findIndex(gljOprObj.sheetData,{'ID':result.ID});
-                gljOprObj.sheetData[index]=result;
+                //result.adjustState;
+                var data =result.data;
+                var index = _.findIndex(gljOprObj.sheetData,{'ID':data.ID});
+                gljOprObj.sheetData[index]=data;
                 gljOprObj.showRationGLJSheetData();
                 project.projectGLJ.loadData();
+                selected.data.adjustState=result.adjustState;
+                projectObj.mainController.refreshTreeNode([selected]);
             }
             $("#glj_tree_div").modal('hide');
         })
@@ -828,15 +835,18 @@ var gljOprObj = {
         var me=this;
         var oldData=me.sheetData[gljContextMenu.selectedRow];
         var project= projectObj.project;
-        var selectCode=gljOprObj.GLJSelection[0];
+        var selectCode=me.GLJSelection[0];
         project.ration_glj.mReplaceGLJ(selectCode,oldData,function (result) {
+            var data=result.data;
+            var stateList= result.stateList;
             _.forEach(project.ration_glj.datas,function (t) {
-                if(t.code==result.query.code&&t.name==result.query.name){
-                    me.updateProperty(t,result.doc);
+                if(t.code==data.query.code&&t.name==data.query.name){
+                    me.updateProperty(t,data.doc);
                 }
             })
-            gljOprObj.showRationGLJSheetData();
+            me.showRationGLJSheetData();
             project.projectGLJ.loadData();
+            me.refreshStateAfterMreplace(stateList);
             $("#glj_tree_div").modal('hide');
         })
     },
@@ -845,6 +855,19 @@ var gljOprObj = {
             obj[key] = n;
         });
     },
+    refreshStateAfterMreplace:function (stateList) {
+        var nodes=[];
+        _.forEach(stateList,function (s) {
+          var node = _.find(projectObj.project.mainTree.items,function (n) {
+              return n.sourceType==ModuleNames.ration&&n.data.ID==s.rationID;
+          })
+          if(node){
+              node.data.adjustState=s.adjustState;
+              nodes.push(node);
+          }
+        });
+        projectObj.mainController.refreshTreeNode(nodes);
+    },
     refreshView:function () {
         this.showRationGLJData();
     }
@@ -858,6 +881,7 @@ $(function(){
             gljOprObj.gljLibSheet = gljOprObj.gljLibSpresd.getSheet(0);
             gljOprObj.gljLibSheet.options.isProtected = true;
             gljOprObj.gljLibSheet.name('glj_lib');
+            console.log("show feeRate tree");
         }
         gljOprObj.gljLibSheetData =gljOprObj.AllRecode;
         var selected=null;

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

@@ -43,7 +43,7 @@ let MainTreeCol = {
         },
         forCalcBase: function (node) {
             // to do according to billsParentType
-            return MainTreeCol.readOnly.billsParent(node) || MainTreeCol.readOnly.non_bills(node);
+            return MainTreeCol.readOnly.billsParent(node) || MainTreeCol.readOnly.non_bills(node)||MainTreeCol.readOnly.leafBillsWithDetail(node);
         },
         forUnitFee: function (node) {
             return MainTreeCol.readOnly.ration(node) || MainTreeCol.readOnly.billsParent(node) || MainTreeCol.readOnly.leafBillsWithDetail(node);
@@ -58,8 +58,11 @@ let MainTreeCol = {
             combo.itemHeight(10).items(['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件',
                 '根', '组', '系统', '台', '套', '株', '丛', '缸', '支', '只', '块', '座', '对', '份', '樘', '攒', '榀']);
             return combo;
+        },
+        feeRate: function () {
+            return feeRateObject.getFeeRateEditCellType();
         }
-    },
+     },
     getEvent: function (eventName) {
         let names = eventName.split('.');
         let event = this;

+ 4 - 0
web/building_saas/main/js/views/options_view.js

@@ -56,6 +56,10 @@ let optionsOprObj = {
             }
         }
         return rst;
+    },
+    getOption: function (type, optionName) {
+        let opts = this.getOptsByType(this.options, type);
+        return opts[optionName];
     }
 };
 

+ 55 - 5
web/building_saas/main/js/views/project_property_labour_coe_view.js

@@ -7,10 +7,27 @@ let labourCoeView = {
     spread: null,
     sheet: null,
 
-    buildSheet: function (){
+    init(){
         let me = this;
-        me.datas = calcLabourCoes;
 
+        function getStdLabourCoeFilesHtml(stdLabourCoeLibs) {
+            let result = '<option value="">请选择人工系数标准库</option>';
+            if (stdLabourCoeLibs.length <= 0) {
+                return result;
+            };
+
+            for (let lib of stdLabourCoeLibs){
+                result += '<option value="'+ lib.id +'">'+ lib.name +'</option>';
+            };
+            return result;
+        };
+
+        let stdLCHtml = getStdLabourCoeFilesHtml(projectInfoObj.projectInfo.engineeringInfo.artificial_lib);
+        $("#std_labour_coe_files").html(stdLCHtml);
+    },
+
+    buildSheet: function (){
+        let me = this;
         if (me.spread) {
             me.spread.destroy();
             me.spread = null;
@@ -35,8 +52,9 @@ let labourCoeView = {
         sheet.resumePaint();
     },
 
-    loadData(){          // 树结构转换二维表显示,行列转换
+    loadData(datas){          // 树结构转换二维表显示,行列转换
         let me = this;
+        me.datas = datas;
         let libArr = [];
         for (let v of me.datas) {if (!v.ParentID) libArr.push(v);};
 
@@ -53,7 +71,7 @@ let labourCoeView = {
         me.sheet.setRowCount(row, GC.Spread.Sheets.SheetArea.viewport);
         me.sheet.setText(0, 0, "定额工种", GC.Spread.Sheets.SheetArea.colHeader);
         me.sheet.options.isProtected = true;
-        me.sheet.getRange(-1, 1, -1, libArr.length + 1, GC.Spread.Sheets.SheetArea.viewport).locked(false); 
+        me.sheet.getRange(-1, 1, -1, libArr.length + 1, GC.Spread.Sheets.SheetArea.viewport).locked(false);
 
         // 列名称
         for (let c = 0; c <= libArr.length - 1; c++) {
@@ -75,8 +93,10 @@ let labourCoeView = {
 
     showData(){
         let me = this;
+        let datas = projectObj.project.labourCoe.datas !== null ? projectObj.project.labourCoe.datas.coes : [];
+        me.init();
         me.buildSheet();
-        me.loadData();
+        me.loadData(datas);
     }
 };
 
@@ -84,4 +104,34 @@ $(document).ready(function(){
     $("#tab_poj-settings-6").on('shown.bs.tab', function (e) {
         labourCoeView.showData();
     });
+
+    $("#std_labour_coe_files").change(function() {
+        // 取标准库数据过来显示。
+        let libID = $(this).val();
+        if (libID == ''){
+            labourCoeView.loadData([]);
+            return false;
+        };
+
+        $.ajax({
+            type:"POST",
+            url: '/labourCoe/getStdLabourCoe',
+            data: {"ID": libID},
+            dataType: 'json',
+            cache: false,
+            timeout: 50000,
+            success: function(result){
+                if (result.error === 0) {
+                    labourCoeView.buildSheet();
+                    labourCoeView.loadData(result.data.coes);
+
+                } else {
+                    alert('error: ' + result.message);
+                }
+            },
+            error: function(jqXHR, textStatus, errorThrown){
+                alert('error ' + textStatus + " " + errorThrown);
+            }
+        });
+    });
 });

+ 111 - 11
web/building_saas/main/js/views/project_view.js

@@ -139,6 +139,7 @@ var projectObj = {
             calcFees.setFee(node.data, fieldName, value);
             calc.calcNode(node, true);
             nodes = getNodes(node);
+            project.Bills.updateNodes(nodes, true);
         } else if (node.sourceType === projectObj.project.VolumePrice.getSourceType()) {
             project.beginUpdate('VolumePrice_QuantityChange');
             project.VolumePrice.updateField(node.source, fieldName, value, false);
@@ -163,6 +164,85 @@ var projectObj = {
         this.mainController.refreshTreeNode(nodes, false);
         calc = null;
     },
+    updateBillsCode: function (node, value) {
+        let project = projectObj.project;
+        let stdMatchCode, formatCode, matchs;
+        let searchStdBillsAndUpdate = function (stdCode, formatCode) {
+            let orgCode = node.data.code.substr(0, 9);
+            if (stdCode === orgCode || projectInfoObj.projectInfo.engineeringInfo.bill_lib.length === 0) {
+                project.Bills.updateField(node.source, 'code', formatCode, true);
+                projectObj.mainController.refreshTreeNode([node], false);
+            } else if (projectInfoObj.projectInfo.engineeringInfo.bill_lib.length > 0) {
+                let libId = projectInfoObj.projectInfo.engineeringInfo.bill_lib[0].id;
+                CommonAjax.post('/stdBillsEditor/getStdBillsByCode', {userId: userID, billsLibId: libId, code: stdCode}, function (data) {
+                    if (data) {
+                        data.itemCharacter = pageCCOprObj.safeItemCharater(data.itemCharacter);
+                        if (/\//.test(data.unit)) {
+                            ConfirmModal.stdBillsUnit.check(data, function (std) {
+                                project.Bills.replaceBills(node.source, std, formatCode);
+                                projectObj.mainController.refreshTreeNode([node], false);
+                            }, function () {
+                                projectObj.mainController.refreshTreeNode([node], false);
+                            });
+                        } else {
+                            project.Bills.replaceBills(node.source, data, formatCode);
+                            projectObj.mainController.refreshTreeNode([node], false);
+                        }
+                    } else {
+                        project.Bills.updateField(node.source, 'code', formatCode, true);
+                        projectObj.mainController.refreshTreeNode([node], false);
+                    }
+                });
+            }
+        }
+        if (value.length === 9 && /^[\d]+$/.test(value)) {
+            stdMatchCode = value;
+            formatCode = project.Bills.newFormatCode(stdMatchCode);
+            searchStdBillsAndUpdate(stdMatchCode, formatCode);
+        } else if (value.length === 12 && /^[\d]+$/.test(value)) {
+            stdMatchCode = value.substr(0, 9);
+            matchs = project.Bills.sameStdCode(stdMatchCode, node.data.code);
+            if (matchs.indexOf(value) === -1) {
+                searchStdBillsAndUpdate(stdMatchCode, value);
+            } else if (confirm('已存在该编码的清单,是否继续?')) {
+                formatCode = project.Bills.newFormatCode(stdMatchCode, node.data.code);
+                searchStdBillsAndUpdate(stdMatchCode, formatCode);
+            }
+        } else {
+            project.Bills.updateField(node.source, 'code', value, true);
+            this.mainController.refreshTreeNode([node], false);
+        } 
+    },
+    updateRationCode: function (node, value) {
+        if (/[\w]{2}[\d]{4}/.test(value)) {
+            if (projectInfoObj.projectInfo.engineeringInfo.ration_lib.length === 0) {
+                alert('当前项目无定额库,请添加定额库。');
+                this.mainController.refreshTreeNode([node], false);
+            } else {
+                let libId = projectInfoObj.projectInfo.engineeringInfo.ration_lib[0].id;
+                CommonAjax.postRationLib('/rationRepository/api/matchRation', {user_id: userID, rationLibId: libId, code: value}, function (data) {
+                    if (data) {
+                        projectObj.project.Ration.replaceRation(node.source, data);
+                        projectObj.project.ration_glj.addRationGLJ(node.source, data);
+                    } else {
+                        alert('当前库中找不到定额"' + value + '"');
+                    }
+                    projectObj.mainController.refreshTreeNode([node], false);
+                });
+            }
+        } else {
+            alert('输入的定额编码有误,请检查。');
+            this.mainController.refreshTreeNode([node], false);
+        }
+    },
+    updateCode: function (node, value) {
+        let project = projectObj.project;
+        if (node.sourceType === project.Bills.getSourceType()) {
+            this.updateBillsCode(node, value);
+        } else if (node.sourceType === project.Ration.getSourceType()) {
+            this.updateRationCode(node, value);
+        }
+    },
     mainSpreadEditEnded: function (sender, info) {
         let project = projectObj.project;
         let node = project.mainTree.items[info.row];
@@ -173,7 +253,7 @@ var projectObj = {
 
         if (value && value !== calcFees.getFee(node.data, fieldName)) {
             if (fieldName === 'code') {
-
+                projectObj.updateCode(node, value);
             } else if (fieldName === 'quantity' && project.quantity_detail.quantityEditChecking(value,node,fieldName)) {
                 projectObj.updateAndReCalculate(node, fieldName, value);
             } else if (fieldName === 'feesIndex.common.unitFee') {
@@ -210,8 +290,7 @@ var projectObj = {
         this.project.loadDatas(function (err) {
             if (!err) {
                 that.project.calcFields = JSON.parse(JSON.stringify(feeType));
-                that.project.setCalcFlag(rationContent);
-
+                that.project.initCalcFields();
                 let str = JSON.stringify(that.project.projSetting.main_tree_col);
                 that.project.projSetting.mainGridSetting = JSON.parse(str);
                 that.project.projSetting.mainGridSetting.frozenCols = 4;
@@ -232,9 +311,11 @@ var projectObj = {
                         col.data.decimal = that.project.getDecimal(col.data.digit);
                         col.data.formatter = MainTreeCol.getNumberFormatter(col.data.decimal);
                     }
+                    if (col.data.field === 'code') {
+                        col.data.formatter = '@';
+                    }
                 });
 
-                that.project.calcProgram = new CalcProgram(that.project);
                 that.project.calcProgram.compileAllTemps();
 
                 that.mainController = TREE_SHEET_CONTROLLER.createNew(that.project.mainTree, that.mainSpread.getActiveSheet(), that.project.projSetting.mainGridSetting);
@@ -244,7 +325,6 @@ var projectObj = {
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, that.treeSelectedChanged);
 
                 that.mainSpread.bind(GC.Spread.Sheets.Events.EditEnded, that.mainSpreadEditEnded);
-
                 that.loadMainSpreadContextMenu();
             }
             else {
@@ -457,11 +537,31 @@ $('#downMove').click(function () {
     }
 });
 
-$('#rationContent').val(rationContent);
-$('#rationPrice').val(rationPrice);
-$('#rationPriceConverse').val(rationPriceConverse);
-$('#billsPrice').val(billsPrice);
+$('#poj-set').on('show.bs.modal', function () {
+    let setCalcFlag = function (obj, val, curFlag) {
+        obj.val(val);
+        if (val === curFlag) {
+            obj.attr('checked', true);
+        } else {
+            obj.removeAttr('checked');
+        }
+    }
+    if (projectObj.project) {
+        let mode = projectObj.project.projSetting.billsCalcMode;
+        setCalcFlag($('#rationContent'), projectObj.project.projSetting.billsCalcModeConst.rationContent, mode);
+        setCalcFlag($('#rationPrice'), projectObj.project.projSetting.billsCalcModeConst.rationPrice, mode);
+        setCalcFlag($('#rationPriceConverse'), projectObj.project.projSetting.billsCalcModeConst.rationPriceConverse, mode);
+        setCalcFlag($('#billsPrice'), projectObj.project.projSetting.billsCalcModeConst.billsPrice, mode);
+    }
+});
 $('#property_ok').click(function () {
-    projectObj.project.setCalcFlag(parseInt($("input[name='calcFlag']:checked").val()));
-    projectObj.calculateAll();
+    let project = projectObj.project, mode = parseInt($("input[name='calcFlag']:checked").val());
+    if (mode !== project.projSetting.billsCalcMode) {
+        project.setBillsCalcMode(mode);
+        projectObj.calculateAll();
+        project.pushNow('editBillsCalcMode',
+            [project.projSetting.moduleName, project.Bills.getSourceType()],
+            [{projectID: project.ID(), billsCalcMode: project.projSetting.billsCalcMode}, project.Bills.getUpdateAllData()]
+        );
+    }
 });

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

@@ -66,7 +66,7 @@ var billsLibObj = {
         var stdBillsTreeController = TREE_SHEET_CONTROLLER.createNew(stdBillsTree, billsLibObj.stdBillsSpread.getActiveSheet(), billsLibObj.stdBillsTreeSetting);
         var findData = function (value, field, Array) {
             var i = 0;
-            for (i = 0; i < Array.length - 1; i++) {
+            for (i = 0; i < Array.length; i++) {
                 if (value[field] === Array[i][field]) {
                     return Array[i];
                 }
@@ -144,10 +144,24 @@ var billsLibObj = {
 
             stdBillsTreeController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, showBillsRela);
             that.stdBillsSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, function (sender, args) {
+                let selectNode = stdBillsTree.items[args.row];
                 if (stdBillsTree.items[args.row].children.length === 0) {
                     //特征及内容转化
                     pageCCOprObj.setItemContentNode(stdBillsTree.items[args.row], getBillsJobs(stdBillsTree.items[args.row]), getBillsFeatures(stdBillsTree.items[args.row]));
-                    ProjectController.addBills(projectObj.project, projectObj.mainController, stdBillsTree.items[args.row]);
+                    if (/\//.test(selectNode.data.unit)) {
+                        let existB = projectObj.project.Bills.sameStdCodeBillsData(selectNode.data.code);
+                        if (existB) {
+                            let std = JSON.parse(JSON.stringify(selectNode.data));
+                            std.unit = existB.unit;
+                            ProjectController.addBills(projectObj.project, projectObj.mainController, std);
+                        } else {
+                            ConfirmModal.stdBillsUnit.check(selectNode.data, function (std) {
+                                ProjectController.addBills(projectObj.project, projectObj.mainController, std);
+                            });
+                        }
+                    } else {
+                        ProjectController.addBills(projectObj.project, projectObj.mainController, selectNode.data);
+                    }
                 }
             });
         }, function () {

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

@@ -86,6 +86,44 @@ var rationLibObj = {
             });
         }
     },
+    loadStdRationContextMenu: function () {
+        let rationSpread = rationLibObj.sectionRationsSpread, rationSheet = rationSpread.getActiveSheet();
+        $.contextMenu({
+            selector: '#stdSectionRations',
+            build: function ($trigger, e) {
+                let target = SheetDataHelper.safeRightClickSelection($trigger, e, rationSpread);
+                return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                "insertStdRation": {
+                    name: "插入定额",
+                    icon: 'fa-sign-in',
+                    callback: function (key, opt) {
+                        let select = $('#stdRationLibSelect'), rationSelect = rationSheet.getSelections();
+                        let rationCode = rationSelect.length > 0 ? rationSheet.getText(rationSelect[0].row, 0) : '';
+                        if (rationCode !== '') {
+                            CommonAjax.postRationLib('/rationRepository/api/getRationItem', {user_id: userID, rationLibId: select.val(), code: rationCode}, function (data) {
+                                ProjectController.addRation(projectObj.project, projectObj.mainController, data);
+                            });
+                        }
+                    }
+                },
+                "replaceStdRation": {
+                    name: "替换定额",
+                    icon: 'fa-sign-in',
+                    callback: function (key, opt) {
+                        let select = $('#stdRationLibSelect'), rationSelect = rationSheet.getSelections();
+                        let rationCode = rationSelect.length > 0 ? rationSheet.getText(rationSelect[0].row, 0) : '';
+                        if (rationCode !== '') {
+                            CommonAjax.postRationLib('/rationRepository/api/getRationItem', {user_id: userID, rationLibId: select.val(), code: rationCode}, function (data) {
+                                ProjectController.replaceRation(projectObj.project, projectObj.mainController, data);
+                            });
+                        }
+                    }
+                },
+            }
+        });
+    },
     rationChapterTreeSetting: {
         "emptyRows":0,
         "headRows":1,
@@ -195,6 +233,7 @@ $('#stdRationTab').bind('click', function () {
     rationLibObj.checkSpread();
     if (select[0].options.length === 0) {
         rationLibObj.loadStdRationLibs();
+        rationLibObj.loadStdRationContextMenu();
     };
 });
 $('#stdRationLibSelect').change(function () {

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

@@ -84,8 +84,10 @@ $("#linkJSCX").click(function(){        // 计算程序
     refreshSubSpread();
     subSpread.setActiveSheetIndex(4);
     calcProgramObj.initSheet(subSpread.getSheet(4));
-    let sel = projectObj.mainController.tree.selected;
 
+    if (!projectObj.mainController.tree.selected)
+        projectObj.mainController.tree.selected = projectObj.mainController.tree.firstNode();
+    let sel = projectObj.mainController.tree.selected;
     if (sel.sourceType === projectObj.project.Bills.getSourceType() || sel.sourceType === projectObj.project.Ration.getSourceType()) {
         calcProgramObj.showData(sel);
     } else {

+ 7 - 0
web/building_saas/pm/js/pm_main.js

@@ -741,12 +741,19 @@ function AddTender() {
                 break;
             }
         }
+
+        let libs = null;
         for(let tmp of engineeringList) {
             if (tmp.engineering == engineering) {
                 engineering_id = tmp.engineering_id;
+                libs = tmp.lib;
                 break;
             }
         }
+        // 一个项目里面,这两个文件必须得有,而界面又没有像费率、单价文件那样给出可选项。所以这里给出提示。
+        if (!libs.artificial_lib)  throw '编办没有绑定人工系数标准文件';
+        if (!libs.program_lib)  throw '编办没有绑定计算程序标准文件';
+
         let engineeringName = $('#tender-engineering').children("option:selected").text();
 
         let callback = function() {

BIN
web/dest/css/img/feeRate_btn.jpg