Bläddra i källkod

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

zhongzewei 7 år sedan
förälder
incheckning
353e9ceb25
71 ändrade filer med 2729 tillägg och 1036 borttagningar
  1. 5 2
      config/gulpConfig.js
  2. 2 2
      gulpfile.js
  3. 54 1
      modules/fee_rates/controllers/fee_rates_controller.js
  4. 9 9
      modules/fee_rates/facade/fee_rates_facade.js
  5. 3 1
      modules/fee_rates/routes/fee_rates_route.js
  6. 60 0
      modules/glj/controllers/glj_controller.js
  7. 9 6
      modules/glj/models/glj_list_model.js
  8. 3 0
      modules/glj/models/schemas/mix_ratio.js
  9. 2 0
      modules/glj/models/schemas/unit_price.js
  10. 2 2
      modules/glj/models/unit_price_model.js
  11. 1 0
      modules/glj/routes/glj_router.js
  12. 18 2
      modules/main/controllers/labour_coe_controller.js
  13. 4 0
      modules/main/controllers/project_controller.js
  14. 1 0
      modules/main/facade/calc_program_facade.js
  15. 34 2
      modules/main/facade/labour_coe_facade.js
  16. 28 5
      modules/main/models/project.js
  17. 1 0
      modules/main/routes/labour_coe_route.js
  18. 1 1
      modules/pm/models/project_model.js
  19. 44 35
      modules/reports/controllers/rpt_controller.js
  20. 3 0
      modules/reports/controllers/rpt_tpl_controller.js
  21. 1 0
      modules/reports/models/rpt_template.js
  22. 10 4
      modules/reports/routes/report_router.js
  23. 1 0
      modules/reports/rpt_component/jpc_ex.js
  24. 321 77
      modules/reports/util/rpt_construct_data_util.js
  25. 57 20
      public/calc_util.js
  26. 8 8
      public/fsUtil.js
  27. 6 6
      public/scMathUtil.js
  28. 10 11
      public/treeUtil.js
  29. 82 0
      public/web/PerfectLoad.js
  30. 0 23
      public/web/calculation/calc_util.js
  31. 12 3
      public/web/number_util.js
  32. 8 5
      public/web/rpt_value_define.js
  33. 40 24
      public/web/scMathUtil.js
  34. 20 21
      public/web/sheet/sheet_common.js
  35. 62 42
      public/web/treeDataHelper.js
  36. 13 0
      test/calculation/testArrayCalc.js
  37. 337 0
      test/unit/reports/rpt_cfg.js
  38. 79 53
      test/unit/reports/test_tpl_09_1.js
  39. 3 11
      web/building_saas/fee_rates/fee_rate.html
  40. 2 2
      web/building_saas/glj/html/glj_index.html
  41. 1 1
      web/building_saas/glj/js/common_spread.js
  42. 3 0
      web/building_saas/glj/js/composition.js
  43. 1 1
      web/building_saas/glj/js/composition_spread.js
  44. 1 0
      web/building_saas/glj/js/project_glj.js
  45. 7 7
      web/building_saas/main/html/calc_program_manage.html
  46. 161 308
      web/building_saas/main/html/main.html
  47. 13 8
      web/building_saas/main/js/controllers/project_controller.js
  48. 13 0
      web/building_saas/main/js/main.js
  49. 77 0
      web/building_saas/main/js/models/composition.js
  50. 179 44
      web/building_saas/main/js/models/fee_rate.js
  51. 17 0
      web/building_saas/main/js/models/labour_coe.js
  52. 16 1
      web/building_saas/main/js/models/main_consts.js
  53. 3 1
      web/building_saas/main/js/models/project.js
  54. 2 0
      web/building_saas/main/js/models/ration.js
  55. 0 66
      web/building_saas/main/js/rpt/rpt_main.js
  56. 47 32
      web/building_saas/main/js/views/calc_program_manage.js
  57. 12 9
      web/building_saas/main/js/views/calc_program_view.js
  58. 180 149
      web/building_saas/main/js/views/fee_rate_view.js
  59. 5 1
      web/building_saas/main/js/views/glj_view.js
  60. 3 0
      web/building_saas/main/js/views/main_tree_col.js
  61. 57 23
      web/building_saas/main/js/views/project_property_labour_coe_view.js
  62. 14 3
      web/building_saas/main/js/views/project_view.js
  63. 1 0
      web/building_saas/main/js/views/sub_fee_rate_views.js
  64. 6 0
      web/building_saas/main/js/views/sub_view.js
  65. 160 0
      web/building_saas/report/html/rpt_main.html
  66. 209 0
      web/building_saas/report/js/jpc_output.js
  67. 49 0
      web/building_saas/report/js/jpc_output_value_define.js
  68. 5 4
      web/building_saas/main/js/rpt/rpt_cfg_const.js
  69. 128 0
      web/building_saas/report/js/rpt_main.js
  70. 2 0
      web/common/html/header.html
  71. 1 0
      web/users/html/login.html

+ 5 - 2
config/gulpConfig.js

@@ -8,7 +8,9 @@ module.exports = {
         'lib/jquery/jquery-3.2.1.min.js',
         'lib/jquery/jquery-3.2.1.min.js',
         'lib/popper/popper.min.js',
         'lib/popper/popper.min.js',
         'lib/bootstrap/bootstrap.min.js',
         'lib/bootstrap/bootstrap.min.js',
-        'web/building_saas/js/*.js'
+        'web/building_saas/js/*.js',
+        'public/web/scMathUtil.js',
+        'public/web/PerfectLoad.js'
     ],
     ],
     common_css:[
     common_css:[
         'lib/bootstrap/css/bootstrap.min.css',
         'lib/bootstrap/css/bootstrap.min.css',
@@ -38,6 +40,7 @@ module.exports = {
         '!lib/JSExpressionEval_src/JsHashMap.js',
         '!lib/JSExpressionEval_src/JsHashMap.js',
         'lib/jquery-contextmenu/*.js',
         'lib/jquery-contextmenu/*.js',
         'lib/lodash/lodash.js',
         'lib/lodash/lodash.js',
+        'web/building_saas/main/js/models/main_consts.js',
         'web/building_saas/glj/js/project_glj.js',
         'web/building_saas/glj/js/project_glj.js',
         'web/building_saas/glj/js/composition.js',
         'web/building_saas/glj/js/composition.js',
         'web/building_saas/glj/js/common_spread.js',
         'web/building_saas/glj/js/common_spread.js',
@@ -58,12 +61,12 @@ module.exports = {
        // 'lib/spreadjs/views/gc.spread.views.dataview.10.0.0.min.js',
        // 'lib/spreadjs/views/gc.spread.views.dataview.10.0.0.min.js',
        // "lib/spreadjs/views/common/gc.spread.common.10.0.0.min.js",
        // "lib/spreadjs/views/common/gc.spread.common.10.0.0.min.js",
       //  'lib/spreadjs/views/plugins/gc.spread.views.gridlayout.10.0.0.min.js',
       //  'lib/spreadjs/views/plugins/gc.spread.views.gridlayout.10.0.0.min.js',
-        'web/building_saas/main/js/models/main_consts.js',
         'web/building_saas/main/js/models/project.js',
         'web/building_saas/main/js/models/project.js',
         'web/building_saas/main/js/models/bills.js',
         'web/building_saas/main/js/models/bills.js',
         'web/building_saas/main/js/models/ration.js',
         'web/building_saas/main/js/models/ration.js',
         'web/building_saas/main/js/models/glj.js',
         'web/building_saas/main/js/models/glj.js',
         'web/building_saas/main/js/models/project_glj.js',
         'web/building_saas/main/js/models/project_glj.js',
+        'web/building_saas/main/js/models/composition.js',
         'web/building_saas/main/js/models/fee_rate.js',
         'web/building_saas/main/js/models/fee_rate.js',
         'web/building_saas/main/js/models/ration_glj.js',
         'web/building_saas/main/js/models/ration_glj.js',
         'web/building_saas/main/js/models/ration_coe.js',
         'web/building_saas/main/js/models/ration_coe.js',

+ 2 - 2
gulpfile.js

@@ -81,7 +81,7 @@ function minify(options) {
     if(options.jspaths){
     if(options.jspaths){
         return gulp.src(options.jspaths)
         return gulp.src(options.jspaths)
             .pipe($.plumber())
             .pipe($.plumber())
-           // .pipe(uglify())
+            .pipe(uglify())
             .pipe($.concat(options.concatName+"."+version+".js"))
             .pipe($.concat(options.concatName+"."+version+".js"))
             .pipe(gulp.dest(scriptsDest));
             .pipe(gulp.dest(scriptsDest));
     }
     }
@@ -110,7 +110,7 @@ function inject(options) {
 
 
 function htmlmin(options) {
 function htmlmin(options) {
     return gulp.src(options.htmlDest+'/*.html')
     return gulp.src(options.htmlDest+'/*.html')
-    //  .pipe($.htmlmin({collapseWhitespace: true}))
+       // .pipe($.htmlmin({collapseWhitespace: true}))
         .pipe(gulp.dest(options.htmlDest));
         .pipe(gulp.dest(options.htmlDest));
 }
 }
 
 

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

@@ -54,7 +54,10 @@ module.exports = {
     getChangeInfo:getChangeInfo,
     getChangeInfo:getChangeInfo,
     changeFeeRateFileFromCurrent:changeFeeRateFileFromCurrent,
     changeFeeRateFileFromCurrent:changeFeeRateFileFromCurrent,
     changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
     changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
-    setFeeRateToBill:setFeeRateToBill
+    setFeeRateToBill:setFeeRateToBill,
+    updateFeeRate:updateFeeRate,
+    updateRates:updateRates,
+    feeRateFileSaveAs:feeRateFileSaveAs
 }
 }
 
 
 function libNames(req, res) {
 function libNames(req, res) {
@@ -193,4 +196,54 @@ async function setFeeRateToBill(req,res) {
         result.message = err.message;
         result.message = err.message;
     }
     }
     res.json(result);
     res.json(result);
+}
+
+async function updateFeeRate(req,res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        let uresult= await feeRateFacde.updateFeeRate(data);
+        result.data=uresult;
+    }catch (err){
+        console.log(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
+function updateRates(req,res){
+    let result={
+        error:0
+    }
+    let data = req.body.data;
+    data=JSON.parse(data);
+    feeRateFacde.updateRates(data.user_id,data)(function (err,re) {
+        if(err){
+            result.error=1;
+            result.message = err.message;
+        }else {
+            result.data = re;
+        }
+        res.json(result);
+    })
+}
+
+function feeRateFileSaveAs(req,res){
+    let result={
+        error:0
+    }
+    let data = req.body.data;
+    data=JSON.parse(data);
+    feeRateFacde.feeRateFileSaveAs(data.user_id,data)(function (err,re) {
+        if(err){
+            result.error=1;
+            result.message = err.message;
+        }else {
+            result.data = re;
+        }
+        res.json(result);
+    })
 }
 }

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

@@ -27,8 +27,11 @@ module.exports={
     changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
     changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
     newFeeRateFile:newFeeRateFile,
     newFeeRateFile:newFeeRateFile,
     getFeeRatesByProject:getFeeRatesByProject,
     getFeeRatesByProject:getFeeRatesByProject,
+    getGCFeeRateFiles: getGCFeeRateFiles ,
     setFeeRateToBill:setFeeRateToBill,
     setFeeRateToBill:setFeeRateToBill,
-    getGCFeeRateFiles: getGCFeeRateFiles
+    updateFeeRate:updateFeeRate,
+    updateRates:update_rates,
+    feeRateFileSaveAs:feeRateFileSaveAs
 };
 };
 let operationMap={
 let operationMap={
     'ut_create':create_fee_rate,
     'ut_create':create_fee_rate,
@@ -43,14 +46,6 @@ let updateFunctionMap = {
     'feeRateFileSaveAs':feeRateFileSaveAs
     'feeRateFileSaveAs':feeRateFileSaveAs
 }
 }
 
 
-//测试数据 key projectID, value feeRateFileID
-let project_feeRateF_map={
-    99:'da059df1-7c18-11e7-9e2f-1390b52643b4'
-}
-
-
-
-
 
 
 function create_fee_rate() {
 function create_fee_rate() {
 
 
@@ -359,6 +354,11 @@ async function setFeeRateToBill(data){
     return "ok";
     return "ok";
 }
 }
 
 
+async function updateFeeRate(data) {
+    data=JSON.parse(data);
+   return  await feeRateModel.findOneAndUpdate(data.query,data.doc);
+}
+
 async function changeFeeRateFileFromCurrent(jdata){
 async function changeFeeRateFileFromCurrent(jdata){
     let data = JSON.parse(jdata);
     let data = JSON.parse(jdata);
     let newFeeRateFile=data.newFeeRateFile;
     let newFeeRateFile=data.newFeeRateFile;

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

@@ -19,7 +19,9 @@ module.exports = function (app) {
     frRouter.post('/changeFeeRateFileFromCurrent', frController.changeFeeRateFileFromCurrent);
     frRouter.post('/changeFeeRateFileFromCurrent', frController.changeFeeRateFileFromCurrent);
     frRouter.post('/changeFeeRateFileFromOthers', frController.changeFeeRateFileFromOthers);
     frRouter.post('/changeFeeRateFileFromOthers', frController.changeFeeRateFileFromOthers);
     frRouter.post('/setFeeRateToBill', frController.setFeeRateToBill);
     frRouter.post('/setFeeRateToBill', frController.setFeeRateToBill);
-
+    frRouter.post('/updateFeeRate', frController.updateFeeRate);
+    frRouter.post('/updateRates', frController.updateRates);
+    frRouter.post('/feeRateFileSaveAs', frController.feeRateFileSaveAs);
     app.use('/feeRates',frRouter);
     app.use('/feeRates',frRouter);
 }
 }
 
 

+ 60 - 0
modules/glj/controllers/glj_controller.js

@@ -428,6 +428,66 @@ class GLJController extends BaseController {
     }
     }
 
 
     /**
     /**
+     * 获取项目中所有组成物数据(用户缓存到前端变量)
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async getComposition(request, response) {
+        let projectId = request.body.project_id;
+        projectId = parseInt(projectId);
+
+        let responseData = {
+            err: 0,
+            data: null
+        };
+        try {
+            // 当前单价文件id
+            let currentUnitPriceId = await ProjectModel.getUnitPriceFileId(projectId);
+            if (currentUnitPriceId <= 0) {
+                throw '没有找到对应的单价文件';
+            }
+
+            // 获取组成物数据
+            let mixRatioModel = new MixRatioModel();
+            let compositionData = await mixRatioModel.findDataByCondition({unit_price_file_id: currentUnitPriceId}, null, false);
+            if (compositionData === null) {
+                throw '没有找到组成物数据';
+            }
+            compositionData = JSON.parse(JSON.stringify(compositionData));
+            // 查找对应的单价数据
+            let unitPriceModel = new UnitPriceModel();
+            let unitPriceData = await unitPriceModel.findDataByCondition({unit_price_file_id: currentUnitPriceId}, null, false, 'glj_id');
+
+            // 整理数据
+            let result = {};
+            for(let composition of compositionData) {
+                let tmpId = composition.glj_id !== undefined ? composition.glj_id : -1;
+                let tmpData = {
+                    market_price: unitPriceData[tmpId] !== undefined ?
+                        unitPriceData[tmpId].market_price : 0,
+                    base_price: unitPriceData[tmpId] !== undefined ?
+                        unitPriceData[tmpId].base_price : 0,
+                    consumption: composition.consumption,
+                    glj_type: composition.glj_type,
+                    connect_code: composition.connect_code
+                };
+                if (result[tmpId] === undefined) {
+                    result[tmpId] = [];
+                }
+                result[tmpId].push(tmpData);
+            }
+            responseData.data = result;
+        } catch (error) {
+            responseData.err = 1;
+            responseData.data = null;
+        }
+
+        response.json(responseData);
+    }
+
+    /**
      * 模拟定额插入
      * 模拟定额插入
      *
      *
      * @param {object} request
      * @param {object} request

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

@@ -16,6 +16,7 @@ import STDGLJLibGLJListModel from "../../common/std/std_glj_lib_glj_list_model";
 import MixRatioModel from "./mix_ratio_model";
 import MixRatioModel from "./mix_ratio_model";
 import GljModel from "../../complementary_glj_lib/models/gljModel";
 import GljModel from "../../complementary_glj_lib/models/gljModel";
 const ProjectModel = require('../../pm/models/project_model').project;
 const ProjectModel = require('../../pm/models/project_model').project;
+const scMathUtil = require('../../../public/scMathUtil').getUtil();
 
 
 class GLJListModel extends BaseModel {
 class GLJListModel extends BaseModel {
 
 
@@ -130,7 +131,7 @@ class GLJListModel extends BaseModel {
                 for (let tmp of mixRatioList) {
                 for (let tmp of mixRatioList) {
                     totalComposition[tmp.connect_code] = totalComposition[tmp.connect_code] === undefined ? tmp.consumption :
                     totalComposition[tmp.connect_code] = totalComposition[tmp.connect_code] === undefined ? tmp.consumption :
                         totalComposition[tmp.connect_code] + tmp.consumption;
                         totalComposition[tmp.connect_code] + tmp.consumption;
-                    totalComposition[tmp.connect_code] = Number(totalComposition[tmp.connect_code].toFixed(4));
+                    totalComposition[tmp.connect_code] = scMathUtil.roundTo(totalComposition[tmp.connect_code], -4);
 
 
                     if (mixRatioData[tmp.glj_id] !== undefined) {
                     if (mixRatioData[tmp.glj_id] !== undefined) {
                         mixRatioData[tmp.glj_id].push(tmp);
                         mixRatioData[tmp.glj_id].push(tmp);
@@ -204,18 +205,18 @@ class GLJListModel extends BaseModel {
             glj.quantity = quantityList[projectGljId] !== undefined ? quantityList[projectGljId] : 0;
             glj.quantity = quantityList[projectGljId] !== undefined ? quantityList[projectGljId] : 0;
             glj.quantity = totalComposition[glj.code] !== undefined ? totalComposition[glj.code] : glj.quantity;
             glj.quantity = totalComposition[glj.code] !== undefined ? totalComposition[glj.code] : glj.quantity;
             glj.quantity = compositionConsumption[gljId] !== undefined ?  glj.quantity + compositionConsumption[gljId] : glj.quantity;
             glj.quantity = compositionConsumption[gljId] !== undefined ?  glj.quantity + compositionConsumption[gljId] : glj.quantity;
-            glj.quantity = parseFloat(glj.quantity).toFixed(3);
+            glj.quantity = scMathUtil.roundTo(parseFloat(glj.quantity), -3);
 
 
             // 组成物数据
             // 组成物数据
             gljList[index].ratio_data = mixRatioData[gljId] !== undefined ? mixRatioData[gljId] : [];
             gljList[index].ratio_data = mixRatioData[gljId] !== undefined ? mixRatioData[gljId] : [];
 
 
-            glj.unit_price.base_price = parseFloat(glj.unit_price.base_price).toFixed(2);
-            glj.unit_price.market_price = parseFloat(glj.unit_price.market_price).toFixed(2);
+            glj.unit_price.base_price = scMathUtil.roundTo(parseFloat(glj.unit_price.base_price), -2);
+            glj.unit_price.market_price = scMathUtil.roundTo(parseFloat(glj.unit_price.market_price), -2);
             // 计算调整基价
             // 计算调整基价
             switch (glj.unit_price.type + '') {
             switch (glj.unit_price.type + '') {
                 // 人工: 调整基价=基价单价*调整系数
                 // 人工: 调整基价=基价单价*调整系数
                 case GLJTypeConst.LABOUR:
                 case GLJTypeConst.LABOUR:
-                    glj.adjust_price = parseFloat(glj.adjustment * glj.unit_price.base_price).toFixed(2);
+                    glj.adjust_price = scMathUtil.roundTo(parseFloat(glj.adjustment * glj.unit_price.base_price), -2);
                     break;
                     break;
                 // 机械类型的算法
                 // 机械类型的算法
                 case GLJTypeConst.MACHINE:
                 case GLJTypeConst.MACHINE:
@@ -439,7 +440,8 @@ class GLJListModel extends BaseModel {
                 glj_id: tmp.ID,
                 glj_id: tmp.ID,
                 unit_price_file_id: unitPriceFileId,
                 unit_price_file_id: unitPriceFileId,
                 connect_code: tmp.connectCode,
                 connect_code: tmp.connectCode,
-                glj_type: tmp.gljType
+                glj_type: tmp.gljType,
+                code: tmp.code,
             };
             };
             mixRatioInsertData.push(mixRatioData);
             mixRatioInsertData.push(mixRatioData);
         }
         }
@@ -484,6 +486,7 @@ class GLJListModel extends BaseModel {
                 unit_price_file_id: unitPriceFileId,
                 unit_price_file_id: unitPriceFileId,
                 type: tmp.gljType,
                 type: tmp.gljType,
                 short_name: tmp.shortName === undefined ? '' : tmp.shortName,
                 short_name: tmp.shortName === undefined ? '' : tmp.shortName,
+                glj_id: tmp.ID,
             };
             };
             unitPriceInsertData.push(unitPriceData);
             unitPriceInsertData.push(unitPriceData);
         }
         }

+ 3 - 0
modules/glj/models/schemas/mix_ratio.js

@@ -29,6 +29,9 @@ let modelSchema = {
         type: String,
         type: String,
         index: true
         index: true
     },
     },
+    // 对应工料机code
+    code: String,
+    // 工料机类型
     glj_type: Number
     glj_type: Number
 };
 };
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

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

@@ -32,6 +32,8 @@ let modelSchema = {
     short_name: String,
     short_name: String,
     // 单价文件表id
     // 单价文件表id
     unit_price_file_id: Number,
     unit_price_file_id: Number,
+    // 对应标准库工料机id
+    glj_id: Number
 };
 };
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 export {model as default, collectionName as collectionName};
 export {model as default, collectionName as collectionName};

+ 2 - 2
modules/glj/models/unit_price_model.js

@@ -107,7 +107,6 @@ class UnitPriceModel extends BaseModel {
             data.name = regular.test(data.name) ? data.name.replace(regular, changeString) :
             data.name = regular.test(data.name) ? data.name.replace(regular, changeString) :
                 data.name + changeString;
                 data.name + changeString;
         }
         }
-
         let insertData = {
         let insertData = {
             code: data.code,
             code: data.code,
             base_price: data.base_price,
             base_price: data.base_price,
@@ -115,7 +114,8 @@ class UnitPriceModel extends BaseModel {
             unit_price_file_id: unitPriceFileId,
             unit_price_file_id: unitPriceFileId,
             name: data.name,
             name: data.name,
             type: data.type,
             type: data.type,
-            short_name: data.shortName !== undefined ? data.shortName : ''
+            short_name: data.shortName !== undefined ? data.shortName : '',
+            glj_id: data.glj_id
         };
         };
 
 
         let addPriceResult = await this.add(insertData);
         let addPriceResult = await this.add(insertData);

+ 1 - 0
modules/glj/routes/glj_router.js

@@ -20,6 +20,7 @@ router.post('/delete-ratio', gljController.init, gljController.deleteMixRatio);
 router.post('/get-project-info', gljController.init, gljController.getProjectInfo);
 router.post('/get-project-info', gljController.init, gljController.getProjectInfo);
 router.post('/change-file', gljController.init, gljController.changeUnitPriceFile);
 router.post('/change-file', gljController.init, gljController.changeUnitPriceFile);
 router.post('/save-as', gljController.init, gljController.unitPriceSaveAs);
 router.post('/save-as', gljController.init, gljController.unitPriceSaveAs);
+router.post('/get-composition', gljController.init, gljController.getComposition);
 
 
 router.get('/test', gljController.init, gljController.test);
 router.get('/test', gljController.init, gljController.test);
 router.get('/testModify', gljController.init, gljController.testModify);
 router.get('/testModify', gljController.init, gljController.testModify);

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

@@ -7,7 +7,8 @@ let labourCoeFacade = require('../facade/labour_coe_facade');
 
 
 module.exports = {
 module.exports = {
     getProjectLabourCoe: getProjectLabourCoe,
     getProjectLabourCoe: getProjectLabourCoe,
-    getStdLabourCoe: getStdLabourCoe
+    getStdLabourCoe: getStdLabourCoe,
+    save: save
 };
 };
 
 
 async function getProjectLabourCoe(req, res) {
 async function getProjectLabourCoe(req, res) {
@@ -29,7 +30,7 @@ async function getStdLabourCoe(req, res) {
     let result = {error: 0, message: '', data: null};
     let result = {error: 0, message: '', data: null};
 
 
     try {
     try {
-        let stdLC = await labourCoeFacade.getStdLabourCoe(req.body.ID);
+        let stdLC = await labourCoeFacade.getStdLabourCoe(JSON.parse(req.body.data).ID);
         result.data= stdLC;
         result.data= stdLC;
     }catch (err){
     }catch (err){
         console.log(err);
         console.log(err);
@@ -39,3 +40,18 @@ async function getStdLabourCoe(req, res) {
 
 
     res.json(result);
     res.json(result);
 };
 };
+
+function save(req, res) {
+    let result = {error: 0, message: '', data: null};
+
+    labourCoeFacade.save(req.body.data, function (err, message, data) {
+        if (err == 0){
+            result.data = data;
+        }else{
+            result.error = 1;
+            result.message = message;
+        }
+    });
+
+    res.json(result);
+};

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

@@ -22,6 +22,10 @@ module.exports = {
     },
     },
     getData: function (req, res) {
     getData: function (req, res) {
         var data = JSON.parse(req.body.data);
         var data = JSON.parse(req.body.data);
+        // 注释代码用于测试getFilterData
+        // Project.getFilterData(data.project_id, ['bills', 'projectGLJ'], function (err, result) {
+        //     console.log(result);
+        // });
         Project.getData(data.project_id, function (err, message, result) {
         Project.getData(data.project_id, function (err, message, result) {
             if (!err) {
             if (!err) {
                 callback(req, res, err, message, result);
                 callback(req, res, err, message, result);

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

@@ -88,6 +88,7 @@ function save (user_id, datas, callback) {
 }
 }
 
 
 function saveCalcItem(dataObj, callback) {
 function saveCalcItem(dataObj, callback) {
+    dataObj=JSON.parse(dataObj);
     projectCalcProgramsModel.findOne({projectID: dataObj.projectID}, function (err, data) {
     projectCalcProgramsModel.findOne({projectID: dataObj.projectID}, function (err, data) {
         if(!err){
         if(!err){
             for (let i = 0; i < data.templates.length; i++){
             for (let i = 0; i < data.templates.length; i++){

+ 34 - 2
modules/main/facade/labour_coe_facade.js

@@ -83,6 +83,38 @@ function getData(projectID, callback) {
 };
 };
 
 
 // 统一的 save() 方法供project调用
 // 统一的 save() 方法供project调用
-function save (user_id, datas, callback) {
-    projectLabourCoesModel.update({"projectID": 553}, {"libName":"goo"}, callback(null, {data: 'ok'}));
+// data 格式要求:{projectID: projectID, libID: libID, libName: libName, newItemArr: needUpdateDatas}
+// needUpdateDatas: [{ID: 5, value: 2.87}, {ID: 13, value: 2.91}]
+function save (data, callback) {
+    let updateArr = [];
+    let datas = JSON.parse(data);
+
+    if (datas.libID){
+        let ItemObj = {
+            updateOne: {
+                filter: {projectID: datas.projectID},
+                update: { 'libID': datas.projectID, 'libName': datas.libName }
+            }
+        };
+        updateArr.push(ItemObj);
+    };
+
+    for (let Item of datas.newItemArr) {
+         let ItemObj = {
+             updateOne: {
+                 filter: {projectID: datas.projectID, 'coes.ID': Item.ID},
+                 update: { 'coes.$.coe': Item.coe }
+             }
+         };
+         updateArr.push(ItemObj);
+    };
+    // console.log(JSON.stringify(updateArr));
+    projectLabourCoesModel.bulkWrite(updateArr)
+        .then(function(){
+            logger.info(`Project LabourCoe saved successful : ${datas.projectID}`);
+            callback(0, '', null);
+        })
+        .catch(function (err) {
+            logger.err(err);
+            callback(1, err, null)});
 }
 }

+ 28 - 5
modules/main/models/project.js

@@ -14,9 +14,13 @@ let projSetting = require('./proj_setting_model');
 let volumePriceData = require('../../volume_price/models/volume_price_model');
 let volumePriceData = require('../../volume_price/models/volume_price_model');
 var labour_coe_facade = require('../facade/labour_coe_facade');
 var labour_coe_facade = require('../facade/labour_coe_facade');
 var calc_program_facade = require('../facade/calc_program_facade');
 var calc_program_facade = require('../facade/calc_program_facade');
+
+const ProjectModel = require('../../pm/models/project_model').project;
+import GLJListModel from "../../glj/models/glj_list_model";
+
 var consts = require('./project_consts');
 var consts = require('./project_consts');
 var projectConsts = consts.projectConst;
 var projectConsts = consts.projectConst;
-var async = require("async");
+var asyncTool = require("async");
 
 
 var moduleMap = {};
 var moduleMap = {};
 
 
@@ -73,7 +77,7 @@ Project.prototype.save = function(datas, callback){
         functions.push(saveModule(item));
         functions.push(saveModule(item));
     }
     }
 
 
-    async.parallel(functions, function(err, results) {
+    asyncTool.parallel(functions, function(err, results) {
         if (!err){
         if (!err){
             callback(null, '', results)
             callback(null, '', results)
         }
         }
@@ -98,7 +102,7 @@ Project.prototype.getData = function(projectID, callback){
         })(itemName))
         })(itemName))
     }
     }
 
 
-    async.parallel(functions, function(err, results) {
+    asyncTool.parallel(functions, function(err, results) {
         if (!err){
         if (!err){
             callback(null, '', results)
             callback(null, '', results)
         }
         }
@@ -111,11 +115,29 @@ Project.prototype.getData = function(projectID, callback){
 Project.prototype.getFilterData = function (projectID, filter, callback) {
 Project.prototype.getFilterData = function (projectID, filter, callback) {
     let functions = [];
     let functions = [];
     let getModuleData = function (moduleName) {
     let getModuleData = function (moduleName) {
-        return function (cb) {
+        return async function (cb) {
             if (moduleMap[moduleName]) {
             if (moduleMap[moduleName]) {
                 moduleMap[moduleName].getData(projectID, function (err, name, data) {
                 moduleMap[moduleName].getData(projectID, function (err, name, data) {
                     cb(err, {'moduleName': name, 'data': data})
                     cb(err, {'moduleName': name, 'data': data})
                 });
                 });
+            } else if (moduleName === projectConsts.PROJECTGLJ) {
+                try {
+                    if (isNaN(projectID) || projectID <= 0) {
+                        throw '标段id有误';
+                    }
+                    // 获取标段对应的单价文件id
+                    let unitPriceFileId = await ProjectModel.getUnitPriceFileId(projectID);
+                    if (unitPriceFileId <= 0) {
+                        throw '没有对应的单价文件';
+                    }
+                    // 先获取对应标段的项目工料机数据
+                    let gljListModel = new GLJListModel();
+                    let [gljList, mixRatioConnectData] = await gljListModel.getListByProjectId(projectID, unitPriceFileId);
+
+                    cb(null, {'moduleName': moduleName, 'data': gljList});
+                } catch (error) {
+                    cb(error, null);
+                }
             } else {
             } else {
                 throw '要查询的项目模块不存在';
                 throw '要查询的项目模块不存在';
             }
             }
@@ -124,7 +146,8 @@ Project.prototype.getFilterData = function (projectID, filter, callback) {
     for (let itemName of filter) {
     for (let itemName of filter) {
         functions.push(getModuleData(itemName));
         functions.push(getModuleData(itemName));
     }
     }
-    async.parallel(functions, function (err, results) {
+    asyncTool.parallel(functions, function (err, results) {
+        //console.log(results);
         if (err) {
         if (err) {
             throw '获取项目数据出错';
             throw '获取项目数据出错';
         } else {
         } else {

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

@@ -11,6 +11,7 @@ module.exports = function (app) {
 
 
     lcRouter.post('/getProjectLabourCoe', lcController.getProjectLabourCoe);
     lcRouter.post('/getProjectLabourCoe', lcController.getProjectLabourCoe);
     lcRouter.post('/getStdLabourCoe', lcController.getStdLabourCoe);
     lcRouter.post('/getStdLabourCoe', lcController.getStdLabourCoe);
+    lcRouter.post('/save', lcController.save);
 
 
     app.use('/labourCoe',lcRouter);
     app.use('/labourCoe',lcRouter);
 }
 }

+ 1 - 1
modules/pm/models/project_model.js

@@ -86,7 +86,7 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
                         name: data.updateData.name,
                         name: data.updateData.name,
                         project_id: data.updateData.ID,
                         project_id: data.updateData.ID,
                         user_id: userId,
                         user_id: userId,
-                        root_project_id: data.property.rootProjectID
+                        root_project_id: data.updateData.property.rootProjectID
                     };
                     };
                     let addResult = await unitPriceFileModel.add(insertData);
                     let addResult = await unitPriceFileModel.add(insertData);
                     if (!addResult) {
                     if (!addResult) {

+ 44 - 35
modules/reports/controllers/rpt_controller.js

@@ -8,6 +8,9 @@ import async from "async";
 import JV from "../rpt_component/jpc_value_define";
 import JV from "../rpt_component/jpc_value_define";
 
 
 let Template = mongoose.model('rpt_templates');
 let Template = mongoose.model('rpt_templates');
+let rptTplDataFacade = require("../facade/rpt_tpl_data_facade");
+//let fsUtil = require("../../../public/fsUtil");
+
 import rptTplFacade from "../facade/rpt_template_facade";
 import rptTplFacade from "../facade/rpt_template_facade";
 import demoTemplateFacade from "../facade/rpt_tpl_data_demo_facade";
 import demoTemplateFacade from "../facade/rpt_tpl_data_demo_facade";
 
 
@@ -17,6 +20,7 @@ import rpt_xl_util from "../util/rpt_excel_util";
 import rpt_pdf_util from "../util/rpt_pdf_util";
 import rpt_pdf_util from "../util/rpt_pdf_util";
 import fs from "fs";
 import fs from "fs";
 import strUtil from "../../../public/stringUtil";
 import strUtil from "../../../public/stringUtil";
+import rptDataExtractor from "../util/rpt_construct_data_util";
 
 
 //统一回调函数
 //统一回调函数
 let callback = function(req, res, err, data){
 let callback = function(req, res, err, data){
@@ -68,42 +72,36 @@ function getAllPagesCommonOrg(rpt_id, pageSize, option, cb) {
     );
     );
 }
 }
 
 
-function getAllPagesCommon(rpt_id, pageSize, cb) {
+function getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, option, cb) {
     let rptTpl = null;
     let rptTpl = null;
     rptTplFacade.getRptTemplate(rpt_id).then(function(rst) {
     rptTplFacade.getRptTemplate(rpt_id).then(function(rst) {
         rptTpl = rst;
         rptTpl = rst;
         if (rptTpl) {
         if (rptTpl) {
-            let tplData = {};
-            if (rptTpl[JV.NODE_FIELD_MAP]) {
-                //1. 离散数据
-                if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS] && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS].length > 0) {
-                    tplData[JV.DATA_DISCRETE_DATA] = [];
-                }
-                //2. 主数据
-                if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS] && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS].length > 0) {
-                    tplData[JV.DATA_MASTER_DATA] = [];
-                }
-                //3. 从数据
-                if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS] && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS].length > 0) {
-                    tplData[JV.DATA_DETAIL_DATA] = [];
-                }
-                //2. Ex主数据
-                if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS_EX] && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS_EX].length > 0) {
-                    tplData[JV.DATA_MASTER_DATA_EX] = [];
-                }
-                //3. Ex从数据
-                if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX] && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX].length > 0) {
-                    tplData[JV.DATA_DETAIL_DATA_EX] = [];
-                }
-                //4. 重点: 开始组装$PROJECT对象
-                let $PROJECT = {};
-                //let $PROJECT.COMMON = {};
-                //return demoTemplateData.getPromise(rptTpl.ID_KEY);
-                //return demoTemplateData.findOne({"Data_Key": rptTpl.ID_KEY}).exec();
+            let rptDataUtil = new rptDataExtractor();
+            rptDataUtil.initialize((rptTpl._doc)?rptTpl._doc:rptTpl);
+            let filter = rptDataUtil.getDataRequestFilter();
+            rptTplDataFacade.prepareProjectData(user_id, prj_id, filter, function (err, msg, rawDataObj) {
+                if (!err) {
+                    let tplData = rptDataUtil.assembleData(rawDataObj);
+                    let printCom = JpcEx.createNew();
+                    rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_PAGE_SIZE] = pageSize;
+                    let defProperties = rptUtil.getReportDefaultCache();
+                    let dftOption = option||JV.PAGING_OPTION_NORMAL;
+                    printCom.initialize(rptTpl);
+                    printCom.analyzeData(rptTpl, tplData, defProperties, dftOption);
+                    let maxPages = printCom.totalPages;
+                    let pageRst = printCom.outputAsSimpleJSONPageArray(rptTpl, tplData, 1, maxPages, defProperties);
+                    if (pageRst) {
+                        //fsUtil.wirteObjToFile(pageRst, "D:/GitHome/ConstructionCost/tmp/testBuiltPageResult.js");
+                        cb(null, pageRst);
+                    } else {
+                        cb('Have errors while on going...', null);
+                    }
 
 
-            } else {
-                cb('No report template data were found!', null);
-            }
+                } else {
+                    cb('No report data were found!', null);
+                }
+            });
         } else {
         } else {
             cb('No report template was found!', null);
             cb('No report template was found!', null);
         }
         }
@@ -111,7 +109,18 @@ function getAllPagesCommon(rpt_id, pageSize, cb) {
 }
 }
 
 
 module.exports = {
 module.exports = {
-    getReportAllPages: function(req, res){
+    getReportAllPages: function (req, res) {
+        let params = JSON.parse(req.body.params),
+            rpt_id = params.rpt_tpl_id,
+            prj_id = params.prj_id,
+            user_id = params.user_id,
+            pageSize = params.pageSize;
+        getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, null, function (err, pageRst) {
+            callback(req, res, err, pageRst);
+        });
+    },
+
+    getTestReportAllPages: function(req, res){
         let rpt_id = req.body.ID;
         let rpt_id = req.body.ID;
         let pageSize = req.body.pageSize;
         let pageSize = req.body.pageSize;
         getAllPagesCommonOrg(rpt_id, pageSize, JV.PAGING_OPTION_NORMAL, function(err, pageRst){
         getAllPagesCommonOrg(rpt_id, pageSize, JV.PAGING_OPTION_NORMAL, function(err, pageRst){
@@ -119,7 +128,7 @@ module.exports = {
             callback(req, res, err, pageRst);
             callback(req, res, err, pageRst);
         })
         })
     },
     },
-    getExcel: function(req, res) {
+    getTestExcel: function(req, res) {
         let rpt_id = req.params.id,
         let rpt_id = req.params.id,
             pageSize = req.params.size,
             pageSize = req.params.size,
             rptName = req.params.rptName,
             rptName = req.params.rptName,
@@ -145,7 +154,7 @@ module.exports = {
             }
             }
         })
         })
     },
     },
-    getExcelInOneBook: function(req, res) {
+    getTestExcelInOneBook: function(req, res) {
         let rpt_ids = req.params.ids.split(','),
         let rpt_ids = req.params.ids.split(','),
             pageSize = req.params.size,
             pageSize = req.params.size,
             rptName = req.params.rptName,
             rptName = req.params.rptName,
@@ -185,7 +194,7 @@ module.exports = {
             }
             }
         })
         })
     },
     },
-    getPDF:function (req, res) {
+    getTestPDF:function (req, res) {
         let rpt_id = req.params.id,
         let rpt_id = req.params.id,
             pageSize = req.params.size,
             pageSize = req.params.size,
             rptName = req.params.rptName;
             rptName = req.params.rptName;

+ 3 - 0
modules/reports/controllers/rpt_tpl_controller.js

@@ -52,6 +52,9 @@ let mExport = {
             compilationId = params.compilationId,
             compilationId = params.compilationId,
             userId = params.userId,
             userId = params.userId,
             engineerId = params.engineerId;
             engineerId = params.engineerId;
+        if (!compilationId) {
+            compilationId = req.session.sessionCompilation._id;
+        }
         rttFacade.findTplTree(compilationId, engineerId, userId).then(function(result) {
         rttFacade.findTplTree(compilationId, engineerId, userId).then(function(result) {
             if (result) {
             if (result) {
                 callback(req,res,false,"", result);
                 callback(req,res,false,"", result);

+ 1 - 0
modules/reports/models/rpt_template.js

@@ -16,6 +16,7 @@ let RptTemplateSchema = new Schema({
         "主数据指标_拓展集合": Array,
         "主数据指标_拓展集合": Array,
         "从数据指标_拓展集合": Array
         "从数据指标_拓展集合": Array
     },
     },
+    "映射数据预处理": Array,
     "布局框_集合": Array,
     "布局框_集合": Array,
     "流水式表_信息": Schema.Types.Mixed,
     "流水式表_信息": Schema.Types.Mixed,
     "流水式表_拓展信息": Schema.Types.Mixed,
     "流水式表_拓展信息": Schema.Types.Mixed,

+ 10 - 4
modules/reports/routes/report_router.js

@@ -17,11 +17,17 @@ module.exports =function (app) {
                     userID: req.session.managerData.userID});
                     userID: req.session.managerData.userID});
         }
         }
     });
     });
-    rptRouter.post('/getReport', reportController.getReportAllPages);
 
 
-    rptRouter.get('/getExcel/:id/:size/:rptName/:isOneSheet/:option', reportController.getExcel);
-    rptRouter.get('/getExcelInOneBook/:ids/:size/:rptName/:option', reportController.getExcelInOneBook);
+    //test
+    rptRouter.post('/getTestReport', reportController.getTestReportAllPages);
+    rptRouter.get('/getTestExcel/:id/:size/:rptName/:isOneSheet/:option', reportController.getTestExcel);
+    rptRouter.get('/getTestExcelInOneBook/:ids/:size/:rptName/:option', reportController.getTestExcelInOneBook);
+    rptRouter.get('/getTestPDF/:id/:size/:rptName', reportController.getTestPDF);
+    //now is the real:
+    rptRouter.post('/getReport', reportController.getReportAllPages);
+    // rptRouter.get('/getExcel/:id/:size/:rptName/:isOneSheet/:option', reportController.getExcel);
+    // rptRouter.get('/getExcelInOneBook/:ids/:size/:rptName/:option', reportController.getExcelInOneBook);
+    // rptRouter.get('/getPDF/:id/:size/:rptName', reportController.getPDF);
 
 
-    rptRouter.get('/getPDF/:id/:size/:rptName', reportController.getPDF);//2/A4/07-1表
     app.use("/report_api", rptRouter);
     app.use("/report_api", rptRouter);
 };
 };

+ 1 - 0
modules/reports/rpt_component/jpc_ex.js

@@ -157,6 +157,7 @@ JpcExSrv.prototype.createNew = function(){
                 let expression = me.formulas[i][JV.PROP_EXPRESSION];
                 let expression = me.formulas[i][JV.PROP_EXPRESSION];
                 if (expression) {
                 if (expression) {
                     let $ME = me.formulas[i];
                     let $ME = me.formulas[i];
+                    console.log(expression);
                     eval(expression);
                     eval(expression);
                 }
                 }
             }
             }

+ 321 - 77
modules/reports/util/rpt_construct_data_util.js

@@ -5,23 +5,65 @@
 let JV = require('../rpt_component/jpc_value_define');
 let JV = require('../rpt_component/jpc_value_define');
 let $JE = require('../rpt_component/jpc_rte');
 let $JE = require('../rpt_component/jpc_rte');
 let consts = require('../../../modules/main/models/project_consts');
 let consts = require('../../../modules/main/models/project_consts');
+
+let fsUtil = require("../../../public/fsUtil");
+
+let treeUtil = require('../../../public/treeUtil');
 let projectConst = consts.projectConst;
 let projectConst = consts.projectConst;
 let projectConstList = consts.projectConstList;
 let projectConstList = consts.projectConstList;
 
 
 class Rpt_Common{
 class Rpt_Common{
-    initialize(Projects) {
-        this.Projects = Projects;
+    initialize(rpt_tpl, currentDataObj) {
+        this.template = rpt_tpl;
+        this.currentDataObj = currentDataObj;
     };
     };
-
-    getSerialNo(fieldId, $CURRENT_RPT, $CURRENT_DATA){
-        let itemSerialNoRec = $JE.F(fieldId, $CURRENT_RPT);
-        if (itemSerialNoRec) {
-            itemSerialNoRec[JV.PROP_AD_HOC_DATA] = [];
-            for (var innerFmlIdx = 0; innerFmlIdx < $CURRENT_DATA[JV.DATA_DETAIL_DATA][0].length; innerFmlIdx++) {
-                itemSerialNoRec[JV.PROP_AD_HOC_DATA][innerFmlIdx] = (innerFmlIdx + 1);
-            }
-            itemSerialNoRec = null;
+    Multiply(val1, val2, fixFormat) {
+        let rst = [], maxLen = val1.length, minLen = val2.length;
+        if (minLen > maxLen) {
+            maxLen = maxLen + minLen; minLen = maxLen - minLen; maxLen = maxLen - minLen;
+        }
+        for (let i = 0; i < maxLen; i++) {
+            let value = ((i < val1.length)?val1[i]:val1[minLen - 1]) * ((i < val2.length)?val2[i]:val2[minLen - 1]);
+            if (fixFormat) value = value.toFixed(fixFormat);
+            rst.push(value);
+        }
+        return rst;
+    };
+    Divide(val1, val2, fixFormat) {
+        let rst = [], maxLen = val1.length, minLen = val2.length;
+        if (minLen > maxLen) {
+            maxLen = maxLen + minLen; minLen = maxLen - minLen; maxLen = maxLen - minLen;
         }
         }
+        for (let i = 0; i < maxLen; i++) {
+            let value = ((i < val1.length)?val1[i]:val1[minLen - 1]) / ((i < val2.length)?val2[i]:val2[minLen - 1]);
+            if (fixFormat) value = value.toFixed(fixFormat);
+            rst.push(value);
+        }
+        return rst;
+    };
+    Plus(val1, val2, fixFormat) {
+        let rst = [], maxLen = val1.length, minLen = val2.length;
+        if (minLen > maxLen) {
+            maxLen = maxLen + minLen; minLen = maxLen - minLen; maxLen = maxLen - minLen;
+        }
+        for (let i = 0; i < maxLen; i++) {
+            let value = ((i < val1.length)?val1[i]:val1[minLen - 1]) + ((i < val2.length)?val2[i]:val2[minLen - 1]);
+            if (fixFormat) value = value.toFixed(fixFormat);
+            rst.push(value);
+        }
+        return rst;
+    };
+    Minus(val1, val2, fixFormat) {
+        let rst = [], maxLen = val1.length, minLen = val2.length;
+        if (minLen > maxLen) {
+            maxLen = maxLen + minLen; minLen = maxLen - minLen; maxLen = maxLen - minLen;
+        }
+        for (let i = 0; i < maxLen; i++) {
+            let value = ((i < val1.length)?val1[i]:val1[minLen - 1]) - ((i < val2.length)?val2[i]:val2[minLen - 1]);
+            if (fixFormat) value = value.toFixed(fixFormat);
+            rst.push(value);
+        }
+        return rst;
     };
     };
 }
 }
 
 
@@ -34,6 +76,7 @@ class Rpt_Data_Extractor {
         this.rptTpl = tpl;
         this.rptTpl = tpl;
     };
     };
 
 
+    //-- 根据报表模板映射指标(非离散指标)的定义,罗列出所有需要用到的data对象key,作为数据请求的过滤依据
     getDataRequestFilter() {
     getDataRequestFilter() {
         let rst = [];
         let rst = [];
         let tpl = this.rptTpl;
         let tpl = this.rptTpl;
@@ -43,56 +86,56 @@ class Rpt_Data_Extractor {
                     if (field[JV.PROP_FIELD_EXP_MAP]) {
                     if (field[JV.PROP_FIELD_EXP_MAP]) {
                         if (field[JV.PROP_FIELD_EXP_MAP].indexOf('.' + key + '.') >= 0) {
                         if (field[JV.PROP_FIELD_EXP_MAP].indexOf('.' + key + '.') >= 0) {
                             rst.push(key);
                             rst.push(key);
+                            if (key === projectConst.RATION_GLJ && (rst.indexOf(projectConst.PROJECTGLJ) < 0)) {
+                                rst.push(projectConst.PROJECTGLJ);
+                            }
+                            if (key === projectConst.PROJECTGLJ && (rst.indexOf(projectConst.RATION_GLJ) < 0)) {
+                                rst.push(projectConst.RATION_GLJ);
+                            }
                         }
                         }
                     }
                     }
                 }
                 }
             }
             }
         };
         };
-        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS]) {
-            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_DISCRETE_FIELDS]) {
-                pri_func_chk_filter(field);
-            }
-        }
-        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS]) {
-            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS]) {
-                pri_func_chk_filter(field);
-            }
-        }
-        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]) {
-            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]) {
-                pri_func_chk_filter(field);
-            }
-        }
-        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS_EX]) {
-            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS_EX]) {
-                pri_func_chk_filter(field);
-            }
-        }
-        if (tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX]) {
-            for (let field of tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX]) {
-                pri_func_chk_filter(field);
+        let pri_setup_filter = function (FIELD_LIST_KEY) {
+            if (tpl[JV.NODE_FIELD_MAP][FIELD_LIST_KEY]) {
+                for (let field of tpl[JV.NODE_FIELD_MAP][FIELD_LIST_KEY]) {
+                    pri_func_chk_filter(field);
+                }
             }
             }
-        }
+        };
+        pri_setup_filter(JV.NODE_DISCRETE_FIELDS);
+        pri_setup_filter(JV.NODE_MASTER_FIELDS);
+        pri_setup_filter(JV.NODE_DETAIL_FIELDS);
+        pri_setup_filter(JV.NODE_MASTER_FIELDS_EX);
+        pri_setup_filter(JV.NODE_DETAIL_FIELDS_EX);
         return rst;
         return rst;
     };
     };
 
 
     //--- 装配数据(把收集到的数据,依据报表模板的指示,预处理(如:排序、过滤、合计)及装配到相关指标) ---//
     //--- 装配数据(把收集到的数据,依据报表模板的指示,预处理(如:排序、过滤、合计)及装配到相关指标) ---//
     assembleData(rawDataObj) {
     assembleData(rawDataObj) {
-        let $PROJECT = {"COMMON": {}, "MAIN": {}, "DETAIL": {}};
+        let $PROJECT = {"COMMON": null, "MAIN": {}, "DETAIL": {}};
         let tpl = this.rptTpl;
         let tpl = this.rptTpl;
+        this.COMMON.initialize(tpl, rawDataObj);
+        $PROJECT.COMMON = this.COMMON;
         $PROJECT.MAIN["myOwnRawDataObj"] = rawDataObj.prj._doc;
         $PROJECT.MAIN["myOwnRawDataObj"] = rawDataObj.prj._doc;
         $PROJECT.MAIN.getProperty = ext_mainGetPropety;
         $PROJECT.MAIN.getProperty = ext_mainGetPropety;
         $PROJECT.MAIN.getFee = ext_mainGetFee;
         $PROJECT.MAIN.getFee = ext_mainGetFee;
-        $PROJECT.DETAIL.getRationPropertyByID = ext_getRationPropertyByID;
         if (tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
         if (tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
             for (let preHandle of tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
             for (let preHandle of tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
+                let srcData = getModuleDataByKey(rawDataObj.prjData, preHandle[JV.PROP_DATA_KEY]);
                 switch(preHandle[JV.PROP_HANDLE_TYPE]) {
                 switch(preHandle[JV.PROP_HANDLE_TYPE]) {
                     case JV.PROP_HANDLE_TYPE_SORT:
                     case JV.PROP_HANDLE_TYPE_SORT:
+                        sortData(srcData, preHandle);
                         break;
                         break;
                     case JV.PROP_HANDLE_TYPE_FILTER:
                     case JV.PROP_HANDLE_TYPE_FILTER:
+                        filterData(srcData, preHandle, rawDataObj.prjData);
                         break;
                         break;
                     case JV.PROP_HANDLE_TYPE_SUM:
                     case JV.PROP_HANDLE_TYPE_SUM:
-                        //
+                        summaryData(srcData, preHandle, rawDataObj.prjData);
+                        break;
+                    default:
+                        break;
                 }
                 }
             }
             }
         }
         }
@@ -118,17 +161,189 @@ class Rpt_Data_Extractor {
         // console.log(JV.DATA_MASTER_DATA_EX);
         // console.log(JV.DATA_MASTER_DATA_EX);
         // console.log(rptDataObj[JV.DATA_MASTER_DATA_EX]);
         // console.log(rptDataObj[JV.DATA_MASTER_DATA_EX]);
         assembleFields(tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX], rptDataObj[JV.DATA_DETAIL_DATA_EX], $PROJECT);
         assembleFields(tpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS_EX], rptDataObj[JV.DATA_DETAIL_DATA_EX], $PROJECT);
-        // console.log(JV.DATA_DETAIL_DATA_EX);
-        // console.log(rptDataObj[JV.DATA_DETAIL_DATA_EX]);
+        console.log(JV.DATA_DETAIL_DATA_EX);
+        console.log(rptDataObj[JV.DATA_DETAIL_DATA_EX]);
+        return rptDataObj;
     };
     };
 
 
 }
 }
 
 
+function getModuleDataByKey(prjData, key) {
+    let rst = null;
+    for (let item of prjData) {
+        if (item.moduleName === key) {
+            rst = item;
+            break;
+        }
+    }
+    return rst;
+}
+
+function summaryData(sourceData, handleCfg, prjData){
+    let rstArr = [], tempRstArr = [];
+    let curParentPrjData = {};
+    for (let item of sourceData.data) {
+        if (item._doc) {
+            tempRstArr.push(item._doc);
+        } else {
+            tempRstArr.push(item);
+        }
+    }
+    let private_get_grp_key = function (item) {
+        let keys = [];
+        for (let cfg of handleCfg[JV.PROP_SUM_GROUP_KEYS]) {
+            if (typeof cfg === "string") {
+                keys.push(item[cfg]);
+            } else {
+                if (!curParentPrjData[cfg["seeking_parent"]]) curParentPrjData[cfg["seeking_parent"]] = getModuleDataByKey(prjData, cfg["seeking_parent"]);
+                for (let pDataItem of curParentPrjData[cfg["seeking_parent"]].data) {
+                    let data = (pDataItem._doc)?pDataItem._doc:pDataItem;
+                    if (item[cfg["seeking_key"]] === data[cfg["parent_key"]]) {
+                        keys.push(data[cfg["parent_grp_key"]]);
+                        break;
+                    }
+                }
+            }
+        }
+        return ( "grp_key_" + keys.join('_'));
+    }
+    let sumObj = {};
+    for (let dtl of tempRstArr) {
+        let grpKey = private_get_grp_key(dtl);
+        if (sumObj[grpKey] === null || sumObj[grpKey] === undefined) {
+            sumObj[grpKey] = dtl;
+            rstArr.push(dtl);
+        } else {
+            for (let sumKey of handleCfg[JV.PROP_SUM_SUM_KEYS]) {
+                if (dtl[sumKey]) {
+                    sumObj[grpKey][sumKey] += dtl[sumKey];
+                }
+            }
+        }
+    }
+    delete sourceData.data;
+    sourceData.data = rstArr;
+    // fsUtil.wirteObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/sumRst.js");
+}
+
+function filterData(sourceData, handleCfg, prjData) {
+    let rstArr = [], tempRstArr = [];
+    for (let item of sourceData.data) {
+        if (item._doc) {
+            tempRstArr.push(item._doc);
+        } else {
+            tempRstArr.push(item);
+        }
+    }
+    let private_chkVal = function (src, dest, compStr) {
+        let rst = true;
+        switch (compStr) {
+            case "==" :
+                rst = (src == dest);
+                break;
+            case "===" :
+                rst = (src === dest);
+                break;
+            case ">" :
+                rst = (src > dest);
+                break;
+            case ">=" :
+                rst = (src >= dest);
+                break;
+            case "<" :
+                rst = (src < dest);
+                break;
+            case "<=" :
+                rst = (src <= dest);
+                break;
+            case "!=" :
+                rst = (src != dest);
+                break;
+            case "!==" :
+                rst = (src !== dest);
+                break;
+            default:
+                rst = true;
+        }
+        return rst;
+    }
+    for (let item of tempRstArr) {
+        let compRst = true;
+        let curComparePrjData = null;
+        for (let cfg of handleCfg[JV.PROP_FILTER_KEY]) {
+            if (cfg[JV.PROP_FILTER_COMPARE_VAL]) {
+                //比较key值
+                compRst = private_chkVal(item[cfg.key], cfg[JV.PROP_FILTER_COMPARE_VAL], cfg[JV.PROP_FILTER_CONDITION]);
+            } else if (cfg[JV.PROP_FILTER_COMPARE_OBJ] && cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]){
+                //通过其他对象来过滤
+                if (!curComparePrjData) {
+                    curComparePrjData = getModuleDataByKey(prjData, cfg[JV.PROP_FILTER_COMPARE_OBJ]);
+                }
+                for (let data of curComparePrjData.data) {
+                    compRst = private_chkVal(item[cfg.key], data[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]], cfg[JV.PROP_FILTER_CONDITION]);
+                    if (compRst) break;
+                }
+            }
+        }
+        if (compRst) {
+            rstArr.push(item);
+        }
+    }
+    delete sourceData.data;
+    sourceData.data = rstArr;
+    // fsUtil.wirteObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/filteredRst.js");
+}
+
+function sortData(sourceData, sortCfg) {
+    let rst = sourceData.data, tempRstArr = [];
+    let sortType = sortCfg[JV.PROP_SORT_TYPE];
+    for (let item of sourceData.data) {
+        if (item._doc) {
+            tempRstArr.push(item._doc);
+        } else {
+            tempRstArr.push(item);
+        }
+    }
+    switch (sortType) {
+        case "tree":
+            rst = treeUtil.buildTreeNodeDirectly(tempRstArr);
+            let destArr = [];
+            treeUtil.getFlatArray(rst, destArr);
+            delete sourceData.data;
+            sourceData.data = destArr;
+            // fsUtil.wirteObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/sortedAndFlattedRst.js");
+            break;
+        case "normal":
+            tempRstArr.sort(function(a, b){
+                let compRst = 0;
+                for (let comp of sortCfg[JV.PROP_SORT_KEYS]) {
+                    let reverse = (comp.order === 'ascend')?1:(-1);
+                    if (a[comp.key] > b[comp.key]) {
+                        compRst = reverse;
+                        break;
+                    } else if (a[comp.key] < b[comp.key]) {
+                        compRst = -reverse;
+                        break;
+                    }
+                }
+                return compRst;
+            });
+            delete sourceData.data;
+            sourceData.data = tempRstArr;
+            // fsUtil.wirteObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/normalSortedRst.js");
+            break;
+        default:
+            //
+    }
+    return rst;
+}
+
 function setupFunc(obj, prop, ownRawObj) {
 function setupFunc(obj, prop, ownRawObj) {
     obj[prop] = {};
     obj[prop] = {};
     obj[prop]["myOwnRawDataObj"] = ownRawObj;
     obj[prop]["myOwnRawDataObj"] = ownRawObj;
     obj[prop].getProperty = ext_getPropety;
     obj[prop].getProperty = ext_getPropety;
     obj[prop].getFee = ext_getFee;
     obj[prop].getFee = ext_getFee;
+    obj[prop].getPropertyByForeignId = ext_getPropertyByForeignId;
 }
 }
 
 
 function assembleFields(fieldList, rstDataArr, $PROJECT) {
 function assembleFields(fieldList, rstDataArr, $PROJECT) {
@@ -146,11 +361,9 @@ function shielded_exec_env($PROJECT, $ME, rptDataItemObj) {
 }
 }
 
 
 function ext_mainGetPropety(propKey) {
 function ext_mainGetPropety(propKey) {
-    let rst = [];
-    let parentObj = this;
-    //console.log(this);
+    let rst = [], parentObj = this;
     let dtObj = parentObj["myOwnRawDataObj"];
     let dtObj = parentObj["myOwnRawDataObj"];
-    if ((dtObj) && (propKey)) {
+    if (propKey && dtObj) {
         if (dtObj.hasOwnProperty("property")) {
         if (dtObj.hasOwnProperty("property")) {
             rst.push(dtObj["property"][propKey]);
             rst.push(dtObj["property"][propKey]);
         } else  {
         } else  {
@@ -160,7 +373,25 @@ function ext_mainGetPropety(propKey) {
     return rst;
     return rst;
 }
 }
 
 
-function ext_mainGetFee(feeKey) {
+function ext_getPropety(propKey) {
+    let rst = [], parentObj = this;
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if (propKey && dtObj) {
+        for (let dItem of dtObj.data) {
+            let doc = (dItem._doc === null || dItem._doc === undefined)?dItem:dItem._doc;
+            if (doc.hasOwnProperty("property")) {
+                rst.push(doc["property"][propKey]);
+            } else if (doc.hasOwnProperty(propKey)) {
+                rst.push(doc[propKey]);
+            } else {
+                rst.push('');
+            }
+        }
+    }
+    return rst;
+}
+
+function ext_mainGetFee(feeKey, dtlFeeKey) {
     let rst = [];
     let rst = [];
     let parentObj = this;
     let parentObj = this;
     let dtObj = parentObj["myOwnRawDataObj"];
     let dtObj = parentObj["myOwnRawDataObj"];
@@ -168,7 +399,11 @@ function ext_mainGetFee(feeKey) {
         if (dtObj.hasOwnProperty("fees")) {
         if (dtObj.hasOwnProperty("fees")) {
             for (let fee of dtObj["fees"]) {
             for (let fee of dtObj["fees"]) {
                 if (fee["fieldName"] === feeKey) {
                 if (fee["fieldName"] === feeKey) {
-                    rst.push(dtObj["fees"][feeKey]);
+                    if (dtlFeeKey) {
+                        rst.push(fee[dtlFeeKey]);
+                    } else {
+                        rst.push(fee["unitFee"]);
+                    }
                     break;
                     break;
                 }
                 }
             }
             }
@@ -181,56 +416,65 @@ function ext_mainGetFee(feeKey) {
     return rst;
     return rst;
 }
 }
 
 
-function ext_getPropety(propKey) {
-    let rst = [], parentObj = this;
-    let dtObj = parentObj["myOwnRawDataObj"];
-    if (propKey && dtObj) {
-        for (let dItem of dtObj.data) {
-            let doc = dItem._doc;
-            if (doc.hasOwnProperty("property")) {
-                rst.push(doc["property"][propKey]);
-            } else if (doc.hasOwnProperty(propKey)) {
-                rst.push(doc[propKey]);
-            } else {
-                rst.push('');
-            }
-        }
-    }
-    return rst;
-}
-
-function ext_getFee(feeKey) {
+function ext_getFee(feeKey, dtlFeeKey) {
     let rst = [], parentObj = this;
     let rst = [], parentObj = this;
     let dtObj = parentObj["myOwnRawDataObj"];
     let dtObj = parentObj["myOwnRawDataObj"];
     if (feeKey && dtObj) {
     if (feeKey && dtObj) {
         for (let dItem of dtObj.data) {
         for (let dItem of dtObj.data) {
+            let hasValue = false;
             if (dItem.hasOwnProperty("fees")) {
             if (dItem.hasOwnProperty("fees")) {
                 for (let fee of dItem["fees"]) {
                 for (let fee of dItem["fees"]) {
                     if (fee["fieldName"] === feeKey) {
                     if (fee["fieldName"] === feeKey) {
-                        rst.push(dItem["fees"][feeKey]);
+                        if (dtlFeeKey) {
+                            rst.push(fee[dtlFeeKey]);
+                        } else {
+                            rst.push(fee["unitFee"]);
+                        }
+                        hasValue = true;
                         break;
                         break;
                     }
                     }
                 }
                 }
             } else if (dItem.hasOwnProperty(feeKey)) {
             } else if (dItem.hasOwnProperty(feeKey)) {
+                hasValue = true;
                 rst.push(dItem[feeKey]);
                 rst.push(dItem[feeKey]);
             } else {
             } else {
-                rst.push[0];
+                hasValue = true;
+                rst.push(0);
+            }
+            if (!hasValue) {
+                rst.push(0);
             }
             }
         }
         }
     }
     }
     return rst;
     return rst;
 }
 }
 
 
-function ext_getRationPropertyByID(IdVal, propKey) {
-    let rst = [], me = this;
-    if (IdVal !== null && IdVal !== undefined && me[projectConst.RATION]) {
+function ext_getPropertyByForeignId(foreignIdVal, adHocIdKey, propKey) {
+    let rst = [], parentObj = this;
+    let IdKey = (adHocIdKey)?adHocIdKey:"ID";
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if (foreignIdVal !== null && foreignIdVal !== undefined) {
         let isFound = false;
         let isFound = false;
-        if (IdVal instanceof Array) {
-            for (let id of IdVal) {
+        if (foreignIdVal instanceof Array) {
+            for (let idVal of foreignIdVal) {
                 isFound = false;
                 isFound = false;
-                for (let item of me[projectConst.RATION]["myOwnRawDataObj"].data) {
-                    if (item.ID === id) {
-                        rst.push(item[propKey]);
+                for (let i = 0; i < dtObj.data.length; i++) {
+                    let item = (dtObj.data[i]._doc)?dtObj.data[i]._doc:dtObj.data[i];
+                    if (item[IdKey] === idVal) {
+                        let splitPKey = propKey.split(".");
+                        if (splitPKey.length > 1) {
+                            let rstP = null;
+                            for (let i = 0; i < splitPKey.length; i++) {
+                                if (i === 0) {
+                                    rstP = item[splitPKey[i]];
+                                } else {
+                                    rstP = rstP[splitPKey[i]];
+                                }
+                            }
+                            rst.push(rstP);
+                        } else {
+                            rst.push(item[propKey]);
+                        }
                         isFound = true;
                         isFound = true;
                         break;
                         break;
                     }
                     }
@@ -238,8 +482,8 @@ function ext_getRationPropertyByID(IdVal, propKey) {
                 // if (!isFound) rst.push[null];
                 // if (!isFound) rst.push[null];
             }
             }
         } else {
         } else {
-            for (let item of me[projectConst.RATION]["myOwnRawDataObj"].data) {
-                if (item.ID === IdVal) {
+            for (let item of dtObj.data) {
+                if (item[IdKey] === foreignIdVal) {
                     rst.push(item[propKey]);
                     rst.push(item[propKey]);
                     isFound = true;
                     isFound = true;
                     break;
                     break;

+ 57 - 20
public/calc_util.js

@@ -4,6 +4,12 @@
  * added by CSL, 2017-09-01 增加公式解析对象analyzer,用于解析用户修改公式、自定义表达式。
  * added by CSL, 2017-09-01 增加公式解析对象analyzer,用于解析用户修改公式、自定义表达式。
  */
  */
 
 
+// 需求说小数位数固定为2位,这里预留缓冲接口,防止以后需求变卦。
+const Digit_Calc_Program = -2;      // 这里指定计算程序用到的小数位数。
+function round(num) {
+    return scMathUtil.roundTo(num, Digit_Calc_Program);
+};
+
 let executeObj = {
 let executeObj = {
     treeNode: null,
     treeNode: null,
     template: null,
     template: null,
@@ -22,25 +28,56 @@ let executeObj = {
             base = me.calcBase[calcBaseName];
             base = me.calcBase[calcBaseName];
 
 
         if (base != null) {
         if (base != null) {
-            let price = 0, aprice = 0, mprice = 0, tmpSum = 0;
-            for (let glj of me.treeNode.data.gljList) {
-                if (base.gljTypes.indexOf(glj.type) >= 0) {
-                    if (base.calcType == baseCalc){ price = glj["basePrice"];}
-                    else if (base.calcType == adjustCalc){price = glj["adjustPrice"];}
-                    else if (base.calcType == budgetCalc){price = glj["marketPrice"];}
-                    else if (base.calcType == diffCalc){
-                        aprice = glj["adjustPrice"];
-                        if (!aprice) aprice = 0;
-                        mprice = glj["marketPrice"];
-                        if (!mprice) mprice = 0;
-                        price = mprice - aprice;
+            let price = 0, aprice = 0, mprice = 0, tmpSum = 0, mdSum = 0;
+
+            function isSubset(sub, arr){
+                // if(!(sub instanceof Array) || !(arr instanceof Array)) return false;
+                // if(sub.length > arr.length) return false;
+                for(var i = 0, len = sub.length; i < len; i++){
+                    if(arr.indexOf(sub[i]) == -1) return false;
+                }
+                return true;
+            }
+
+            // 机上人工费:多一层
+            if (isSubset(base.gljTypes, [gljType.MACHINE_LABOUR])) {
+                for (let glj of me.treeNode.data.gljList) {
+                       if (glj.type == gljType.GENERAL_MACHINE) {
+                            // 获取机械组成物
+                           let mds = projectObj.project.composition.getCompositionByCode(glj.code);
+                           if (!mds) mds = [];
+                           for (let md of mds){
+                               if (base.gljTypes.indexOf(md.glj_type) >= 0) {
+                                   price = md["base_price"];
+                                   if (!price) price = 0;
+                                   mdSum = mdSum +  round(md["consumption"] * price);
+                               }
+                           };
+                           tmpSum = tmpSum + glj["quantity"] * mdSum;     // 这里不能四舍五入
+                       }
+                };
+            }else{
+                for (let glj of me.treeNode.data.gljList) {
+                    if (base.gljTypes.indexOf(glj.type) >= 0) {
+                        if (base.calcType == baseCalc){ price = glj["basePrice"];}
+                        else if (base.calcType == adjustCalc){price = glj["adjustPrice"];}
+                        else if (base.calcType == budgetCalc){price = glj["marketPrice"];}
+                        else if (base.calcType == diffCalc){
+                            aprice = glj["adjustPrice"];
+                            if (!aprice) aprice = 0;
+                            mprice = glj["marketPrice"];
+                            if (!mprice) mprice = 0;
+                            price = mprice - aprice;
+                        };
+                        if (!price) price = 0;
+                        tmpSum = tmpSum + glj["quantity"] * price;
                     };
                     };
-                    if (!price) price = 0;
-                    tmpSum = tmpSum + glj["quantity"] * price;
                 };
                 };
             };
             };
-            rst = tmpSum;
+
+            rst = round(tmpSum);
         };
         };
+
         return rst;
         return rst;
     }
     }
 };
 };
@@ -294,12 +331,12 @@ class Calculation {
         let private_compile_items = function() {
         let private_compile_items = function() {
             for (let idx of template.compiledSeq) {
             for (let idx of template.compiledSeq) {
                 let item = template.calcItems[idx];
                 let item = template.calcItems[idx];
+                item.dispExprUser = item.dispExpr;    // 用于界面显示。disExpr是公式模板,不允许修改:人工系数占位符被修改后变成数值,第二次无法正确替换。
                 item.compiledExpr = item.expression.split('@(').join('$CE.at(');
                 item.compiledExpr = item.expression.split('@(').join('$CE.at(');
                 item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
                 item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
-
                 if (item.labourCoeID){
                 if (item.labourCoeID){
                     let lc = me.compiledLabourCoes["LabourCoe_" + item.labourCoeID].coe;
                     let lc = me.compiledLabourCoes["LabourCoe_" + item.labourCoeID].coe;
-                    item.dispExpr = item.dispExpr.replace(/L/gi, lc.toString());
+                    item.dispExprUser = item.dispExpr.replace(/L/gi, lc.toString());
                     item.compiledExpr = item.compiledExpr.replace(/L/gi, lc.toString());
                     item.compiledExpr = item.compiledExpr.replace(/L/gi, lc.toString());
                 };
                 };
 
 
@@ -337,7 +374,7 @@ class Calculation {
 
 
     calculate($treeNode){
     calculate($treeNode){
         let me = this;
         let me = this;
-        let templateID = $treeNode.data.calcTemplateID;
+        let templateID = $treeNode.data.programID;
         if (!templateID) templateID = 1;
         if (!templateID) templateID = 1;
         let template = me.compiledTemplates[templateID];
         let template = me.compiledTemplates[templateID];
         $treeNode.data.calcTemplate = template;
         $treeNode.data.calcTemplate = template;
@@ -358,11 +395,11 @@ class Calculation {
 
 
                 let feeRate = calcItem.feeRate;
                 let feeRate = calcItem.feeRate;
                 if (!feeRate) feeRate = 100;    // 100%
                 if (!feeRate) feeRate = 100;    // 100%
-                calcItem.unitFee = eval(calcItem.compiledExpr) * feeRate * 0.01;   // 如果eval()对清单树有影响,就换成小麦的Expression对象再试
+                calcItem.unitFee = round(eval(calcItem.compiledExpr) * feeRate * 0.01);   // 如果eval()对清单树有影响,就换成小麦的Expression对象再试
 
 
                 let quantity = $treeNode.data.quantity;
                 let quantity = $treeNode.data.quantity;
                 if (!quantity) quantity = 0;
                 if (!quantity) quantity = 0;
-                calcItem.totalFee = calcItem.unitFee * quantity;
+                calcItem.totalFee = round(calcItem.unitFee * quantity);
 
 
                 // 费用同步到定额
                 // 费用同步到定额
                 // 引入小麦的字段检测后,快速切换定额出现计算卡顿现象,过多的循环造成。这里把她的代码拆出来,减少微循环。
                 // 引入小麦的字段检测后,快速切换定额出现计算卡顿现象,过多的循环造成。这里把她的代码拆出来,减少微循环。

+ 8 - 8
public/fsUtil.js

@@ -2,26 +2,26 @@
  * Created by Tony on 2017/4/10.
  * Created by Tony on 2017/4/10.
  */
  */
 
 
-var fs = require('fs');
+let fs = require('fs');
 
 
 module.exports = {
 module.exports = {
     writeArrayToFile: function(arr, filePath) {
     writeArrayToFile: function(arr, filePath) {
         if (arr && filePath && Array.isArray(arr)) {
         if (arr && filePath && Array.isArray(arr)) {
-            var chunks = [], len = 0;
-            for (var i = 0; i < arr.length; i++) {
-                var buffer = new Buffer(arr[i]);
+            let chunks = [], len = 0;
+            for (let i = 0; i < arr.length; i++) {
+                let buffer = new Buffer(arr[i]);
                 chunks.push(buffer);
                 chunks.push(buffer);
                 len += buffer.length;
                 len += buffer.length;
                 //
                 //
             }
             }
-            var resultBuffer = new Buffer(len);
-            for(var i=0,size=chunks.length,pos=0;i<size;i++){
+            let resultBuffer = new Buffer(len);
+            for(let i=0,size=chunks.length,pos=0;i<size;i++){
                 chunks[i].copy(resultBuffer,pos);
                 chunks[i].copy(resultBuffer,pos);
                 pos += chunks[i].length;
                 pos += chunks[i].length;
             }
             }
             fs.writeFile(filePath, resultBuffer, function(err){
             fs.writeFile(filePath, resultBuffer, function(err){
                 if(err) throw err;
                 if(err) throw err;
-                console.log('Write file: ' + filePath + ' ok!');
+                //console.log('Write file: ' + filePath + ' ok!');
             });
             });
         }
         }
     },
     },
@@ -32,4 +32,4 @@ module.exports = {
             this.writeArrayToFile(arr, filePath);
             this.writeArrayToFile(arr, filePath);
         }
         }
     }
     }
-}
+};

+ 6 - 6
public/scMathUtil.js

@@ -2,16 +2,16 @@
  * Created by Tony on 2017/4/14.
  * Created by Tony on 2017/4/14.
  */
  */
 const fs = require('fs');
 const fs = require('fs');
-var scMath = null;
+let scMath = null;
 
 
-getScMathUtil = function() {
+let getScMathUtil = function() {
     if (!(scMath)) {
     if (!(scMath)) {
-        var data = fs.readFileSync(__dirname + '/web/scMathUtil.js', 'utf8', 'r');
+        let data = fs.readFileSync(__dirname + '/web/scMathUtil.js', 'utf8', 'r');
         //console.log(data);
         //console.log(data);
-        eval(data);
-        scMath = scMathUtil;
+        eval(data + ' scMath = scMathUtil;');
+        //scMath = scMathUtil;
     }
     }
     return scMath;
     return scMath;
-}
+};
 
 
 exports.getUtil = getScMathUtil;
 exports.getUtil = getScMathUtil;

+ 10 - 11
public/treeUtil.js

@@ -2,17 +2,16 @@
  * Created by Tony on 2017/3/14.
  * Created by Tony on 2017/3/14.
  */
  */
 
 
-const fs = require('fs');
-var treeNodeUtil = null;
+import fs from 'fs';
 
 
-getTreeNodeUtil = function() {
-    if (!(treeNodeUtil)) {
-        var data = fs.readFileSync(__dirname + '/web/treeDataHelper.js', 'utf8', 'r');
-        //console.log(data);
-        eval(data);
-        treeNodeUtil = tree_Data_Helper;
-    }
-    return treeNodeUtil;
+function getTreeNodeUtil() {
+    let tmpRst = null;
+    let data = fs.readFileSync(__dirname + '/web/treeDataHelper.js', 'utf8', 'r');
+    //console.log(data);
+    eval(data + ' ; tmpRst = tree_Data_Helper; ');
+    return tmpRst;
 }
 }
 
 
-exports.getUtil = getTreeNodeUtil;
+const treeNodeUtil = getTreeNodeUtil();
+
+module.exports = treeNodeUtil;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 82 - 0
public/web/PerfectLoad.js


+ 0 - 23
public/web/calculation/calc_util.js

@@ -1,23 +0,0 @@
-/**
- * Created by Tony on 2017/6/19.
- */
-
-class calculation {
-    init(calcTpl, calFee){
-        let me = this;
-        me.calcTpl = calcTpl;
-        me.calFee = calFee;
-        me.hasCompiled = false;
-    };
-
-    compile(){
-        let me = this;
-        me.hasCompiled = false;
-        if (me.calcTpl && me.calcTpl.calcItems && me.calcTpl.calcItems.length > 0) {
-            me.calcTpl.compiledSeq = [];
-        }
-    };
-    calculate(){
-        //
-    }
-}

+ 12 - 3
public/web/number_util.js

@@ -2,9 +2,9 @@
  * Created by chen on 2017/7/5.
  * Created by chen on 2017/7/5.
  */
  */
 
 
-Number.prototype.toDecimal = function (ADigit) {
-    return parseFloat(this.toFixed(ADigit));
-};
+// Number.prototype.toDecimal = function (ADigit) {
+//     return parseFloat(this.toFixed(ADigit));
+// };
 
 
 var  number_util = {
 var  number_util = {
     isNumber : function (obj) {
     isNumber : function (obj) {
@@ -24,5 +24,14 @@ var  number_util = {
             value = editingText;
             value = editingText;
         }
         }
         return value;
         return value;
+    },
+    roundToString:function(obj,decimal){
+        let value;
+        if(this.isNumber(obj)){
+            value = scMathUtil.roundTo(obj,-decimal)
+        }else {
+            value = scMathUtil.roundTo(Number(obj),-decimal);
+        }
+        return value.toFixed(decimal);
     }
     }
 }
 }

+ 8 - 5
public/web/rpt_value_define.js

@@ -45,16 +45,19 @@ const JV = {
     NODE_BIZ_TYPE_SUM: "汇总类型",
     NODE_BIZ_TYPE_SUM: "汇总类型",
     NODE_BIZ_TYPE_DETAIL: "明细类型",
     NODE_BIZ_TYPE_DETAIL: "明细类型",
 
 
-    NODE_MAP_DATA_HANDLE_INFO: "映射数据过滤及统计处理",
+    NODE_MAP_DATA_HANDLE_INFO: "映射数据处理",
     PROP_DATA_KEY: "映射数据对象",
     PROP_DATA_KEY: "映射数据对象",
     PROP_HANDLE_TYPE: "预处理类型",
     PROP_HANDLE_TYPE: "预处理类型",
-    PROP_FILTER_KEY: "过滤键属性",
-    PROP_FILTER_DEPENDENT_ON: "过滤依据对象",
-    PROP_FILTER_DEPENDENT_ON_KEY: "过滤依据对象键属性",
-    PROP_FILTER_CONDITION: "条件",
+    PROP_FILTER_KEY: "过滤键值集",
+    PROP_FILTER_COMPARE_OBJ: "compareObjKey",
+    PROP_FILTER_COMPARE_OBJ_KEY: "compareObjIdKey",
+    PROP_FILTER_COMPARE_VAL: "compareValue",
+    PROP_FILTER_CONDITION: "判断条件",
     PROP_HANDLE_TYPE_FILTER: "过滤",
     PROP_HANDLE_TYPE_FILTER: "过滤",
     PROP_HANDLE_TYPE_SUM: "合计",
     PROP_HANDLE_TYPE_SUM: "合计",
     PROP_HANDLE_TYPE_SORT: "排序",
     PROP_HANDLE_TYPE_SORT: "排序",
+    PROP_SORT_TYPE: "排序方式",
+    PROP_SORT_KEYS: "排序键值集",
     PROP_SUM_GROUP_KEYS: "分组键值集",
     PROP_SUM_GROUP_KEYS: "分组键值集",
     PROP_SUM_SUM_KEYS: "统计键值集",
     PROP_SUM_SUM_KEYS: "统计键值集",
     PROP_FIELD_EXP_MAP: "mapExpression",
     PROP_FIELD_EXP_MAP: "mapExpression",

+ 40 - 24
public/web/scMathUtil.js

@@ -2,45 +2,45 @@
  * Created by jimiz on 2017/3/28.
  * Created by jimiz on 2017/3/28.
  */
  */
 
 
-var scMathUtil = {
+let scMathUtil = {
     innerRoundTo: function(num, digit){
     innerRoundTo: function(num, digit){
-        var lFactor = Math.pow(10, digit);
-        var fOffSet = 0.5;
-        var sign = '';
+        let lFactor = Math.pow(10, digit);
+        let fOffSet = 0.5;
+        let sign = '';
         if (num < 0){
         if (num < 0){
             sign = '-';
             sign = '-';
             num = Math.abs(num);
             num = Math.abs(num);
         }
         }
-        var result = Math.floor((num / lFactor) + fOffSet).toString();
-        var iLength = result.length;
-        var r1 = result.substring(0, iLength + digit);
-        var r2 = result.substring(iLength + digit, iLength);
+        let result = Math.floor((num / lFactor) + fOffSet).toString();
+        let iLength = result.length;
+        let r1 = result.substring(0, iLength + digit);
+        let r2 = result.substring(iLength + digit, iLength);
         return Number(sign + r1 + '.' + r2);
         return Number(sign + r1 + '.' + r2);
     },
     },
     floatToBin: function(num) {
     floatToBin: function(num) {
         return num.toString(2);
         return num.toString(2);
     },
     },
     binToFloat: function(bin) {
     binToFloat: function(bin) {
-        var result = 0;
-        var iLength = bin.length;
-        var sign = '';
+        let result = 0;
+        let iLength = bin.length;
+        let sign = '';
         if (iLength > 0 && bin[0]==='-'){
         if (iLength > 0 && bin[0]==='-'){
             sign = '-';
             sign = '-';
             bin = bin.substring(1, iLength);
             bin = bin.substring(1, iLength);
         }
         }
         iLength = bin.length;
         iLength = bin.length;
-        var iDot = bin.indexOf('.');
+        let iDot = bin.indexOf('.');
         if (iDot >= 0) {
         if (iDot >= 0) {
-            for (var i = 0; i < iLength; i++) {
-                var num = Number(bin[i]);
-                var idx = iDot - i;
+            for (let i = 0; i < iLength; i++) {
+                let num = Number(bin[i]);
+                let idx = iDot - i;
                 if (idx === 0) {
                 if (idx === 0) {
                     continue
                     continue
                 };
                 };
                 if (idx > 0) {
                 if (idx > 0) {
                     idx -= 1
                     idx -= 1
                 };
                 };
-                var r = Math.pow(2, idx);
+                let r = Math.pow(2, idx);
                 result += num * r;
                 result += num * r;
             }
             }
         }
         }
@@ -49,17 +49,24 @@ var scMathUtil = {
         };
         };
         return sign + result;
         return sign + result;
     },
     },
+    zeroString: function(length){
+        let result = '';
+        for (let i = 0; i < length; i++){
+            result = result + '0';
+        };
+        return result;
+    },    
     incMantissa: function(bin){
     incMantissa: function(bin){
-        var result = bin;
-        var iDot = bin.indexOf('.');
+        let result = bin;
+        let iDot = bin.indexOf('.');
         if (iDot < 0){return result};
         if (iDot < 0){return result};
-        var iLength = bin.length;
-        for (var i = iLength - 1; i > iDot; i--){
-            var num = Number(bin[i]);
+        let iLength = bin.length;
+        for (let i = iLength - 1; i > iDot; i--){
+            let num = Number(bin[i]);
             if (num === 0){
             if (num === 0){
                 num = 1;
                 num = 1;
-                var bin1 = bin.substring(0, i);
-                var bin2 = bin.substring(i + 1, iLength);
+                let bin1 = bin.substring(0, i);
+                let bin2 = this.zeroString(iLength - (i + 1));//bin.substring(i + 1, iLength);
                 result = bin1 + num.toString() + bin2;
                 result = bin1 + num.toString() + bin2;
                 break;
                 break;
             }
             }
@@ -68,7 +75,16 @@ var scMathUtil = {
         return result;
         return result;
     },
     },
     roundTo: function(num, digit){
     roundTo: function(num, digit){
-        var me = this;
+        let me = this;
         return me.innerRoundTo(me.binToFloat(me.incMantissa(me.floatToBin(num))), digit);
         return me.innerRoundTo(me.binToFloat(me.incMantissa(me.floatToBin(num))), digit);
     }
     }
+};
+
+Number.prototype.toDecimal = function (ADigit) {
+    //return parseFloat(this.toFixed(ADigit));
+    digit = (ADigit && typeof(ADigit) === 'number' && Number.isInteger(ADigit) && ADigit >= 0) ? -ADigit : -2;
+    // var s = scMathUtil.roundTo(this, digit);
+    // console.log('Number: ' + this + '   Digit: ' + digit + '    Result: ' + s);
+    // return parseFloat(s);
+    return scMathUtil.roundTo(this, digit);
 };
 };

+ 20 - 21
public/web/sheet/sheet_common.js

@@ -4,12 +4,11 @@
 var sheetCommonObj = {
 var sheetCommonObj = {
     // CSL.2017.06.05
     // CSL.2017.06.05
     // createSpread、initSheet 在一个Spread多个Sheet分别调用时的情况下使用。
     // createSpread、initSheet 在一个Spread多个Sheet分别调用时的情况下使用。
-    // buildSheet 在一个Spread、一个Sheet的情况下使用。
     createSpread: function(container, SheetCount){
     createSpread: function(container, SheetCount){
         var me = this;
         var me = this;
         var spreadBook = new GC.Spread.Sheets.Workbook(container, { sheetCount: SheetCount });
         var spreadBook = new GC.Spread.Sheets.Workbook(container, { sheetCount: SheetCount });
         spreadBook.options.tabStripVisible = false;
         spreadBook.options.tabStripVisible = false;
-         spreadBook.options.showHorizontalScrollbar = true;
+        spreadBook.options.showHorizontalScrollbar = true;
         spreadBook.options.allowCopyPasteExcelStyle = false;
         spreadBook.options.allowCopyPasteExcelStyle = false;
         spreadBook.options.allowUserDragDrop = true;
         spreadBook.options.allowUserDragDrop = true;
         return spreadBook;
         return spreadBook;
@@ -20,10 +19,24 @@ var sheetCommonObj = {
         var spreadNS = GC.Spread.Sheets;
         var spreadNS = GC.Spread.Sheets;
         sheet.suspendPaint();
         sheet.suspendPaint();
         sheet.suspendEvent();
         sheet.suspendEvent();
+
         sheet.setRowCount(1, spreadNS.SheetArea.colHeader);
         sheet.setRowCount(1, spreadNS.SheetArea.colHeader);
         sheet.setColumnCount(setting.header.length, spreadNS.SheetArea.viewport);
         sheet.setColumnCount(setting.header.length, spreadNS.SheetArea.viewport);
+
+        if (setting && setting.view && setting.view.colHeaderHeight) {
+            sheet.setRowHeight(0, setting.view.colHeaderHeight, spreadNS.SheetArea.colHeader);
+        };
+        if (setting && setting.view && setting.view.rowHeaderWidth) {
+            sheet.setColumnWidth(0, setting.view.rowHeaderWidth, spreadNS.SheetArea.rowHeader);
+        };
+
         sheet.options.colHeaderAutoTextIndex = 1;
         sheet.options.colHeaderAutoTextIndex = 1;
         sheet.options.colHeaderAutoText = spreadNS.HeaderAutoText.numbers;
         sheet.options.colHeaderAutoText = spreadNS.HeaderAutoText.numbers;
+
+        sheet.options.protectionOptions = {
+            allowResizeColumns: true
+        };
+
         sheet.showRowOutline(false);
         sheet.showRowOutline(false);
         me.buildHeader(sheet, setting);
         me.buildHeader(sheet, setting);
         if (rowCount > 0) sheet.setRowCount(rowCount);
         if (rowCount > 0) sheet.setRowCount(rowCount);
@@ -31,29 +44,15 @@ var sheetCommonObj = {
         sheet.resumePaint();
         sheet.resumePaint();
     },
     },
 
 
+    // buildSheet 在一个Spread、一个Sheet的情况下使用。
     buildSheet: function(container, setting, rowCount) {
     buildSheet: function(container, setting, rowCount) {
         var me = this;
         var me = this;
-        var spreadBook = new GC.Spread.Sheets.Workbook(container, { sheetCount: 1 });
-        spreadBook.options.tabStripVisible = false;
-        spreadBook.options.showHorizontalScrollbar = true;
-        var spreadNS = GC.Spread.Sheets;
+        var spreadBook = me.createSpread(container, { sheetCount: 1 });
         var sheet = spreadBook.getSheet(0);
         var sheet = spreadBook.getSheet(0);
-        sheet.suspendPaint();
-        sheet.suspendEvent();
-        //Set rowHeader count and columnHeader count.
-        sheet.setRowCount(1, spreadNS.SheetArea.colHeader);
-        sheet.setColumnCount(setting.header.length, spreadNS.SheetArea.viewport);
-        sheet.options.colHeaderAutoTextIndex = 1;
-        sheet.options.colHeaderAutoText = spreadNS.HeaderAutoText.numbers;
-        sheet.showRowOutline(false);
-        //setup column header
-        me.buildHeader(sheet, setting);
-        //setup cells
-        if (rowCount > 0) sheet.setRowCount(rowCount);
-        sheet.resumeEvent();
-        sheet.resumePaint();
+        me.initSheet(sheet, setting, rowCount);
         return spreadBook;
         return spreadBook;
     },
     },
+
     buildHeader: function(sheet, setting){
     buildHeader: function(sheet, setting){
         var me = this, ch = GC.Spread.Sheets.SheetArea.colHeader;
         var me = this, ch = GC.Spread.Sheets.SheetArea.colHeader;
         for (var i = 0; i < setting.header.length; i++) {
         for (var i = 0; i < setting.header.length; i++) {
@@ -194,7 +193,7 @@ var sheetCommonObj = {
             sheet.options.isProtected = true;
             sheet.options.isProtected = true;
             sheet.getRange(-1, 0, -1, setting.header.length, GC.Spread.Sheets.SheetArea.viewport).locked(false);
             sheet.getRange(-1, 0, -1, setting.header.length, GC.Spread.Sheets.SheetArea.viewport).locked(false);
             for (var i = 0; i < setting.view.lockColumns.length; i++) {
             for (var i = 0; i < setting.view.lockColumns.length; i++) {
-                sheet.getRange(-1,setting.view.lockColumns[i] , -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
+                sheet.getRange(-1,setting.view.lockColumns[i], -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
             }
             }
         }
         }
     },
     },

+ 62 - 42
public/web/treeDataHelper.js

@@ -3,22 +3,22 @@
  */
  */
 const NODE_ID = "ID", P_ID = "ParentID", NEXT_ID = "NextSiblingID", ADHOC_PRE_ID="Previous_ID", CHILDREN_NODE = "items", SUB_ID = "sub_ids", EMPTY_ID_VAL = -1;
 const NODE_ID = "ID", P_ID = "ParentID", NEXT_ID = "NextSiblingID", ADHOC_PRE_ID="Previous_ID", CHILDREN_NODE = "items", SUB_ID = "sub_ids", EMPTY_ID_VAL = -1;
 
 
-var tree_Data_Helper = {
+let tree_Data_Helper = {
     buildTreeNodeDirectly: function(data) {
     buildTreeNodeDirectly: function(data) {
-        var me = this, topArr = [], rst = [], tmpNodes = {}, prefix = "id_";
-        private_getTopNode = function (idArr) {
-            var rst = null;
-            for (var i = 0; i < idArr.length; i++) {
-                if (tmpNodes[prefix + idArr[i]][ADHOC_PRE_ID] == EMPTY_ID_VAL) {
+        let topArr = [], rst = [], tmpNodes = {}, prefix = "id_";
+        let private_getTopNode = function (idArr) {
+            let rst = null;
+            for (let i = 0; i < idArr.length; i++) {
+                if (tmpNodes[prefix + idArr[i]][ADHOC_PRE_ID] === EMPTY_ID_VAL) {
                     rst = tmpNodes[prefix + idArr[i]];
                     rst = tmpNodes[prefix + idArr[i]];
                     break;
                     break;
                 }
                 }
             }
             }
             return rst;
             return rst;
-        }
-        private_buildNodeData = function(parentItem, idArr) {
-            var iter = [], nextNode = private_getTopNode(idArr);
-            while (nextNode != null && nextNode != undefined ) {
+        };
+        let private_buildNodeData = function(parentItem, idArr) {
+            let iter = [], nextNode = private_getTopNode(idArr);
+            while (nextNode !== null && nextNode !== undefined ) {
                 if (parentItem) {
                 if (parentItem) {
                     parentItem[CHILDREN_NODE].push(nextNode);
                     parentItem[CHILDREN_NODE].push(nextNode);
                 } else {
                 } else {
@@ -27,25 +27,25 @@ var tree_Data_Helper = {
                 iter.push(nextNode);
                 iter.push(nextNode);
                 nextNode = tmpNodes[prefix + nextNode[NEXT_ID]];
                 nextNode = tmpNodes[prefix + nextNode[NEXT_ID]];
             }
             }
-            for (var i = 0; i < iter.length; i++) {
+            for (let i = 0; i < iter.length; i++) {
                 private_buildNodeData(iter[i], iter[i][SUB_ID]);
                 private_buildNodeData(iter[i], iter[i][SUB_ID]);
             }
             }
-        }
+        };
 
 
-        for (var i = 0; i < data.length; i++) {
+        for (let i = 0; i < data.length; i++) {
             tmpNodes[prefix + data[i][NODE_ID]] = data[i];
             tmpNodes[prefix + data[i][NODE_ID]] = data[i];
             data[i][ADHOC_PRE_ID] = EMPTY_ID_VAL;
             data[i][ADHOC_PRE_ID] = EMPTY_ID_VAL;
             data[i][SUB_ID] = [];
             data[i][SUB_ID] = [];
             data[i][CHILDREN_NODE] = [];
             data[i][CHILDREN_NODE] = [];
-            if (data[i][P_ID] == EMPTY_ID_VAL) {
+            if (data[i][P_ID] === EMPTY_ID_VAL) {
                 topArr.push(data[i][NODE_ID]);
                 topArr.push(data[i][NODE_ID]);
             }
             }
         }
         }
-        for (var i = 0; i < data.length; i++) {
-            if (data[i][NEXT_ID] != EMPTY_ID_VAL) {
+        for (let i = 0; i < data.length; i++) {
+            if (data[i][NEXT_ID] !== EMPTY_ID_VAL) {
                 tmpNodes[prefix + data[i][NEXT_ID]][ADHOC_PRE_ID] = data[i][NODE_ID];
                 tmpNodes[prefix + data[i][NEXT_ID]][ADHOC_PRE_ID] = data[i][NODE_ID];
             }
             }
-            if (data[i][P_ID] != EMPTY_ID_VAL) {
+            if (data[i][P_ID] !== EMPTY_ID_VAL) {
                 tmpNodes[prefix + data[i][P_ID]][SUB_ID].push(data[i][NODE_ID]);
                 tmpNodes[prefix + data[i][P_ID]][SUB_ID].push(data[i][NODE_ID]);
             }
             }
         }
         }
@@ -55,34 +55,54 @@ var tree_Data_Helper = {
         topArr.length = 0;
         topArr.length = 0;
         return rst;
         return rst;
     },
     },
-    reSettleRelatedID: function(treeData) {
-        if (treeData && treeData.length > 0) {
-            for (var i = 0; i < treeData[CHILDREN_NODE].length; i++) {
-                var nI = null;
-                if (i < treeData[CHILDREN_NODE].length - 1) {
-                    nI = treeData[CHILDREN_NODE][i+1];
+
+    getFlatArray: function (srcArr, destArr) {
+        let private_put = function (parentItem) {
+            destArr.push(parentItem);
+            if (parentItem.items) {
+                for (let subItem of parentItem.items) {
+                    private_put(subItem);
                 }
                 }
-                settleNodeRelatedID(null, nI, treeData[CHILDREN_NODE][i]);
             }
             }
         }
         }
-    },
-    settleNodeRelatedID : function(parentItem, nextItem, node) {
-        if (parentItem) {
-            node[P_ID] = parentItem[NODE_ID];
-        } else {
-            node[P_ID] = EMPTY_ID_VAL;
+        for (let node of srcArr) {
+            private_put(node);
         }
         }
-        if (nextItem) {
-            node[NEXT_ID] = nextItem[NODE_ID];
-        } else {
-            node[NEXT_ID] = EMPTY_ID_VAL;
-        }
-        for (var i = 0; i < node[CHILDREN_NODE].length; i++) {
-            var nI = null;
-            if (i < node[CHILDREN_NODE].length - 1) {
-                nI = node[CHILDREN_NODE][i+1];
-            }
-            private_settleNodeRelatedID(node, nI, node[CHILDREN_NODE][i]);
+        for (let item of destArr) {
+            delete item[CHILDREN_NODE];
+            delete item[SUB_ID];
+            delete item[ADHOC_PRE_ID];
         }
         }
     }
     }
-}
+
+    // reSettleRelatedID: function(treeData) {
+    //     if (treeData && treeData.length > 0) {
+    //         for (let i = 0; i < treeData[CHILDREN_NODE].length; i++) {
+    //             let nI = null;
+    //             if (i < treeData[CHILDREN_NODE].length - 1) {
+    //                 nI = treeData[CHILDREN_NODE][i+1];
+    //             }
+    //             settleNodeRelatedID(null, nI, treeData[CHILDREN_NODE][i]);
+    //         }
+    //     }
+    // },
+    // settleNodeRelatedID : function(parentItem, nextItem, node) {
+    //     if (parentItem) {
+    //         node[P_ID] = parentItem[NODE_ID];
+    //     } else {
+    //         node[P_ID] = EMPTY_ID_VAL;
+    //     }
+    //     if (nextItem) {
+    //         node[NEXT_ID] = nextItem[NODE_ID];
+    //     } else {
+    //         node[NEXT_ID] = EMPTY_ID_VAL;
+    //     }
+    //     for (let i = 0; i < node[CHILDREN_NODE].length; i++) {
+    //         let nI = null;
+    //         if (i < node[CHILDREN_NODE].length - 1) {
+    //             nI = node[CHILDREN_NODE][i+1];
+    //         }
+    //         private_settleNodeRelatedID(node, nI, node[CHILDREN_NODE][i]);
+    //     }
+    // }
+};

+ 13 - 0
test/calculation/testArrayCalc.js

@@ -0,0 +1,13 @@
+/**
+ * Created by Tony on 2017/10/31.
+ */
+
+var test = require('tape');
+
+test('测试数组运算', function(t){
+    let demo = [1, 2, 3];
+    let rst = demo*3; //failed!
+    console.log(rst);
+    t.pass('just pass');
+    t.end('just end');
+});

+ 337 - 0
test/unit/reports/rpt_cfg.js

@@ -0,0 +1,337 @@
+module.exports = {
+    "fonts" : [
+        {
+            "ID" : "ReportTitle_Main",
+            "CfgDispName" : "主标题",
+            "Name" : "smartSimSun",
+            "FontHeight" : "27",
+            "FontColor" : "BLACK",
+            "FontBold" : "T",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "ReportTitle_Vice_1",
+            "CfgDispName" : "副标题",
+            "Name" : "smartSimSun",
+            "FontHeight" : "20",
+            "FontColor" : "BLACK",
+            "FontBold" : "T",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "HeaderColumn",
+            "CfgDispName" : "栏头",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "Header",
+            "CfgDispName" : "表头",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "FooterColumn",
+            "CfgDispName" : "栏尾",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "Footer",
+            "CfgDispName" : "表尾",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "GramdTotal",
+            "CfgDispName" : "总合计",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "SectionTotal",
+            "CfgDispName" : "章合计",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "Content",
+            "CfgDispName" : "正文内容",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "0"
+        },
+        {
+            "ID" : "Header_V1",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "90"
+        },
+        {
+            "ID" : "Header_V2",
+            "Name" : "smartSimSun",
+            "FontHeight" : "12",
+            "FontColor" : "BLACK",
+            "FontBold" : "F",
+            "FontItalic" : "F",
+            "FontUnderline" : "F",
+            "FontStrikeOut" : "F",
+            "FontAngle" : "-90"
+        }
+    ],
+    "styles" : [
+        {
+            "ID" : "Default_None",
+            "CfgDispName" : "空白",
+            "border_style" : []
+        },
+        {
+            "ID" : "Default",
+            "CfgDispName" : "默认",
+            "border_style" : []
+        },
+        {
+            "ID" : "Default_Normal",
+            "CfgDispName" : "正常",
+            "border_style" : [
+                {
+                    "Position" : "Left",
+                    "LineWeight" : "1",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Right",
+                    "LineWeight" : "1",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Top",
+                    "LineWeight" : "1",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Bottom",
+                    "LineWeight" : "1",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                }
+            ]
+        },
+        {
+            "ID" : "Label_Underline",
+            "CfgDispName" : "字符底线",
+            "border_style" : [
+                {
+                    "Position" : "Left",
+                    "LineWeight" : "0",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Right",
+                    "LineWeight" : "0",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Top",
+                    "LineWeight" : "0",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Bottom",
+                    "LineWeight" : "1",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                }
+            ]
+        },
+        {
+            "ID" : "BORDER_ALL_AROUND",
+            "CfgDispName" : "报表边框",
+            "border_style" : [
+                {
+                    "Position" : "Left",
+                    "LineWeight" : "0.0",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Right",
+                    "LineWeight" : "0.0",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Top",
+                    "LineWeight" : "2.0",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                },
+                {
+                    "Position" : "Bottom",
+                    "LineWeight" : "2.0",
+                    "DashStyle" : "SOLID",
+                    "Color" : "BLACK"
+                }
+            ]
+        }
+    ],
+    "ctrls" : [
+        {
+            "ID" : "Default",
+            "CfgDispName" : "默认",
+            "Shrink" : "T",
+            "ShowZero" : "T",
+            "Horizon" : "left",
+            "Vertical" : "bottom",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Title",
+            "CfgDispName" : "标题",
+            "Shrink" : "T",
+            "ShowZero" : "T",
+            "Horizon" : "center",
+            "Vertical" : "center",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Header",
+            "CfgDispName" : "表头",
+            "Shrink" : "T",
+            "ShowZero" : "T",
+            "Horizon" : "left",
+            "Vertical" : "center",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Footer",
+            "CfgDispName" : "表尾",
+            "Shrink" : "T",
+            "ShowZero" : "T",
+            "Horizon" : "left",
+            "Vertical" : "center",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Column",
+            "CfgDispName" : "表栏",
+            "Shrink" : "T",
+            "ShowZero" : "T",
+            "Horizon" : "center",
+            "Vertical" : "center",
+            "Wrap" : "false",
+            "FillAfterWrap" : "true"
+        },
+        {
+            "ID" : "Column_Left",
+            "CfgDispName" : "表栏_左",
+            "Shrink" : "T",
+            "ShowZero" : "T",
+            "Horizon" : "left",
+            "Vertical" : "center",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Column_Right",
+            "CfgDispName" : "表栏_右",
+            "Shrink" : "T",
+            "ShowZero" : "T",
+            "Horizon" : "right",
+            "Vertical" : "center",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Content_Left",
+            "CfgDispName" : "正文内容",
+            "Shrink" : "T",
+            "ShowZero" : "F",
+            "Horizon" : "left",
+            "Vertical" : "bottom",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Content_Right",
+            "CfgDispName" : "正文内容_右",
+            "Shrink" : "T",
+            "ShowZero" : "F",
+            "Horizon" : "right",
+            "Vertical" : "bottom",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Content_Center",
+            "CfgDispName" : "正文内容_中",
+            "Shrink" : "T",
+            "ShowZero" : "F",
+            "Horizon" : "center",
+            "Vertical" : "bottom",
+            "Wrap" : "false"
+        },
+        {
+            "ID" : "Numeric",
+            "Shrink" : "T",
+            "ShowZero" : "F",
+            "Horizon" : "right",
+            "Vertical" : "bottom",
+            "Wrap" : "false"
+        }
+    ]
+}

+ 79 - 53
test/unit/reports/test_tpl_09_1.js

@@ -2,11 +2,13 @@
  * Created by Tony on 2017/10/18.
  * Created by Tony on 2017/10/18.
  */
  */
 let test = require('tape');
 let test = require('tape');
+import JpcEx from "../../../modules/reports/rpt_component/jpc_ex";
 import JV from "../../../modules/reports/rpt_component/jpc_value_define";
 import JV from "../../../modules/reports/rpt_component/jpc_value_define";
 let mongoose = require("mongoose");
 let mongoose = require("mongoose");
 let fileUtils = require("../../../modules/common/fileUtils");
 let fileUtils = require("../../../modules/common/fileUtils");
 let path = require('path');
 let path = require('path');
 let dbm = require("../../../config/db/db_manager");
 let dbm = require("../../../config/db/db_manager");
+let rpt_cfg = require('./rpt_cfg');
 dbm.connect();
 dbm.connect();
 let consts = require('../../../modules/main/models/project_consts');
 let consts = require('../../../modules/main/models/project_consts');
 let projectConsts = consts.projectConst;
 let projectConsts = consts.projectConst;
@@ -26,7 +28,8 @@ fileUtils.getGlobbedFiles('../../../modules/reports/models/*.js').forEach(functi
 //暂时引入其它模块的model
 //暂时引入其它模块的model
 require('../../../modules/fee_rates/models/fee_rates');
 require('../../../modules/fee_rates/models/fee_rates');
 // 引入人工系数模块
 // 引入人工系数模块
-require('../../../modules/main/models/labour_coe');
+require('../../../modules/main/models/labour_coe_model');
+require('../../../modules/main/models/calc_program_model');
 
 
 let fsUtil = require("../../../public/fsUtil");
 let fsUtil = require("../../../public/fsUtil");
 
 
@@ -35,9 +38,7 @@ let projectDataMdl = require('../../../modules/main/models/project');
 let demoPrjId = - 1;
 let demoPrjId = - 1;
 let demoRptId = 226, pagesize = "A4";
 let demoRptId = 226, pagesize = "A4";
 
 
-demoPrjId = 469; //QA: 1号教学楼建筑工程
-// demoPrjId = 491; //QA: 2号教学楼建筑工程
-// demoPrjId = 492; //QA: 3号教学楼建筑工程
+demoPrjId = 610; //QA: 建筑工程
 let userId_Leng = 1142; //小冷User Id
 let userId_Leng = 1142; //小冷User Id
 
 
 let rptTplFacade = require("../../../modules/reports/facade/rpt_template_facade");
 let rptTplFacade = require("../../../modules/reports/facade/rpt_template_facade");
@@ -45,66 +46,90 @@ let rptTplDataFacade = require("../../../modules/reports/facade/rpt_tpl_data_fac
 
 
 import rptDataExtractor from "../../../modules/reports/util/rpt_construct_data_util";
 import rptDataExtractor from "../../../modules/reports/util/rpt_construct_data_util";
 
 
-// test('测试 - 获取project数据: ', function (t) {
-//     projectDataMdl.getData(demoPrjId, function (err, message, result) {
-//         if (!err) {
-//             fsUtil.wirteObjToFile(result, "D:/GitHome/ConstructionCost/tmp/ProjectDataFullObject.js");
-//             t.pass('pass succeeded!');
-//             t.end();
-//         } else {
-//             //callback(req, res, err, message, null);
-//             t.pass('pass failed!');
-//             t.end();
-//         }
-//     });
-// });
+let fs = require('fs');
+//设置Date Format函数
+fs.readFile(__dirname.slice(0, __dirname.length - 18) + '/public/web/date_util.js', 'utf8', 'r', function (err, data) {
+    eval(data);
+});
 
 
-// test('测试 - 获取project部分数据: ', function (t) {
-//     let filter = [];
-//     filter.push(projectConsts.BILLS);
-//     filter.push(projectConsts.RATION);
-//     filter.push(projectConsts.RATION_GLJ);
-//     filter.push(projectConsts.FEERATE);
-//     prjMdl.project.getUserProject(userId_Leng, demoPrjId, function(err, msg, prjObj){
-//         if (!err) {
-//             projectDataMdl.getFilterData(demoPrjId, filter, function (results) {
-//                 if (results) {
-//                     // let newData = [];
-//                     // for (let item of results) {
-//                     //     newData.push(JSON.stringify(item));
-//                     // }
-//                     // fsUtil.writeArrayToFile(newData, "D:/GitHome/ConstructionCost/tmp/getProjectData_partial.js");
-//                     fsUtil.wirteObjToFile(prjObj, "D:/GitHome/ConstructionCost/tmp/getProjectObjectNew.js");
-//                     fsUtil.wirteObjToFile(results, "D:/GitHome/ConstructionCost/tmp/getProjectData_partialNew.js");
-//                     t.pass('pass succeeded!');
-//                     t.end();
-//                 } else {
-//                     //callback(req, res, err, message, null);
-//                     t.pass('get project data failed!');
-//                     t.end();
-//                 }
-//             });
-//         } else {
-//             t.pass('get project failed!');
-//             t.end();
-//         }
-//     });
-// });
+/*/
+test('测试 - 获取project数据: ', function (t) {
+    projectDataMdl.getData(demoPrjId, function (err, message, result) {
+        if (!err) {
+            fsUtil.wirteObjToFile(result, "D:/GitHome/ConstructionCost/tmp/ProjectDataFullObject.js");
+            t.pass('pass succeeded!');
+            t.end();
+        } else {
+            //callback(req, res, err, message, null);
+            t.pass('pass failed!');
+            t.end();
+        }
+    });
+});
+//*/
+/*/
+test('测试 - 获取project部分数据: ', function (t) {
+    let filter = [];
+    filter.push(projectConsts.BILLS);
+    filter.push(projectConsts.RATION);
+    filter.push(projectConsts.RATION_GLJ);
+    filter.push(projectConsts.FEERATE);
+    prjMdl.project.getUserProject(userId_Leng, demoPrjId, function(err, msg, prjObj){
+        if (!err) {
+            projectDataMdl.getFilterData(demoPrjId, filter, function (results) {
+                if (results) {
+                    // let newData = [];
+                    // for (let item of results) {
+                    //     newData.push(JSON.stringify(item));
+                    // }
+                    // fsUtil.writeArrayToFile(newData, "D:/GitHome/ConstructionCost/tmp/getProjectData_partial.js");
+                    fsUtil.wirteObjToFile(prjObj, "D:/GitHome/ConstructionCost/tmp/getProjectObjectNew.js");
+                    fsUtil.wirteObjToFile(results, "D:/GitHome/ConstructionCost/tmp/getProjectData_partialNew.js");
+                    t.pass('pass succeeded!');
+                    t.end();
+                } else {
+                    //callback(req, res, err, message, null);
+                    t.pass('get project data failed!');
+                    t.end();
+                }
+            });
+        } else {
+            t.pass('get project failed!');
+            t.end();
+        }
+    });
+});
+//*/
 
 
+//*
 test('测试 - 测试模板啦: ', function (t) {
 test('测试 - 测试模板啦: ', function (t) {
-    rptTplFacade.getRptTemplate(demoRptId).then(function(tpl) {
+    rptTplFacade.getRptTemplate(demoRptId).then(function(rptTpl) {
         let rptDataUtil = new rptDataExtractor();
         let rptDataUtil = new rptDataExtractor();
-        rptDataUtil.initialize(tpl);
+        rptDataUtil.initialize(rptTpl._doc);
         let filter = rptDataUtil.getDataRequestFilter();
         let filter = rptDataUtil.getDataRequestFilter();
         console.log(filter);
         console.log(filter);
         //正常应该根据报表模板定义的数据类型来请求数据
         //正常应该根据报表模板定义的数据类型来请求数据
         rptTplDataFacade.prepareProjectData(userId_Leng, demoPrjId, filter, function (err, msg, rawDataObj) {
         rptTplDataFacade.prepareProjectData(userId_Leng, demoPrjId, filter, function (err, msg, rawDataObj) {
             if (!err) {
             if (!err) {
-                rptDataUtil.assembleData(rawDataObj);
+                let tplData = rptDataUtil.assembleData(rawDataObj);
+                // fsUtil.wirteObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataObject.js");
+                //it's time to build the report!!!
+                let printCom = JpcEx.createNew();
+                rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_PAGE_SIZE] = pagesize;
+                let defProperties = rpt_cfg;
+                let dftOption = JV.PAGING_OPTION_NORMAL;
+                printCom.initialize(rptTpl);
+                printCom.analyzeData(rptTpl, tplData, defProperties, dftOption);
+                let maxPages = printCom.totalPages;
+                let pageRst = printCom.outputAsSimpleJSONPageArray(rptTpl, tplData, 1, maxPages, defProperties);
+                if (pageRst) {
+                    fsUtil.wirteObjToFile(pageRst, "D:/GitHome/ConstructionCost/tmp/testBuiltPageResult.js");
+                } else {
+                    console.log("oh! no pages were created!")
+                }
+
                 t.pass('pass succeeded!');
                 t.pass('pass succeeded!');
                 t.end();
                 t.end();
-                //fsUtil.wirteObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataObject1.js");
-                //准备执行公式需要的对象
             } else {
             } else {
                 console.log(msg);
                 console.log(msg);
                 t.pass('pass with error!');
                 t.pass('pass with error!');
@@ -113,6 +138,7 @@ test('测试 - 测试模板啦: ', function (t) {
         })
         })
     });
     });
 });
 });
+//*/
 
 
 test('close the connection', function (t) {
 test('close the connection', function (t) {
     setTimeout(function () {
     setTimeout(function () {

+ 3 - 11
web/building_saas/fee_rates/fee_rate.html

@@ -1,14 +1,6 @@
-<!DOCTYPE html>
-<html lang="en">
 
 
-<head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-    <meta http-equiv="x-ua-compatible" content="ie=edge">
 
 
-</head>
-
-<body >
+<div >
 <div class="toolsbar px-1">
 <div class="toolsbar px-1">
     <div class="form-inline py-1">
     <div class="form-inline py-1">
         <label class="mx-2" >当前使用:<span id="feeRateFileName">费率1</span>(<a href="#" id="pop-lv"><span id="projectCount">3</span> 单位工程使用</a>)
         <label class="mx-2" >当前使用:<span id="feeRateFileName">费率1</span>(<a href="#" id="pop-lv"><span id="projectCount">3</span> 单位工程使用</a>)
@@ -164,5 +156,5 @@
 </div>
 </div>
 
 
 
 
-</body>
-</html>
+</div>
+

+ 2 - 2
web/building_saas/glj/html/glj_index.html

@@ -21,7 +21,7 @@
             <div class="bottom-content">
             <div class="bottom-content">
                 <ul class="nav nav-tabs" role="tablist">
                 <ul class="nav nav-tabs" role="tablist">
                     <li class="nav-item">
                     <li class="nav-item">
-                        <a class="nav-link active" data-toggle="tab" data-name="ration" href="#de" role="tab">相关定额</a>
+                        <a class="nav-link active" data-toggle="tab" data-name="ration" href="#glj_de" role="tab">相关定额</a>
                     </li>
                     </li>
                     <li class="nav-item">
                     <li class="nav-item">
                         <a class="nav-link" data-toggle="tab" data-name="mix-ratio" href="#ph" role="tab">配合比表</a>
                         <a class="nav-link" data-toggle="tab" data-name="mix-ratio" href="#ph" role="tab">配合比表</a>
@@ -32,7 +32,7 @@
                 </ul>
                 </ul>
                 <!-- Tab panes -->
                 <!-- Tab panes -->
                 <div class="tab-content">
                 <div class="tab-content">
-                    <div class="tab-pane active" id="de" role="tabpanel">
+                    <div class="tab-pane active" id="glj_de" role="tabpanel">
                         <div class="main-data-bottom ovf-hidden">
                         <div class="main-data-bottom ovf-hidden">
                             相关定额
                             相关定额
                         </div>
                         </div>

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

@@ -194,7 +194,7 @@ CommonSpreadJs.prototype.filterData = function(field, filterList) {
     let fieldColumn = this.getFieldColumn(field);
     let fieldColumn = this.getFieldColumn(field);
     fieldColumn = parseInt(fieldColumn);
     fieldColumn = parseInt(fieldColumn);
 
 
-    let filter = new GC.Spread.Sheets.Filter.HideRowFilter(new GC.Spread.Sheets.Range(-1, 5, -1, 1));
+    let filter = new GC.Spread.Sheets.Filter.HideRowFilter(new GC.Spread.Sheets.Range(-1, fieldColumn, -1, 1));
     this.sheet.rowFilter(filter);
     this.sheet.rowFilter(filter);
 
 
     let rowFilter = this.sheet.rowFilter();
     let rowFilter = this.sheet.rowFilter();

+ 3 - 0
web/building_saas/glj/js/composition.js

@@ -69,4 +69,7 @@ function compositionSuccess(info) {
     projectGLJSheet.setCellByField('unit_price.market_price', info.parentMarketPrice, false);
     projectGLJSheet.setCellByField('unit_price.market_price', info.parentMarketPrice, false);
     projectGLJSheet.setCellByField('unit_price.base_price', info.parentBasePrice, false);
     projectGLJSheet.setCellByField('unit_price.base_price', info.parentBasePrice, false);
     projectGLJSheet.setCellByField('adjust_price', info.parentMarketPrice, false);
     projectGLJSheet.setCellByField('adjust_price', info.parentMarketPrice, false);
+
+    // 更新组成物缓存
+    projectObj.project.composition.loadData();
 }
 }

+ 1 - 1
web/building_saas/glj/js/composition_spread.js

@@ -92,7 +92,7 @@ CompositionSpread.prototype.initRightClick = function(target) {
                     let row = self.rightClickTarget.row;
                     let row = self.rightClickTarget.row;
                     let idColumn = self.sheetObj.getFieldColumn('mix_ratio_id');
                     let idColumn = self.sheetObj.getFieldColumn('mix_ratio_id');
                     let deleteId = activeSheet.getValue(row, idColumn);
                     let deleteId = activeSheet.getValue(row, idColumn);
-                    self.deleteComposition(deleteId, row, mixRatioSuccess);
+                    self.deleteComposition(deleteId, row, self.successCallback);
                 }
                 }
             },
             },
         }
         }

+ 1 - 0
web/building_saas/glj/js/project_glj.js

@@ -26,6 +26,7 @@ let currentTag = '';
 let isChanging = false;
 let isChanging = false;
 $(document).ready(function () {
 $(document).ready(function () {
     $('#tab_gongliaoji').on('show.bs.tab', function (e) {
     $('#tab_gongliaoji').on('show.bs.tab', function (e) {
+        $(e.relatedTarget.hash).removeClass('active');
         init();
         init();
     });
     });
 
 

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

@@ -9,22 +9,22 @@
 
 
 <body>
 <body>
 <div style="">
 <div style="">
-    <img id="f_btn" src="/web/dest/css/img/feeRate_btn.jpg" alt="" />
+    <img id="f_btn" src="/web/dest/css/img/feeRate_btn.jpg" alt="" style="display: block" />
 </div>
 </div>
     <div class="toolsbar px-1">
     <div class="toolsbar px-1">
     </div>
     </div>
     <div class="container-fluid">
     <div class="container-fluid">
         <div class="row">
         <div class="row">
-        <div class="col-lg-3 p-0">
-            <div class="main-data-not" id="mainSpread">
+            <div class="col-lg-2 p-0">
+                <div class="main-data-not" id="mainSpread">
+                </div>
             </div>
             </div>
-        </div>
-        <div class="col-lg-9 p-0">
-            <div class="main-data-not" id="detailSpread">
+            <div class="col-lg-10 p-0">
+                <div class="main-data-not" id="detailSpread">
+                </div>
             </div>
             </div>
         </div>
         </div>
     </div>
     </div>
-    </div>
 
 
     <!--弹出 计算基数-->
     <!--弹出 计算基数-->
 <div class="modal fade" id="jsjs" data-backdrop="static">
 <div class="modal fade" id="jsjs" data-backdrop="static">

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 161 - 308
web/building_saas/main/html/main.html


+ 13 - 8
web/building_saas/main/js/controllers/project_controller.js

@@ -18,17 +18,22 @@ ProjectController = {
         if (!project || !sheetController) { return null; }
         if (!project || !sheetController) { return null; }
 
 
         let target = project.getParentTarget(project.mainTree.selected, 'sourceType', project.Bills.getSourceType());
         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;
+        let newSource = null, newNode = null, parentID, nextSiblingID;
+        if (target) {
+            console.log(target.depth());
+            parentID = target.depth() === 0 ? target.source.getID() : target.source.getParentID();
+            nextSiblingID = target ? target.source.getNextSiblingID() : project.Bills.tree.setting.rootId;
 
 
-        if (std) {
-            let newCode = project.Bills.newFormatCode(std.code);
-            newSource = project.Bills.insertStdBills(parentID, nextSiblingID, std, newCode);
+            if (std) {
+                let newCode = project.Bills.newFormatCode(std.code);
+                newSource = project.Bills.insertStdBills(parentID, nextSiblingID, std, newCode);
+            } else {
+                newSource = project.Bills.insertBills(parentID, nextSiblingID);
+            }
+            newNode = project.mainTree.insert(target.depth() === 0 ? target.getID() : target.getParentID(), target.getNextSiblingID());
         } else {
         } else {
-            newSource = project.Bills.insertBills(parentID, nextSiblingID);
+            alert('不可添加清单');
         }
         }
-        newNode = project.mainTree.insert(target.getParentID(), target.getNextSiblingID());
 
 
         if (newNode) {
         if (newNode) {
             newNode.source = newSource;
             newNode.source = newSource;

+ 13 - 0
web/building_saas/main/js/main.js

@@ -6,4 +6,17 @@ $(function () {
     projectInfoObj.showProjectInfo();
     projectInfoObj.showProjectInfo();
     projectObj.checkMainSpread();
     projectObj.checkMainSpread();
     projectObj.loadProjectData();
     projectObj.loadProjectData();
+
+    $('#tab_baobiao').on('shown.bs.tab', function (e) {
+        $(e.relatedTarget.hash).removeClass('active');
+        // do something
+    });
+
+    $('#tab_zaojiashu').on('shown.bs.tab', function (e) {
+        $(e.relatedTarget.hash).removeClass('active');
+        $("#subItems").addClass('active');
+        $(gljOprObj.activeTab).addClass('active');
+        // do something
+    });
+
 });
 });

+ 77 - 0
web/building_saas/main/js/models/composition.js

@@ -0,0 +1,77 @@
+/**
+ * 组成物相关数据
+ *
+ * @author CaiAoLin
+ * @date 2017/10/27
+ * @version
+ */
+
+function Composition() {
+    this.datas = null;
+    this.isLoading = false;
+}
+/**
+ * 加载数据
+ *
+ * @param {function} callback
+ * @return {boolean}
+ */
+Composition.prototype.loadData = function (callback = null) {
+    let self = this;
+    if (self.isLoading) {
+        return false;
+    }
+    // 加载组成物数据
+    $.ajax({
+        url: '/glj/get-composition',
+        type: 'post',
+        dataType: 'json',
+        data: {project_id: scUrlUtil.GetQueryString('project')},
+        error: function() {
+            // alert('数据传输错误');
+        },
+        beforeSend: function() {
+            self.isLoading = true;
+        },
+        success: function(response) {
+            self.isLoading = false;
+            if (response.err === 1) {
+                let msg = response.msg !== undefined && response.msg !== '' ? response.msg : '读取组成物数据失败!';
+                alert(msg);
+                return false;
+            }
+            self.datas = response.data;
+            // 回调函数
+            if (callback !== null) {
+                callback(response.data);
+            }
+            // 存入缓存
+            projectObj.project.composition = self;
+        }
+    });
+};
+
+/**
+ * 获取对应code的组成物数据
+ *
+ * @param {String} code
+ * @param {Number} gljType
+ * @return {Array}
+ */
+Composition.prototype.getCompositionByCode = function(code, gljType = 0) {
+    let result = [];
+    if (code === '') {
+        return result;
+    }
+    if (gljType === 0) {
+        return this.datas[code] !== undefined ? this.datas[code] : result;
+    }
+
+    for(let composition of this.datas[code]) {
+        if (composition.glj_type === gljType) {
+            result.push(composition);
+        }
+    }
+
+    return result;
+};

+ 179 - 44
web/building_saas/main/js/models/fee_rate.js

@@ -8,6 +8,7 @@ var FeeRate = {
 
 
         function FeeRate(proj){
         function FeeRate(proj){
             this.datas = null;
             this.datas = null;
+            this.datasBackup = null;
             this.sourceType = ModuleNames.feeRate;
             this.sourceType = ModuleNames.feeRate;
             proj.registerModule(ModuleNames.feeRate, this);
             proj.registerModule(ModuleNames.feeRate, this);
         };
         };
@@ -15,15 +16,14 @@ var FeeRate = {
             this.datas = datas;
             this.datas = datas;
             socketObject.connect();
             socketObject.connect();
         };
         };
-   /*     FeeRate.prototype.getViewDatas = function(){
-            var  rates=[];
-            _.forEach(this.datas,function (item) {
-                if(item.status == 'activate'){
-                    rates= item.rates;
-                }
-            })
-            return rates;
-        };*/
+        FeeRate.prototype.backupDatas=function () {
+          this.datasBackup = _.cloneDeep(this.datas);
+        };
+        FeeRate.prototype.dataRecovery=function () {
+            this.datas = this.datasBackup;
+            feeRateObject.activateFeeRate = this.getActivateFeeRate();
+            feeRateObject.datas = feeRateObject.activateFeeRate.rates;
+        };
         FeeRate.prototype.getActivateFeeRate = function () {
         FeeRate.prototype.getActivateFeeRate = function () {
             var feeRate={
             var feeRate={
                 rates:[]
                 rates:[]
@@ -126,20 +126,35 @@ var FeeRate = {
             doc.rate.rate =doc.rate.rate.toDecimal(feeRate_consts.decimal);
             doc.rate.rate =doc.rate.rate.toDecimal(feeRate_consts.decimal);
             this.updateFeeRate(query,doc);
             this.updateFeeRate(query,doc);
             if(this.ifRateChange(params)){
             if(this.ifRateChange(params)){
-                this.synchronizeFeeRate();
+                //this.synchronizeFeeRate();
+                this.onFeeRateChange(params.dataItem.ID,params.dataItem.rate);
             }
             }
         };
         };
 
 
         FeeRate.prototype.batchUpdateFeeRate = function (items,feerate) {
         FeeRate.prototype.batchUpdateFeeRate = function (items,feerate) {
-            var query={
-                ID:feerate.feeRateID
-            };
-            this.updateFeeRate(query,items);
+            var me = this;
+            var data={
+                query:{
+                    ID:feerate.feeRateID
+                },
+                doc:items,
+                user_id:userID
+            }
+            var errCallBack=function () {
+                me.dataRecovery();
+                $.bootstrapLoading.end();
+            }
+            CommonAjax.post('/feeRates/updateRates', data, function (result) {
+                _.forEach(items,function (t) {
+                     feeRateObject.mainViews.data.updateItem(t.rateIndex,t.rate);
+                 })
+                 me.onFeeRateFileChange();
+                $.bootstrapLoading.end();
+            },errCallBack);
         };
         };
         FeeRate.prototype.updateFeeRate=function (query,doc) {
         FeeRate.prototype.updateFeeRate=function (query,doc) {
           var updateData = this.getUpdateData('ut_update',query,doc,'update_rates');
           var updateData = this.getUpdateData('ut_update',query,doc,'update_rates');
             project.pushNow('updateFeeRate',[this.sourceType],updateData);
             project.pushNow('updateFeeRate',[this.sourceType],updateData);
-            socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());
         };
         };
         FeeRate.prototype.updateStatusBySelected = function (updateTasks) {
         FeeRate.prototype.updateStatusBySelected = function (updateTasks) {
             var updateData = [];
             var updateData = [];
@@ -155,18 +170,102 @@ var FeeRate = {
             var node = project.mainTree.selected;
             var node = project.mainTree.selected;
             if(node){
             if(node){
                 if (node.sourceType==='ration' && calcProgramObj.sheet) {
                 if (node.sourceType==='ration' && calcProgramObj.sheet) {
-                    project.calcProgram.compileAllTemps();
                     calcProgramObj.showData(node);
                     calcProgramObj.showData(node);
                 }
                 }
             }
             }
         };
         };
         FeeRate.prototype.ifRateChange=function (params) {
         FeeRate.prototype.ifRateChange=function (params) {
-            if(params.dataItem.rate!=params.oldDataItem.rate){
+            if(params.dataItem.memo==params.oldDataItem.memo){
                 return true;
                 return true;
             }else {
             }else {
                 return false;
                 return false;
             }
             }
         };
         };
+        FeeRate.prototype.onFeeRateChange=function (rateID,value) {
+            var node = project.mainTree.selected;
+            this.refreshCalProgramByRateID(rateID,value);
+            this.refreshBillsByRateID(rateID,value);
+            if(node){
+                if (node.sourceType==='ration' && calcProgramObj.sheet) {
+                    calcProgramObj.showData(node);
+                }
+            }
+            socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());
+        };
+        FeeRate.prototype.onFeeRateFileChange=function () {
+            this.refreshCalProgramWhenFeeFileChange();
+            this.refreshBillsWhenFeeFileChange();
+            var node = project.mainTree.selected;
+            if(node){
+                if (node.sourceType==='ration' && calcProgramObj.sheet) {
+                    calcProgramObj.showData(node);
+                }
+            }
+            socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());
+        };
+
+        FeeRate.prototype.refreshBillsWhenFeeFileChange=function(){
+            var me = this;
+            var nodes = _.filter(projectObj.project.mainTree.items,function (n) {
+                if(n.sourceType==ModuleNames.bills&&n.data.feeRateID){
+                    if(n.data.hasOwnProperty("feeRateID")&&n.data.feeRateID){
+                        var rate = me.getFeeRateByID(n.data.feeRateID);
+                        if(rate){
+                            n.data.feeRate=number_util.roundToString(rate.rate,feeRate_consts.decimal);
+                            return true;
+                        }else {
+                            n.data.feeRate=null;
+                            return true;
+                        }
+                    }
+                }
+                return false;
+            })
+            if(nodes.length>0){
+                projectObj.mainController.refreshTreeNode(nodes)
+            }
+        };
+        FeeRate.prototype.refreshCalProgramWhenFeeFileChange=function () {
+            var me = this;
+            var templates = project.calcProgram.datas.templates;
+            for(var i =0;i<templates.length;i++){
+                _.forEach(templates[i].calcItems,function (item) {
+                    if(item.hasOwnProperty("feeRateID")&&item.feeRateID){
+                        var rate = me.getFeeRateByID(item.feeRateID);
+                        if(rate){
+                            item.feeRate = rate.rate;
+                        }
+                    }
+                })
+            }
+            project.calcProgram.compileAllTemps();
+            rationPM.refreshDetailSheet();
+        }
+        FeeRate.prototype.refreshCalProgramByRateID=function (rateID,value) {
+            var templates = project.calcProgram.datas.templates;
+            for(var i =0;i<templates.length;i++){
+                _.forEach(templates[i].calcItems,function (item) {
+                    if(item.feeRateID==rateID){
+                        item.feeRate = value;
+                    }
+                })
+            }
+            project.calcProgram.compileAllTemps();
+            rationPM.refreshDetailSheet();
+        };
+        FeeRate.prototype.refreshBillsByRateID=function(rateID,value){
+            var nodes = _.filter(projectObj.project.mainTree.items,function (n) {
+                if(n.sourceType==ModuleNames.bills&&n.data.feeRateID==rateID){
+                    n.data.feeRate=number_util.roundToString(value,feeRate_consts.decimal);
+                    return true;
+                }else {
+                    return false;
+                }
+            })
+            if(nodes.length>0){
+                projectObj.mainController.refreshTreeNode(nodes)
+            }
+        };
         FeeRate.prototype.changeFeeRateStandard=function(newVal,callback){
         FeeRate.prototype.changeFeeRateStandard=function(newVal,callback){
             var me =this;
             var me =this;
             var feeRate = this.getActivateFeeRate();
             var feeRate = this.getActivateFeeRate();
@@ -182,9 +281,11 @@ var FeeRate = {
                     me.datas.libName=data.libName;
                     me.datas.libName=data.libName;
                     me.datas.feeRateID=data.feeRateID;
                     me.datas.feeRateID=data.feeRateID;
                     me.datas.rates=data.rates;
                     me.datas.rates=data.rates;
-                    socket.emit('feeRateChangeNotify', me.getActivateFeeRateFileID());
+                    me.onFeeRateFileChange();
                     callback();
                     callback();
                 }
                 }
+            },function () {
+                $.bootstrapLoading.end();
             });
             });
         };
         };
         FeeRate.prototype.checkFeeRateName = function(newVal,callback){
         FeeRate.prototype.checkFeeRateName = function(newVal,callback){
@@ -198,17 +299,26 @@ var FeeRate = {
                 callback(data);
                 callback(data);
             });
             });
         };
         };
-        FeeRate.prototype.feeRateFileSaveAs = function (newName) {
+        FeeRate.prototype.feeRateFileSaveAs = function (newName,callback) {
+            var me = this;
+            $.bootstrapLoading.start();
+            this.backupDatas();
             this.datas.name = newName;
             this.datas.name = newName;
             this.datas.ID = uuid.v1();
             this.datas.ID = uuid.v1();
             this.datas.feeRateID=uuid.v1();
             this.datas.feeRateID=uuid.v1();
             this.datas.usageProjects=[];
             this.datas.usageProjects=[];
             this.datas.usageProjects.push({name:projectInfoObj.projectInfo.name,ID:projectInfoObj.projectInfo.ID});
             this.datas.usageProjects.push({name:projectInfoObj.projectInfo.name,ID:projectInfoObj.projectInfo.ID});
-            var updateData = this.getUpdateData('ut_update',{projectID:projectInfoObj.projectInfo.ID},this.datas,'feeRateFileSaveAs');
-            project.pushNow('updateFeeRate',[this.sourceType],updateData);
-
-            socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());
-            return  this.datas;
+            var data={
+                query:{projectID:projectInfoObj.projectInfo.ID},
+                doc:this.datas,
+                user_id:userID
+            }
+            CommonAjax.post('/feeRates/feeRateFileSaveAs', data, function (data) {
+                callback(me.datas);
+            },function () {
+                me.dataRecovery();
+                $.bootstrapLoading.end();
+            });
         };
         };
         FeeRate.prototype.getChangeInfo = function (callback) {
         FeeRate.prototype.getChangeInfo = function (callback) {
            // var projectID = projectInfoObj.projectInfo.ID;
            // var projectID = projectInfoObj.projectInfo.ID;
@@ -235,8 +345,8 @@ var FeeRate = {
                     var data=me.getfbUpdateData(rate,bill,value);
                     var data=me.getfbUpdateData(rate,bill,value);
                     this.setFeeRateToBill(data,function (result) {
                     this.setFeeRateToBill(data,function (result) {
                         if(data.hasOwnProperty('feeRate')){
                         if(data.hasOwnProperty('feeRate')){
-                            me.refreshBillsByRateID(rate,value);
-                            socket.emit('feeRateChangeNotify', me.getActivateFeeRateFileID());
+                            rate.rate=value;
+                            me.onFeeRateChange(rate.ID,value);
                         }else {
                         }else {
                             bill.feeRate=value;
                             bill.feeRate=value;
                             projectObj.mainController.refreshTreeNode([node])
                             projectObj.mainController.refreshTreeNode([node])
@@ -247,20 +357,44 @@ var FeeRate = {
                 }
                 }
             }
             }
         };
         };
-        FeeRate.prototype.refreshBillsByRateID=function(rate,value){
-            rate.rate=value;
-            var nodes = _.filter(projectObj.project.mainTree.items,function (n) {
-                if(n.sourceType==ModuleNames.bills&&n.data.feeRateID==rate.ID){
-                    n.data.feeRate=value;
-                    return true;
-                }else {
-                    return false;
+
+        FeeRate.prototype.updateFeeRateFromCalc=function (value,editInfo) {
+            var value= number_util.checkNumberValue(value,feeRate_consts.decimal);
+            if(value){
+                if(editInfo.calcItem.feeRateID){
+                    var rate = projectObj.project.FeeRate.getFeeRateByID(editInfo.calcItem.feeRateID);
+                    if(rate!=undefined){
+                        this.updateFeeRateByCalc(rate,value);
+                        return;
+                    }
                 }
                 }
-            })
-            if(nodes.length>0){
-                projectObj.mainController.refreshTreeNode(nodes)
+                editInfo.calcItem.feeRate=value;
+                editInfo.calcItem.feeRateID=null;
+                var data={'projectID': projectObj.project.ID(),'templatesID': editInfo.template.ID,'calcItem': editInfo.calcItem};
+                rationPM.saveCalcItem(data,function (result) {
+                    project.calcProgram.compileAllTemps();
+                    rationPM.refreshDetailSheet();
+                })
+            }else {
+                rationPM.refreshDetailSheet();
             }
             }
         };
         };
+        FeeRate.prototype.updateFeeRateByCalc=function (rate,value) {
+            var me=this;
+            var data={
+                query:{
+                    'ID':this.getActivateFeeRateID(),
+                    'rates.ID':rate.ID
+                },
+                doc:{
+                    'rates.$.rate':value
+                }
+            }
+            CommonAjax.post('/feeRates/updateFeeRate', data, function (data) {
+                rate.rate=value;
+                me.onFeeRateChange(rate.ID,value);
+            });
+        }
 
 
         FeeRate.prototype.getfbUpdateData=function (rate,bill,value) {
         FeeRate.prototype.getfbUpdateData=function (rate,bill,value) {
             var data={};
             var data={};
@@ -324,6 +458,9 @@ var FeeRate = {
                 }
                 }
             this.setFeeRateToBill(data,callback);
             this.setFeeRateToBill(data,callback);
         };
         };
+
+       
+
         FeeRate.prototype.setFeeRateToBill=function(data,callback){
         FeeRate.prototype.setFeeRateToBill=function(data,callback){
             CommonAjax.post('/feeRates/setFeeRateToBill', data, function (data) {
             CommonAjax.post('/feeRates/setFeeRateToBill', data, function (data) {
                 callback(data);
                 callback(data);
@@ -333,7 +470,7 @@ var FeeRate = {
             if(node.data.feeRateID){
             if(node.data.feeRateID){
                 var feeRate = this.getFeeRateByID(node.data.feeRateID);
                 var feeRate = this.getFeeRateByID(node.data.feeRateID);
                 if(feeRate){
                 if(feeRate){
-                    node.data.feeRate=parseFloat(feeRate.rate).toFixed(feeRate_consts.decimal);
+                    node.data.feeRate=number_util.roundToString(feeRate.rate,feeRate_consts.decimal);// parseFloat(feeRate.rate).toFixed(feeRate_consts.decimal);
                 }
                 }
             }
             }
         };
         };
@@ -347,9 +484,10 @@ var FeeRate = {
             CommonAjax.post('/feeRates/changeFeeRateFileFromCurrent', data, function (data) {
             CommonAjax.post('/feeRates/changeFeeRateFileFromCurrent', data, function (data) {
                 if (data) {
                 if (data) {
                     me.datas=data;
                     me.datas=data;
-                    socket.emit('feeRateChangeNotify', me.getActivateFeeRateFileID());
                     callback();
                     callback();
                 }
                 }
+            },function () {
+                $.bootstrapLoading.end();
             });
             });
         };
         };
 
 
@@ -365,17 +503,14 @@ var FeeRate = {
             CommonAjax.post('/feeRates/changeFeeRateFileFromOthers', data, function (data) {
             CommonAjax.post('/feeRates/changeFeeRateFileFromOthers', data, function (data) {
                 if (data) {
                 if (data) {
                     me.datas=data;
                     me.datas=data;
-                    socket.emit('feeRateChangeNotify', me.getActivateFeeRateFileID());
                     callback();
                     callback();
                 }
                 }
+            },function () {
+                $.bootstrapLoading.end();
             });
             });
 
 
         };
         };
 
 
-        FeeRate.prototype.getRate = function (fileID, rateID){
-            return 1.25;
-        };
-
         var feeRate = new FeeRate(project);
         var feeRate = new FeeRate(project);
         return feeRate;
         return feeRate;
     },
     },

+ 17 - 0
web/building_saas/main/js/models/labour_coe.js

@@ -21,5 +21,22 @@ class LabourCoe {
             // do
             // do
         }
         }
     };
     };
+
+    refreshData (data){
+        let me = this;
+        if (data.libID && data.libID != me.datas.libID){
+            me.datas.libID = data.libID;
+            me.datas.libName = data.libName;
+        };
+
+        for (let newItem of data.newItemArr){
+              for (let oldItem of me.datas.coes){
+                   if (oldItem.ID == newItem.ID){
+                       oldItem.coe = newItem.coe;
+                       break;
+                   }
+              };
+        };
+    }
 }
 }
 
 

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

@@ -16,6 +16,21 @@ const ModuleNames = {
     labour_coe: 'labour_coe',
     labour_coe: 'labour_coe',
     calc_program: 'calc_program'
     calc_program: 'calc_program'
 };
 };
+
 const feeRate_consts={
 const feeRate_consts={
     decimal:3
     decimal:3
-}
+};
+
+const CP_Col_Width = {          // 多处计算程序界面的列宽统一设置
+    rowHeader: 30,
+    colHeader: 30,              // 这个是标题栏高度不是宽度,也写在一起
+    code: 70,
+    name: 200,
+    dispExprUser: 180,
+    feeRate: 60,
+    displayFieldName: 120,
+    statement: 380,
+    memo: 110,
+    unitFee: 90,
+    totalFee: 90
+};

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

@@ -80,9 +80,11 @@ var PROJECT = {
             this.VolumePrice = VolumePrice.createNew(this);
             this.VolumePrice = VolumePrice.createNew(this);
             this.projectGLJ = new ProjectGLJ();
             this.projectGLJ = new ProjectGLJ();
             this.projectGLJ.loadData();
             this.projectGLJ.loadData();
+            this.composition = new Composition();
+            this.composition.loadData();
             this.Decimal = {
             this.Decimal = {
                 common: {
                 common: {
-                    quantity: 3,
+                    quantity: 4,
                     unitFee: 2,
                     unitFee: 2,
                     totalFee: 2
                     totalFee: 2
                 }
                 }

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

@@ -174,6 +174,7 @@ var Ration = {
                         data.updateData.comments = std.chapter.explanation;
                         data.updateData.comments = std.chapter.explanation;
                         data.updateData.ruleText = std.chapter.ruleText;
                         data.updateData.ruleText = std.chapter.ruleText;
                     }
                     }
+                    data.updateData.programID = std.feeType;
                     data.updateData.rationAssList =  projectObj.project.ration_ass.CreateNewAss(std);
                     data.updateData.rationAssList =  projectObj.project.ration_ass.CreateNewAss(std);
                     // calculate ration Quantity
                     // calculate ration Quantity
                     that.CalculateQuantity(data.updateData);
                     that.CalculateQuantity(data.updateData);
@@ -329,6 +330,7 @@ var Ration = {
                 ration.comments = std.chapter.explanation;
                 ration.comments = std.chapter.explanation;
                 ration.ruleText = std.chapter.ruleText;
                 ration.ruleText = std.chapter.ruleText;
             }
             }
+            ration.programID = std.feeType;
             ration.rationAssList = projectObj.project.ration_ass.CreateNewAss(std);
             ration.rationAssList = projectObj.project.ration_ass.CreateNewAss(std);
             // calculate ration Quantity
             // calculate ration Quantity
             this.CalculateQuantity(ration);
             this.CalculateQuantity(ration);

+ 0 - 66
web/building_saas/main/js/rpt/rpt_main.js

@@ -1,66 +0,0 @@
-/**
- * Created by Tony on 2017/6/26.
- */
-'use strict'
-
-let rptTplObj = {
-    iniPage: function() {
-        let me = this
-        zTreeOprObj.getReportTemplateTree(RT.GrpType.CONSTRUCT);
-    }
-}
-
-let zTreeOprObj = {
-    treeObj: null,
-    currentNode: null,
-    getReportTemplateTree: function(grpType) {
-        let me = zTreeOprObj, params = {};
-        params.grpType = grpType;
-        params.userId = userID;
-        params.tplType = RT.TplType.ALL;
-        CommonAjax.postEx("report_tpl_api/getRptTplTree", params, 20000, true, function(result){
-                zTreeHelper.createTree(result, setting, "rptTplTree", me);
-                me.refreshNodes();
-            }, null, null
-        );
-    },
-    refreshNodes: function() {
-        let me = this;
-        let private_setupIsParent = function(node){
-            if (node.nodeType == RT.NodeType.NODE) {
-                node.isParent = true;
-            } else {
-                node.isParent = false;
-            }
-            if (node.items && node.items.length) {
-                for (let i = 0; i < node.items.length; i++) {
-                    private_setupIsParent(node.items[i]);
-                }
-            }
-        };
-        let topNodes = me.treeObj.getNodes();
-        for (let i = 0; i < topNodes.length; i++) {
-            private_setupIsParent(topNodes[i]);
-        }
-        me.treeObj.refresh();
-    },
-    onCheck: function() {
-        //count();
-        //if (clearFlag) {
-        //    clearCheckedOldNodes();
-        //}
-    },
-    onClick: function(event,treeId,treeNode) {
-        let me = zTreeOprObj;
-        if (treeNode.nodeType == RT.NodeType.NODE) {
-            me.currentNode = treeNode;
-            $("#rpt_tpl_display_label")[0].innerText = "...";
-        } else if (treeNode.nodeType == RT.NodeType.TEMPLATE) {
-            me.currentNode = null;
-            $("#rpt_tpl_display_label")[0].innerText = treeNode.name;
-            if (treeNode.refId < 0) {
-                //创建新报表模板
-            }
-        }
-    }
-}

+ 47 - 32
web/building_saas/main/js/views/calc_program_manage.js

@@ -14,24 +14,28 @@ let rationPM = {
         ],
         ],
         view:{
         view:{
             comboBox:[],
             comboBox:[],
-            lockColumns:[0,1]
+            lockColumns:[0,1],
+            colHeaderHeight: CP_Col_Width.colHeader,
+            rowHeaderWidth: CP_Col_Width.rowHeader
         }
         }
     },
     },
 
 
     detailSetting: {
     detailSetting: {
         header:[
         header:[
             // {headerName:"ID",headerWidth:80,dataCode:"ID", hAlign: "center"},
             // {headerName:"ID",headerWidth:80,dataCode:"ID", hAlign: "center"},
-            {headerName:"费用代号",headerWidth:80,dataCode:"code", dataType: "String"},
-            {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",hAlign: "left"},
-            {headerName:"字段名称",headerWidth:140,dataCode:"displayFieldName", dataType: "String", hAlign: "center"},
-            {headerName:"备注",headerWidth:100,dataCode:"memo", dataType: "String"}
+            {headerName:"费用代号",headerWidth:CP_Col_Width.code, dataCode:"code", dataType: "String"},
+            {headerName:"费用名称",headerWidth:CP_Col_Width.name, dataCode:"name", dataType: "String"},
+            {headerName:"计算基数",headerWidth:CP_Col_Width.dispExprUser, dataCode:"dispExprUser", dataType: "String"},
+            {headerName:"费率",headerWidth:CP_Col_Width.feeRate, dataCode:"feeRate", dataType: "Number",hAlign: "right",tofix: feeRate_consts.decimal},
+            {headerName:"费用类别",headerWidth:CP_Col_Width.displayFieldName, dataCode:"displayFieldName", dataType: "String", hAlign: "center"},
+            {headerName:"基数说明",headerWidth:CP_Col_Width.statement, dataCode:"statement", dataType: "String"},
+            {headerName:"备注",headerWidth:CP_Col_Width.memo, dataCode:"memo", dataType: "String"}
         ],
         ],
         view:{
         view:{
             comboBox:[],
             comboBox:[],
-            lockColumns:[0,1,2,3,6]
+            lockColumns:[0,1,2,3,5,6],
+            colHeaderHeight: CP_Col_Width.colHeader,
+            rowHeaderWidth: CP_Col_Width.rowHeader
         }
         }
     },
     },
 
 
@@ -51,20 +55,18 @@ let rationPM = {
 
 
         var fieldName = new GC.Spread.Sheets.CellTypes.ComboBox();
         var fieldName = new GC.Spread.Sheets.CellTypes.ComboBox();
         fieldName.items(projectObj.project.calcProgram.calc.compiledFeeTypeNames);
         fieldName.items(projectObj.project.calcProgram.calc.compiledFeeTypeNames);
-        // fieldName.items(["直接费","人工费","材料费","机械费","主材费","企业管理费","利润","风险费","人工价差","材料价差","机械价差","工程造价","调整人工费","调整机上人工费","甲供材料费"]);
-        me.detailSpread.getSheet(0).getRange(-1, 5, -1, 1).cellType(fieldName);
+        me.detailSpread.getSheet(0).getRange(-1, 4, -1, 1).cellType(fieldName);
 
 
         me.mainSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EnterCell, me.onMainEnterCell);
         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.CellChanged, me.onDetailCellChanged);
-        //me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.CellClick, me.onCellClick);
+        me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
         let mSheet = me.mainSpread.getSheet(0);
         let mSheet = me.mainSpread.getSheet(0);
         sheetCommonObj.showData(mSheet, me.mainSetting, me.datas);
         sheetCommonObj.showData(mSheet, me.mainSetting, me.datas);
 
 
         let dSheet = me.detailSpread.getSheet(0);
         let dSheet = me.detailSpread.getSheet(0);
-        feeRateObject.setFeeRateCellCol(dSheet,4);
+        feeRateObject.setFeeRateCellCol(dSheet,_.findIndex(me.detailSetting.header,{'dataCode':'feeRate'}));
         dSheet.name('calc_detail');
         dSheet.name('calc_detail');
         sheetCommonObj.showData(dSheet, me.detailSetting, me.datas[0].calcItems);
         sheetCommonObj.showData(dSheet, me.detailSetting, me.datas[0].calcItems);
-
     },
     },
     onMainEnterCell: function(sender, args) {
     onMainEnterCell: function(sender, args) {
         var me = rationPM;
         var me = rationPM;
@@ -76,30 +78,25 @@ let rationPM = {
         sheetCommonObj.showData(dSheet, me.detailSetting, dData);
         sheetCommonObj.showData(dSheet, me.detailSetting, dData);
         me.detailSpread.resumePaint();
         me.detailSpread.resumePaint();
     },
     },
-
-    saveCalcItem: function (projectID, templatesID, calcItem) {
+    onEditEnded: function(sender, args) {
+        var me = rationPM;
+        if(me.detailSetting.header[args.col].dataCode=='feeRate'){
+            var editInfo= me.getSelectionInfo();
+            projectObj.project.FeeRate.updateFeeRateFromCalc(args.editingText,editInfo);
+        }
+    },
+    saveCalcItem: function (data,callback) {//data
         let me = this;
         let me = this;
-/*        let projectID = projectInfoObj.projectInfo.ID,
-            templatesID = me.datas,
-            calcItem = {
-                "ID" : 99,
-                "code" : "test",
-                "name" : "testName",
-                "fieldName" : "direct",
-                "dispExpr" : "F2+F5+F6+F10",
-                "expression" : "@('2') + @('5') + @('6') + @('10')",
-                "compiledExpr" : "",
-                "statement" : "基价人工费+基价材料费+基价机械费+未计价材料费"
-            };*/
-
         $.ajax({
         $.ajax({
-            type: 'post',
+            type: 'POST',
             url: '/calcProgram/saveCalcItem',
             url: '/calcProgram/saveCalcItem',
-            data: {projectID: projectID, templatesID: templatesID, calcItem: calcItem},
+            data: {'data':JSON.stringify(data)},
             dataType: 'json',
             dataType: 'json',
             success: function (result) {
             success: function (result) {
                 if(!result.error){
                 if(!result.error){
-                    alert('成功:' + result.message);
+                    if(callback){
+                        callback(result);
+                    }
                 }
                 }
                 else{
                 else{
                     alert('失败:' + result.message);
                     alert('失败:' + result.message);
@@ -107,10 +104,28 @@ let rationPM = {
             }
             }
         })
         })
     },
     },
+    getSelectionInfo:function () {
+        var templateIndex = this.mainSpread.getActiveSheet().getActiveRowIndex();
+        var dIndex = this.detailSpread.getActiveSheet().getActiveRowIndex();
+        var info = {
+            template:this.datas[templateIndex],
+            calcItem:this.datas[templateIndex].calcItems[dIndex]
+        }
+        return info;
+    },
+    refreshDetailSheet:function () {
+        var me=this;
+        if(me.mainSpread&&me.detailSpread){
+            var mainSheetIndex = me.mainSpread.getActiveSheet().getActiveRowIndex();
+            sheetCommonObj.showData(me.detailSpread.getSheet(0), me.detailSetting,me.datas[mainSheetIndex].calcItems);
+        }
+    }
+
 };
 };
 
 
 $(document).ready(function(){
 $(document).ready(function(){
     $('#tab_calc_program_manage').on('shown.bs.tab', function (e) {
     $('#tab_calc_program_manage').on('shown.bs.tab', function (e) {
+        $(e.relatedTarget.hash).removeClass('active');
         rationPM.buildSheet();
         rationPM.buildSheet();
     });
     });
 });
 });

+ 12 - 9
web/building_saas/main/js/views/calc_program_view.js

@@ -201,18 +201,21 @@ let calcProgramObj = {
 
 
     setting: {
     setting: {
         header: [
         header: [
-            {headerName: "费用代号", headerWidth: 75, dataCode: "code", dataType: "String", hAlign: "left"},
-            {headerName: "费用名称", headerWidth: 200, dataCode: "name", dataType: "String"},
-            {headerName: "计算基数", headerWidth: 200, dataCode: "dispExpr", dataType: "String"},
-            {headerName: "基数说明", headerWidth: 400, dataCode: "statement", dataType: "String"},
-            {headerName: "费率", headerWidth: 80, dataCode: "feeRate", dataType: "Number"},   // precision: 3
-            {headerName: "单价", headerWidth: 100, dataCode: "unitFee", dataType: "Number"},  // execRst
-            {headerName: "合价", headerWidth: 100, dataCode: "totalFee", dataType: "Number"},
-            {headerName: "备注", headerWidth: 120, dataCode: "memo", dataType: "String"}
+            {headerName: "费用代号", headerWidth: CP_Col_Width.code, dataCode: "code", dataType: "String", hAlign: "left"},
+            {headerName: "费用名称", headerWidth: CP_Col_Width.name, dataCode: "name", dataType: "String"},
+            {headerName: "计算基数", headerWidth: CP_Col_Width.dispExprUser, dataCode: "dispExprUser", dataType: "String"},
+            {headerName: "费率", headerWidth: CP_Col_Width.feeRate, dataCode: "feeRate", dataType: "Number"},   // precision: 3
+            {headerName:"费用类别", headerWidth:CP_Col_Width.displayFieldName, dataCode:"displayFieldName", dataType: "String", hAlign: "center"},
+            {headerName: "基数说明", headerWidth: CP_Col_Width.statement, dataCode: "statement", dataType: "String"},
+            {headerName: "单价", headerWidth: CP_Col_Width.unitFee, dataCode: "unitFee", dataType: "Number"},  // execRst
+            {headerName: "合价", headerWidth: CP_Col_Width.totalFee, dataCode: "totalFee", dataType: "Number"},
+            {headerName: "备注", headerWidth: CP_Col_Width.memo, dataCode: "memo", dataType: "String"}
         ],
         ],
         view: {
         view: {
             comboBox: [],
             comboBox: [],
-            lockColumns: [0, 1, 2, 3, 4, 5, 6, 7]
+            lockColumns: [0,1,2,3,4,5,6,7,8],
+            colHeaderHeight: CP_Col_Width.colHeader,
+            rowHeaderWidth: CP_Col_Width.rowHeader
         }
         }
     },
     },
 
 

+ 180 - 149
web/building_saas/main/js/views/fee_rate_view.js

@@ -7,6 +7,7 @@
 var feeRateObject={
 var feeRateObject={
     mainViews:null,
     mainViews:null,
     datas:null,
     datas:null,
+    datasBackup:null,
     canEdit:false,
     canEdit:false,
     activateFeeRate:null,
     activateFeeRate:null,
     needCascadeSet:false,
     needCascadeSet:false,
@@ -350,6 +351,10 @@ var feeRateObject={
             this.mainViews.destroy();
             this.mainViews.destroy();
             this.mainViews = null;
             this.mainViews = null;
         }
         }
+        if(subRateObject.views){
+            subRateObject.views.destroy();
+            subRateObject.views = null;
+        }
         this.activateFeeRate = projectObj.project.FeeRate.getActivateFeeRate();
         this.activateFeeRate = projectObj.project.FeeRate.getActivateFeeRate();
         this.datas = this.activateFeeRate.rates;
         this.datas = this.activateFeeRate.rates;
         this.mainViews = new GC.Spread.Views.DataView($('#divFee')[0],
         this.mainViews = new GC.Spread.Views.DataView($('#divFee')[0],
@@ -363,6 +368,7 @@ var feeRateObject={
     },
     },
     updateBySelect:function (rate,selectMap,mapID) {
     updateBySelect:function (rate,selectMap,mapID) {
        var selected = this.mainViews.getSelections()[0];
        var selected = this.mainViews.getSelections()[0];
+        projectObj.project.FeeRate.backupDatas();
        var item = this.datas[selected.sourceRow];
        var item = this.datas[selected.sourceRow];
         item.rate = rate;
         item.rate = rate;
         _.forEach(selectMap,function (value,key) {
         _.forEach(selectMap,function (value,key) {
@@ -381,7 +387,7 @@ var feeRateObject={
         }else {
         }else {
             this.mainViews.data.updateItem(selected.sourceRow,item);
             this.mainViews.data.updateItem(selected.sourceRow,item);
         }
         }
-        projectObj.project.FeeRate.synchronizeFeeRate();
+        //projectObj.project.FeeRate.synchronizeFeeRate();
 
 
         //this.views.data.updateItem()
         //this.views.data.updateItem()
     },
     },
@@ -448,11 +454,6 @@ var feeRateObject={
                 }
                 }
             }
             }
         })
         })
-
-        _.forEach(items,function (t) {
-            feeRateObject.mainViews.data.updateItem(t.rateIndex,t.rate);
-        })
-
         projectObj.project.FeeRate.batchUpdateFeeRate(items,feeRateObject.activateFeeRate);
         projectObj.project.FeeRate.batchUpdateFeeRate(items,feeRateObject.activateFeeRate);
     },
     },
     loadPageContent:function(){
     loadPageContent:function(){
@@ -483,11 +484,13 @@ var feeRateObject={
         });
         });
     },
     },
     changeFeeRateStandard:function(newVal){
     changeFeeRateStandard:function(newVal){
+        $.bootstrapLoading.start();
         var callback=function () {
         var callback=function () {
             feeRateObject.createSpreadView();
             feeRateObject.createSpreadView();
             feeRateObject.loadPageContent();
             feeRateObject.loadPageContent();
             projectObj.project.FeeRate.synchronizeFeeRate();
             projectObj.project.FeeRate.synchronizeFeeRate();
             subRateObject.destorySpreadView();
             subRateObject.destorySpreadView();
+            $.bootstrapLoading.end();
         };
         };
         projectObj.project.FeeRate.changeFeeRateStandard(newVal,callback);
         projectObj.project.FeeRate.changeFeeRateStandard(newVal,callback);
     },
     },
@@ -507,7 +510,6 @@ var feeRateObject={
                 $('#saveAsConfirm').removeAttr("disabled");
                 $('#saveAsConfirm').removeAttr("disabled");
                 $('#nameError').hide();
                 $('#nameError').hide();
             }
             }
-            console.log(data);
         };
         };
         projectObj.project.FeeRate.checkFeeRateName(newVal,callback);
         projectObj.project.FeeRate.checkFeeRateName(newVal,callback);
     },
     },
@@ -534,9 +536,15 @@ var feeRateObject={
         }
         }
     },
     },
     submitSaveAs:function (newName) {
     submitSaveAs:function (newName) {
-        this.activateFeeRate =  projectObj.project.FeeRate.feeRateFileSaveAs(newName);
-        feeRateObject.loadPageContent();
-        $('#copy-lv').modal('hide');
+        var me = this;
+          projectObj.project.FeeRate.feeRateFileSaveAs(newName,function (result) {
+              me.activateFeeRate = result;
+              me.loadPageContent();
+              $('#copy-lv').modal('hide');
+              socket.emit('feeRateChangeNotify', projectObj.project.FeeRate.getActivateFeeRateFileID());
+              $.bootstrapLoading.end();
+        });
+
     },
     },
     getChangeInfo:function () {
     getChangeInfo:function () {
         var me = this;
         var me = this;
@@ -569,6 +577,7 @@ var feeRateObject={
         }
         }
     },
     },
     changeFeeRateFileFromCurrent:function(){
     changeFeeRateFileFromCurrent:function(){
+        $.bootstrapLoading.start();
         var newVal = $("#currentOptions").val();
         var newVal = $("#currentOptions").val();
         if($("#currentOptions").val()==this.activateFeeRate.ID){
         if($("#currentOptions").val()==this.activateFeeRate.ID){
             return;
             return;
@@ -581,7 +590,8 @@ var feeRateObject={
         var callback=function () {
         var callback=function () {
             feeRateObject.createSpreadView();
             feeRateObject.createSpreadView();
             feeRateObject.loadPageContent();
             feeRateObject.loadPageContent();
-            projectObj.project.FeeRate.synchronizeFeeRate();
+            projectObj.project.FeeRate.onFeeRateFileChange();
+            $.bootstrapLoading.end();
         }
         }
         projectObj.project.FeeRate.changeFeeRateFileFromCurrent(newFeeRateFile,callback);
         projectObj.project.FeeRate.changeFeeRateFileFromCurrent(newFeeRateFile,callback);
     },
     },
@@ -602,10 +612,12 @@ var feeRateObject={
         }
         }
     },
     },
     changeFeeRateFileConfirm:function(feeRateFileID,name){
     changeFeeRateFileConfirm:function(feeRateFileID,name){
+        $.bootstrapLoading.start();
         var callback=function () {
         var callback=function () {
             feeRateObject.createSpreadView();
             feeRateObject.createSpreadView();
             feeRateObject.loadPageContent();
             feeRateObject.loadPageContent();
-            projectObj.project.FeeRate.synchronizeFeeRate();
+            projectObj.project.FeeRate.onFeeRateFileChange();
+            $.bootstrapLoading.end();
         }
         }
         projectObj.project.FeeRate.changeFeeRateFileFromOthers(feeRateFileID,name,callback);
         projectObj.project.FeeRate.changeFeeRateFileFromOthers(feeRateFileID,name,callback);
     },
     },
@@ -640,11 +652,25 @@ var feeRateObject={
             $("#fee_rate_tree").modal('hide');
             $("#fee_rate_tree").modal('hide');
         });
         });
     },
     },
+    submitFeeRateFromCalc:function () {
+        var rate = feeRateObject.feeRateSelection;
+        var calInfo = rationPM.getSelectionInfo();
+        calInfo.calcItem.feeRateID=rate.ID;
+        calInfo.calcItem.feeRate=null;
+        var data={'projectID': projectObj.project.ID(),'templatesID': calInfo.template.ID,'calcItem': calInfo.calcItem};
+        rationPM.saveCalcItem(data,function (result) {
+            calInfo.calcItem.feeRate=rate.rate;
+            projectObj.project.calcProgram.compileAllTemps();
+            rationPM.refreshDetailSheet();
+            $("#fee_rate_tree").modal('hide');
+        });
+        console.log(calInfo);
+    },
     submitFeeRateBySelect:function () {
     submitFeeRateBySelect:function () {
         var validate = this.checkSelectedFeeRate();
         var validate = this.checkSelectedFeeRate();
         if(validate){
         if(validate){
             if($('#edit_from').val()=='calc_detail'){
             if($('#edit_from').val()=='calc_detail'){
-                //do calc_detail
+                this.submitFeeRateFromCalc();
             }else {
             }else {
                 this.submitFeeRateFromBill();
                 this.submitFeeRateFromBill();
             }
             }
@@ -667,165 +693,170 @@ function getPopoverContent() {
     return popover_content;
     return popover_content;
 }
 }
 
 
-$('#pop-lv').popover({
-        placement:"bottom",
-        html:true,
-        trigger:"hover | focus",
-        content:getPopoverContent
-    }
-);
-
-$('#tab_fee_rate').on('shown.bs.tab', function (e) {
-    feeRateObject.reFreshRateViews();
-    feeRateObject.loadPageContent();
-});
+$(function(){
+    $('#pop-lv').popover({
+            placement:"bottom",
+            html:true,
+            trigger:"hover | focus",
+            content:getPopoverContent
+        }
+    );
 
 
-$('#setNewFeeRate').bind('click', function () {
-    var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate();
-    var usageProjects = feeRateFile.usageProjects;
-    var listString ='';
-    _.forEach(usageProjects,function (u) {
-        listString+="<li>"+u.name+"</li>"
-    })
-    $("#usageProjectList").html(listString);
-    $("#set-lv-feeRateName").text(feeRateFile.name);
-    $("#set-use-feeRateName").text(feeRateFile.name);
+    $('#tab_fee_rate').on('shown.bs.tab', function (e) {
+        $(e.relatedTarget.hash).removeClass('active');
+        feeRateObject.reFreshRateViews();
+        feeRateObject.loadPageContent();
+    });
 
 
-    feeRateObject.getFeeRateStandards(function (data) {
-        $('#standardSelect').empty();
-        _.forEach(data,function (s) {
-            var option =  $("<option>").val(s.ID).text(s.libName);
-            $('#standardSelect').append(option);
+    $('#setNewFeeRate').bind('click', function () {
+        var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate();
+        var usageProjects = feeRateFile.usageProjects;
+        var listString ='';
+        _.forEach(usageProjects,function (u) {
+            listString+="<li>"+u.name+"</li>"
         })
         })
-        $('#standardSelect').val(feeRateFile.libID);
+        $("#usageProjectList").html(listString);
+        $("#set-lv-feeRateName").text(feeRateFile.name);
+        $("#set-use-feeRateName").text(feeRateFile.name);
+
+        feeRateObject.getFeeRateStandards(function (data) {
+            $('#standardSelect').empty();
+            _.forEach(data,function (s) {
+                var option =  $("<option>").val(s.ID).text(s.libName);
+                $('#standardSelect').append(option);
+            })
+            $('#standardSelect').val(feeRateFile.libID);
+        });
+    });
+    $('#changeConfirm').bind('click', function (){
+        var newVal=$('#standardSelect').val();
+        var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate();
+        if(newVal&&newVal!=feeRateFile.libID){
+            feeRateObject.changeFeeRateStandard(newVal);
+        }
     });
     });
-});
-$('#changeConfirm').bind('click', function (){
-    var newVal=$('#standardSelect').val();
-    var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate();
-    if(newVal&&newVal!=feeRateFile.libID){
-        feeRateObject.changeFeeRateStandard(newVal);
-    }
-});
 
 
-$('#saveAs').bind('click', function (){
-    var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate();
-    $('#copyFeeRateName').val(feeRateFile.name+'副本');
-    $('#valid_name').val(feeRateFile.name+'副本');
-    $('#nameError').hide();
-});
+    $('#saveAs').bind('click', function (){
+        var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate();
+        $('#copyFeeRateName').val(feeRateFile.name+'副本');
+        $('#valid_name').val(feeRateFile.name+'副本');
+        $('#nameError').hide();
+    });
 
 
-$('#saveAsConfirm').bind('click',function () {
-    feeRateObject.feeRateFileSaveAs($('#copyFeeRateName').val());
-})
+    $('#saveAsConfirm').bind('click',function () {
+        feeRateObject.feeRateFileSaveAs($('#copyFeeRateName').val());
+    })
 
 
 
 
-$('#copyFeeRateName').change(function () {
-    feeRateObject.checkFeeRateName(this.value);
-});
+    $('#copyFeeRateName').change(function () {
+        feeRateObject.checkFeeRateName(this.value);
+    });
 
 
-$('#newFeeRateName').change(function () {
-    var newName = $(this).val();
-    if(!newName||newName==""){
-        $('#renameConfirm').attr("disabled","disabled");
-        $('#renameError').text("请输入文件名称。").show();
-        return;
-    }
-    var callback=function (data) {
-        if(data){
+    $('#newFeeRateName').change(function () {
+        var newName = $(this).val();
+        if(!newName||newName==""){
             $('#renameConfirm').attr("disabled","disabled");
             $('#renameConfirm').attr("disabled","disabled");
-            $('#renameError').text("本建设项目中已存在同名费率文件。").show();
-        }else {
-            $('#renameConfirm').removeAttr("disabled");
-            $('#renameError').hide();
+            $('#renameError').text("请输入文件名称。").show();
+            return;
         }
         }
-    };
-    projectObj.project.FeeRate.checkFeeRateName(newName,callback);
-});
+        var callback=function (data) {
+            if(data){
+                $('#renameConfirm').attr("disabled","disabled");
+                $('#renameError').text("本建设项目中已存在同名费率文件。").show();
+            }else {
+                $('#renameConfirm').removeAttr("disabled");
+                $('#renameError').hide();
+            }
+        };
+        projectObj.project.FeeRate.checkFeeRateName(newName,callback);
+    });
 
 
 
 
-function changeFRadioClick() {
-    var radioV= $("input[name='chaneg-lv-Radio']:checked").val();
-    if(radioV==='0'){
+    $('#changeFeeRateConfirm').bind('click',function (){
+        var radioV= $("input[name='chaneg-lv-Radio']:checked").val();
+        if(radioV==='0'){
+            feeRateObject.changeFeeRateFileFromCurrent();
+        }else {
+            feeRateObject.changeFeeRateFileFromOthers();
+        }
+    })
+
+    $('#changFeeRateFile').bind('click',function (){
+        $("input[name='chaneg-lv-Radio']")[0].checked=true;
         $("#fromProject").show();
         $("#fromProject").show();
         $("#fromOther").hide();
         $("#fromOther").hide();
-    }else {
-        $("#fromProject").hide();
-        $("#fromOther").show();
-    }
-}
-$('#changeFeeRateConfirm').bind('click',function (){
-    var radioV= $("input[name='chaneg-lv-Radio']:checked").val();
-    if(radioV==='0'){
-        feeRateObject.changeFeeRateFileFromCurrent();
-    }else {
-        feeRateObject.changeFeeRateFileFromOthers();
-    }
-})
+        feeRateObject.getChangeInfo();
+    })
 
 
-$('#changFeeRateFile').bind('click',function (){
-    $("input[name='chaneg-lv-Radio']")[0].checked=true;
-    $("#fromProject").show();
-    $("#fromOther").hide();
-    feeRateObject.getChangeInfo();
-})
+    $('#otherProject').change(function(){
+        var newVal = $(this).val();
+        var projects = feeRateObject.changeInfo.others;
+        var selected = _.find(projects,{ID:parseInt(newVal)});
+        $('#otherFeeRateOption').empty();
+        _.forEach(selected.optionList,function (f) {
+            var option =  $("<option>").val(f.ID).text(f.name);
+            $('#otherFeeRateOption').append(option);
+        });
+    })
 
 
-$('#otherProject').change(function(){
-    var newVal = $(this).val();
-    var projects = feeRateObject.changeInfo.others;
-    var selected = _.find(projects,{ID:parseInt(newVal)});
-    $('#otherFeeRateOption').empty();
-    _.forEach(selected.optionList,function (f) {
-        var option =  $("<option>").val(f.ID).text(f.name);
-        $('#otherFeeRateOption').append(option);
-    });
-})
+    $('#renameConfirm').bind('click',function (){
+        var feeRateFileID= $("#newFeeRateID").val();
+        var name = $("#newFeeRateName").val();
+        feeRateObject.changeFeeRateFileConfirm(feeRateFileID,name);
+    })
 
 
-$('#renameConfirm').bind('click',function (){
-    var feeRateFileID= $("#newFeeRateID").val();
-    var name = $("#newFeeRateName").val();
-    feeRateObject.changeFeeRateFileConfirm(feeRateFileID,name);
-})
 
 
+    $('#inlineFormCustomSelect').change(function(){
+        var updateTask = [];
+        var selectID = $(this).val();
+        var oldValue=0;
+        _.forEach(projectObj.project.FeeRate.datas,function (feeRate) {
+            if(feeRate.status=='activate'){
+                oldValue=feeRate.ID;
+            }
+            if(feeRate.ID ==selectID){
+                feeRate.status='activate';
+            }else {
+                feeRate.status='disable';
+            }
+            updateTask.push({query:{ID:feeRate.feeRateID},doc:{status:feeRate.status}});
+        })
+        projectObj.project.FeeRate.updateStatusBySelected(updateTask);
+        feeRateObject.createSpreadView();
+        subRateObject.destorySpreadView();
+        socket.emit('changeActivateFeeRate',{oldRoom:oldValue,newRoom:selectID});
+    })
 
 
-$('#inlineFormCustomSelect').change(function(){
-    var updateTask = [];
-    var selectID = $(this).val();
-    var oldValue=0;
-    _.forEach(projectObj.project.FeeRate.datas,function (feeRate) {
-        if(feeRate.status=='activate'){
-            oldValue=feeRate.ID;
-        }
-        if(feeRate.ID ==selectID){
-            feeRate.status='activate';
-        }else {
-            feeRate.status='disable';
+    $('#fee_rate_tree').on('shown.bs.modal', function (e) {
+        if(feeRateObject.feeRateSpreads==null){
+            feeRateObject.createSheet();
         }
         }
-        updateTask.push({query:{ID:feeRate.feeRateID},doc:{status:feeRate.status}});
+        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();
     })
     })
-    projectObj.project.FeeRate.updateStatusBySelected(updateTask);
-    feeRateObject.createSpreadView();
-    subRateObject.destorySpreadView();
-    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('');
+function changeFRadioClick() {
+    var radioV= $("input[name='chaneg-lv-Radio']:checked").val();
+    if(radioV==='0'){
+        $("#fromProject").show();
+        $("#fromOther").hide();
+    }else {
+        $("#fromProject").hide();
+        $("#fromOther").show();
     }
     }
-});
+}
 
 
-$('#fee_selected_conf').bind('click',function (){
-    feeRateObject.submitFeeRateBySelect();
-})

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

@@ -16,6 +16,7 @@ var gljOprObj = {
     detailData:[],
     detailData:[],
     GLJSelection:[],
     GLJSelection:[],
     parentNodeIds:{},
     parentNodeIds:{},
+    activeTab:'#linkGLJ',
     setting: {
     setting: {
         header: [
         header: [
             {headerName: "编码", headerWidth: 100, dataCode: "code", dataType: "String", formatter: "@"},
             {headerName: "编码", headerWidth: 100, dataCode: "code", dataType: "String", formatter: "@"},
@@ -301,7 +302,7 @@ var gljOprObj = {
         if(args.row>=me.sheetData.length){
         if(args.row>=me.sheetData.length){
             return;
             return;
         }
         }
-        if(me.setting.header[args.col].dataCode=='marketPriceAdjust'){//市场单价调整
+        if(me.setting.header[args.col]&&me.setting.header[args.col].dataCode=='marketPriceAdjust'){//市场单价调整
             var type = me.sheetData[args.row].shortName;
             var type = me.sheetData[args.row].shortName;
             var index= _.indexOf(me.setting.notEditedType,type);
             var index= _.indexOf(me.setting.notEditedType,type);
             if(index!=-1){
             if(index!=-1){
@@ -582,6 +583,9 @@ var gljOprObj = {
         details=_.sortBy(details,'seq');
         details=_.sortBy(details,'seq');
         sheetCommonObj.showData(this.detailSheet,this.detailSetting,details);
         sheetCommonObj.showData(this.detailSheet,this.detailSetting,details);
         this.detailData = details;
         this.detailData = details;
+        if(MainTreeCol.readOnly.forQuantifyDetail(node)){
+            this.detailSheet.getRange(-1,0,-1,this.detailSetting.header.length).locked(true);
+        }
     },
     },
     clearSheetData:function () {
     clearSheetData:function () {
         sheetCommonObj.showData(this.sheet,this.setting,[]);
         sheetCommonObj.showData(this.sheet,this.setting,[]);

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

@@ -50,6 +50,9 @@ let MainTreeCol = {
         },
         },
         forTotalFee: function (node) {
         forTotalFee: function (node) {
             return MainTreeCol.readOnly.non_bills(node) || MainTreeCol.readOnly.billsParent(node) || (MainTreeCol.readOnly.leafBillsWithDetail(node));
             return MainTreeCol.readOnly.non_bills(node) || MainTreeCol.readOnly.billsParent(node) || (MainTreeCol.readOnly.leafBillsWithDetail(node));
+        },
+        forQuantifyDetail:function (node) {
+            return !(node.sourceType==ModuleNames.ration||!MainTreeCol.readOnly.billsParent(node));
         }
         }
     },
     },
     cellType: {
     cellType: {

+ 57 - 23
web/building_saas/main/js/views/project_property_labour_coe_view.js

@@ -6,6 +6,7 @@ let labourCoeView = {
     datas: [],
     datas: [],
     spread: null,
     spread: null,
     sheet: null,
     sheet: null,
+    needUpdateDatas: [],
 
 
     init(){
     init(){
         let me = this;
         let me = this;
@@ -17,7 +18,7 @@ let labourCoeView = {
             };
             };
 
 
             for (let lib of stdLabourCoeLibs){
             for (let lib of stdLabourCoeLibs){
-                result += '<option value="'+ lib.id +'">'+ lib.name +'</option>';
+                result += '<option value='+ lib.id +'>'+ lib.name +'</option>';
             };
             };
             return result;
             return result;
         };
         };
@@ -36,7 +37,6 @@ let labourCoeView = {
         me.spread.options.tabStripVisible = false;
         me.spread.options.tabStripVisible = false;
         me.spread.options.showVerticalScrollbar = false;
         me.spread.options.showVerticalScrollbar = false;
         me.spread.options.showHorizontalScrollbar = false;
         me.spread.options.showHorizontalScrollbar = false;
-        me.spread.options.rowHeight = 50;
         let sheetArea = GC.Spread.Sheets.SheetArea;
         let sheetArea = GC.Spread.Sheets.SheetArea;
         let sheet = me.spread.getSheet(0);
         let sheet = me.spread.getSheet(0);
         me.sheet = sheet;
         me.sheet = sheet;
@@ -47,13 +47,41 @@ let labourCoeView = {
         sheet.setRowCount(1, sheetArea.colHeader);
         sheet.setRowCount(1, sheetArea.colHeader);
         sheet.setRowCount(20, sheetArea.viewport);
         sheet.setRowCount(20, sheetArea.viewport);
         sheet.setRowHeight(0, 30, sheetArea.colHeader);
         sheet.setRowHeight(0, 30, sheetArea.colHeader);
-
+        sheet.bind(GC.Spread.Sheets.Events.CellChanged, me.onCellChanged);
         sheet.resumeEvent();
         sheet.resumeEvent();
         sheet.resumePaint();
         sheet.resumePaint();
     },
     },
 
 
+    onCellChanged: function(sender, args){
+        var me = labourCoeView;
+        if (args.propertyName !== "value"){return;};
+        let cell = me.sheet.getCell(args.row, args.col);
+        me.addNeedUpdateData({ID: cell.tag(), coe: cell.value()});
+    },
+
+    addNeedUpdateData: function (data) {
+        let me = this;
+        let isExist = false;
+        for (let el of me.needUpdateDatas){
+             if (el.ID == data.ID){
+                 isExist = true;
+                 el.coe = data.coe;
+                 return;
+             };
+        };
+        if (!isExist){
+            me.needUpdateDatas.push(data);
+        }
+    },
+
+    needSave: function (){
+        let me = this;
+        return me.needUpdateDatas.length > 0;
+    },
+
     loadData(datas){          // 树结构转换二维表显示,行列转换
     loadData(datas){          // 树结构转换二维表显示,行列转换
         let me = this;
         let me = this;
+        me.spread.suspendEvent();
         me.datas = datas;
         me.datas = datas;
         let libArr = [];
         let libArr = [];
         for (let v of me.datas) {if (!v.ParentID) libArr.push(v);};
         for (let v of me.datas) {if (!v.ParentID) libArr.push(v);};
@@ -83,12 +111,15 @@ let labourCoeView = {
                 let rowName = me.sheet.getText(r, 0);
                 let rowName = me.sheet.getText(r, 0);
                 for (let v of me.datas) {
                 for (let v of me.datas) {
                     if ((v.ParentID == libID) && (v.name == rowName)) {
                     if ((v.ParentID == libID) && (v.name == rowName)) {
-                        me.sheet.setValue(r, c + 1, v.coe);
+                        let cell = me.sheet.getCell(r, c+ 1);
+                        cell.value(v.coe);
+                        cell.tag(v.ID);
                         break;
                         break;
                     };
                     };
                 };
                 };
             };
             };
         };
         };
+        me.spread.resumeEvent();
     },
     },
 
 
     showData(){
     showData(){
@@ -97,6 +128,23 @@ let labourCoeView = {
         me.init();
         me.init();
         me.buildSheet();
         me.buildSheet();
         me.loadData(datas);
         me.loadData(datas);
+    },
+
+    save(){
+        let me = this;
+        if (me.needUpdateDatas.length > 0){
+            let projectID = projectInfoObj.projectInfo.ID;
+            let libID = $("#std_labour_coe_files").children("option:selected").val();
+            let libName = $("#std_labour_coe_files").children("option:selected").text();
+            let data = {projectID: projectID, libID: libID, libName: libName, newItemArr: me.needUpdateDatas};
+            CommonAjax.post('/labourCoe/save', data, function (){
+                projectObj.project.labourCoe.refreshData(data);
+                me.needUpdateDatas.splice(0, me.needUpdateDatas.length);
+                projectObj.project.calcProgram.compileAllTemps();
+                rationPM.buildSheet();
+                $("#std_labour_coe_files").val('');
+            });
+        }
     }
     }
 };
 };
 
 
@@ -113,25 +161,11 @@ $(document).ready(function(){
             return false;
             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);
-            }
+        CommonAjax.post('/labourCoe/getStdLabourCoe', {"ID": libID}, function (data) {
+            labourCoeView.buildSheet();
+            labourCoeView.loadData(data.coes);
+            labourCoeView.needUpdateDatas.splice(0, labourCoeView.needUpdateDatas.length);
+            labourCoeView.needUpdateDatas.push(...data.coes);
         });
         });
     });
     });
 });
 });

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

@@ -89,7 +89,9 @@ var projectObj = {
         if (colSetting.data.decimal) {
         if (colSetting.data.decimal) {
             value = Number(editingText);
             value = Number(editingText);
             if (number_util.isNumber(value)) {
             if (number_util.isNumber(value)) {
-                value = value.toDecimal(colSetting.data.decimal);
+                if (colSetting.data.decimal) {
+                    value = value.toDecimal(colSetting.data.decimal);
+                }
             } else {
             } else {
                 value = null;
                 value = null;
                 alert('当前输入的数据类型不正确,请重新输入。');
                 alert('当前输入的数据类型不正确,请重新输入。');
@@ -111,7 +113,9 @@ var projectObj = {
             }
             }
         }
         }
         if (value) {
         if (value) {
-            value = value.toDecimal(colSetting.data.decimal);
+            if (colSetting.data.decimal) {
+                value = value.toDecimal(colSetting.data.decimal);   
+            }
         } else if (editingText && editingText !== '') {
         } else if (editingText && editingText !== '') {
             value = null;
             value = null;
             alert('当前输入的数据类型不正确,请重新输入。');
             alert('当前输入的数据类型不正确,请重新输入。');
@@ -135,6 +139,7 @@ var projectObj = {
             }
             }
             return nodes;
             return nodes;
         }
         }
+        value = value.toDecimal(projectObj.project.Decimal.common.quantity);
         if (node.sourceType === projectObj.project.Bills.getSourceType()) {
         if (node.sourceType === projectObj.project.Bills.getSourceType()) {
             calcFees.setFee(node.data, fieldName, value);
             calcFees.setFee(node.data, fieldName, value);
             calc.calcNode(node, true);
             calc.calcNode(node, true);
@@ -273,8 +278,10 @@ var projectObj = {
                 }
                 }
                 projectObj.mainController.refreshTreeNode([node]);
                 projectObj.mainController.refreshTreeNode([node]);
             }
             }
-        }else if(value==null&&fieldName ==='feeRate'){
+        } else if(value==null && fieldName ==='feeRate'){
             project.FeeRate.cleanFeeRateID(node);
             project.FeeRate.cleanFeeRateID(node);
+        } else {
+            projectObj.mainController.refreshTreeNode([node], false);
         }
         }
     },
     },
     checkMainSpread: function () {
     checkMainSpread: function () {
@@ -575,6 +582,10 @@ $('#property_ok').click(function () {
         project.projSetting.zanguCalcMode = zanguMode;
         project.projSetting.zanguCalcMode = zanguMode;
         reCalc = true;
         reCalc = true;
     }
     }
+    if (labourCoeView.needSave()){
+        labourCoeView.save();
+        reCalc = true;
+    }
     if (reCalc) {
     if (reCalc) {
         projectObj.calculateAll();
         projectObj.calculateAll();
         project.pushNow('editBillsCalcMode',
         project.pushNow('editBillsCalcMode',

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

@@ -83,6 +83,7 @@ var subRateObject={
         var selectValueList=[];
         var selectValueList=[];
         var selectMap={};
         var selectMap={};
         if(me.datas&&me.datas.length>0){
         if(me.datas&&me.datas.length>0){
+            $.bootstrapLoading.start();
             _.forEach(me.datas,function (d,key) {
             _.forEach(me.datas,function (d,key) {
                 var selectValue = $('#'+d.ID).val();
                 var selectValue = $('#'+d.ID).val();
                 selectValueList.push(selectValue);
                 selectValueList.push(selectValue);

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

@@ -40,6 +40,7 @@ $("#linkGLJ").click(function(){
     subSpread.setActiveSheetIndex(0);
     subSpread.setActiveSheetIndex(0);
     $.contextMenu( 'destroy', "#subSpread" );
     $.contextMenu( 'destroy', "#subSpread" );
     gljContextMenu.loadGLJSpreadContextMenu();
     gljContextMenu.loadGLJSpreadContextMenu();
+    gljOprObj.activeTab='#linkGLJ';
     // for test
     // for test
     //subSpread.getActiveSheet().setValue(0, 0, "工料机");
     //subSpread.getActiveSheet().setValue(0, 0, "工料机");
 });
 });
@@ -51,6 +52,7 @@ $("#linkFZDE").click(function(){
     refreshSubSpread();
     refreshSubSpread();
     subSpread.setActiveSheetIndex(1);
     subSpread.setActiveSheetIndex(1);
     $.contextMenu( 'destroy', "#subSpread" );
     $.contextMenu( 'destroy', "#subSpread" );
+    gljOprObj.activeTab='#linkFZDE';
     // for test
     // for test
   //  subSpread.getActiveSheet().setValue(0, 0, "辅助定额");
   //  subSpread.getActiveSheet().setValue(0, 0, "辅助定额");
 });
 });
@@ -61,6 +63,7 @@ $("#linkFZTJ").click(function(){
     refreshSubSpread();
     refreshSubSpread();
     subSpread.setActiveSheetIndex(2);
     subSpread.setActiveSheetIndex(2);
     $.contextMenu( 'destroy', "#subSpread" );
     $.contextMenu( 'destroy', "#subSpread" );
+    gljOprObj.activeTab='#linkFZTJ';
     // for test
     // for test
     //subSpread.getActiveSheet().setValue(0, 0, "附注条件");
     //subSpread.getActiveSheet().setValue(0, 0, "附注条件");
 });
 });
@@ -73,6 +76,7 @@ $("#linkGCLMX").click(function(){
     subSpread.setActiveSheetIndex(3);
     subSpread.setActiveSheetIndex(3);
     $.contextMenu( 'destroy', "#subSpread" );
     $.contextMenu( 'destroy', "#subSpread" );
     gljContextMenu.loadQuantityDetailMenu();
     gljContextMenu.loadQuantityDetailMenu();
+    gljOprObj.activeTab='#linkGCLMX';
     // for test
     // for test
     //subSpread.getActiveSheet().setValue(0, 0, "工程量明细");
     //subSpread.getActiveSheet().setValue(0, 0, "工程量明细");
 });
 });
@@ -93,6 +97,7 @@ $("#linkJSCX").click(function(){        // 计算程序
     } else {
     } else {
         calcProgramObj.clearData();
         calcProgramObj.clearData();
     };
     };
+    gljOprObj.activeTab='#linkJSCX';
 });
 });
 
 
 //特征及内容
 //特征及内容
@@ -109,6 +114,7 @@ $("#linkTZJNR").click(function () {
     else{
     else{
         pageCCOprObj.clearData();
         pageCCOprObj.clearData();
     }
     }
+    gljOprObj.activeTab='#linkTZJNR';
 });
 });
 function SubActiveSheetNameIs(sheetName){
 function SubActiveSheetNameIs(sheetName){
     let rst = subSpread.getActiveSheet().name() == sheetName;
     let rst = subSpread.getActiveSheet().name() == sheetName;

+ 160 - 0
web/building_saas/report/html/rpt_main.html

@@ -0,0 +1,160 @@
+
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-lg-2 p-0">
+            <div class="print-list">
+                <div class="list-tools d-flex justify-content-center">
+                    <button class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#editForm"><i class="fa fa-cog"></i> 管理报表</button>
+                </div>
+                <div class="form-list">
+                    <ul id="rptTplTree" class="ztree"></ul>
+                </div>
+            </div>
+        </div>
+        <div class="col-lg-10 p-0">
+            <div class="toolsbar">
+                <div class="print-toolsbar">
+                    <div class="panel">
+                        <div class="panel-body">
+                            <button class="btn btn-secondary btn-sm" type="button">
+                                <i class="fa fa-print"></i><br>
+                                打印 <span id="checkCount" class="badge badge-primary">5</span>
+                            </button>
+                        </div>
+                    </div>
+                    <div class="panel">
+                        <div class="panel-body">
+                            <div class="btn-group" role="group" aria-label="Button group with nested dropdown">
+                                <div class="btn-group" role="group">
+                                    <button id="btnGroupDrop1" type="button" class="btn btn-secondary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                        纵向
+                                    </button>
+                                    <div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
+                                        <a class="dropdown-item" href="#">横向</a>
+                                    </div>
+                                </div>
+                                <div class="btn-group" role="group">
+                                    <button id="btnGroupDrop2" type="button" class="btn btn-secondary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                        A4
+                                    </button>
+                                    <div class="dropdown-menu" aria-labelledby="btnGroupDrop2">
+                                        <a class="dropdown-item" href="#">A3</a>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="panel-foot text-muted">
+                            预览设置
+                        </div>
+                    </div>
+                    <div class="panel">
+                        <div class="panel-body">
+                            <div class="btn-group" role="group">
+                                <button type="button" class="btn btn-secondary btn-sm">-</button>
+                                <a class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="重置默认大小">1000%</a>
+                                <button type="button" class="btn btn-secondary btn-sm">+</button>
+                            </div>
+                        </div>
+                        <div class="panel-foot text-muted">
+                            缩放
+                        </div>
+                    </div>
+                    <div class="panel">
+                        <div class="panel-body">
+                            <div class="btn-group" role="group" aria-label="Button group with nested dropdown">
+                                <button type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#paper"><i class="fa fa-file-o"></i> 纸张</button>
+                                <button type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#format"><i class="fa fa-bold"></i> 格式</button>
+                                <button type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#content"><i class="fa fa-file-text-o"></i> 内容</button>
+                            </div>
+                        </div>
+                        <div class="panel-foot text-muted">
+                            报表设置
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="print-view poj-list">
+                <div class="pageContainer">
+                    <canvas id="rptCanvas" height="820" width="920"></canvas>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<!--报表的弹窗-->
+<!--1弹出纸张-->
+<div class="modal fade" id="paper" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">纸张</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a href="" class="btn btn-primary">确定</a>
+            </div>
+        </div>
+    </div>
+</div>
+<!--2弹出页面-->
+<div class="modal fade" id="format" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">格式</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a href="" class="btn btn-primary">确定</a>
+            </div>
+        </div>
+    </div>
+</div>
+<!--3弹出格式-->
+<div class="modal fade" id="content" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">内容</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a href="" class="btn btn-primary">确定</a>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const SCREEN_DPI = [];
+    function getScreenDPI() {
+        if (SCREEN_DPI.length === 0) {
+            if (window.screen.deviceXDPI != undefined) {
+                SCREEN_DPI.push(window.screen.deviceXDPI);
+                SCREEN_DPI.push(window.screen.deviceYDPI);
+            } else {
+                let tmpNode = document.createElement("DIV");
+                tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
+                document.body.appendChild(tmpNode);
+                SCREEN_DPI.push(parseInt(tmpNode.offsetWidth));
+                SCREEN_DPI.push(parseInt(tmpNode.offsetHeight));
+                tmpNode.parentNode.removeChild(tmpNode);
+            }
+        }
+        return SCREEN_DPI;
+    }
+</script>

+ 209 - 0
web/building_saas/report/js/jpc_output.js

@@ -0,0 +1,209 @@
+/**
+ * Created by Tony on 2017/11/2.
+ */
+let JpcCanvasOutput = {
+    offsetX: 10,
+    offsetY: 10,
+    cleanCanvas: function (canvas) {
+        let ctx = canvas.getContext("2d");
+        ctx.save();
+        ctx.fillStyle="white";
+        ctx.clearRect(0,0, canvas.width, canvas.height);
+        ctx.restore();
+    },
+    drawToCanvas : function(pageObj, canvas, pageIdx) {
+        let me = this;
+        let ctx = canvas.getContext("2d");
+
+        function private_setupAreaH(area, type, fontAngle, dftFontHeight, outputPoint) {
+            let lType = type;
+            if (type != "left" && type != "right" && type != "center") lType = "left";
+            switch (lType) {
+                case "left":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[1] = 1 * area[JV.IDX_TOP] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[1] = 1 * area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+                    } else outputPoint[0] = 1 * area[JV.IDX_LEFT] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+                    ctx.textAlign="start";
+                    break;
+                case "right":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[1] = 1 * area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[1] = 1 * area[JV.IDX_TOP] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+                    } else outputPoint[0] = 1 * area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+                    ctx.textAlign="end";
+                    break;
+                case "center":
+                    if (fontAngle == JV.VERTICAL_ANGLE || fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[1] = (1 * area[JV.IDX_TOP] + 1 * area[JV.IDX_BOTTOM]) / 2;
+                    } else outputPoint[0] = (1 * area[JV.IDX_LEFT] + 1 * area[JV.IDX_RIGHT]) / 2;
+                    ctx.textAlign="center";
+                    break;
+            }
+        }
+        function private_setupAreaV(area, type, fontAngle, dftFontHeight, outputPoint) {
+            let lType = type;
+            if (type != "top" && type != "bottom" && type != "center") lType = "top";
+            switch (lType) {
+                case "top":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[0] = 1 * area[JV.IDX_RIGHT] - dftFontHeight - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[0] = 1 * area[JV.IDX_LEFT] + dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                    } else outputPoint[1] = 1 * area[JV.IDX_TOP] + dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                    break;
+                case "bottom":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[0] = 1 * area[JV.IDX_LEFT] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[0] = 1 * area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+                    } else outputPoint[1] = 1 * area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+                    break;
+                case "center":
+                    if (fontAngle == JV.VERTICAL_ANGLE) {
+                        outputPoint[0] = (1 * area[JV.IDX_LEFT] + 1 * area[JV.IDX_RIGHT] - dftFontHeight) / 2;
+                    } else if (fontAngle == JV.ANTI_VERTICAL_ANGLE) {
+                        outputPoint[0] = (1 * area[JV.IDX_LEFT] + 1 * area[JV.IDX_RIGHT] + dftFontHeight) / 2;
+                    } else outputPoint[1] = (1 * area[JV.IDX_TOP] + 1 * area[JV.IDX_BOTTOM] + dftFontHeight) / 2;
+                    break;
+            }
+        }
+        function private_drawText(val, area, font, control) {
+            let dftFontHeight = 12;
+            let output = [];
+            if (font) {
+                dftFontHeight = 1 * font[JV.FONT_PROPS[1]];
+                let dftOthers = "";
+                let dftFontBold = font[JV.FONT_PROPS[3]];
+                if (dftFontBold && dftFontBold == 'T') {
+                    dftOthers = "bold " + dftOthers ;
+                }
+                let dftFontItalic = font[JV.FONT_PROPS[4]];
+                if (dftFontItalic && dftFontItalic == 'T') {
+                    dftOthers = dftOthers + "italic ";
+                }
+                ctx.font = dftOthers + dftFontHeight + "px " + font[JV.PROP_NAME];
+            }
+            if (control) {
+                private_setupAreaH(area, control.Horizon, font.FontAngle, dftFontHeight, output);
+                private_setupAreaV(area, control.Vertical, font.FontAngle, dftFontHeight, output);
+            } else {
+                private_setupAreaH(area, "left", font.FontAngle, dftFontHeight, output);
+                private_setupAreaV(area, "bottom", font.FontAngle, dftFontHeight, output);
+            }
+            let w = area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - area[JV.IDX_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+            if (font.FontAngle != "0") {
+                w = area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] - area[JV.IDX_TOP] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+            }
+            ctx.save();
+            ctx.translate(output[0], output[1]);
+            if (font.FontAngle === JV.VERTICAL_ANGLE) {
+                ctx.rotate(Math.PI/2);
+            } else if (font.FontAngle === JV.ANTI_VERTICAL_ANGLE) {
+                ctx.rotate(-Math.PI/2);
+            }
+            if (w >= ctx.measureText(val).width) {
+                ctx.fillText(val, 0, 0);
+            } else {
+                while (true) {
+                    dftFontHeight--;
+                    ctx.font = "" + dftFontHeight + "px " + font[JV.PROP_NAME];
+                    if (w >=  ctx.measureText(val).width || dftFontHeight < 6) {
+                        ctx.fillText(val, 0, 0);
+                        break;
+                    }
+                }
+            }
+            ctx.restore();
+        }
+        function private_drawCellText(cell, fonts, controls) {
+            if (cell[JV.PROP_VALUE]) {
+                let values = ("" + cell[JV.PROP_VALUE]).split('|');
+                let font = fonts[cell[JV.PROP_FONT]];
+                let control = controls[cell[JV.PROP_CONTROL]];
+                let height = cell[JV.PROP_AREA][JV.PROP_BOTTOM] - cell[JV.PROP_AREA][JV.PROP_TOP];
+                let area = [cell[JV.PROP_AREA][JV.PROP_LEFT] + me.offsetX, cell[JV.PROP_AREA][JV.PROP_TOP] + me.offsetY, cell[JV.PROP_AREA][JV.PROP_RIGHT] + me.offsetX, cell[JV.PROP_AREA][JV.PROP_BOTTOM] + me.offsetY];
+                for (let i = 0; i < values.length; i++) {
+                    area[JV.IDX_TOP] = cell[JV.PROP_AREA][JV.PROP_TOP] + i * (height / values.length) + me.offsetY;
+                    area[JV.IDX_BOTTOM] = cell[JV.PROP_AREA][JV.PROP_TOP] + (i + 1) * (height / values.length) + me.offsetY;
+                    private_drawText(values[i], area, font, control);
+                }
+            }
+        }
+        function private_drawLine(cell, ctx, style, styleBorderDest, startP, destP, mergedBand, styles, isNeedMergeBand) {
+            ctx.beginPath();
+            let destStyle = style;
+            if (mergedBand) {
+                if (isNeedMergeBand && mergedBand[styleBorderDest] == cell[JV.PROP_AREA][styleBorderDest]) {
+                    destStyle = styles[mergedBand[JV.PROP_STYLE][JV.PROP_ID]];
+                }
+            }
+            ctx.moveTo(cell[JV.PROP_AREA][startP[0]] + me.offsetX, cell[JV.PROP_AREA][startP[1]] + me.offsetY);
+            if (destStyle[styleBorderDest] && destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT] != 0) {
+                ctx.lineWidth = 1.0 * destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT];
+                ctx.strokeStyle = destStyle[styleBorderDest][JV.PROP_COLOR];
+                ctx.lineTo(cell[JV.PROP_AREA][destP[0]] + me.offsetX, cell[JV.PROP_AREA][destP[1]] + me.offsetY);
+            }
+            ctx.stroke();
+        }
+        function private_chkIfInMergedBand(mergedBand, cell) {
+            let rst = false;
+            if (mergedBand && cell) {
+                rst = mergedBand[JV.PROP_TOP] <= cell[JV.PROP_AREA][JV.PROP_TOP] && mergedBand[JV.PROP_BOTTOM] >= cell[JV.PROP_AREA][JV.PROP_BOTTOM] &&
+                    mergedBand[JV.PROP_LEFT] <= cell[JV.PROP_AREA][JV.PROP_LEFT] && mergedBand[JV.PROP_RIGHT] >= cell[JV.PROP_AREA][JV.PROP_RIGHT];
+            }
+            return rst;
+        }
+        function private_drawCell(cell, fonts, styles, controls, mergedBand) {
+            ctx.save();
+            ctx.translate(0.5,0.5);
+            let style = styles[cell[JV.PROP_STYLE]];
+            if (style) {
+                let isNeedMergeBand = private_chkIfInMergedBand(mergedBand, cell);
+                private_drawLine(cell, ctx, style, JV.PROP_TOP, [JV.PROP_LEFT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_TOP], mergedBand, styles, isNeedMergeBand);
+                private_drawLine(cell, ctx, style, JV.PROP_RIGHT, [JV.PROP_RIGHT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_BOTTOM], mergedBand, styles, isNeedMergeBand);
+                private_drawLine(cell, ctx, style, JV.PROP_BOTTOM, [JV.PROP_RIGHT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_BOTTOM], mergedBand, styles, isNeedMergeBand);
+                private_drawLine(cell, ctx, style, JV.PROP_LEFT, [JV.PROP_LEFT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_TOP], mergedBand, styles, isNeedMergeBand);
+            }
+            private_drawCellText(cell, fonts, controls);
+            ctx.restore();
+        }
+
+        if (pageObj && pageObj.items.length > 0 && canvas && pageObj.items.length >= pageIdx) {
+            let page = pageObj.items[pageIdx - 1],
+                fonts = pageObj[JV.NODE_FONT_COLLECTION],
+                styles = pageObj[JV.NODE_STYLE_COLLECTION],
+                controls = pageObj[JV.NODE_CONTROL_COLLECTION],
+                mergedBand = pageObj[JV.BAND_PROP_MERGE_BAND];
+            for (let j = 0; j < page.cells.length; j++) {
+                let cell = page.cells[j];
+                private_drawCell(cell, fonts, styles, controls, mergedBand);
+            }
+        }
+    },
+    drawPageBorder: function(rptTpl, canvas, resolution) {
+        let me = this;
+        let size = rptTpl[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE].slice(0);
+        size[0] = Math.round(resolution[0] * size[0]);
+        size[1] = Math.round(resolution[0] * size[1]);
+
+        let ctx = canvas.getContext("2d");
+        ctx.save();
+        ctx.beginPath();
+        ctx.translate(0.5,0.5);
+        ctx.lineWidth = 1;
+        ctx.moveTo(me.offsetX, me.offsetY);
+        ctx.lineTo(size[0] + me.offsetX, me.offsetY);
+        ctx.lineTo(size[0] + me.offsetX, size[1] + me.offsetY);
+        ctx.lineTo(me.offsetX, size[1] + me.offsetY);
+        ctx.lineTo(me.offsetX, me.offsetY);
+        ctx.stroke();
+        ctx.restore();
+
+        ctx.fillStyle="black";
+        ctx.fillRect(size[0] + me.offsetX,10 + me.offsetY,10,size[1]);
+        ctx.fillRect(10 + me.offsetX,size[1] + me.offsetY,size[0],10);
+    }
+};

+ 49 - 0
web/building_saas/report/js/jpc_output_value_define.js

@@ -0,0 +1,49 @@
+/**
+ * Created by Tony on 2017/1/4.
+ */
+
+let JV = {
+    NODE_MAIN_INFO: "主信息",
+    NODE_PAGE_INFO: "打印页面_信息",
+    NODE_PAGE_SIZE: "纸张宽高",
+    NODE_MARGINS: "页边距",
+
+    NODE_FONT_COLLECTION: "font_collection",
+    NODE_STYLE_COLLECTION: "style_collection",
+    NODE_CONTROL_COLLECTION: "control_collection",
+
+    BAND_PROP_MERGE_BAND: "MergeBand",
+
+    PROP_NAME: "Name",
+    PROP_VALUE: "Value",
+    PROP_FONT: "font",
+    PROP_CONTROL: "control",
+    PROP_STYLE: "style",
+    PROP_AREA: "area",
+    PROP_ID: "ID",
+    PROP_LEFT: "Left",
+    PROP_RIGHT: "Right",
+    PROP_TOP: "Top",
+    PROP_BOTTOM: "Bottom",
+
+    IDX_LEFT: 0,
+    IDX_TOP: 1,
+    IDX_RIGHT: 2,
+    IDX_BOTTOM: 3,
+
+    CONTROL_PROPS: ["Shrink", "ShowZero", "Horizon", "Vertical", "Wrap"],
+    BORDER_STYLE_PROPS: ["LineWeight", "DashStyle", "Color"],
+    PROP_LINE_WEIGHT: "LineWeight",
+    PROP_DASH_STYLE: "DashStyle",
+    PROP_COLOR: "Color",
+    FONT_PROPS: ["Name", "FontHeight", "FontColor", "FontBold", "FontItalic", "FontUnderline", "FontStrikeOut", "FontAngle"],
+
+    OUTPUT_OFFSET: [2,1,2,3],
+    OFFSET_IDX_LEFT: 0,
+    OFFSET_IDX_RIGHT: 1,
+    OFFSET_IDX_TOP: 2,
+    OFFSET_IDX_BOTTOM: 3,
+
+    VERTICAL_ANGLE: "90",
+    ANTI_VERTICAL_ANGLE: "-90"
+};

+ 5 - 4
web/building_saas/main/js/rpt/rpt_cfg_const.js

@@ -2,7 +2,9 @@
  * Created by Tony on 2017/6/26.
  * Created by Tony on 2017/6/26.
  */
  */
 
 
-let setting = {
+const   TPL_TYPE_NODE = 1,
+        TPL_TYPE_TEMPLATE = 2;
+let rpt_tpl_setting = {
     view: {
     view: {
         selectedMulti: false
         selectedMulti: false
     },
     },
@@ -19,12 +21,11 @@ let setting = {
         },
         },
         simpleData: {
         simpleData: {
             enable: true,
             enable: true,
-            idKey: "ID",
-            pIdKey: "ParentID",
             rootPId: -1
             rootPId: -1
         }
         }
     },
     },
     callback: {
     callback: {
-        onCheck: zTreeOprObj.onCheck
+        //onCheck: zTreeOprObj.onCheck
+        onClick: zTreeOprObj.onClick
     }
     }
 };
 };

+ 128 - 0
web/building_saas/report/js/rpt_main.js

@@ -0,0 +1,128 @@
+/**
+ * Created by Tony on 2017/6/26.
+ */
+'use strict'
+
+let rptTplObj = {
+    hasInitialized: false,
+    iniPage: function() {
+        let me = this;
+        if (!me.hasInitialized) {
+            zTreeOprObj.getReportTemplateTree(userID);
+            me.hasInitialized = true;
+            let canvas = document.getElementById("rptCanvas");
+            canvas.onclick = canvasOprObj.cavansOnClick;
+            canvas.onmousemove = canvasOprObj.canvasOnMouseMove;
+        }
+    }
+}
+
+let zTreeOprObj = {
+    treeObj: null,
+    currentNode: null,
+    currentRptPageRst: null,
+    currentPage: 1,
+    maxPages: 0,
+    getReportTemplateTree: function(userId) {
+        let me = zTreeOprObj, params = {};
+        params.userId = [];
+        params.userId.push(userId);
+        params.userId.push(-100);
+        // let allEngIds = [];
+        // for (let item of engineeringList) {
+        //     allEngIds.push(item.value);
+        // }
+        // params.engineerId = allEngIds;
+        params.engineerId = projectInfoObj.projectInfo.property.engineering;
+        CommonAjax.postEx("report_tpl_api/getRptTplTree", params, 20000, true, function(result){
+                zTreeHelper.createTreeDirectly(result, rpt_tpl_setting, "rptTplTree", me);
+                me.refreshNodes();
+            }, null, null
+        );
+    },
+    refreshNodes: function() {
+        let me = this;
+        let private_setupIsParent = function(node){
+            node.isParent = (node.nodeType === RT.NodeType.NODE || node.level === 0);
+            if (node.items && node.items.length) {
+                for (let i = 0; i < node.items.length; i++) {
+                    private_setupIsParent(node.items[i]);
+                }
+            }
+        };
+        let topNodes = me.treeObj.getNodes();
+        for (let i = 0; i < topNodes.length; i++) {
+            private_setupIsParent(topNodes[i]);
+        }
+        me.treeObj.refresh();
+    },
+    onCheck: function() {
+        //count();
+        //if (clearFlag) {
+        //    clearCheckedOldNodes();
+        //}
+    },
+    onClick: function(event,treeId,treeNode) {
+        let me = zTreeOprObj;
+        let canvas = document.getElementById("rptCanvas");
+        if (treeNode.nodeType === TPL_TYPE_TEMPLATE && treeNode.refId > 0) {
+            let params = {};
+            let pageSize = "A4";
+            params.user_id = userID;
+            params.pageSize = pageSize;
+            params.rpt_tpl_id = treeNode.refId;
+            params.prj_id = projectInfoObj.projectInfo.ID;
+            CommonAjax.postEx("report_api/getReport", params, 5000, true, function(result){
+                    let pageRst = result;
+                    if (pageRst) {
+                        me.currentRptPageRst = pageRst;
+                        me.maxPages = pageRst.items.length;
+                        me.currentPage = 1;
+                        if (pageSize === "A4") {
+                            canvas.width = 1200;
+                            canvas.height = 900;
+                        } else if (pageSize === "A3") {
+                            canvas.width = 1880;
+                            canvas.height = 1200;
+                        }
+                        me.showPage(0, canvas);
+                    }
+                }, null, null
+            );
+        }
+    },
+    showPage: function (pageStep, canvas) {
+        let me = zTreeOprObj;
+        if (me.currentPage + pageStep >= 1 && me.currentPage + pageStep <= me.maxPages) {
+            me.currentPage = me.currentPage + pageStep;
+            JpcCanvasOutput.cleanCanvas(canvas);
+            JpcCanvasOutput.drawPageBorder(me.currentRptPageRst, canvas, getScreenDPI());
+            JpcCanvasOutput.drawToCanvas(me.currentRptPageRst, canvas, me.currentPage);
+        }
+    }
+};
+
+let canvasOprObj = {
+    canvasOnMouseMove: function (event) {
+        let x = event.offsetX - JpcCanvasOutput.offsetX,
+            canvas = event.originalTarget
+        ;
+        if (x < 300) {
+            canvas.style.cursor = "e-resize";
+        } else if ((canvas.width - x) < 300) {
+            canvas.style.cursor = "w-resize";
+        } else {
+            canvas.style.cursor = "";
+        }
+    },
+    cavansOnClick: function(event){
+        let x = event.offsetX - JpcCanvasOutput.offsetX,
+            //y = event.offsetY - JpcCanvasOutput.offsetY,
+            canvas = event.originalTarget;
+        if (x < 300) {
+            zTreeOprObj.showPage(-1, canvas);
+        } else if ((canvas.width - x) < 300) {
+            zTreeOprObj.showPage(1, canvas);
+        }
+    }
+};

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

@@ -61,4 +61,6 @@
 <script src="/lib/jquery/jquery-3.2.1.min.js"></script>
 <script src="/lib/jquery/jquery-3.2.1.min.js"></script>
 <script type="text/javascript" src="/web/building_saas/js/moment.min.js"></script>
 <script type="text/javascript" src="/web/building_saas/js/moment.min.js"></script>
 <script type="text/javascript" src="/web/building_saas/js/message.js"></script>
 <script type="text/javascript" src="/web/building_saas/js/message.js"></script>
+<script type="text/javascript" src="/public/web/scMathUtil.js"></script>
+<script type="text/javascript" src="/public/web/PerfectLoad.js"></script>
 <!-- endinject -->
 <!-- endinject -->

+ 1 - 0
web/users/html/login.html

@@ -69,6 +69,7 @@
     </div>
     </div>
     <!-- JS. -->
     <!-- JS. -->
     <!-- inject:js -->
     <!-- inject:js -->
+    <script type="text/javascript" src="/public/web/scMathUtil.js"></script>
     <script src="/lib/jquery/jquery-3.2.1.min.js"></script>
     <script src="/lib/jquery/jquery-3.2.1.min.js"></script>
     <script src="/public/web/url_util.js"></script>
     <script src="/public/web/url_util.js"></script>
     <script src="/lib/popper/popper.min.js"></script>
     <script src="/lib/popper/popper.min.js"></script>