Przeglądaj źródła

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

zhangweicheng 7 lat temu
rodzic
commit
98d863d603
49 zmienionych plików z 1533 dodań i 763 usunięć
  1. 3 0
      modules/main/facade/prj_properties_facade.js
  2. 78 0
      modules/main/models/prj_properties.js
  3. 1 1
      modules/main/models/project_glj.js
  4. 0 63
      modules/main/models/project_properties.js
  5. 3 1
      modules/reports/controllers/rpt_cfg_controller.js
  6. 8 4
      modules/reports/controllers/rpt_controller.js
  7. 18 3
      modules/reports/controllers/rpt_tpl_controller.js
  8. 1 3
      modules/reports/models/rpt_cfg.js
  9. 1 3
      modules/reports/models/rpt_mapping_field.js
  10. 1 3
      modules/reports/models/rpt_template.js
  11. 3 5
      modules/reports/models/rpt_tpl_data.js
  12. 22 20
      modules/reports/models/rpt_tpl_data_demo.js
  13. 9 10
      modules/reports/models/tpl_tree_node.js
  14. 5 1
      modules/reports/util/rpt_util.js
  15. 1 1
      modules/users/controllers/boot_controller.js
  16. 9 3
      modules/users/controllers/login_controller.js
  17. 12 5
      modules/users/controllers/user_controller.js
  18. 3 3
      modules/users/models/schema/user.js
  19. 26 0
      modules/users/models/schema/version.js
  20. 1 1
      modules/users/models/user_model.js
  21. 35 0
      modules/users/models/version_model.js
  22. 1 1
      modules/users/routes/boot_route.js
  23. 2 0
      modules/volume_price/models/volume_price_schema.js
  24. 117 99
      public/calc_util.js
  25. 25 0
      public/web/sheet/sheet_data_helper.js
  26. 3 0
      public/web/tree_sheet/tree_sheet_helper.js
  27. 9 3
      server.js
  28. 23 0
      test/demo/JSONtest.js
  29. 23 18
      test/tmp_data/bills_grid_setting.js
  30. 11 0
      test/tmp_data/test_ration_calc/ration_calc_base.js
  31. 1 1
      web/building_saas/css/main.css
  32. 2 1
      web/building_saas/main/html/main.html
  33. 6 7
      web/building_saas/main/js/calc/bills_calc.js
  34. 21 2
      web/building_saas/main/js/calc/calc_fees.js
  35. 23 2
      web/building_saas/main/js/models/bills.js
  36. 23 1
      web/building_saas/main/js/models/project.js
  37. 22 0
      web/building_saas/main/js/models/ration.js
  38. 0 403
      web/building_saas/main/js/models/ration_calc.js
  39. 568 0
      web/building_saas/main/js/models/ration_program.js
  40. 30 0
      web/building_saas/main/js/models/volume_price.js
  41. 210 0
      web/building_saas/main/js/views/calc_program_view.js
  42. 40 0
      web/building_saas/main/js/views/main_tree_col.js
  43. 70 1
      web/building_saas/main/js/views/project_view.js
  44. 7 67
      web/building_saas/main/js/views/ration_calc_view.js
  45. 6 4
      web/building_saas/main/js/views/sub_view.js
  46. 1 1
      web/users/html/login-infoinput.html
  47. 15 15
      web/users/html/login.html
  48. 6 2
      web/users/html/user-set.html
  49. 28 5
      web/users/js/login.js

+ 3 - 0
modules/main/facade/prj_properties_facade.js

@@ -0,0 +1,3 @@
+/**
+ * Created by Tony on 2017/8/3.
+ */

+ 78 - 0
modules/main/models/prj_properties.js

@@ -0,0 +1,78 @@
+/**
+ * Created by jimiz on 2017/5/19.
+ */
+// var mongoose = require("mongoose");
+// var db = require("../db/project_db");
+// var subSchema = require("./bills_sub_schemas");
+// var Schema = mongoose.Schema;
+// var deleteSchema = require('../../../public/models/delete_schema');
+// var consts = require('./project_consts');
+// var projectConsts = consts.projectConst;
+// var commonConsts = consts.commonConst;
+//
+// var projectPropertiesSchema = new Schema({
+//     ID: Number,
+//     unitPriceFileID: Number,
+//     unitPriceFileVer: Number,
+//     deleteInfo: deleteSchema
+// });
+//
+// var projectProperties = db.model("prj_properties", projectPropertiesSchema, "prj_properties");
+//
+// var projectPropertiesDAO = function(){};
+//
+// projectPropertiesDAO.prototype.getData = function(projectID, callback){
+//     projectProperties.find({'$or': [{ID: projectID, deleteInfo: null}, {ID: projectID, 'deleteInfo.deleted': {$in: [null, false]}}]}, '-_id', function(err, datas){
+//         if (!err) {
+//             callback(0, projectConsts.PROPERTIES, datas);
+//         } else {
+//             callback(1, '', null);
+//         };
+//     });
+// };
+//
+// projectPropertiesDAO.prototype.save = function(datas, callback){
+//     var functions = [];
+//     var data;
+//
+//     function saveOne(data) {
+//         return function (cb) {
+//             switch (data.updateType) {
+//                 case commonConsts.UT_UPDATE:
+//                     projectProperties.update({ID: data.ID}, data, cb);
+//                     break;
+//                 case commonConsts.UT_CREATE:
+//                     projectProperties.create(data, cb);
+//                     break;
+//                 case commonConsts.UT_DELETE:
+//                 /* 假删除
+//                  var item = new GLJ(doc);
+//                  item.remove(cb);
+//                  */
+//             }
+//         }
+//     }
+//     for (var i = 0; i < datas.length; i++){
+//         data = datas[i];
+//         functions.push(saveOne(data));
+//     }
+//
+//     async.parallel(functions, callback);
+// };
+//
+// module.exports = new projectPropertiesDAO();
+
+var mongoose = require('mongoose'),
+    Schema = mongoose.Schema;
+
+var prj_property = new Schema({
+    projectID: Number,
+    items: [
+        {
+            key: String,
+            value: String
+        }
+    ]
+},{versionKey:false});
+
+mongoose.model('prj_properties', prj_property, 'prj_properties');

+ 1 - 1
modules/main/models/project_glj.js

@@ -12,7 +12,7 @@ var projectConsts = consts.projectConst;
 var commonConsts = consts.commonConst;
 var unitPriceFile = require('../../glj/models/unit_price_file');
 var upGLJList = require('../../glj/models/glj_list');
-var projectProperties = require('./project_properties.js')
+var projectProperties = require('./prj_properties.js')
 
 var projectGLJSchema = new Schema({
     ID: Number,

+ 0 - 63
modules/main/models/project_properties.js

@@ -1,63 +0,0 @@
-/**
- * Created by jimiz on 2017/5/19.
- */
-var mongoose = require("mongoose");
-var db = require("../db/project_db");
-var subSchema = require("./bills_sub_schemas");
-var Schema = mongoose.Schema;
-var deleteSchema = require('../../../public/models/delete_schema');
-var consts = require('./project_consts');
-var projectConsts = consts.projectConst;
-var commonConsts = consts.commonConst;
-
-var projectPropertiesSchema = new Schema({
-    ID: Number,
-    unitPriceFileID: Number,
-    unitPriceFileVer: Number,
-    deleteInfo: deleteSchema
-});
-
-var projectProperties = db.model("projectProperties", projectPropertiesSchema, "projectProperties");
-
-var projectPropertiesDAO = function(){};
-
-projectPropertiesDAO.prototype.getData = function(projectID, callback){
-    projectProperties.find({'$or': [{ID: projectID, deleteInfo: null}, {ID: projectID, 'deleteInfo.deleted': {$in: [null, false]}}]}, '-_id', function(err, datas){
-        if (!err) {
-            callback(0, projectConsts.PROPERTIES, datas);
-        } else {
-            callback(1, '', null);
-        };
-    });
-};
-
-projectPropertiesDAO.prototype.save = function(datas, callback){
-    var functions = [];
-    var data;
-
-    function saveOne(data) {
-        return function (cb) {
-            switch (data.updateType) {
-                case commonConsts.UT_UPDATE:
-                    projectProperties.update({ID: data.ID}, data, cb);
-                    break;
-                case commonConsts.UT_CREATE:
-                    projectProperties.create(data, cb);
-                    break;
-                case commonConsts.UT_DELETE:
-                /* 假删除
-                 var item = new GLJ(doc);
-                 item.remove(cb);
-                 */
-            }
-        }
-    }
-    for (var i = 0; i < datas.length; i++){
-        data = datas[i];
-        functions.push(saveOne(data));
-    }
-
-    async.parallel(functions, callback);
-};
-
-module.exports = new projectPropertiesDAO();

+ 3 - 1
modules/reports/controllers/rpt_cfg_controller.js

@@ -2,8 +2,10 @@
  * Created by Tony on 2017/7/5.
  */
 
+let mongoose = require('mongoose');
 let rpt_util = require('../util/rpt_util');
-let Rpt_Map_Fld_Mdl = require('../models/rpt_mapping_field');
+let Rpt_Map_Fld_Mdl = mongoose.model('rpt_mapping_field');
+
 
 //统一回调函数
 let callback = function(req, res, err, message, data){

+ 8 - 4
modules/reports/controllers/rpt_controller.js

@@ -2,11 +2,14 @@
  * Created by Tony on 2017/3/13.
  */
 
+let mongoose = require('mongoose');
+
 let JV = require('../rpt_component/jpc_value_define');
-let Template = require('../models/rpt_template');
-let TemplateData = require('../models/rpt_tpl_data_demo');
+
+let Template = mongoose.model('rpt_templates');
+let demoTemplateData = mongoose.model('rpt_temp_tpl_data');
+
 let JpcEx = require('../rpt_component/jpc_ex');
-//let cache = require('../../../public/cache/cacheUtil');
 let rptUtil = require("../util/rpt_util");
 let rpt_xl_util = require('../util/rpt_excel_util');
 let fs = require('fs');
@@ -29,7 +32,8 @@ function getAllPagesCommon(req, res, rpt_id, pageSize, cb) {
         rptTpl = rst;
         if (rptTpl) {
             if (rptTpl.ID_KEY) {
-                return TemplateData.getPromise(rptTpl.ID_KEY);
+                //return demoTemplateData.getPromise(rptTpl.ID_KEY);
+                return demoTemplateData.findOne({"Data_Key": rptTpl.ID_KEY}).exec();
             } else {
                 callback(req, res, 'No report template data were found!', null);
             }

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

@@ -2,11 +2,14 @@
  * Created by Tony on 2017/6/1.
  */
 
+let mongoose = require('mongoose');
+
 let async = require("async");
 let counter = require('../../../public/counter/counter');
 
-let RptTplModel = require('../models/rpt_template');
-let TreeNodeModel = require('../models/tpl_tree_node');
+let RptTplModel = mongoose.model('rpt_templates');
+let TreeNodeModel = mongoose.model('rpt_tpl_tree');
+
 let rptTplDef = require("../../../public/rpt_tpl_def").getUtil();
 let stringUtil = require("../../../public/stringUtil");
 let JV = require('../rpt_component/jpc_value_define');
@@ -19,6 +22,16 @@ let callback = function(req, res, err, message, data){
 }
 
 module.exports = {
+    getDftTemplates(req, res) {
+        let filter = {"userId": -100, "$or": [{"isDeleted": null}, {"isDeleted": false} ]};
+        TreeNodeModel.find(filter, '-_id', function(err, data){
+            if (err) {
+                callback(req,res, true,"", null);
+            } else {
+                callback(req,res,false,"", data);
+            }
+        });
+    },
     getRptTplTree: function(req, res) {
         let params = JSON.parse(req.body.params),
             grpType = params.grpType,
@@ -34,7 +47,9 @@ module.exports = {
         TreeNodeModel.find(filter, '-_id', function(err, data){
             if (err) {
                 callback(req,res, true,"", null);
-            } else callback(req,res,false,"", data);
+            } else {
+                callback(req,res,false,"", data);
+            }
         });
         // let obj = test_glj_type_util.getStdGljTypeCacheObj();
         // console.log(obj.toArray());

+ 1 - 3
modules/reports/models/rpt_cfg.js

@@ -2,8 +2,6 @@
  * Created by Tony on 2017/6/14.
  */
 let mongoose = require('mongoose');
-let dbm = require("../../../config/db/db_manager");
-let smartcostdb = dbm.getCfgConnection("scConstruct");
 let Schema = mongoose.Schema;
 let FormatSchema = new Schema({
     "ID" : String,
@@ -44,6 +42,6 @@ let RptCfgSchema = new Schema({
     "formats" : [FormatSchema]
 });
 
-let Rpt_Cfg_Mdl = smartcostdb.model("rpt_cfg", RptCfgSchema, "rpt_cfg");
+let Rpt_Cfg_Mdl = mongoose.model("rpt_cfg", RptCfgSchema, "rpt_cfg");
 
 module.exports = Rpt_Cfg_Mdl;

+ 1 - 3
modules/reports/models/rpt_mapping_field.js

@@ -2,8 +2,6 @@
  * Created by Tony on 2017/7/11.
  */
 let mongoose = require('mongoose');
-let dbm = require("../../../config/db/db_manager");
-let smartcostdb = dbm.getCfgConnection("scConstruct");
 let MapFieldSchema = new mongoose.Schema({
     "fieldMapGrpName" : String,
     "dispName": String,
@@ -17,6 +15,6 @@ let MapFieldSchema = new mongoose.Schema({
     }]
 });
 
-let Rpt_Map_Field_Mdl = smartcostdb.model("rpt_mapping_field", MapFieldSchema, "rpt_mapping_field");
+let Rpt_Map_Field_Mdl = mongoose.model("rpt_mapping_field", MapFieldSchema, "rpt_mapping_field");
 
 module.exports = Rpt_Map_Field_Mdl;

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

@@ -2,8 +2,6 @@
  * Created by Tony on 2016/12/23.
  */
 let mongoose = require('mongoose');
-let dbm = require("../../../config/db/db_manager");
-let smartcostdb = dbm.getCfgConnection("scConstruct");
 let Schema = mongoose.Schema;
 let RptTemplateSchema = new Schema({
     "ID" : Number,
@@ -20,6 +18,6 @@ let RptTemplateSchema = new Schema({
     "计算式_集合": Array
 });
 
-let Template = smartcostdb.model("rpt_templates", RptTemplateSchema, "rpt_templates");
+let Template = mongoose.model("rpt_templates", RptTemplateSchema, "rpt_templates");
 
 module.exports = Template;

+ 3 - 5
modules/reports/models/rpt_tpl_data.js

@@ -3,8 +3,6 @@
  */
 
 let mongoose = require('mongoose');
-let dbm = require("../../../config/db/db_manager");
-let smartcostdb = dbm.getCfgConnection("scConstruct");
 let Schema = mongoose.Schema;
 
 let rptTplPrjSchema = new Schema({
@@ -26,9 +24,9 @@ let rptTplRationSchema = new Schema({
 
 });
 
-let tplPrjData = smartcostdb.model("temp_tpl_data", rptTplPrjSchema, "projects");
-let tplBillsData = smartcostdb.model("temp_tpl_data", rptTplBillsSchema, "bills");
-let tplRationData = smartcostdb.model("temp_tpl_data", rptTplRationSchema, "ration");
+let tplPrjData = mongoose.model("tpl_data_projects", rptTplPrjSchema, "projects");
+let tplBillsData = mongoose.model("tpl_data_bills", rptTplBillsSchema, "bills");
+let tplRationData = mongoose.model("tpl_data_ration", rptTplRationSchema, "ration");
 
 module.exports = {
     prjMdl: tplPrjData,

+ 22 - 20
modules/reports/models/rpt_tpl_data_demo.js

@@ -2,8 +2,8 @@
  * Created by Tony on 2016/12/28.
  */
 let mongoose = require('mongoose');
-let dbm = require("../../../config/db/db_manager");
-let smartcostdb = dbm.getCfgConnection("scConstruct");
+// let dbm = require("../../../config/db/db_manager");
+// let smartcostdb = dbm.getCfgConnection("scConstruct");
 let Schema = mongoose.Schema;
 let RptTemplateDataSchema = new Schema({
     "Data_Key": String,
@@ -12,23 +12,25 @@ let RptTemplateDataSchema = new Schema({
     "detail_data": Array
 });
 
-let TemplateData = smartcostdb.model("temp_tpl_data", RptTemplateDataSchema, "rpt_temp_tpl_data");
+let TemplateData = mongoose.model("rpt_temp_tpl_data", RptTemplateDataSchema, "rpt_temp_tpl_data");
 
-class RplTplDataDAO{
-    //根据id获取临时数据
-    get(tpl_id, callback){
-        TemplateData.find({"Data_Key": tpl_id}, function(err, templates){
-            if(templates.length){
-                callback(false, templates[0]);
-            }
-            else{
-                callback('查找不到模板临时数据!');
-            }
-        })
-    };
-    getPromise(tpl_id, callback){
-        return TemplateData.findOne({"Data_Key": tpl_id}).exec();
-    }
-};
+// class RplTplDataDAO{
+//     //根据id获取临时数据
+//     get(tpl_id, callback){
+//         TemplateData.find({"Data_Key": tpl_id}, function(err, templates){
+//             if(templates.length){
+//                 callback(false, templates[0]);
+//             }
+//             else{
+//                 callback('查找不到模板临时数据!');
+//             }
+//         })
+//     };
+//     getPromise(tpl_id, callback){
+//         return TemplateData.findOne({"Data_Key": tpl_id}).exec();
+//     }
+// };
+//
+// module.exports = new RplTplDataDAO();
 
-module.exports = new RplTplDataDAO();
+module.exports = TemplateData;

+ 9 - 10
modules/reports/models/tpl_tree_node.js

@@ -1,23 +1,22 @@
 /**
  * Created by Tony on 2017/5/31.
  */
-var mongoose = require('mongoose');
-var dbm = require("../../../config/db/db_manager");
-var db = dbm.getCfgConnection("scConstruct");
-var Schema = mongoose.Schema;
-var TreeNodeSchema = new Schema({
+let mongoose = require('mongoose');
+let Schema = mongoose.Schema;
+let TreeNodeSchema = new Schema({
     ID:Number,
     ParentID:Number,
     NextSiblingID:Number,
-    grpType: Number, //建筑(const : 1)/公路(const 2)/其他 etc...
-    nodeType: Number,//节点类型:树节点(枝) 或 模板节点(叶)
-    tplType: Number, //概算、预算、招投标 etc...
+    grpType: Number,  //建筑(const : 1)/公路(const 2)/其他 etc...
+    nodeType: Number, //节点类型:树节点(枝) 或 模板节点(叶)
+    tplType: Number,  //概算、预算、招投标 etc...
     userId: String,   //用户自定义模板用
-    refId: Number,   //
+    refId: Number,    //引用报表模板id (引用 collection: rpt_templates)
+    released: Boolean,//是否已发布, refId > -1 时才有意义
     name: String,
     isDeleted: Boolean
 });
 
-var TreeNodeModel = db.model("rpt_tpl_tree", TreeNodeSchema, "rpt_tpl_tree");
+let TreeNodeModel = mongoose.model("rpt_tpl_tree", TreeNodeSchema, "rpt_tpl_tree");
 
 module.exports = TreeNodeModel;

+ 5 - 1
modules/reports/util/rpt_util.js

@@ -1,8 +1,12 @@
 /**
  * Created by Tony on 2017/3/24.
  */
+let mongoose = require('mongoose');
+//let rpt_cfg_mdl = mongoose.model('rpt_cfg');
+
 let cache = require('../../../public/cache/cacheUtil');
-let Rpt_Cfg_Mdl = require('../models/rpt_cfg');
+//let Rpt_Cfg_Mdl = require('../models/rpt_cfg');
+let Rpt_Cfg_Mdl = mongoose.model('rpt_cfg');
 
 const RPT_CFG_GRP = 'rpt_cfg';
 

+ 1 - 1
modules/users/controllers/boot_controller.js

@@ -30,7 +30,7 @@ class BootController extends BaseController {
             provinceList: userModel.province,
             companyTypeList: userModel.companyType,
             companyScaleList: userModel.companyScale,
-            area: request.params.area
+            version: request.params.version
         };
         response.render('users/html/login-infoinput', renderData);
     }

+ 9 - 3
modules/users/controllers/login_controller.js

@@ -7,6 +7,7 @@
  */
 import UserModel from "../models/user_model";
 import SettingModel from "../models/setting_model";
+import VersionModel from "../models/version_model";
 
 class LoginController {
 
@@ -17,11 +18,12 @@ class LoginController {
      * @param {object} response
      * @return {void}
      */
-    index(request, response) {
+    async index(request, response) {
         let sessionUser = request.session.sessionUser;
         if (sessionUser !== undefined && sessionUser.ssoId >= 0) {
             return response.redirect("/pm");
         }
+
         response.render('users/html/login', {});
     }
 
@@ -36,7 +38,7 @@ class LoginController {
         let account = request.body.account;
         let password = request.body.pw;
         let preferenceSetting = {};
-
+        let versionList = [];
         try {
             // 调用接口验证登录信息
             let userModel = new UserModel();
@@ -70,11 +72,15 @@ class LoginController {
                 throw '标记用户信息失败!';
             }
 
+            // 获取版本信息
+            let versionModel = new VersionModel();
+            versionList = await versionModel.getVersionData();
+
         } catch (error) {
             console.log(error);
             return response.json({error: 1, msg: error});
         }
-        response.json({error: 0, msg: '', login_ask: preferenceSetting.login_ask});
+        response.json({error: 0, msg: '', login_ask: preferenceSetting.login_ask, version_list: JSON.stringify(versionList)});
     }
 
 }

+ 12 - 5
modules/users/controllers/user_controller.js

@@ -11,6 +11,7 @@ import LogType from "../../common/const/log_type_const";
 import LogModel from "../models/log_model";
 import SettingModel from "../models/setting_model";
 import SettingType from "../../common/const/setting_type_const";
+import VersionModel from "../models/version_model";
 
 class UserController extends BaseController {
 
@@ -24,9 +25,10 @@ class UserController extends BaseController {
     async info(request, response) {
         // 获取当前用户数据
         let sessionUser = request.session.sessionUser;
+
         let userModel = new UserModel();
         let userData = await userModel.findDataByName(sessionUser.username);
-        userData = userData.length <= 0 ? [] : userData[0];
+        userData = Object.keys(userData).length <= 0 ? [] : userData;
 
         let renderData = {
             userData: userData,
@@ -52,7 +54,7 @@ class UserController extends BaseController {
                 company: request.body.company,
                 company_type: request.body.company_type,
                 company_scale: request.body.company_scale,
-                area: request.body.area
+                version: request.body.version
             };
             let sessionUser = request.session.sessionUser;
             // 切换验证场景
@@ -125,17 +127,23 @@ class UserController extends BaseController {
     async preferences(request, response) {
         let sessionUserData = request.session.sessionUser;
         let preferenceSetting = {};
+        let versionList = [];
         try {
             // 获取配置信息
             let settingModel = new SettingModel();
             preferenceSetting = await settingModel.getPreferenceSetting(sessionUserData.id);
 
+            // 获取版本信息
+            let versionModel = new VersionModel();
+            versionList = await versionModel.getVersionData();
+
         } catch(error) {
             console.log(error);
         }
 
         let renderData = {
-            preferenceSetting: preferenceSetting
+            preferenceSetting: preferenceSetting,
+            versionList: versionList
         };
         response.render('users/html/user-set', renderData);
     }
@@ -151,13 +159,12 @@ class UserController extends BaseController {
         let loginAsk = request.body.login_ask;
         loginAsk = parseInt(loginAsk);
         let selectVersion = request.body.select_version;
-        selectVersion = parseInt(selectVersion);
         let sessionUserData = request.session.sessionUser;
 
         try {
             let data = {
                 login_ask: loginAsk,
-                select_version: loginAsk === 0 ? selectVersion : -1
+                select_version: loginAsk === 0 ? selectVersion : ''
             };
             let settingModel = new SettingModel();
             let result = await settingModel.save(sessionUserData.id, SettingType.PREFERENCE, data);

+ 3 - 3
modules/users/models/schema/user.js

@@ -28,9 +28,9 @@ let schema = {
         type: Number,
         default: -1
     },
-    area: {
-        type: Number,
-        default: 0
+    version: {
+        type: String,
+        default: ''
     },
     company_type: {
         type: Number,

+ 26 - 0
modules/users/models/schema/version.js

@@ -0,0 +1,26 @@
+/**
+ * 版本管理数据模型
+ *
+ * @author CaiAoLin
+ * @date 2017/7/28
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'version';
+let modelSchema = {
+    // 自增id
+    id: {
+        type: Number,
+        index: true
+    },
+    // 名称
+    name: String,
+    // 标准清单
+    standard_bill: Schema.Types.Mixed,
+    // 定额库
+    ration_lib: Schema.Types.Mixed
+};
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};

+ 1 - 1
modules/users/models/user_model.js

@@ -112,7 +112,7 @@ class UserModel extends BaseModel {
                 this.model.schema.path('real_name').required(true);
                 this.model.schema.path('company').required(true);
                 this.model.schema.path('province').required(true);
-                this.model.schema.path('area').required(true);
+                this.model.schema.path('version').required(true);
                 break;
         }
     }

+ 35 - 0
modules/users/models/version_model.js

@@ -0,0 +1,35 @@
+/**
+ * 版本管理业务逻辑模型
+ *
+ * @author CaiAoLin
+ * @date 2017/8/1
+ * @version
+ */
+import BaseModel from "../../common/base/base_model";
+import VersionSchema from "./schema/version";
+
+class VersionModel extends BaseModel {
+
+    /**
+     * 构造函数
+     *
+     * @return {void}
+     */
+    constructor () {
+        let parent = super();
+        parent.model = VersionSchema;
+        parent.init();
+    }
+
+    /**
+     * 获取版本数据
+     *
+     * @return {Promise}
+     */
+    getVersionData() {
+        return this.findDataByCondition({name: {$ne: ''}}, {_id: 1, name: 1}, false);
+    }
+
+}
+
+export default VersionModel;

+ 1 - 1
modules/users/routes/boot_route.js

@@ -13,6 +13,6 @@ module.exports=function (app){
     let bootController = new BootController();
 
 // 引导页面
-    router.get('/:area', bootController.boot);
+    router.get('/:version', bootController.boot);
     app.use('/boot', router);
 };

+ 2 - 0
modules/volume_price/models/volume_price_schema.js

@@ -18,6 +18,8 @@ let volumePriceSchema = new Schema({
     billsItemID: Number,
     // 排序
     serialNo: Number,
+    // 编号
+    code: String,
     // 名称
     name: String,
     // 单位

+ 117 - 99
public/calc_util.js

@@ -1,80 +1,56 @@
 /**
  * Created by Tony on 2017/6/21.
+ * Modified by CSL, 2017-08-01
  */
-let calcBaseCodeCollection = ["定额基价人工费", "定额基价材料费", "定额基价机械费"
-    , "定额基价人工费(调整后)", "定额基价材料费(调整后)", "定额基价机械费(调整后)"
-    , "市场价格人工费", "市场价格材料费", "市场价格机械费"
-    , "定额基价机上人工费", "主材费", "设备费"
-];
-let dummyCalcBaseCodeTypeCollection = [[2], [6], [64]
-    , [], [], []
-    , [], [], []
-    , [], [], []
-];
 
 let executeObj = {
-    currentTpl : null,
-    currentRationItem: null,
-    currentFeeRateFile: null,
+    ration: null,
     at: function(ID) {
         let me = executeObj,
             rst = 0;
-        rst = me.currentTpl.compileAssistantObj[ID].unitFee;
+        rst = me.ration.data.calcTemplate.compiledTemplate[ID].unitFee;
         rst = parseFloat(rst);
         return rst;
     },
-    base: function(calcBaseCode) {
+    base: function(calcBaseName) {
         let me = executeObj, rst = 0,
-            idx = calcBaseCodeCollection.indexOf(calcBaseCode);
-        if (idx >= 0) {
-            if (dummyCalcBaseCodeTypeCollection[idx].length > 0) {
-                let tmpSum = 0;
-                for (let glj of me.currentRationItem.data.gljList) {
-                    if (dummyCalcBaseCodeTypeCollection[idx].indexOf(glj["type"]) >= 0) {
-                        tmpSum += glj["basePrice"] * glj["quantity"];
-                    }
-                }
-                rst = tmpSum;
-            } else {
-                //rst = 10 + idx; //随便给个数
-            }
-        }
-        //rst = idx; //暂时返回值,测试用
-        return rst;
-    },
-    fee: function(feeID) {
-        let me = executeObj, rst = 0;
-        /*
-        for (let fee of me.currentFeeRateFile) {
-            if (fee.ID == feeID) {
-                rst = fee.rate;
-                break;
-            }
-        }
-        /*/
-        if (me.compiledFeeRateFile["fee_" + feeID]) rst = me.compiledFeeRateFile["fee_" + feeID].rate;
-        //*/
+            base = getRationCalcBase(calcBaseName);
+
+        if (base != null) {
+            let price = 0, tmpSum = 0;
+            for (let glj of me.ration.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){price = glj["marketPrice"] - glj["adjustPrice"];};
+                };
+                tmpSum = tmpSum + glj["quantity"] * price;
+                glj = null;
+            };
+            rst = tmpSum;
+        };
         return rst;
-    },
-    factor: function(factorCode) {
+    }
+/*    factor: function(factorID) {
         let me = executeObj;
-        let rst = 0.89; //暂时固定输出,测试用
+        let rst = 7.77;
         return rst;
-    }
+    }*/
 };
 
-class calculation {
-    init(calcTpl, calFee){
+class Calculation {
+/*    init(template, feeRates){
         let me = this;
-        me.calcTpl = calcTpl;
-        me.calFee = calFee;
+        me.template = template;
+        me.feeRates = feeRates;
         me.hasCompiled = false;
-    };
+    };*/
 
-    compile(){
+    compile(template, feeRates, labourCoes){
         let me = this;
-        me.hasCompiled = false;
-        me.errs = [];
+        template.hasCompiled = false;
+        template.errs = [];
 
         let private_extract_ID = function(str, idx){
             let rst = '', lBracket = 0, rBracket = 0, firstIdx = idx, lastIdx = 0;
@@ -101,92 +77,134 @@ class calculation {
             return rst;
         };
         let private_parse_ref = function(item, itemIdx){
-            //let expr = item.expression.split('at(').join('@(');
-            //item.expression = expr;
-            //console.log('expression: ' + expr);
             let idx = item.expression.indexOf('@(', 0);
             while (idx >= 0) {
                 let ID = private_extract_ID(item.expression, idx);
                 if (ID.length > 0) {
-                    let subItem = me.compileAssistantObj[ID];
+                    let subItem = template.compiledTemplate[ID];
                     if (subItem) {
                         if (subItem.ID !== item.ID) {
-                            private_parse_ref(subItem, me.compileAssistantObj[ID + "_idx"]);
+                            private_parse_ref(subItem, template.compiledTemplate[ID + "_idx"]);
                         } else {
-                            me.errs.push("There exists the self refer ID: " + ID);
+                            template.errs.push("There exists the self refer ID: " + ID);
                         }
                     } else {
-                        me.errs.push("There exists the invalid ID by which could not find the item: " + ID);
+                        template.errs.push("There exists the invalid ID by which could not find the item: " + ID);
                         console.log('invalid ID: ' + ID);
                     }
                 }
                 idx = item.expression.indexOf('@(', idx + ID.length + 3);
             }
-            if (me.calcTpl.compiledSeq.indexOf(itemIdx) < 0) {
-                me.calcTpl.compiledSeq.push(itemIdx);
+            if (template.compiledSeq.indexOf(itemIdx) < 0) {
+                template.compiledSeq.push(itemIdx);
             }
         };
         let private_setup_seq = function(item, itemIdx){
-            if (me.calcTpl.compiledSeq.indexOf(itemIdx) < 0) {
+            if (template.compiledSeq.indexOf(itemIdx) < 0) {
                 private_parse_ref(item, itemIdx);
             }
         };
         let private_compile_items = function() {
-            for (let idx of me.calcTpl.compiledSeq) {
-                let item = me.calcTpl.calcItems[idx];
+            for (let idx of template.compiledSeq) {
+                let item = template.calcItems[idx];
                 item.compiledExpr = item.expression.split('@(').join('$CE.at(');
                 item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
-                item.compiledExpr = item.compiledExpr.split('fee(').join('$CE.fee(');
-                item.compiledExpr = item.compiledExpr.split('factor(').join('$CE.factor(');
-                //console.log(item.compiledExpr);
+                //item.compiledExpr = item.compiledExpr.split('rate(').join('$CE.rate(');
+                //item.compiledExpr = item.compiledExpr.split('factor(').join('$CE.factor(');
+                if (item.labourCoeID){
+                    let lc = me.compiledLabourCoes["LabourCoe_" + item.labourCoeID].coe;
+                    item.dispExpr = item.dispExpr.replace(/L/gi, lc.toString());
+                    item.compiledExpr = item.compiledExpr.replace(/L/gi, lc.toString());
+                }
             }
         };
-        let private_comile_feeFile = function() {
-            if (me.calFee) {
-                me.compiledFee = {};
-                for (let fee of me.calFee) {
-                    me.compiledFee["fee_" + fee.ID] = fee;
+        let private_compile_feeFile = function() {
+            if (feeRates) {
+                me.compiledFeeRate = {};
+                for (let rate of feeRates) {
+                    me.compiledFeeRate["feeRate_" + rate.ID] = rate;
+                }
+            }
+        };
+        let private_compile_labourCoeFile = function() {
+            if (labourCoes) {
+                me.compiledLabourCoes = {};
+                for (let coe of labourCoes) {
+                    me.compiledLabourCoes["LabourCoe_" + coe.ID] = coe;
                 }
             }
         };
 
-        if (me.calcTpl && me.calcTpl.calcItems && me.calcTpl.calcItems.length > 0) {
-            me.calcTpl.compiledSeq = [];
-            me.compileAssistantObj = {};
+        if (template && template.calcItems && template.calcItems.length > 0) {
+            template.compiledSeq = [];
+            template.compiledTemplate = {};
             //1. first round -> prepare
-            private_comile_feeFile();
-            for (let i = 0; i < me.calcTpl.calcItems.length; i++) {
-                let item = me.calcTpl.calcItems[i];
-                me.compileAssistantObj[item.ID] = item;
-                me.compileAssistantObj[item.ID + "_idx"] = i;
+            private_compile_feeFile();
+            private_compile_labourCoeFile();
+            for (let i = 0; i < template.calcItems.length; i++) {
+                let item = template.calcItems[i];
+                template.compiledTemplate[item.ID] = item;
+                template.compiledTemplate[item.ID + "_idx"] = i;
             }
             //2. second round -> go!
-            for (let i = 0; i < me.calcTpl.calcItems.length; i++) {
-                private_setup_seq(me.calcTpl.calcItems[i], i);
+            for (let i = 0; i < template.calcItems.length; i++) {
+                private_setup_seq(template.calcItems[i], i);
             }
-            if (me.errs.length == 0) {
+            if (template.errs.length == 0) {
                 private_compile_items();
-                if (me.errs.length == 0) me.hasCompiled = true;
+                template.hasCompiled = true;
             } else {
-                console.log('errors: ' + me.errs.toString());
+                console.log('errors: ' + template.errs.toString());
             }
         }
     };
-    calculate( $RATION){
+
+    calculate($RATION){         // 参数$RATION也可以是清单
         let me = this;
-        if ($RATION && me.hasCompiled) {
+        let template = $RATION.data.calcTemplate;
+
+        if ($RATION && template.hasCompiled) {
             let $CE = executeObj;
-            $CE.currentRationItem = $RATION;
-            $CE.currentTpl = me;
-            $CE.currentFeeRateFile = me.calFee;
-            $CE.compiledFeeRateFile = me.compiledFee;
-            for (let idx of me.calcTpl.compiledSeq) {
-                let item = me.calcTpl.calcItems[idx];
-                item.unitFee = eval(item.compiledExpr);
-                item.totalFee = item.unitFee * 3;     // AAAAA 5为测试值 $RATION.data.Quantity
+            $CE.ration = $RATION;
+
+            if (!$RATION.fees) {
+                $RATION.fees = [];
+                $RATION.feesIndex = {};
+            };
+
+            for (let idx of template.compiledSeq) {
+                let calcItem = template.calcItems[idx];
+
+                let feeRate = 100;    // 100%
+                // 下面三项用于界面显示。
+                if (calcItem.feeRateID) {
+                    feeRate = me.compiledFeeRate["feeRate_" + calcItem.feeRateID].rate;
+                    calcItem.feeRate = feeRate;
+                };
+                calcItem.unitFee = eval(calcItem.compiledExpr) * feeRate * 0.01;   // 如果eval()对清单树有影响,就换成小麦的Expression对象再试
+                calcItem.totalFee = calcItem.unitFee * 3;     // AAAAAA 测试值,因目前定额无数量(保存不上) $RATION.data.Quantity
+
+                // 费用同步到定额
+                // 引入小麦的字段检测后,快速切换定额出现计算卡顿现象,过多的循环造成。这里把她的代码拆出来,减少微循环。
+                if (!$RATION.feesIndex[calcItem.fieldName]){
+                    let fee = {
+                        'fieldName': calcItem.fieldName,
+                        'unitFee': calcItem.unitFee,
+                        'totalFee': calcItem.totalFee,
+                        'tenderUnitFee': 0,
+                        'tenderTotalFee': 0
+                    };
+                    $RATION.fees.push(fee);
+                    $RATION.feesIndex[calcItem.fieldName] = fee;
+                }
+                else{
+                    $RATION.feesIndex[calcItem.fieldName].unitFee = calcItem.unitFee;
+                    $RATION.feesIndex[calcItem.fieldName].totalFee = calcItem.totalFee;
+                }
             }
         }
     }
 }
 
+
 //module.exports = new calculation();

+ 25 - 0
public/web/sheet/sheet_data_helper.js

@@ -97,7 +97,32 @@ var SheetDataHelper = {
             sheet.setStyle(-1, iCol, SheetDataHelper.getSheetCellStyle(colSetting));
             datas.forEach(function (data, iRow) {
                 var cell = sheet.getCell(iRow, iCol, GC.Spread.Sheets.SheetArea.viewport);
+                var getFieldText2 = function () {
+                    var fields = colSetting.data.field.split('.'), iField, value = data;
+                    for (iField = 0; iField < fields.length; iField++) {
+                        if (value[fields[iField]]) {
+                            value = value[fields[iField]];
+                        } else {
+                            return '';
+                        }
+                    }
+                    return value;
+                };
                 cell.value(data[colSetting.data.field]);
+                if (colSetting.data.getText) {
+                    cell.value(colSetting.data.getText(data));
+                } else {
+                    cell.value(getFieldText2());
+                }
+                if (colSetting.readOnly) {
+                    if (Object.prototype.toString.apply(colSetting.readOnly) === "[object Function]") {
+                        cell.locked(colSetting.readOnly(node));
+                    } else {
+                        cell.locked(true);
+                    }
+                } else {
+                    cell.locked(false);
+                }
             });
         });
 

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

@@ -11,6 +11,9 @@ var TREE_SHEET_HELPER = {
         style.hAlign = setting.data.hAlign;
         style.vAlign = setting.data.vAlign;
         style.wordWrap = setting.data.wordWrap;
+        if (setting.data.formatter) {
+            style.formatter = setting.data.formatter;
+        }
         return style;
     },
     loadSheetHeader: function (setting, sheet) {

+ 9 - 3
server.js

@@ -5,9 +5,6 @@ let fileUtils = require("./modules/common/fileUtils");
 let dbm = require("./config/db/db_manager");
 //config.setToLocalDb();
 config.setToQaDb();
-//config.setupCache();
-let cfgCacheUtil = require("./config/cacheCfg");
-cfgCacheUtil.setupDftCache();
 
 let path = require('path');
 let session = require('express-session');
@@ -24,6 +21,15 @@ fileUtils.getGlobbedFiles('./modules/ration_glj/models/*.js').forEach(function(m
 //暂时引入其它模块的model
 require('./modules/fee_rates/models/fee_rates');
 
+//引入报表模块
+fileUtils.getGlobbedFiles('./modules/reports/models/*.js').forEach(function(modelPath) {
+    require(path.resolve(modelPath));
+})
+
+//config.setupCache();
+let cfgCacheUtil = require("./config/cacheCfg");
+cfgCacheUtil.setupDftCache();
+
 let app = express();
 let _rootDir = __dirname;
 app.use(express.static(_rootDir));

+ 23 - 0
test/demo/JSONtest.js

@@ -0,0 +1,23 @@
+/**
+ * Created by Tony on 2017/8/3.
+ */
+let test = require('tape');
+
+
+test('JSON引用测试', function(t){
+    let testData = {
+        name: "hello!",
+        items: [
+            {key: "key1", value: "value1"},
+            {key: "key2", value: "value2"},
+            {key: "key3", value: "value3"}
+        ]
+    }
+    for (let item of testData.items) {
+        testData[item.key] = item;
+        item.value += "_change!";
+    }
+    console.log(JSON.stringify(testData));
+    t.pass('just logging and pass!');
+    t.end();
+})

+ 23 - 18
test/tmp_data/bills_grid_setting.js

@@ -136,7 +136,7 @@ var BillsGridSetting ={
         },
         {
             "width":180,
-            "readOnly":false,
+            "readOnly":'readOnly.volumePrice',
             "head":{
                 "titleNames":[
                     "项目特征"
@@ -166,7 +166,7 @@ var BillsGridSetting ={
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.volumePrice',
             "head":{
                 "titleNames":[
                     "工作内容"
@@ -196,7 +196,7 @@ var BillsGridSetting ={
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.volumePrice',
             "head":{
                 "titleNames":[
                     "工程专业"
@@ -226,7 +226,7 @@ var BillsGridSetting ={
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.volumePrice',
             "head":{
                 "titleNames":[
                     "取费专业"
@@ -286,7 +286,7 @@ var BillsGridSetting ={
         },
         {
             "width":120,
-            "readOnly":false,
+            "readOnly":true,
             "head":{
                 "titleNames":[
                     "定额调整状态"
@@ -316,7 +316,7 @@ var BillsGridSetting ={
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.billsParent',
             "head":{
                 "titleNames":[
                     "工程量"
@@ -341,12 +341,13 @@ var BillsGridSetting ={
                 "field":"quantity",
                 "vAlign":1,
                 "hAlign":2,
-                "font":"Arial"
+                "font":"Arial",
+                "digit": 'common.quantity'
             }
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.volumePrice',
             "head":{
                 "titleNames":[
                     "含量"
@@ -376,7 +377,7 @@ var BillsGridSetting ={
         },
         {
             "width":120,
-            "readOnly":false,
+            "readOnly":'readOnly.forCalcBase',
             "head":{
                 "titleNames":[
                     "计算基数"
@@ -406,7 +407,7 @@ var BillsGridSetting ={
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.volumePrice',
             "head":{
                 "titleNames":[
                     "费率(%)"
@@ -436,7 +437,7 @@ var BillsGridSetting ={
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.ration',
             "head":{
                 "titleNames":[
                     "综合单价"
@@ -461,12 +462,13 @@ var BillsGridSetting ={
                 "field":"feesIndex.common.unitFee",
                 "vAlign":1,
                 "hAlign":2,
-                "font":"Arial"
+                "font":"Arial",
+                "digit": 'common.unitFee'
             }
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.ration',
             "head":{
                 "titleNames":[
                     "综合合价"
@@ -491,12 +493,13 @@ var BillsGridSetting ={
                 "field":"feesIndex.common.totalFee",
                 "vAlign":1,
                 "hAlign":2,
-                "font":"Arial"
+                "font":"Arial",
+                "digit": 'common.totalFee'
             }
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.volumePrice',
             "head":{
                 "titleNames":[
                     "暂估单价"
@@ -521,12 +524,13 @@ var BillsGridSetting ={
                 "field":"feesIndex.zangu.unitFee",
                 "vAlign":1,
                 "hAlign":2,
-                "font":"Arial"
+                "font":"Arial",
+                "digit": 'common.unitFee'
             }
         },
         {
             "width":80,
-            "readOnly":false,
+            "readOnly":'readOnly.volumePrice',
             "head":{
                 "titleNames":[
                     "暂估合价"
@@ -551,7 +555,8 @@ var BillsGridSetting ={
                 "field":"feesIndex.zangu.totalFee",
                 "vAlign":1,
                 "hAlign":2,
-                "font":"Arial"
+                "font":"Arial",
+                "digit": 'common.totalFee'
             }
         },
         {

+ 11 - 0
test/tmp_data/test_ration_calc/ration_calc_base.js

@@ -84,3 +84,14 @@ let rationCalcBase = [
         'gljTypes': [gljType.EQUIPMENT]
     }
 ];
+
+function getRationCalcBase(dispName){
+    let rst = null;
+    for (let base of rationCalcBase) {
+       if (base.dispName == dispName) {
+           rst = base;
+           break;
+       };
+    }
+    return rst;
+};

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

@@ -234,7 +234,7 @@ body {
     }
 }
 .bottom-content .tab-content .main-data-bottom{
-    height: 200px;
+    height: 400px;
     overflow: auto;
 }
 .bottom-content .tab-content .ovf-hidden{

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

@@ -543,7 +543,7 @@
     <script type="text/javascript" src="/web/building_saas/main/js/calc/ration_calc.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/calc/bills_calc.js"></script>
     <script type="text/javascript" src="/public/calc_util.js"></script>
-    <script type="text/javascript" src="/web/building_saas/main/js/models/ration_calc.js"></script>
+    <script type="text/javascript" src="/web/building_saas/main/js/models/ration_program.js"></script>
     <!-- Controller -->
     <script type="text/javascript" src="/public/web/tree_sheet/tree_sheet_controller.js"></script>
     <script type="text/javascript" src="/public/web/tree_sheet/tree_sheet_helper.js"></script>
@@ -566,6 +566,7 @@
     <script type="text/javascript" src="/web/building_saas/main/js/views/std_ration_lib.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/models/quantity_detail.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/glj_view_contextMenu.js"></script>
+    <script type="text/javascript" src="/web/building_saas/main/js/views/calc_program_view.js"></script>
     <!-- reports -->
     <script type="text/javascript" src="/public/web/treeDataHelper.js"></script>
     <script type="text/javascript" src="/public/web/ztree_common.js"></script>

+ 6 - 7
web/building_saas/main/js/calc/bills_calc.js

@@ -220,7 +220,6 @@ class BillsCalcHelper {
     constructor (project, CalcFlag) {
         this.project = project;
         this.CalcFlag = CalcFlag;
-        this.digit = 2;
         switch (this.CalcFlag) {
             case rationContent:
                 this.calcField = rationContentCalcFields;
@@ -250,7 +249,7 @@ class BillsCalcHelper {
     };
     calcRationLeaf (node, fields) {
         nodeCalcObj.node = node;
-        nodeCalcObj.digit = this.digit;
+        nodeCalcObj.digit = this.project.Decimal.unitFee;
         calcFees.checkFields(node.data, fields);
         let nodeCalc = nodeCalcObj, virData= null;
 
@@ -266,10 +265,10 @@ class BillsCalcHelper {
             nodeCalcObj.field = field;
             switch (field.unitFeeFlag) {
                 case rationContentUnitFeeFlag:
-                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.rationContentUnitFee().toDecimal(this.digit);
+                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.rationContentUnitFee().toDecimal(this.project.Decimal.common.unitFee);
                     break;
                 case averageQtyUnitFeeFlag:
-                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.averageQty().toDecimal(this.digit);
+                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.averageQty().toDecimal(this.project.Decimal.common.unitFee);
                     break;
                  case billsPriceUnitFeeFlag:
                      node.data.feesIndex[field.type].unitFee = virData[field.type];
@@ -279,10 +278,10 @@ class BillsCalcHelper {
             }
             switch (field.totalFeeFlag) {
                 case sumTotalFeeFlag:
-                    node.data.feesIndex[field.type].totalFee = nodeCalcObj.sumTotalFee().toDecimal(this.digit);
+                    node.data.feesIndex[field.type].totalFee = nodeCalcObj.sumTotalFee().toDecimal(this.project.Decimal.common.totalFee);
                     break;
                 case totalFeeFlag:
-                    node.data.feesIndex[field.type].totalFee = nodeCalcObj.totalFee().toDecimal(this.digit);
+                    node.data.feesIndex[field.type].totalFee = nodeCalcObj.totalFee().toDecimal(this.project.Decimal.common.totalFee);
                     break;
                 default:
                     node.data.feesIndex[field.type].totalFee = 0;
@@ -297,7 +296,7 @@ class BillsCalcHelper {
         calcFees.checkFields(node.data, fields);
         for (let field of fields) {
             nodeCalcObj.field = field;
-            node.data.feesIndex[field.type].totalFee = nodeCalcObj.sumTotalFee().toDecimal(this.digit);
+            node.data.feesIndex[field.type].totalFee = nodeCalcObj.sumTotalFee().toDecimal(this.project.Decimal.common.totalFee);
         }
     };
     calcNodes (nodes) {

+ 21 - 2
web/building_saas/main/js/calc/calc_fees.js

@@ -19,6 +19,7 @@ let calcFees = {
     findFee: function (data, fieldName) {
         if (!data.fees) {
             data.fees = [];
+            data.feesIndex = {};
         }
         for (let fee of data.fees) {
             if (fee.fieldName === fieldName) {
@@ -27,7 +28,7 @@ let calcFees = {
         }
         return null;
     },
-    AddFee: function (data, fieldName) {
+    addFee: function (data, fieldName) {
         let fee = {
             'fieldName': fieldName,
             'unitFee': 0,
@@ -45,7 +46,7 @@ let calcFees = {
         }
         for (let field of fields) {
             if (!this.findFee(data, field.type)) {
-                this.AddFee(data, field.type);
+                this.addFee(data, field.type);
             }
         }
     },
@@ -70,5 +71,23 @@ let calcFees = {
             }
         }
         return value;
+    },
+    setFee: function (data, fullField, value) {
+        let fields = fullField.split('.'), valueField = data;
+        for (let i in fields) {
+            if (valueField[fields[i]]) {
+                if (i == fields.length - 1) {
+                    valueField[fields[i]] = value;
+                } else {
+                    valueField = valueField[fields[i]];
+                }
+            } else {
+                if (i == fields.length - 1) {
+                    valueField[fields[i]] = value;
+                } else {
+                    valueField[fields[i]] = {};
+                };
+            }
+        }
     }
 }

+ 23 - 2
web/building_saas/main/js/models/bills.js

@@ -178,7 +178,6 @@ var Bills = {
             return this.tree.delete(node);
         };
 
-
         bills.prototype.upMoveBills = function (node) {
             var upMoveData = node.getUpMoveData();
             project.pushNow('upMoveBills', this.getSourceType(), tools.coverseTreeUpdateData(upMoveData, this.project.ID()));
@@ -202,7 +201,29 @@ var Bills = {
             project.pushNow('downLevelBills', [this.getSourceType()], [tools.coverseTreeUpdateData(downLevelData, this.project.ID())]);
 
             return node.downLevel();
-        }
+        };
+
+        bills.prototype.updateField = function (node, field, newValue) {
+            calcFees.setFee(node.data, field, newValue);
+            let updateData = [];
+            let data = {'ID': node.getID(), 'projectID': this.project.ID()};
+            if (field === 'quantity') {
+                data[field] = newValue;
+                // to do Calculate
+                if (node.data.fees) {
+                    data.fees = node.data.fees;
+                }
+            } else if (field === 'feesIndex.common.unitFee') {
+                // to do Calculate
+                if (node.data.fees) {
+                    data.fees = node.data.fees;
+                }
+            } else {
+                data[field] = newValue;
+            }
+            updateData.push({'updateType': 'ut_update', 'updateData': data});
+            this.project.pushNow('updateBills', this.getSourceType(), updateData);
+        };
 
         return new bills(project);
     }

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

@@ -74,6 +74,13 @@ var PROJECT = {
             this.quantity_detail = quantity_detail.createNew(this);
             this.FeeRate = FeeRate.createNew(this);
             this.VolumePrice = VolumePrice.createNew(this);
+            this.Decimal = {
+                common: {
+                    quantity: 3,
+                    unitFee: 2,
+                    totalFee: 2
+                }
+            };
 
             this.masterField = {ration: 'billsItemID', volumePrice: 'billsItemID'};
         };
@@ -90,7 +97,22 @@ var PROJECT = {
 
         project.prototype.projCounter = function () {
             return tools.projCounter;
-        }
+        };
+        project.prototype.getDecimal = function (fullName) {
+            let names = fullName.split('.'), decimal = this.Decimal;
+            for (let name of names) {
+                if (decimal[name]) {
+                    decimal = decimal[name];
+                } else {
+                    return null;
+                }
+            }
+            if (Object.prototype.toString.apply(decimal) === '[object Number]') {
+                return decimal;
+            } else {
+                return null;
+            }
+        };
 
         project.prototype.loadMainTree = function () {
             var that = this;

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

@@ -229,6 +229,28 @@ var Ration = {
             ration2.serialNo = preSerialNo;
         };
 
+        ration.prototype.updateField = function (ration, field, newValue) {
+            calcFees.setFee(ration, field, newValue);
+            let updateData = [];
+            let data = {'ID': ration.ID, 'projectID': this.project.ID()};
+            if (field === 'quantity') {
+                data[field] = newValue;
+                // to do Calculate
+                if (ration.fees) {
+                    data.fees = ration.fees;
+                }
+            } else if (field === 'feesIndex.common.unitFee') {
+                // to do Calculate
+                if (ration.fees) {
+                    data.fees = ration.fees;
+                }
+            } else {
+                data[field] = newValue;
+            }
+            updateData.push({'updateType': 'ut_update', 'updateData': data});
+            this.project.pushNow('updateBills', this.getSourceType(), updateData);
+        };
+
         return new ration(project);
     }
 };

+ 0 - 403
web/building_saas/main/js/models/ration_calc.js

@@ -1,403 +0,0 @@
-/**
- * Created by CSL on 2017-07-19.
- */
-
-let calcFeeRate = [
-    {
-        "ID" : 1,
-        "ParentID" : null,
-        "name" : "企业管理费",
-        "rate" : null,
-        "memo" : null
-    },
-    {
-        "ID" : 2,
-        "ParentID" : 1,
-        "name" : "建筑工程",
-        "rate" : null,
-        "memo" : null
-    },
-    {
-        "ID" : 3,
-        "ParentID" : 2,
-        "name" : "一类工程",
-        "rate" : 16.03,
-        "memo" : null
-    },
-    {
-        "ID" : 4,
-        "ParentID" : 2,
-        "name" : "二类工程",
-        "rate" : 14.95,
-        "memo" : null
-    },
-    {
-        "ID" : 5,
-        "ParentID" : 2,
-        "name" : "三类工程",
-        "rate" : 12.47,
-        "memo" : null
-    },
-    {
-        "ID" : 6,
-        "ParentID" : 2,
-        "name" : "四类工程",
-        "rate" : 9.3,
-        "memo" : null
-    },
-    {
-        "ID" : 7,
-        "ParentID" : 1,
-        "name" : "市政工程",
-        "rate" : null,
-        "memo" : null
-    },
-    {
-        "ID" : 8,
-        "ParentID" : 7,
-        "name" : "一类工程",
-        "rate" : 16.33,
-        "memo" : null
-    },
-    {
-        "ID" : 9,
-        "ParentID" : 7,
-        "name" : "二类工程",
-        "rate" : 15,
-        "memo" : null
-    },
-    {
-        "ID" : 10,
-        "ParentID" : 7,
-        "name" : "三类工程",
-        "rate" : 12.5,
-        "memo" : null
-    },
-    {
-        "ID" : 11,
-        "ParentID" : 7,
-        "name" : "四类工程",
-        "rate" : 9.5,
-        "memo" : null
-    },
-    {
-        "ID" : 12,
-        "ParentID" : 1,
-        "name" : "机械土石方",
-        "rate" : 15.5,
-        "memo" : null
-    },
-    {
-        "ID" : 13,
-        "ParentID" : 1,
-        "name" : "仿古建筑工程",
-        "rate" : 12,
-        "memo" : null
-    },
-    {
-        "ID" : 14,
-        "ParentID" : 1,
-        "name" : "建筑修缮工程",
-        "rate" : 12.47,
-        "memo" : null
-    },
-    {
-        "ID" : 15,
-        "ParentID" : 1,
-        "name" : "炉窑砌筑工程",
-        "rate" : null,
-        "memo" : null
-    },
-    {
-        "ID" : 16,
-        "ParentID" : 15,
-        "name" : "一类工程",
-        "rate" : 14.25,
-        "memo" : null
-    },
-    {
-        "ID" : 17,
-        "ParentID" : 15,
-        "name" : "二类工程",
-        "rate" : 12.47,
-        "memo" : null
-    },
-    {
-        "ID" : 18,
-        "ParentID" : 15,
-        "name" : "三类工程",
-        "rate" : 10.8,
-        "memo" : null
-    },
-    {
-        "ID" : 19,
-        "ParentID" : 15,
-        "name" : "四类工程",
-        "rate" : null,
-        "memo" : null
-    },
-    {
-        "ID" : 20,
-        "ParentID" : null,
-        "name" : "规费",
-        "rate" : null,
-        "memo" : null
-    },
-    {
-        "ID" : 21,
-        "ParentID" : 20,
-        "name" : "建筑工程",
-        "rate" : 4.87,
-        "memo" : null
-    },
-    {
-        "ID" : 22,
-        "ParentID" : 20,
-        "name" : "市政工程",
-        "rate" : 3.61,
-        "memo" : null
-    },
-    {
-        "ID" : 23,
-        "ParentID" : 20,
-        "name" : "机械土石方",
-        "rate" : 2.15,
-        "memo" : null
-    },
-    {
-        "ID" : 24,
-        "ParentID" : 20,
-        "name" : "仿古建筑工程",
-        "rate" : 2.84,
-        "memo" : null
-    },
-    {
-        "ID" : 25,
-        "ParentID" : 20,
-        "name" : "建筑修缮工程",
-        "rate" : 2.84,
-        "memo" : null
-    },
-    {
-        "ID" : 26,
-        "ParentID" : 20,
-        "name" : "炉窑砌筑工程",
-        "rate" : 3.61,
-        "memo" : null
-    },
-    {
-        "ID" : 27,
-        "ParentID" : null,
-        "name" : "利润",
-        "rate" : null,
-        "memo" : null
-    },
-    {
-        "ID" : 28,
-        "ParentID" : 27,
-        "name" : "建筑工程",
-        "rate" : null,
-        "memo" : null
-    },
-    {
-        "ID" : 29,
-        "ParentID" : 28,
-        "name" : "一类工程",
-        "rate" : 8.73,
-        "memo" : null
-    },
-    {
-        "ID" : 30,
-        "ParentID" : 28,
-        "name" : "二类工程",
-        "rate" : 6.94,
-        "memo" : null
-    }
-];
-
-let calcTemplate = {
-    calType: 3,
-    calTypeName: "测试用_重庆",
-    compiledSeq: [],
-    calcItems: [
-        {
-            ID: "1",
-            code: "1",
-            name: "基价直接工程费",
-            dispExpr: "F2+F5+F6+F10",
-            expression: "@('2') + @('5') + @('6') + @('10')",
-            compiledExpr: "",
-            statement: "基价人工费+基价材料费+基价机械费+未计价材料费"
-        },
-        {
-            ID: "2",
-            code: "1.1",
-            name: "基价人工费",
-            dispExpr: "F3+F4",
-            expression: "@('3') + @('4')",
-            compiledExpr: "",
-            statement: "定额基价人工费+定额人工单价(基价)调整"
-        },
-        {
-            ID: "3",
-            code: "1.1.1",
-            name: "定额基价人工费",
-            dispExpr: "[定额基价人工费]",
-            expression: "base('定额基价人工费').toFixed(2)",
-            compiledExpr: "",
-            statement: "定额基价人工费"
-        },
-        {
-            ID: "4",
-            code: "1.1.2",
-            name: "[定额人工单价(基价)调整]",
-            dispExpr: "F3*(1.89-1)",
-            expression: "@('3') * (1.89-1)",
-            compiledExpr: "",
-            statement: "定额基价人工费*[定额人工单价(基价)调整系数-1]",
-            memo: "渝建发(2013)51"
-        },
-        {
-            ID: "5",
-            code: "1.2",
-            name: "基价材料费",
-            dispExpr: "[定额基价材料费]",
-            expression: "base('定额基价材料费')",
-            compiledExpr: "",
-            statement: "定额基价材料费"
-        },
-        {
-            ID: "6",
-            code: "1.3",
-            name: "基价机械费",
-            dispExpr: "F7+F9",
-            expression: "@('7') + @('9')",
-            compiledExpr: "",
-            statement: "定额基价机械费+定额机上人工单价(基价)调整"
-        },
-        {
-            ID: "7",
-            code: "1.3.1",
-            name: "定额基价机械费",
-            dispExpr: "[定额基价机械费]",
-            expression: "base('定额基价机械费')",
-            compiledExpr: "",
-            statement: "定额基价机械费"
-        },
-        {
-            ID: "8",
-            code: "1.3.1.1",
-            name: "其中:定额基价机上人工费",
-            dispExpr: "[定额基价机上人工费]",
-            expression: "base('定额基价机上人工费')",
-            compiledExpr: "",
-            statement: "定额基价机上人工费"
-        },
-        {
-            ID: "9",
-            code: "1.3.2",
-            name: "定额机上人工单价(基价)调整",
-            dispExpr: "F8*(1.89-1)",
-            expression: "@('8') * (1.89-1)",
-            compiledExpr: "",
-            statement: "定额基价机上人工费*[定额机上人工单价(基价)调整系数-1]"
-        },
-        {
-            ID: "10",
-            code: "1.4",
-            name: "未计价材料费",
-            dispExpr: "[主材费]+[设备费]",
-            expression: "base('主材费') + base('设备费')",
-            compiledExpr: "",
-            statement: "主材费+设备费"
-        },
-        {
-            ID: "11",
-            code: "2",
-            name: "企业管理费",
-            dispExpr: "F3",
-            expression: "@('3')*8.21 / 100",
-            compiledExpr: "",
-            statement: "定额基价人工费",
-            memo: "渝建发[2014]27号"
-        },
-        {
-            ID: "12",
-            code: "3",
-            name: "利润",
-            dispExpr: "F3",
-            expression: "@('3')*6.5 / 100",
-            compiledExpr: "",
-            statement: "定额基价人工费"
-        },
-        {
-            ID: "13",
-            code: "4",
-            name: "风险因素",
-            dispExpr: "F3",
-            expression: "@('3')*3 / 100",
-            compiledExpr: "",
-            statement: "定额基价人工费",
-            memo: "同定额包干费"
-        },
-        {
-            ID: "14",
-            code: "5",
-            name: "人材机价差",
-            dispExpr: "F15+F16+F17",
-            expression: "@('15') + @('16') + @('17')",
-            compiledExpr: "",
-            statement: "人工费价差+材料费价差+机械费价差"
-        },
-        {
-            ID: "15",
-            code: "5.1",
-            name: "人工费价差",
-            dispExpr: "[市场价格人工费]-[调整后的定额人工费(基价)]",
-            expression: "base('市场价格人工费') - base('定额基价人工费(调整后)')",
-            compiledExpr: "",
-            statement: "市场价格人工费-调整后的定额人工费(基价)"
-        },
-        {
-            ID: "16",
-            code: "5.2",
-            name: "材料费价差",
-            dispExpr: "[市场价格材料费]-[定额基价材料费]",
-            expression: "base('市场价格材料费') - base('定额基价材料费(调整后)')",
-            compiledExpr: "",
-            statement: "市场价格材料费-定额基价材料费"
-        },
-        {
-            ID: "17",
-            code: "5.3",
-            name: "机械费价差",
-            dispExpr: "[市场价格机械费]-[调整后的定额基价机械费(基价)]",
-            expression: "base('市场价格机械费') - base('定额基价机械费(调整后)')",
-            compiledExpr: "",
-            statement: "市场价格机械费-调整后的定额基价机械费(基价)"
-        },
-        {
-            ID: "18",
-            code: "6",
-            name: "综合单价",
-            dispExpr: "F1+F11+F12+F13+F14",
-            expression: "@('1') + @('11') + @('12') + @('13') + @('14')",
-            compiledExpr: "",
-            statement: "基价直接工程费+企业管理费+利润+风险因素+人材机价差"
-        }
-    ]
-};
-
-class RationCalc {
-    constructor(project){
-        this.project = project;
-    };
-
-    calculate(ration){
-        let calc = new calculation();
-        calc.init(calcTemplate, calcFeeRate);
-        calc.compile();
-        ration.data.gljList = projectObj.project.ration_glj.getGljArrByRation(ration.data.ID);
-        calc.calculate(ration);
-    };
-}

+ 568 - 0
web/building_saas/main/js/models/ration_program.js

@@ -0,0 +1,568 @@
+/**
+ * Created by CSL on 2017-07-19.
+ */
+
+// dispExpr: F8*(L-1); expression: "@('8') * (L-1)";
+// 说明:F后跟行号,L替换人工系数值,@后跟ID。用到L的规则必须有labourCoeID属性(反过来不要求),
+// 用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。
+let calcTemplates = [
+    {
+        ID: 1,
+        name: "重庆2015",
+        calcItems: [
+            {
+                ID: "1",
+                code: "1",
+                name: "基价直接工程费",
+                fieldName: "baseDirect",
+                dispExpr: "F2+F5+F6+F10",
+                expression: "@('2') + @('5') + @('6') + @('10')",
+                compiledExpr: "",
+                statement: "基价人工费+基价材料费+基价机械费+未计价材料费"
+            },
+            {
+                ID: "2",
+                code: "1.1",
+                name: "基价人工费",
+                fieldName: "baseLabour",
+                dispExpr: "F3+F4",
+                expression: "@('3') + @('4')",
+                compiledExpr: "",
+                statement: "定额基价人工费+定额人工单价(基价)调整"
+            },
+            {
+                ID: "3",
+                code: "1.1.1",
+                name: "定额基价人工费",
+                fieldName: "rationBaseLabour",
+                dispExpr: "[定额基价人工费]",
+                expression: "base('定额基价人工费').toFixed(2)",
+                compiledExpr: "",
+                statement: "定额基价人工费"
+            },
+            {
+                ID: "4",
+                code: "1.1.2",
+                name: "定额人工单价(基价)调整",
+                fieldName: "rationLabourFixed",
+                dispExpr: "F3*(L-1)",
+                expression: "@('3') * (L-1)",
+                labourCoeID: 2,
+                compiledExpr: "",
+                statement: "定额基价人工费*[定额人工单价(基价)调整系数-1]",
+                memo: "渝建发(2013)51"
+            },
+            {
+                ID: "5",
+                code: "1.2",
+                name: "基价材料费",
+                fieldName: "baseMaterial",
+                dispExpr: "[定额基价材料费]",
+                expression: "base('定额基价材料费')",
+                compiledExpr: "",
+                statement: "定额基价材料费"
+            },
+            {
+                ID: "6",
+                code: "1.3",
+                name: "基价机械费",
+                fieldName: "baseMachine",
+                dispExpr: "F7+F9",
+                expression: "@('7') + @('9')",
+                compiledExpr: "",
+                statement: "定额基价机械费+定额机上人工单价(基价)调整"
+            },
+            {
+                ID: "7",
+                code: "1.3.1",
+                name: "定额基价机械费",
+                fieldName: "rationBaseMachine",
+                dispExpr: "[定额基价机械费]",
+                expression: "base('定额基价机械费')",
+                compiledExpr: "",
+                statement: "定额基价机械费"
+            },
+            {
+                ID: "8",
+                code: "1.3.1.1",
+                name: "其中:定额基价机上人工费",
+                fieldName: "rationBaseMachineLabour",
+                dispExpr: "[定额基价机上人工费]",
+                expression: "base('定额基价机上人工费')",
+                compiledExpr: "",
+                statement: "定额基价机上人工费"
+            },
+            {
+                ID: "9",
+                code: "1.3.2",
+                name: "定额机上人工单价(基价)调整",
+                fieldName: "rationBaseMachineLabourFixed",
+                dispExpr: "F8*(L-1)",
+                expression: "@('8') * (L-1)",
+                labourCoeID: 11,
+                compiledExpr: "",
+                statement: "定额基价机上人工费*[定额机上人工单价(基价)调整系数-1]"
+            },
+            {
+                ID: "10",
+                code: "1.4",
+                name: "未计价材料费",
+                fieldName: "unPriceMaterial",
+                dispExpr: "[主材费]+[设备费]",
+                expression: "base('主材费') + base('设备费')",
+                compiledExpr: "",
+                statement: "主材费+设备费"
+            },
+            {
+                ID: "11",
+                code: "2",
+                name: "企业管理费",
+                fieldName: "manageFee",
+                dispExpr: "F3",
+                feeRateID: 3,
+                expression: "@('3')",
+                compiledExpr: "",
+                statement: "定额基价人工费",
+                memo: "渝建发[2014]27号"
+            },
+            {
+                ID: "12",
+                code: "3",
+                name: "利润",
+                fieldName: "profit",
+                dispExpr: "F3",
+                feeRateID: 4,
+                expression: "@('3')",
+                compiledExpr: "",
+                statement: "定额基价人工费"
+            },
+            {
+                ID: "13",
+                code: "4",
+                name: "风险因素",
+                fieldName: "risk",
+                dispExpr: "F3",
+                feeRateID: 5,
+                expression: "@('3')",
+                compiledExpr: "",
+                statement: "定额基价人工费",
+                memo: "同定额包干费"
+            },
+            {
+                ID: "14",
+                code: "5",
+                name: "人材机价差",
+                fieldName: "lmmDiff",
+                dispExpr: "F15+F16+F17",
+                expression: "@('15') + @('16') + @('17')",
+                compiledExpr: "",
+                statement: "人工费价差+材料费价差+机械费价差"
+            },
+            {
+                ID: "15",
+                code: "5.1",
+                name: "人工费价差",
+                fieldName: "labourDiff",
+                dispExpr: "[人工费价差]",
+                expression: "base('市场价格人工费') - base('定额基价人工费(调整后)')",
+                compiledExpr: "",
+                statement: "市场价格人工费-调整后的定额人工费(基价)"
+            },
+            {
+                ID: "16",
+                code: "5.2",
+                name: "材料费价差",
+                fieldName: "materialDiff",
+                dispExpr: "[材料费价差]",
+                expression: "base('市场价格材料费') - base('定额基价材料费(调整后)')",
+                compiledExpr: "",
+                statement: "市场价格材料费-定额基价材料费"
+            },
+            {
+                ID: "17",
+                code: "5.3",
+                name: "机械费价差",
+                fieldName: "machineDiff",
+                dispExpr: "[机械费价差]",
+                expression: "base('市场价格机械费') - base('定额基价机械费(调整后)')",
+                compiledExpr: "",
+                statement: "市场价格机械费-调整后的定额基价机械费(基价)"
+            },
+            {
+                ID: "18",
+                code: "6",
+                name: "综合单价",
+                fieldName: "common",
+                dispExpr: "F1+F11+F12+F13+F14",
+                expression: "@('1') + @('11') + @('12') + @('13') + @('14')",
+                compiledExpr: "",
+                statement: "基价直接工程费+企业管理费+利润+风险因素+人材机价差"
+            }
+        ]
+    }
+];
+
+let calcFeeRates = [
+    {
+        "ID" : 1,
+        "ParentID" : null,
+        "name" : "企业管理费",
+        "rate" : null,
+        "memo" : null
+    },
+    {
+        "ID" : 2,
+        "ParentID" : 1,
+        "name" : "建筑工程",
+        "rate" : null,
+        "memo" : null
+    },
+    {
+        "ID" : 3,
+        "ParentID" : 2,
+        "name" : "一类工程",
+        "rate" : 16.03,
+        "memo" : null
+    },
+    {
+        "ID" : 4,
+        "ParentID" : 2,
+        "name" : "二类工程",
+        "rate" : 14.95,
+        "memo" : null
+    },
+    {
+        "ID" : 5,
+        "ParentID" : 2,
+        "name" : "三类工程",
+        "rate" : 12.47,
+        "memo" : null
+    },
+    {
+        "ID" : 6,
+        "ParentID" : 2,
+        "name" : "四类工程",
+        "rate" : 9.3,
+        "memo" : null
+    },
+    {
+        "ID" : 7,
+        "ParentID" : 1,
+        "name" : "市政工程",
+        "rate" : null,
+        "memo" : null
+    },
+    {
+        "ID" : 8,
+        "ParentID" : 7,
+        "name" : "一类工程",
+        "rate" : 16.33,
+        "memo" : null
+    },
+    {
+        "ID" : 9,
+        "ParentID" : 7,
+        "name" : "二类工程",
+        "rate" : 15,
+        "memo" : null
+    },
+    {
+        "ID" : 10,
+        "ParentID" : 7,
+        "name" : "三类工程",
+        "rate" : 12.5,
+        "memo" : null
+    },
+    {
+        "ID" : 11,
+        "ParentID" : 7,
+        "name" : "四类工程",
+        "rate" : 9.5,
+        "memo" : null
+    },
+    {
+        "ID" : 12,
+        "ParentID" : 1,
+        "name" : "机械土石方",
+        "rate" : 15.5,
+        "memo" : null
+    },
+    {
+        "ID" : 13,
+        "ParentID" : 1,
+        "name" : "仿古建筑工程",
+        "rate" : 12,
+        "memo" : null
+    },
+    {
+        "ID" : 14,
+        "ParentID" : 1,
+        "name" : "建筑修缮工程",
+        "rate" : 12.47,
+        "memo" : null
+    },
+    {
+        "ID" : 15,
+        "ParentID" : 1,
+        "name" : "炉窑砌筑工程",
+        "rate" : null,
+        "memo" : null
+    },
+    {
+        "ID" : 16,
+        "ParentID" : 15,
+        "name" : "一类工程",
+        "rate" : 14.25,
+        "memo" : null
+    },
+    {
+        "ID" : 17,
+        "ParentID" : 15,
+        "name" : "二类工程",
+        "rate" : 12.47,
+        "memo" : null
+    },
+    {
+        "ID" : 18,
+        "ParentID" : 15,
+        "name" : "三类工程",
+        "rate" : 10.8,
+        "memo" : null
+    },
+    {
+        "ID" : 19,
+        "ParentID" : 15,
+        "name" : "四类工程",
+        "rate" : null,
+        "memo" : null
+    },
+    {
+        "ID" : 20,
+        "ParentID" : null,
+        "name" : "规费",
+        "rate" : null,
+        "memo" : null
+    },
+    {
+        "ID" : 21,
+        "ParentID" : 20,
+        "name" : "建筑工程",
+        "rate" : 4.87,
+        "memo" : null
+    },
+    {
+        "ID" : 22,
+        "ParentID" : 20,
+        "name" : "市政工程",
+        "rate" : 3.61,
+        "memo" : null
+    },
+    {
+        "ID" : 23,
+        "ParentID" : 20,
+        "name" : "机械土石方",
+        "rate" : 2.15,
+        "memo" : null
+    },
+    {
+        "ID" : 24,
+        "ParentID" : 20,
+        "name" : "仿古建筑工程",
+        "rate" : 2.84,
+        "memo" : null
+    },
+    {
+        "ID" : 25,
+        "ParentID" : 20,
+        "name" : "建筑修缮工程",
+        "rate" : 2.84,
+        "memo" : null
+    },
+    {
+        "ID" : 26,
+        "ParentID" : 20,
+        "name" : "炉窑砌筑工程",
+        "rate" : 3.61,
+        "memo" : null
+    },
+    {
+        "ID" : 27,
+        "ParentID" : null,
+        "name" : "利润",
+        "rate" : null,
+        "memo" : null
+    },
+    {
+        "ID" : 28,
+        "ParentID" : 27,
+        "name" : "建筑工程",
+        "rate" : null,
+        "memo" : null
+    },
+    {
+        "ID" : 29,
+        "ParentID" : 28,
+        "name" : "一类工程",
+        "rate" : 8.73,
+        "memo" : null
+    },
+    {
+        "ID" : 30,
+        "ParentID" : 28,
+        "name" : "二类工程",
+        "rate" : 6.94,
+        "memo" : null
+    }
+];
+
+let calcLabourCoes = [
+    {
+        "ID" : 1,
+        "ParentID" : null,
+        "name" : "2006概算定额",
+        "coe" : null
+    },
+    {
+        "ID" : 2,
+        "ParentID" : 1,
+        "name" : "土石方人工",
+        "coe" : 2.94
+    },
+    {
+        "ID" : 3,
+        "ParentID" : 1,
+        "name" : "建筑、市政、维修人工",
+        "coe" : 2.84
+    },
+    {
+        "ID" : 4,
+        "ParentID" : 1,
+        "name" : "装饰人工",
+        "coe" : 1
+    },
+    {
+        "ID" : 5,
+        "ParentID" : 1,
+        "name" : "安装、机械人工",
+        "coe" :2.58
+    },
+    {
+        "ID" : 6,
+        "ParentID" : 1,
+        "name" : "仿古、园林绿化人工",
+        "coe" :1
+    },
+    {
+        "ID" : 7,
+        "ParentID" : 1,
+        "name" : "盾构用工",
+        "coe" :1
+    },
+    {
+        "ID" : 8,
+        "ParentID" : null,
+        "name" : "2008计价定额",
+        "coe" :null
+    },
+    {
+        "ID" : 9,
+        "ParentID" : 8,
+        "name" : "土石方人工",
+        "coe" : 2.41
+    },
+    {
+        "ID" : 10,
+        "ParentID" : 8,
+        "name" : "建筑、市政、维修人工",
+        "coe" : 2.48
+    },
+    {
+        "ID" : 11,
+        "ParentID" : 8,
+        "name" : "装饰人工",
+        "coe" : 3.04
+    },
+    {
+        "ID" : 12,
+        "ParentID" : 8,
+        "name" : "安装、机械人工",
+        "coe" :2.39
+    },
+    {
+        "ID" : 13,
+        "ParentID" : 8,
+        "name" : "仿古、园林绿化人工",
+        "coe" :2.39
+    },
+    {
+        "ID" : 14,
+        "ParentID" : 8,
+        "name" : "盾构用工",
+        "coe" :1
+    },
+    {
+        "ID" : 15,
+        "ParentID" : null,
+        "name" : "2011轨道定额",
+        "coe" :null
+    },
+    {
+        "ID" : 16,
+        "ParentID" : 15,
+        "name" : "土石方人工",
+        "coe" : 1.51
+    },
+    {
+        "ID" : 17,
+        "ParentID" : 15,
+        "name" : "建筑、市政、维修人工",
+        "coe" : 1.55
+    },
+    {
+        "ID" : 18,
+        "ParentID" : 15,
+        "name" : "装饰人工",
+        "coe" : 1
+    },
+    {
+        "ID" : 19,
+        "ParentID" : 15,
+        "name" : "安装、机械人工",
+        "coe" :1.49
+    },
+    {
+        "ID" : 20,
+        "ParentID" : 15,
+        "name" : "仿古、园林绿化人工",
+        "coe" :1
+    },
+    {
+        "ID" : 21,
+        "ParentID" : 15,
+        "name" : "盾构用工",
+        "coe" :1.49
+    }
+];
+
+class RationProgram {
+    constructor(project){
+        this.project = project;
+        this.calc = new Calculation();
+    };
+
+    compileAllTemps(){
+       for (let calcTemplate of calcTemplates){
+           this.calc.compile(calcTemplate, calcFeeRates, calcLabourCoes);
+       };
+    };
+
+    compile(calcTemplate){
+       this.calc.compile(calcTemplate, calcFeeRates, calcLabourCoes);
+    };
+
+    calculate(ration){
+        ration.data.gljList = this.project.ration_glj.getGljArrByRation(ration.data.ID);
+        ration.data.calcTemplate = calcTemplates[0];  // AAAAAA = getCalcTemplate($RATION.calcTemplateID);
+        this.calc.calculate(ration);
+    };
+}

+ 30 - 0
web/building_saas/main/js/models/volume_price.js

@@ -35,7 +35,12 @@ var VolumePrice = {
 
             loadData (datas) {
                 this.datas = datas;
+                // generate Fees & Flags Index,For View & Calculate
                 for (let data of datas) {
+                    data.feesIndex = {};
+                    data.fees.forEach(function (fee) {
+                        data.feesIndex[fee.fieldName] = fee;
+                    });
                     this.maxID(data.ID);
                 }
             };
@@ -135,6 +140,31 @@ var VolumePrice = {
                     }
                 }
             };
+
+            calculate (volumePrice) {
+                if (!calcFees.findFee(volumePrice, 'common')) {
+                    calcFees.addFee(volumePrice, 'common');
+                }
+                volumePrice.feesIndex.common.totalFee = (volumePrice.feesIndex.common.unitFee * volumePrice.quantity).toDecimal(tools.owner.Decimal.common.totalFee);
+                volumePrice.needRefresh = true;
+            }
+            updateField(volumePrice, field, newValue) {
+                calcFees.setFee(volumePrice, field, newValue);
+                let updateData = [];
+                let data = {'ID': volumePrice.ID, 'projectID': this.getProject().ID()};
+                if (field === 'quantity') {
+                    data[field] = newValue;
+                    this.calculate(volumePrice);
+                    data.fees = volumePrice.fees;
+                } else if (field === 'feesIndex.common.unitFee') {
+                    this.calculate(volumePrice);
+                    data.fees = volumePrice.fees;
+                } else {
+                    data[field] = newValue;
+                }
+                updateData.push({'updateType': 'ut_update', 'updateData': data});
+                tools.owner.pushNow('updateVolumePrice', this.getSourceType(), updateData);
+            }
         }
 
         return new volumePrice();

+ 210 - 0
web/building_saas/main/js/views/calc_program_view.js

@@ -0,0 +1,210 @@
+/**
+ * Created by Mai on 2017/7/28.
+ */
+
+let calcProgramSetting ={
+    "emptyRows":0,
+    "headRows":1,
+    "headRowHeight":[
+        35
+    ],
+    "cols":[
+        {
+            "width":75,
+            "readOnly": true,
+            "head":{
+                "titleNames":["序号"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"serialNo",
+                "vAlign":1,
+                "hAlign":1,
+                "font":"Arial"
+            }
+        },
+        {
+            "width":75,
+            "readOnly": false,
+            "head":{
+                "titleNames":["费用代号"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"code",
+                "vAlign":1,
+                "hAlign":0,
+                "font":"Arial"
+            }
+        },
+        {
+            "width":200,
+            "readOnly":false,
+            "head":{
+                "titleNames":["名称"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"name",
+                "vAlign":1,
+                "hAlign":0,
+                "font":"Arial"
+            }
+        },
+        {
+            "width":280,
+            "readOnly":false,
+            "head":{
+                "titleNames":["计算基数"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"dispExpr",
+                "vAlign":1,
+                "hAlign":0,
+                "font":"Arial"
+            }
+        },
+        {
+            "width":220,
+            "readOnly":false,
+            "head":{
+                "titleNames":["基数说明"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"statement",
+                "vAlign":1,
+                "hAlign":0,
+                "font":"Arial"
+            }
+        },
+        {
+            "width":80,
+            "readOnly": false,
+            "head":{
+                "titleNames":["费率"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"feeRate",
+                "vAlign":1,
+                "hAlign":2,
+                "font":"Arial"
+            }
+        },
+        {
+            "width": 100,
+            "readOnly":true,
+            "head":{
+                "titleNames":["单价"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"unitFee",
+                "vAlign":1,
+                "hAlign":2,
+                "font":"Arial"
+            }
+        },
+        {
+            "width":100,
+            "readOnly":true,
+            "head":{
+                "titleNames":["合价"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"totalFee",
+                "vAlign":1,
+                "hAlign":2,
+                "font":"Arial"
+            }
+        },
+        {
+            "width":80,
+            "readOnly": true,
+            "head":{
+                "titleNames":["费用类别"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"type",
+                "vAlign":1,
+                "hAlign":0,
+                "font":"Arial",
+                "getText": function (record) {
+                    if (record.type) {
+                        for (let ft of feeType) {
+                            if (ft.type === record.type) {
+                                return ft.name;
+                            }
+                        }
+                    }
+                    return '';
+                }
+            }
+        },
+        {
+            "width":120,
+            "readOnly":false,
+            "head":{
+                "titleNames":["备注"],
+                "spanCols":[1],
+                "spanRows":[1],
+                "vAlign":[1],
+                "hAlign":[1],
+                "font":["Arial"]
+            },
+            "data":{
+                "field":"memo",
+                "vAlign":1,
+                "hAlign":0,
+                "font":"Arial"
+            }
+        }
+    ]
+};
+
+let calcProgramObj = {
+    showBillsCalcProgram: function (node, calcProgram, sheet) {
+        SheetDataHelper.loadSheetHeader(calcProgramSetting, sheet);
+        SheetDataHelper.loadSheetData(calcProgramSetting, sheet, calcProgram);
+    }
+};

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

@@ -17,8 +17,30 @@ let MainTreeCol = {
         }
     },
     readOnly: {
+        bills: function (node) {
+            return node.sourceType === projectObj.project.Bills.getSourceType();
+        },
+        ration: function (node) {
+            return node.sourceType === projectObj.project.Ration.getSourceType();
+        },
         volumePrice: function (node) {
             return node.sourceType === projectObj.project.VolumePrice.getSourceType();
+        },
+        non_bills: function (node) {
+            return node.sourceType !== projectObj.project.Bills.getSourceType();
+        },
+        non_ration: function (node) {
+            return node.sourceType !== projectObj.project.Ration.getSourceType();
+        },
+        non_volumePrice: function (node) {
+            return node.sourceType !== projectObj.project.Ration.getSourceType();
+        },
+        billsParent: function (node) {
+            return node.sourceType === projectObj.project.Bills.getSourceType() && node.source.children.length > 0;
+        },
+        forCalcBase: function (node) {
+            // to do according to billsParentType
+            return MainTreeCol.readOnly.billsParent && MainTreeCol.readOnly.non_bills;
         }
     },
     getEvent: function (eventName) {
@@ -36,5 +58,23 @@ let MainTreeCol = {
         } else {
             return event;
         }
+    },
+    getNumberFormatter: function (digit) {
+        switch (digit) {
+            case 1:
+                return '0.#';
+            case 2:
+                return '0.##';
+            case 3:
+                return '0.###';
+            case 4:
+                return '0.####';
+            case 5:
+                return '0.#####';
+            case 6:
+                return '0.######';
+            default:
+                return '0.##';
+        }
     }
 }

+ 70 - 1
web/building_saas/main/js/views/project_view.js

@@ -7,6 +7,67 @@ var projectObj = {
     mainSpread: null,
     mainController: null,
     gljSpreed:null,
+    checkCommonField: function (editingText, colSetting) {
+        let value;
+        if (colSetting.data.decimal) {
+            value = Number(editingText);
+            if (number_util.isNumber(value)) {
+                value = value.toDecimal(colSetting.data.decimal);
+            } else {
+                value = null;
+                alert('当前输入的数据类型不正确,请重新输入。');
+            }
+        } else {
+            value = editingText;
+        }
+        return value;
+    },
+    checkQuantityField: function (editingText, colSetting) {
+        let value = Number(editingText);
+        if (!value) {
+            try {
+                let exp = new Expression('');
+                exp.Expression(editingText);
+                value = Number(exp.Evaluate());
+            } catch (error) {
+                value = null;
+            }
+        }
+        if (value) {
+            value = value.toDecimal(colSetting.data.decimal);
+        } else {
+            value = null;
+            alert('当前输入的数据类型不正确,请重新输入。');
+        }
+        return value;
+    },
+    checkSpreadEditingText: function (editingText, colSetting) {
+        if (colSetting.data.field === 'quantity') {
+            return this.checkQuantityField(editingText, colSetting);
+        } else {
+            return this.checkCommonField(editingText, colSetting);
+        }
+    },
+    mainSpreadEditEnded: function (sender, info) {
+        let project = projectObj.project;
+        let node = project.mainTree.items[info.row];
+        let colSetting = projectObj.mainController.setting.cols[info.col];
+        let fieldName = projectObj.mainController.setting.cols[info.col].data.field;
+        let value = projectObj.checkSpreadEditingText(info.editingText, colSetting);
+        if (colSetting.data.wordWrap) {
+            info.sheet.autoFitRow(info.row);
+        }
+        if (value && value != calcFees.getFee(node.data, fieldName)) {
+            if (node.sourceType === project.Bills.getSourceType()) {
+                project.Bills.updateField(node.source, fieldName, value);
+            } else if (node.sourceType === project.Ration.getSourceType()) {
+                project.Ration.updateField(node.source, fieldName, value);
+            } else if (node.sourceType === project.VolumePrice.getSourceType()) {
+                project.VolumePrice.updateField(node.source, fieldName, value);
+            }
+        }
+        projectObj.mainController.refreshTreeNode([node]);
+    },
     checkMainSpread: function () {
         if (!this.mainSpread) {
             this.mainSpread = SheetDataHelper.createNewSpread($('#billsSpread')[0]);
@@ -31,6 +92,10 @@ var projectObj = {
                     if (col.readOnly && Object.prototype.toString.apply(col.readOnly) === "[object String]") {
                         col.readOnly = MainTreeCol.getEvent(col.readOnly);
                     }
+                    if (col.data.digit && Object.prototype.toString.apply(col.data.digit) === "[object String]") {
+                        col.data.decimal = that.project.getDecimal(col.data.digit);
+                        col.data.formatter = MainTreeCol.getNumberFormatter(col.data.decimal);
+                    }
                 });
                 that.mainController = TREE_SHEET_CONTROLLER.createNew(that.project.mainTree, that.mainSpread.getActiveSheet(), BillsGridSetting);
                 that.mainController.showTreeData();
@@ -84,7 +149,7 @@ var projectObj = {
                     // CSL.2017.07.25
                     if (SubActiveSheetNameIs('JSCX')) {
                         if (node.sourceType === that.project.Bills.getSourceType()) {
-                            rationCalcView.clearData();
+                            calcProgramObj.showBillsCalcProgram(node.source, baseCalcField, rationCalcView.sheet);
                         } else if (node.sourceType==='ration') {
                             rationCalcView.showData(node);
                         } else {
@@ -93,12 +158,16 @@ var projectObj = {
                     }
                 });
 
+                that.mainSpread.bind(GC.Spread.Sheets.Events.EditEnded, that.mainSpreadEditEnded);
+
                 that.loadMainSpreadContextMenu();
             }
             else {
 
             }
         });
+        this.rationProgram = new RationProgram(this.project);
+        this.rationProgram.compileAllTemps();
     },
     loadMainSpreadContextMenu: function () {
         var project = this.project, spread = this.mainSpread, controller = this.mainController;

+ 7 - 67
web/building_saas/main/js/views/ration_calc_view.js

@@ -1,63 +1,6 @@
 /**
  * Created by CSL on 2017-07-17.
  */
-//for test AAAAAAAAAAAAA
-let calcRation = {
-    "sectionId" : 76,
-    "ID" : 15,
-    "code" : "AA0001",
-    "name" : "人工挖土方",
-    "unit" : "100m3",
-    "basePrice" : 840.84,
-    "caption" : "人工挖土方",
-    "feeType" : 2,
-    "rationGljList" : [
-        {
-            "glj" : {
-                "repositoryId" : 3,
-                "ID" : 17,
-                "code" : "00010201",
-                "name" : "土石方综合工日",
-                "specs" : null,
-                "unit" : "工日",
-                "basePrice" : 22,
-                "gljDistType" : "人工",
-                "gljType" : 2
-            },
-            "consumeAmt" : 38.22,
-            "proportion" : 0
-        },{
-            "glj": {
-                "repositoryId" : 3,
-                "ID" : 68,
-                "code" : "85030207",
-                "name" : "履带式起重机",
-                "specs" : "50t",
-                "unit" : "台班",
-                "basePrice" : 1194.05,
-                "gljDistType" : "机械",
-                "gljType" : 64
-            },
-            "consumeAmt" : 1.22,
-            "proportion" : 0
-        },{
-            "glj": {
-                "repositoryId" : 3,
-                "ID" : 200,
-                "code" : "36290101",
-                "name" : "水",
-                "specs" : "",
-                "unit" : "m3",
-                "basePrice" : 2,
-                "gljDistType" : "材料",
-                "gljType" : 6
-            },
-            "consumeAmt" : 9.2,
-            "proportion" : 0
-        }
-    ],
-    "rationRepId" : 3
-};
 
 let rationCalcView = {
     sheet: null,
@@ -67,8 +10,8 @@ let rationCalcView = {
         header: [
             {headerName: "费用代号", headerWidth: 75, dataCode: "code", dataType: "String", hAlign: "left"},
             {headerName: "费用名称", headerWidth: 200, dataCode: "name", dataType: "String"},
-            {headerName: "计算基数", headerWidth: 280, dataCode: "dispExpr", dataType: "String"},
-            {headerName: "基数说明", headerWidth: 220, dataCode: "statement", 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"},
@@ -76,24 +19,21 @@ let rationCalcView = {
         ],
         view: {
             comboBox: [],
-            lockColumns: [0, 1, 2, 3, 5, 6, 7]
+            lockColumns: [0, 1, 2, 3, 4, 5, 6, 7]
         }
     },
 
     initSheet: function (sheet) {
         var me = this;
         me.sheet = sheet;
-        sheetCommonObj.initSheet(me.sheet, me.setting, 20);     // AAAAAAAA
+        sheetCommonObj.initSheet(me.sheet, me.setting, 20);
     },
 
     showData: function (ration) {
         var me = this;
-        me.ration = ration;  // AAAAAAA
-        //me.ration = calcRation;
-        let rationCalc = new RationCalc(projectObj.project);
-        rationCalc.calculate(me.ration);
-
-        me.datas = calcTemplate.calcItems;   // AAAAAAAAA
+        me.ration = ration;
+        projectObj.rationProgram.calculate(me.ration);
+        me.datas = me.ration.data.calcTemplate.calcItems;
         sheetCommonObj.showData(me.sheet, me.setting, me.datas);
     },
 

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

@@ -60,12 +60,14 @@ $("#linkJSCX").click(function(){        // 计算程序
     subSpread.setActiveSheetIndex(4);
     rationCalcView.initSheet(subSpread.getSheet(4));
     let sel = projectObj.mainController.tree.selected;
-    if (sel != null && sel.sourceType == 'ration'){
+
+    if (sel.sourceType === projectObj.project.Bills.getSourceType()) {
+        calcProgramObj.showBillsCalcProgram(sel.source, baseCalcField, rationCalcView.sheet);
+    } else if (sel.sourceType==='ration') {
         rationCalcView.showData(sel);
-    }
-    else{
+    } else {
         rationCalcView.clearData();
-    };
+    }
 });
 
 $("#linkFXSM").click(function(){

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

@@ -61,7 +61,7 @@
                         </div>
                     </div>
                     <div class="form-group">
-                        <input type="hidden" name="area" value="<%= area %>"/>
+                        <input type="hidden" name="version" value="<%= version %>"/>
                         <button class="btn btn-primary btn-block" type="submit">下一步</button>
                     </div>
                 </div>

+ 15 - 15
web/users/html/login.html

@@ -48,21 +48,21 @@
                     <p class="m-0 text-warning"><i class="fa fa-exclamation-triangle"></i> <b>偏好设置</b> 中可以修改您的登录习惯。</p>
                 </div>
                 <div class="modal-body">
-                    <div class="row">
-                        <div class="col-sm-6">
-                            <div class="card card-block">
-                                <h3 class="card-title">重庆版免费版</h3>
-                                <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
-                                <a class="btn btn-primary" href="/boot/1">开始使用</a>
-                            </div>
-                        </div>
-                        <div class="col-sm-6">
-                            <div class="card card-block">
-                                <h3 class="card-title">广东版免费版</h3>
-                                <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
-                                <a class="btn btn-primary" href="/boot/2">开始使用</a>
-                            </div>
-                        </div>
+                    <div class="row" id="version-area">
+                        <!--<div class="col-sm-6">-->
+                            <!--<div class="card card-block">-->
+                                <!--<h3 class="card-title">重庆版免费版</h3>-->
+                                <!--<p class="card-text">With supporting text below as a natural lead-in to additional content.</p>-->
+                                <!--<a class="btn btn-primary" href="/boot/1">开始使用</a>-->
+                            <!--</div>-->
+                        <!--</div>-->
+                        <!--<div class="col-sm-6">-->
+                            <!--<div class="card card-block">-->
+                                <!--<h3 class="card-title">广东版免费版</h3>-->
+                                <!--<p class="card-text">With supporting text below as a natural lead-in to additional content.</p>-->
+                                <!--<a class="btn btn-primary" href="/boot/2">开始使用</a>-->
+                            <!--</div>-->
+                        <!--</div>-->
                     </div>
                 </div>
             </div>

+ 6 - 2
web/users/html/user-set.html

@@ -60,8 +60,12 @@
                             <div class="form-group">
                                 <label class="form-control-label">指定版本</label>
                                 <select class="form-control" name="select_version">
-                                  <option value="1" <% if(preferenceSetting.select_version === 1) { %>selected="selected" <% } %>>广东版(专业版)</option>
-                                  <option value="2" <% if(preferenceSetting.select_version === 2) { %>selected="selected" <% } %>>重庆版(免费版)</option>
+                                    <option value="">请选择版本</option>
+                                    <% if (versionList.length > 0) {%>
+                                    <% versionList.forEach(function(version) { %>
+                                    <option value="<%= version._id %>" <% if(preferenceSetting.select_version === version._id.toString()) { %>selected="selected" <% } %>><%= version.name %></option>
+                                    <% }) %>
+                                    <% } %>
                                 </select>
                             </div>
                             <div class="form-group mt-3">

+ 28 - 5
web/users/js/login.js

@@ -24,13 +24,15 @@ $(document).ready(function () {
                     if (response.login_ask === 0) {
                         location.href = '/pm';
                     } else {
+                        response.version_list = response.version_list === undefined || response.version_list === '' ?
+                            null : JSON.parse(response.version_list);
+                        if (response.version_list === null || response.version_list.length <= 0) {
+                            location.href = '/pm';
+                            return false;
+                        }
+                        setVersion(response.version_list);
                         $('#ver').modal('show');
                     }
-                    // if (referer) {
-                    //     location.href = referer;
-                    // } else {
-                    //     location.href = '/';
-                    // }
                 } else {
                     let msg = response.msg !== undefined ? response.msg : '未知错误';
                     showError(msg, $("input"));
@@ -98,4 +100,25 @@ function cleanError() {
     $("input").parent().removeClass('has-danger');
     $("#message").text('');
     $("#error-tips").hide("fast");
+}
+
+/**
+ * 设置版本信息
+ *
+ * @param {Object} versionData
+ * @return {void}
+ */
+function setVersion(versionData) {
+    let html = '';
+    for (let version of versionData) {
+        let tmpHtml = '<div class="col-sm-6">' +
+            '<div class="card card-block">' +
+            '<h3 class="card-title">'+ version.name +'</h3>' +
+            '<p class="card-text">With supporting text below as a natural lead-in to additional content.</p>' +
+            '<a class="btn btn-primary" href="/boot/'+ version._id.toString() +'">开始使用</a>' +
+            '</div>' +
+            '</div>';
+        html += tmpHtml;
+    }
+    $("#version-area").html(html);
 }