فهرست منبع

覆盖主分支

zhangweicheng 5 سال پیش
والد
کامیت
5c73988358
100فایلهای تغییر یافته به همراه3176 افزوده شده و 538 حذف شده
  1. 1 0
      .gitignore
  2. 10 5
      Dockerfile
  3. 25 4
      config/config.js
  4. 2 2
      config/db/db_manager.js
  5. 8 3
      config/menu.js
  6. BIN
      lib/ztree/css/img/diy/10.png
  7. 0 0
      logs/logs.txt
  8. 25 0
      modules/all_models/basic_info_lib.js
  9. 35 0
      modules/all_models/block_lib_model.js
  10. 2 0
      modules/all_models/compilation.js
  11. 1 1
      modules/all_models/compleGlj_glj.js
  12. 23 0
      modules/all_models/compleGlj_section.js
  13. 30 0
      modules/all_models/compleGlj_sectionTemplate.js
  14. 1 1
      modules/all_models/compleRation_ration.js
  15. 31 0
      modules/all_models/compleRation_section.js
  16. 5 5
      modules/all_models/comple_section_template.js
  17. 74 0
      modules/all_models/config_material_list.js
  18. 1 1
      modules/all_models/counter.js
  19. 36 1
      modules/all_models/engineering_lib.js
  20. 32 0
      modules/all_models/log.js
  21. 5 0
      modules/all_models/manager.js
  22. 17 0
      modules/all_models/online_logs.js
  23. 16 0
      modules/all_models/options.js
  24. 49 0
      modules/all_models/permission.js
  25. 26 0
      modules/all_models/permission_group.js
  26. 31 0
      modules/all_models/product.js
  27. 2 0
      modules/all_models/project_feature_lib.js
  28. 26 0
      modules/all_models/ration_template.js
  29. 30 0
      modules/all_models/setting.js
  30. 26 0
      modules/all_models/share_list.js
  31. 7 0
      modules/all_models/stdBills_bills.js
  32. 5 0
      modules/all_models/stdGlj_glj.js
  33. 5 0
      modules/all_models/stdRation_coe.js
  34. 1 0
      modules/all_models/stdRation_lib.js
  35. 9 1
      modules/all_models/stdRation_ration.js
  36. 25 0
      modules/all_models/std_economic_lib.js
  37. 25 0
      modules/all_models/std_engineer_feature_lib.js
  38. 25 0
      modules/all_models/std_engineer_info_lib.js
  39. 25 0
      modules/all_models/std_main_quantity_lib.js
  40. 25 0
      modules/all_models/std_material_lib.js
  41. 25 0
      modules/all_models/std_over_height_lib.js
  42. 25 0
      modules/all_models/system_setting.js
  43. 11 10
      modules/all_models/tpl_tree_node.js
  44. 39 0
      modules/all_models/user_message.js
  45. 101 0
      modules/basic_info_lib/controllers/basic_info_controller.js
  46. 38 0
      modules/basic_info_lib/facade/basic_info_facade.js
  47. 21 0
      modules/basic_info_lib/routes/project_feature_router.js
  48. 15 1
      modules/bills_lib/controllers/bills_lib_controllers.js
  49. 52 1
      modules/bills_lib/controllers/bills_permissionController.js
  50. 3 0
      modules/bills_lib/controllers/stdBillsLib_permissionController.js
  51. 298 2
      modules/bills_lib/models/bills_lib_interfaces.js
  52. 3 0
      modules/bills_lib/routes/bills_lib_routes.js
  53. 27 1
      modules/bills_template_lib/controllers/bills_template_controller.js
  54. 21 1
      modules/bills_template_lib/facade/bills_template_facade.js
  55. 1 0
      modules/bills_template_lib/routes/bills_template_routes.js
  56. 15 1
      modules/calc_program_lib/controllers/calc_program_controller.js
  57. 38 18
      modules/common/base/base_controller.js
  58. 42 2
      modules/common/const/bills_fixed.js
  59. 102 0
      modules/economic_lib/controllers/economic_controller.js
  60. 41 0
      modules/economic_lib/facade/economic_facade.js
  61. 21 0
      modules/economic_lib/routes/economic_routes.js
  62. 102 0
      modules/engineer_feature_lib/controllers/engineer_feature_controller.js
  63. 41 0
      modules/engineer_feature_lib/facade/engineer_feature_facade.js
  64. 21 0
      modules/engineer_feature_lib/routes/engineer_feature_routes.js
  65. 102 0
      modules/engineer_info_lib/controllers/engineer_info_controller.js
  66. 42 0
      modules/engineer_info_lib/facade/engineer_info_facade.js
  67. 21 0
      modules/engineer_info_lib/routes/engineer_info_routes.js
  68. 15 1
      modules/fee_rate_lib/controllers/fee_rate_controller.js
  69. 2 0
      modules/main_col_lib/controllers/main_col_controller.js
  70. 102 0
      modules/main_quantity_lib/controllers/quantity_controller.js
  71. 41 0
      modules/main_quantity_lib/facade/quantity_facade.js
  72. 21 0
      modules/main_quantity_lib/routes/quantity_routes.js
  73. 102 0
      modules/material_lib/controllers/material_controller.js
  74. 41 0
      modules/material_lib/facade/material_facade.js
  75. 21 0
      modules/material_lib/routes/material_routes.js
  76. 4 0
      modules/material_replace_lib/controllers/material_replace_controller.js
  77. 4 0
      modules/material_replace_lib/facade/material_replace_facade.js
  78. 102 0
      modules/over_height_lib/controllers/over_height_controller.js
  79. 41 0
      modules/over_height_lib/facade/over_height_facade.js
  80. 21 0
      modules/over_height_lib/routes/over_height_routes.js
  81. 44 1
      modules/project_feature_lib/controllers/project_feature_controller.js
  82. 17 8
      modules/project_feature_lib/facade/project_feature_facade.js
  83. 9 0
      modules/ration_repository/controllers/coe_controller.js
  84. 20 74
      modules/ration_repository/controllers/ration_controller.js
  85. 48 71
      modules/ration_repository/controllers/ration_repository_controller.js
  86. 19 39
      modules/ration_repository/controllers/ration_section_tree_controller.js
  87. 42 17
      modules/ration_repository/controllers/repository_views_controller.js
  88. 9 9
      modules/ration_repository/controllers/search_controller.js
  89. 5 0
      modules/ration_repository/models/coe.js
  90. 3 2
      modules/ration_repository/models/glj_repository.js
  91. 32 3
      modules/ration_repository/models/installation.js
  92. 318 238
      modules/ration_repository/models/ration_item.js
  93. 43 0
      modules/ration_repository/models/ration_section_tree.js
  94. 6 2
      modules/ration_repository/models/repository_map.js
  95. 7 1
      modules/ration_repository/routes/ration_rep_routes.js
  96. 2 2
      modules/reports/rpt_component/helper/jpc_helper_common.js
  97. 5 1
      modules/reports/rpt_component/helper/jpc_helper_common_output.js
  98. 39 7
      modules/reports/rpt_component/helper/jpc_helper_cross_tab.js
  99. 1 1
      modules/reports/rpt_component/helper/jpc_helper_discrete.js
  100. 0 0
      modules/reports/rpt_component/helper/jpc_helper_field.js

+ 1 - 0
.gitignore

@@ -2,6 +2,7 @@ node_modules/
 .git/
 dist/
 .idea/
+.vscode/
 tmp/
 modules/reports/util/pdf_base_files/*.ttf
 modules/reports/util/pdf_base_files/*.ttc

+ 10 - 5
Dockerfile

@@ -1,14 +1,19 @@
-FROM operationbase:2.0
+FROM operationbase:2.0 as build
 
 WORKDIR /ConstructionOperation
 
-COPY . /ConstructionOperation
+COPY package.json /ConstructionOperation
+
+RUN mkdir tmp \
+    && cnpm install
 
-RUN mkdir tmp
+FROM base-alpine:latest
 
-RUN cnpm install
+COPY --from=build /ConstructionOperation /ConstructionOperation
 
-EXPOSE 6080
+COPY . /ConstructionOperation
+
+WORKDIR /ConstructionOperation
 
 ENV NODE_ENV=prod
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 25 - 4
config/config.js


+ 2 - 2
config/db/db_manager.js

@@ -50,11 +50,11 @@ module.exports = {
         var config = require("../config.js");
         var dbURL = 'mongodb://' + config[env].server + ":" + config[env].port + '/scConstruct';
         if(config[env].dbURL){
-            mg.connect(config[env].dbURL,{connectTimeoutMS: 20000,useMongoClient: true});
+            mg.connect(config[env].dbURL,{connectTimeoutMS: 100000,useMongoClient: true});
         } else if(config[env].options){
             mg.connect(dbURL,config[env].options);
         }else {
-            mg.connect(dbURL,{connectTimeoutMS: 20000,useMongoClient: true});//useMongoClient': true*! //报 DeprecationWarning: `open()` is deprecated in mongoose这个错
+            mg.connect(dbURL,{connectTimeoutMS:100000,useMongoClient: true});//useMongoClient': true*! //报 DeprecationWarning: `open()` is deprecated in mongoose这个错
         }
         var db = mg.connection;
         db.on("error",function (err) {

+ 8 - 3
config/menu.js

@@ -22,12 +22,12 @@ let menuData = {
                 title: '普通用户',
                 url: '/user',
                 name: 'index',
-            }/*,
-            'test-user' : {
+            },
+            'testUser' : {
                 title: '测试用户',
                 url: '/user/test-user',
                 name: 'test-user',
-            }*/
+            }
         }
     },
     'notify': {
@@ -59,6 +59,11 @@ let menuData = {
                 url: '/manager',
                 name: 'index',
             },
+            'authority' : {
+                title: '权限组',
+                url: '/manager/authority',
+                name: 'authority',
+            },
             'admin' : {
                 title: '超级管理员',
                 url: '/manager/admin',

BIN
lib/ztree/css/img/diy/10.png


+ 0 - 0
logs/logs.txt


+ 25 - 0
modules/all_models/basic_info_lib.js

@@ -0,0 +1,25 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/3/5
+ * @version
+ */
+//建设项目基本信息库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const basicInfoLib = new Schema({
+    ID: {type: String, index: true},
+    name: String,
+    creator: String,
+    createDate: Number,
+    recentOpr: [oprSchema],
+    info: {
+        type: Schema.Types.Mixed,
+        default: []
+    }
+}, {versionKey: false});
+mongoose.model('std_basic_info_lib', basicInfoLib, 'std_basic_info_lib');

+ 35 - 0
modules/all_models/block_lib_model.js

@@ -0,0 +1,35 @@
+/**
+ * Created by CSL on 2018-12-17.
+ */
+let mongoose = require('mongoose');
+let Schema = mongoose.Schema;
+
+let dataSchema = new Schema({
+    ID: String,
+    NextSiblingID: String,
+    ParentID: String,
+    children: [],
+    code: String,
+    compilationID: String,
+    copyTime: Number,
+    firstNodeType: Number,
+    isFBFX: {type: Boolean, default: true},
+    itemCharacterText: String,
+    name: String,
+    nodeName: String,
+    type: Number,
+    unit: String,
+    unitFee: String,
+    _id: false
+},{versionKey:false});
+
+let blockLibsSchema = new Schema({
+    userID: String,
+    compilationID: String,
+    libID: String,
+    libName: String,
+    datas: [dataSchema],
+    share: {}
+},{versionKey:false});
+
+mongoose.model('blockLibsModel', blockLibsSchema, 'block_libs');

+ 2 - 0
modules/all_models/compilation.js

@@ -53,6 +53,8 @@ let modelSchema = {
     description: String,
     //代码覆盖路径
     overWriteUrl:String,
+    //例题建设项目ID
+    example: Array,
     // 发布时间
     release_time: {
         type: Number,

+ 1 - 1
modules/all_models/compleGlj_glj.js

@@ -16,7 +16,7 @@ const comple_gljComponent = new Schema(
 );
 //补充工料机跟用户和编办绑定
 const comple_glj = new Schema({
-    userId: Number,
+    userId: String,
     compilationId: String,
     ID: Number,
     code: String,

+ 23 - 0
modules/all_models/compleGlj_section.js

@@ -0,0 +1,23 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/1/2
+ * @version
+ */
+
+import mongoose from 'mongoose';
+
+const Schema = mongoose.Schema;
+const compleGljSection = new Schema({
+    userId: String,
+    compilationId: String,
+    Name: String,
+    ID: String,
+    ParentID: String,
+    NextSiblingID: String,
+});
+
+mongoose.model('complementary_glj_section', compleGljSection, 'complementary_glj_section');

+ 30 - 0
modules/all_models/compleGlj_sectionTemplate.js

@@ -0,0 +1,30 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/1/2
+ * @version
+ */
+
+/*
+ * 我的补充人材机库章节树模板,一个费用定额有一个模板
+ * 模板的生成目前由手工生成(借助定额库编辑器的章节树编辑)
+ * 新用户第一次进入某费用定额的补充定额库时,拷贝模板给该用户
+ *
+ * */
+
+import mongoose from 'mongoose';
+
+const Schema = mongoose.Schema;
+const compleGljSectionTemp = new Schema({
+    compilationId: String,
+    Name: String,
+    ID: Number,
+    ParentID: Number,
+    NextSiblingID: Number,
+});
+
+mongoose.model('complementary_glj_section_templates', compleGljSectionTemp, 'complementary_glj_section_templates');
+

+ 1 - 1
modules/all_models/compleRation_ration.js

@@ -35,7 +35,7 @@ const rationInstSchema = new Schema({
 
 //补充定额
 const compleRationSchema = new Schema({
-    userId: Number,
+    userId: String,
     compilationId: String,
     rationRepId: Number,
     ID:Number,

+ 31 - 0
modules/all_models/compleRation_section.js

@@ -0,0 +1,31 @@
+/**
+ * Created by Zhong on 2018/3/22.
+ */
+/*补充定额库-章节树*/
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const deleteSchema = require('../all_schemas/delete_schema');
+//补充定额章节树
+const compleRationSectionTreeSchema = new Schema({
+    //用户名
+    userId: String,
+    //编办
+    compilationId: String,
+    //标准定额库
+    //rationRepId: Number,
+    //名称
+    name: String,
+    //是否是同层第一个节点
+   // isFirst: Boolean,
+    ID: String,
+    NextSiblingID: String,
+    ParentID: String,
+    deleteInfo: deleteSchema,
+    //以下预留数据,以后开放可用
+    explanation: String,//说明
+    ruleText: String,//计算规则,
+    jobContentSituation: String,//工作内容适用情况,ALL适用本项全部定额,PARTIAL适用本项部分定额
+    annotationSituation: String,//附注适用情况,ALL适用本项全部定额,PARTIAL适用本项部分定额
+}, {versionKey: false});
+
+mongoose.model('complementary_ration_section_tree', compleRationSectionTreeSchema, 'complementary_ration_section_tree');

+ 5 - 5
modules/all_models/comple_section_template.js

@@ -9,11 +9,11 @@
  */
 
 /*
-* 我的补充定额库章节树模板,一个费用定额有一个模板
-* 模板的生成目前由手工生成(借助定额库编辑器的章节树编辑)
-* 新用户第一次进入某费用定额的补充定额库时,拷贝模板给该用户
-*
-* */
+ * 我的补充定额库章节树模板,一个费用定额有一个模板
+ * 模板的生成目前由手工生成(借助定额库编辑器的章节树编辑)
+ * 新用户第一次进入某费用定额的补充定额库时,拷贝模板给该用户
+ *
+ * */
 
 import mongoose from 'mongoose';
 

+ 74 - 0
modules/all_models/config_material_list.js

@@ -0,0 +1,74 @@
+/**
+ * Created by zhang on 2019/9/6.
+ */
+/**
+ * Created by zhang on 2019/3/18.
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let evaluateSchema = {
+    ID:{type:String,  index: true},
+    projectID: {type:Number,index: true},
+    is_related:{type: Number, default: 0},//关联,1关,0不关
+    projectGLJID:Number,//关联工料机ID
+    seq:String,//序号
+    code:String,
+    name:String,
+    specs:String,
+    unit:String,
+    type:Number,
+    market_price:String,
+    quantity:String,
+    locked:{type: Number, default: 0},//锁定,1锁,0不锁
+    remark:String,
+    originPlace:String,//产地
+    vender:String //厂家
+};
+mongoose.model("evaluate_list", new Schema(evaluateSchema, {versionKey: false, collection: "evaluate_list"}));
+
+let bidEvaluationSchema = {
+    ID:{type:String,  index: true},
+    projectID: {type:Number,index: true},
+    is_related:{type: Number, default: 0},//关联,1关,0不关
+    projectGLJID:Number,//关联工料机ID
+    seq:String,//序号
+    code:String,
+    name:String,
+    specs:String,
+    unit:String,
+    type:Number,
+    market_price:String,
+    quantity:String,
+    remark:String,
+    originPlace:String,//产地
+    vender:String //厂家
+};
+
+mongoose.model("bid_evaluation_list", new Schema(bidEvaluationSchema, {versionKey: false, collection: "bid_evaluation_list"}));
+
+
+let contractorSchema = {
+    ID:{type:String,  index: true},
+    projectID: {type:Number,index: true},
+    is_related:{type: Number, default: 0},//关联,1关,0不关
+    projectGLJID:Number,//关联工料机ID
+    seq:String,//序号
+    code:String,
+    name:String,
+    specs:String,
+    unit:String,
+    type:Number,
+    riskCoe:String,//风险系数
+    standardPrice:String,//基准单价
+    FO:String,//基本价格指数
+    FI:String,//现行价格指数
+    market_price:String,
+    quantity:String,
+    remark:String,
+    supply: {type: Number, default: 0},
+    originPlace:String,//产地
+    vender:String //厂家
+};
+
+mongoose.model("contractor_list", new Schema(contractorSchema, {versionKey: false, collection: "contractor_list"}));

+ 1 - 1
modules/all_models/counter.js

@@ -6,5 +6,5 @@ var Schema = mongoose.Schema;
 var counterSchema = new Schema({
     _id: String,
     sequence_value: Number
-});
+},{versionKey:false});
 mongoose.model("counters_operation", counterSchema,"counters_operation");

+ 36 - 1
modules/all_models/engineering_lib.js

@@ -58,6 +58,39 @@ let modelSchema = {
         type: Schema.Types.Mixed,
         default: []
     },
+    info_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
+    engineer_info_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
+    //工程特征指标库
+    engineer_feature_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
+    //主要工料指标库
+    material_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
+    //主要工程量指标库
+    main_quantity_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
+    //主要经济指标库
+    economic_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
+    //超高降效库
+    over_height_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
     //设置人材机显示列
     glj_col:{
         showAdjustPrice:Boolean//是否显示调整价列
@@ -75,7 +108,9 @@ let modelSchema = {
     //单位工程取费专业
     projectEngineering:Number,
     //是否计算安装增加费
-    isInstall:{type: Boolean, default: false}
+    isInstall:{type: Boolean, default: false},
+    indexName:String,//指标专业名称
+    seq:Number//序列号
 };
 mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 

+ 32 - 0
modules/all_models/log.js

@@ -0,0 +1,32 @@
+/**
+ * 日志数据结构
+ *
+ * @author CaiAoLin
+ * @date 2017/7/27
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'log';
+let messageSchema = new Schema({
+    ip: String,
+    ip_info: String,
+    browser: String,
+    os: String
+}, {_id: false});
+let modelSchema = {
+    // 日志类型
+    type: {
+        type: Number
+    },
+    // 日志内容
+    message: messageSchema,
+    // 关联用户id
+    user_id: {
+        type: String
+    },
+    // 创建时间
+    create_time: Number
+};
+mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 5 - 0
modules/all_models/manager.js

@@ -55,6 +55,11 @@ let modelSchema = {
         type: Number,
         default: 0
     },
+    //职称
+    position: {
+        type: String,
+        default: ''
+    },
     // 超级管理员 1为超级管理员
     super_admin: {
         type: Number,

+ 17 - 0
modules/all_models/online_logs.js

@@ -0,0 +1,17 @@
+/**
+ * Created by zhang on 2019/4/12.
+ */
+//用户在线时长统计
+
+let mongoose = require("mongoose");
+let Schema = mongoose.Schema;
+
+// 表结构
+let schema = {
+    userID: String,
+    compilationID: String,
+    dateString: String,
+    dateTime:Number,//dateString转换回毫秒数对应的数值,方便查询
+    online_times: Number
+};
+mongoose.model("online_logs", new Schema(schema, {versionKey: false}),"online_logs");

+ 16 - 0
modules/all_models/options.js

@@ -0,0 +1,16 @@
+/**
+ * Created by Zhong on 2018/3/22.
+ */
+/*选项*/
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const optionSchema = new Schema({
+    user_id: String,
+    compilation_id: String,
+    options: {
+        type: Schema.Types.Mixed,
+        default: {}
+    }
+}, {versionKey: false});
+
+mongoose.model('options', optionSchema, 'options');

+ 49 - 0
modules/all_models/permission.js

@@ -0,0 +1,49 @@
+/**
+ * 后台管理权限数据模型
+ *
+ * @author EllisRan
+ * @date 2018/12/06
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'permission';
+let modelSchema = {
+    // ID
+    ID: {
+        type: Number,
+        default: 0
+    },
+    // 权限名称
+    name: {
+        type: String,
+        index: true
+    },
+    // 控制器名称
+    controller: String,
+    // 针对工具里一个页面多个控制器的问题(特殊优化)
+    otherController: String,
+    // 方法名称
+    action: String,
+    // 路径
+    url: String,
+    // 图标类名
+    iconClass: String,
+    // 父级id(初始默认0为父级)
+    pid: {
+        type: Number,
+        default: 0
+    },
+    // 是否属于菜单列表里的
+    isMenu: {
+        type: Boolean,
+        default: true
+    },
+    // 创建时间
+    create_time: {
+        type: Number,
+        default: 0
+    },
+};
+mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 26 - 0
modules/all_models/permission_group.js

@@ -0,0 +1,26 @@
+/**
+ * 后台管理权限组数据模型
+ *
+ * @author EllisRan
+ * @date 2018/12/06
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'permission_group';
+let modelSchema = {
+    // 组名
+    name: {
+        type: String,
+        index: true
+    },
+    // 权限ID JSON列表
+    permission: String,
+    // 创建时间
+    create_time: {
+        type: Number,
+        default: 0
+    },
+};
+mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 31 - 0
modules/all_models/product.js

@@ -0,0 +1,31 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/3/21
+ * @version
+ */
+/*
+* 与产品绑定的信息都可以在此设置
+* */
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const productSchema = new Schema({
+    name: {
+        type: String,
+        default: '纵横建筑计价'
+    },
+    company: {
+        type: String,
+        default: '珠海纵横创新软件有限公司'
+    },
+    icp: {
+        type: String,
+        default: '粤ICP备14032472号'
+    },
+    version: String
+}, {versionKey: false});
+
+mongoose.model('product', productSchema, 'product');

+ 2 - 0
modules/all_models/project_feature_lib.js

@@ -12,6 +12,8 @@ const project_feature_lib = new Schema({
         createDate: Number,
         recentOpr: [oprSchema],
         name: String,
+        compilationId: String,
+        compilationName: String,
         feature:{
             type: [Schema.Types.Mixed],
             default: []

+ 26 - 0
modules/all_models/ration_template.js

@@ -0,0 +1,26 @@
+/**
+ * Created by zhang on 2018/11/26.
+ */
+
+var mongoose = require('mongoose'),
+    Schema = mongoose.Schema;
+
+let ration_template =  new Schema({
+    ID:String,
+    projectID: Number,
+    rationID:String,
+    createLocation:Number,//提取位置
+    templateList:[new Schema({
+        code:String,
+        name:String,
+        type:String,
+        billsLocation:String,//这个是清单编号
+        fxID:String,//这个是分项对应的ID
+        unit:String,
+        quantity:String,
+        coe:String,
+        billID:String//记取位置对应的清单ID
+    },{ _id: false })]
+},{versionKey:false});
+
+mongoose.model('ration_template', ration_template,"ration_template");

+ 30 - 0
modules/all_models/setting.js

@@ -0,0 +1,30 @@
+/**
+ * 个人设置数据结构
+ *
+ * @author CaiAoLin
+ * @date 2017/7/27
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'setting';
+let modelSchema = {
+    // 设置类型
+    type: {
+        type: Number,
+        index: true
+    },
+    // 设置内容
+    data: {
+        type: Schema.Types.Mixed,
+    },
+    // 关联用户id
+    user_id: {
+        type: String,
+        index: true
+    },
+    // 创建时间
+    create_time: Number
+};
+mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 26 - 0
modules/all_models/share_list.js

@@ -0,0 +1,26 @@
+/*
+ * @Descripttion: 分享列表
+ * @Author: Zhong
+ * @Date: 2020-01-10 10:51:35
+ */
+
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const shareSchema = new Schema({
+    ID: String,
+    projectID: Number,
+    owner: String, // 项目拥有者ID
+    receiver: String, // 接收者ID
+    allowCopy: {
+        type: Boolean,
+        default: false
+    },
+    allowCooperate: {
+        type: Boolean,
+        default: false
+    },
+    shareDate: String,
+    updateDate: String
+}, {versionKey: false});
+
+mongoose.model('share_list', shareSchema, 'share_list');

+ 7 - 0
modules/all_models/stdBills_bills.js

@@ -14,11 +14,18 @@ const stdBills_bills = new Schema({
             ruleText: String,
             engineering: Number, //工程专业,填计算程序工程专业ID
             Expression: String,
+            comment: String, //备注,清单精灵处输入
             jobs: [],
             items: [],
             recharge:String,
             billsLibId: {type:Number,index:true},
             sectionInfo: Schema.Types.Mixed,
+            //经济指标属性
+            economicType:String,//工程经济指标类别
+            quantityIndexType:String,//工程量指标类别
+            quantityIndexUnit:String,//工程量指标单位
+            quantityIndexCoe:Number,//单位转换系数
+
             deleted: Boolean
     },
     {versionKey: false}

+ 5 - 0
modules/all_models/stdGlj_glj.js

@@ -39,6 +39,11 @@ const std_glj = new Schema({
     materialType: Number, //三材类型:钢材1、钢筋2、木材3、水泥4、标准砖5
     materialCoe: Number, //三材系数
     model: Number, //机型
+    //经济指标数据
+    materialIndexType:String,//工料指标类别
+    materialIndexUnit:String,//工料指标单位
+    materialIndexCoe:Number//单位转换系数
+
 },{versionKey: false});
 
 mongoose.model('std_glj_lib_gljList', std_glj, 'std_glj_lib_gljList');

+ 5 - 0
modules/all_models/stdRation_coe.js

@@ -12,6 +12,8 @@ const coeSchema = new Schema({
     amount: String,                 // 调整的量
     gljCode: String,
     gljName: String,
+    replaceCode:String,
+    replaceName:String,
     _id: false
 });
 
@@ -21,6 +23,9 @@ const coeListSchema = new Schema({
     serialNo: Number,                  //编号
     name: String,                       // 名称
     content: String,                    // 说明
+    original_code:String,               //原人材机编码
+    option_codes:String,                //可选人材机编码
+    option_list:[Schema.Types.Mixed],//下拉列表选项
     coes: [coeSchema]
 }, {versionKey: false});
 

+ 1 - 0
modules/all_models/stdRation_lib.js

@@ -8,6 +8,7 @@ const oprSchema = require('../all_schemas/opr_schema');
 const RepositoryMapSchema = new Schema({
     "ID": Number,
     "dispName" : String,
+    "libCode": String, //定额库编码
     "appType" : String, //如:"建筑" / "公路"
     "localeType": String, //如 各个省份 / 部颁
     "descr" : String,

+ 9 - 1
modules/all_models/stdRation_ration.js

@@ -19,7 +19,10 @@ const rationAssItemSchema = new Schema({
     decimal: Number,
     carryBit: String,
     minValue: String,
-    maxValue: String
+    maxValue: String,
+    paramName:String,//参数名称
+    param:String,//参数
+    thirdRationCode:String//第三定额
 }, { _id: false });
 
 //定额安装增加费用
@@ -43,10 +46,15 @@ const rationItemSchema = new Schema({
     feeType: Number,
     jobContent: String,
     annotation: String,
+    manageFeeRate: String, // 管理费费率
     rationGljList: [rationGljItemSchema],
     rationCoeList: Array,
     rationAssList: [rationAssItemSchema],
     rationInstList: [rationInstSchema],
+    rationTemplateList: {
+        type: Array,
+        default: []
+    },
     isDeleted: {type: Boolean, default: false}
 });
 

+ 25 - 0
modules/all_models/std_economic_lib.js

@@ -0,0 +1,25 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/3/5
+ * @version
+ */
+//主要工程量指标库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const economicLib = new Schema({
+    ID: {type: String, index: true},
+    name: String,
+    creator: String,
+    createDate: Number,
+    recentOpr: [oprSchema],
+    index: {
+        type: Schema.Types.Mixed,
+        default: []
+    }
+}, {versionKey: false});
+mongoose.model('std_economic_lib', economicLib, 'std_economic_lib');

+ 25 - 0
modules/all_models/std_engineer_feature_lib.js

@@ -0,0 +1,25 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/3/5
+ * @version
+ */
+//建设项目基本信息库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const engineerFeatureLib = new Schema({
+    ID: {type: String, index: true},
+    name: String,
+    creator: String,
+    createDate: Number,
+    recentOpr: [oprSchema],
+    features: {
+        type: Schema.Types.Mixed,
+        default: []
+    }
+}, {versionKey: false});
+mongoose.model('std_engineer_feature_lib', engineerFeatureLib, 'std_engineer_feature_lib');

+ 25 - 0
modules/all_models/std_engineer_info_lib.js

@@ -0,0 +1,25 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/3/5
+ * @version
+ */
+//建设项目基本信息库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const engineerInfoLib = new Schema({
+    ID: {type: String, index: true},
+    name: String,
+    creator: String,
+    createDate: Number,
+    recentOpr: [oprSchema],
+    info: {
+        type: Schema.Types.Mixed,
+        default: []
+    }
+}, {versionKey: false});
+mongoose.model('std_engineer_info_lib', engineerInfoLib, 'std_engineer_info_lib');

+ 25 - 0
modules/all_models/std_main_quantity_lib.js

@@ -0,0 +1,25 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/3/5
+ * @version
+ */
+//主要工程量指标库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const quantityLib = new Schema({
+    ID: {type: String, index: true},
+    name: String,
+    creator: String,
+    createDate: Number,
+    recentOpr: [oprSchema],
+    index: {
+        type: Schema.Types.Mixed,
+        default: []
+    }
+}, {versionKey: false});
+mongoose.model('std_main_quantity_lib', quantityLib, 'std_main_quantity_lib');

+ 25 - 0
modules/all_models/std_material_lib.js

@@ -0,0 +1,25 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/3/5
+ * @version
+ */
+//建设项目基本信息库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const materialLib = new Schema({
+    ID: {type: String, index: true},
+    name: String,
+    creator: String,
+    createDate: Number,
+    recentOpr: [oprSchema],
+    materials: {
+        type: Schema.Types.Mixed,
+        default: []
+    }
+}, {versionKey: false});
+mongoose.model('std_material_lib', materialLib, 'std_material_lib');

+ 25 - 0
modules/all_models/std_over_height_lib.js

@@ -0,0 +1,25 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/3/5
+ * @version
+ */
+//建设项目基本信息库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const overHeightLib = new Schema({
+    ID: {type: String, index: true},
+    name: String,
+    creator: String,
+    createDate: Number,
+    recentOpr: [oprSchema],
+    list: {
+        type: Schema.Types.Mixed,
+        default: []
+    }
+}, {versionKey: false});
+mongoose.model('std_over_height_lib', overHeightLib, 'std_over_height_lib');

+ 25 - 0
modules/all_models/system_setting.js

@@ -0,0 +1,25 @@
+/**
+ * Created by zhang on 2020/1/2.
+ */
+let mongoose = require("mongoose");
+
+let Schema = mongoose.Schema;
+let collectionName = 'system_setting';
+let modelSchema = {
+    // ID
+    ID: {
+        type: String,
+        index: true
+    },
+    // 专业用户
+    professional: {
+        project: Number,
+        ration:Number
+    },
+    // 免费用户
+    normal: {
+        project: Number,
+        ration:Number
+    },
+};
+mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 11 - 10
modules/all_models/tpl_tree_node.js

@@ -28,14 +28,15 @@ let TplNodeSchema = new Schema({
 });
 
 let RptTplTreeSchema = new Schema({
-    compilationId: String,  //编办的ObjectId
-    // engineerId: Number,     //工程专业Id(参考 /modules/common/const/engineering.js)
-    userId: String,        //用户名的object_id串
-    properties: [],         //这是一个预留的属性,假定未来还会有不同的划分细节(如:招标/投标/清单 ... etc)
-    name: String,           //显示名称
-    released: Boolean,      //是否已发布
-    isDeleted: Boolean,     //删除标记
-    items: []               //TplNodeSchema entity
+    compilationId: String,      //编办的ObjectId
+    // engineerId: Number,         //工程专业Id(参考 /modules/common/const/engineering.js)
+    userId: String,             //用户名的object_id串
+    properties: [],             //这是一个预留的属性,假定未来还会有不同的划分细节(如:招标/投标/清单 ... etc)
+    name: String,               //显示名称
+    released: Boolean,          //是否已发布
+    isDeleted: Boolean,         //删除标记
+    flags: Schema.Types.Mixed,  //额外标记集合(这些标记可能会影响到前端显示,如‘计税方式’等)
+    items: []                   //TplNodeSchema entity
 });
 RptTplTreeSchema.statics.findAndModify = function (query, sort, doc, options, callback) {
     return this.collection.findAndModify(query, sort, doc, options, callback);
@@ -43,8 +44,8 @@ RptTplTreeSchema.statics.findAndModify = function (query, sort, doc, options, ca
 
 mongoose.model("rpt_tpl_tree", RptTplTreeSchema, "rpt_tpl_tree");
 /*
-let TreeNodeModel = mongoose.model("rpt_tpl_tree", TreeNodeSchema, "rpt_tpl_tree");
-/*/
+ let TreeNodeModel = mongoose.model("rpt_tpl_tree", TreeNodeSchema, "rpt_tpl_tree");
+ /*/
 // let TreeNodeModel = mongoose.model("rpt_tpl_tree", RptTplTreeSchema, "rpt_tpl_tree");
 //*/
 

+ 39 - 0
modules/all_models/user_message.js

@@ -0,0 +1,39 @@
+/**
+ * 用户消息数据模型
+ *
+ * @author CaiAoLin
+ * @date 2017/9/22
+ * @version
+ */
+let mongoose = require("mongoose");
+let Schema = mongoose.Schema;
+
+// 表名
+let collectionName = 'user_message';
+
+// 表结构
+let schema = {
+    // 用户id
+    user_id: {
+        type: String,
+    },
+    // 是否已读
+    is_read: {
+        type: Number,
+        default: 0
+    },
+    // 是否删除
+    is_delete: {
+        type: Number,
+        default: 0
+    },
+    // 消息关联数据
+    message: {
+        type: Schema.Types.ObjectId,
+        ref: 'message'
+    },
+    // 创建时间
+    create_time: Number,
+};
+
+mongoose.model(collectionName, new Schema(schema, {versionKey: false}));

+ 101 - 0
modules/basic_info_lib/controllers/basic_info_controller.js

@@ -0,0 +1,101 @@
+/**
+ * Created by zhang on 2018/9/3.
+ */
+import BaseController from "../../common/base/base_controller";
+import basicInfoFacade from "../facade/basic_info_facade";
+let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+
+class BasicInfoController extends BaseController{
+    async main(request, response) {
+        let baiscInfoLibs = await basicInfoFacade.findByCondition({},{feature:0},false);
+        let randerData = {
+            title:'基本信息库',
+            userAccount: request.session.managerData.username,
+            userID: request.session.managerData.userID,
+            basicInfoLibs:baiscInfoLibs,
+            layout: 'maintain/common/html/layout'
+        };
+        response.render("maintain/basic_info_lib/html/main", randerData);
+    }
+    async addLib(request, response){
+        try {
+            await basicInfoFacade.addLib(request.body);
+        }catch (error) {
+            console.log(error);
+        }
+        response.redirect(request.headers.referer);
+    }
+    async findLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let conditions={'ID' : data.ID};
+            let resultData = await basicInfoFacade.findByCondition(conditions);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async saveLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await basicInfoFacade.saveLib(data);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async deleteLibByID(request,response){
+        logger.info(`delete basicInfoLib ${request.ip}`);
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await basicInfoFacade.deleteLibByID(data.ID);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async edit(request,response){
+        //先取出替换库信息:
+        let libID = request.params.libID;
+        let basicInfoLib = await basicInfoFacade.findByCondition({'ID':libID});
+        if(basicInfoLib){
+            let randerData = {
+                title:'基本信息库',
+                mainURL:'/basicInfo/main',
+                libName:basicInfoLib.name,
+                userAccount: request.session.managerData.username,
+                userID: request.session.managerData.userID,
+                basicInfoList:JSON.stringify(basicInfoLib.info),
+                libID:libID,
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                layout: 'maintain/common/html/edit_layout'
+            };
+            response.render("maintain/basic_info_lib/html/edit", randerData);
+        }else {
+            response.redirect(request.headers.referer);
+        }
+    }
+}
+export default BasicInfoController;

+ 38 - 0
modules/basic_info_lib/facade/basic_info_facade.js

@@ -0,0 +1,38 @@
+/**
+ * Created by zhang on 2018/9/3.
+ */
+import mongoose from "mongoose";
+const uuidV1 = require('uuid/v1');
+let moment = require("moment");
+let basicInfoModel = mongoose.model('std_basic_info_lib');
+
+
+let basicInfoLib = {
+    findByCondition:async function(conditions,options,single=true){
+        if(single == true){
+            return await basicInfoModel.findOne(conditions,options);
+        }else {
+            return await  basicInfoModel.find(conditions,options);
+        }
+    },
+    addLib : async function (data){
+        let now = new Date().getTime();
+        let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
+        let newLib = {
+            creator: data.userAccount,
+            createDate: now,
+            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+            name: data.name,
+        };
+        newLib.ID = uuidV1();
+        return await basicInfoModel.create(newLib);
+    },
+    saveLib:async function(param) {
+        return await basicInfoModel.findOneAndUpdate(param.query,param.data,{new:true});
+    },
+    deleteLibByID:async function(ID){
+        return await basicInfoModel.deleteOne({ID:ID});
+    },
+};
+
+export default basicInfoLib

+ 21 - 0
modules/basic_info_lib/routes/project_feature_router.js

@@ -0,0 +1,21 @@
+/**
+ * Created by zhang on 2018/9/3.
+ */
+
+let express = require("express");
+let infoRouter =express.Router();
+import InfoController from "../controllers/basic_info_controller";
+let infoController = new InfoController();
+
+module.exports =function (app){
+
+    infoRouter.get("/main", infoController.auth, infoController.init, infoController.main);
+    infoRouter.post("/addLib", infoController.auth, infoController.init, infoController.addLib);
+    infoRouter.post("/findLib", infoController.auth, infoController.init, infoController.findLib);
+    infoRouter.post("/saveLib", infoController.auth, infoController.init, infoController.saveLib);
+    infoRouter.post("/deleteLibByID", infoController.auth, infoController.init, infoController.deleteLibByID);
+    infoRouter.get("/edit/:libID", infoController.auth, infoController.init, infoController.edit);
+    app.use("/basicInfo", infoRouter);
+};
+
+

+ 15 - 1
modules/bills_lib/controllers/bills_lib_controllers.js

@@ -5,9 +5,22 @@
 let billsLibDao = require("./../models/bills_lib_interfaces");
 let callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
-}
+};
+let logger = require('../../../logs/log_helper').logger;
 
 module.exports = {
+    copyStdBillsLib: async function (req, res) {
+        try {
+            const data = JSON.parse(req.body.data);
+            const userName = req.session.managerData.username;
+            const libName = data.libName;
+            const libId = data.libId;
+            const newLibData = await billsLibDao.copyLib(userName, libName, libId);
+            callback(req, res, 0, 'copyLib success', [newLibData]);
+        } catch (err) {
+            callback(req, res, 1, 'copyLib fail', null);
+        }
+    },
     getMaxNumber: function(req, res){
         let data = JSON.parse(req.body.data);
         billsLibDao.getMaxNumber(data, function(err, message, maxNumber){
@@ -33,6 +46,7 @@ module.exports = {
     },
     deleteStdBillsLib: function(req, res){
         let data = JSON.parse(req.body.data);
+        logger.info(`deleteBillsLib ${req.ip}`);
         billsLibDao.deleteStdBillsLib(data, function(err, message){
             callback(req, res, err, message, null);
         });

+ 52 - 1
modules/bills_lib/controllers/bills_permissionController.js

@@ -2,10 +2,12 @@
  * Created by Zhong on 2017/8/2.
  */
 let billsController = require("./bills_lib_controllers");
+let billsLibDao = require("./../models/bills_lib_interfaces");
 import baseController from "../../common/base/base_controller";
 import fs from 'fs';
 import path from 'path';
 import multiparty from 'multiparty';
+const excel = require("node-xlsx");
 const uuidV1 = require('uuid/v1');
 
 const shareDir = 'public/share/images';
@@ -68,6 +70,56 @@ class billsPermContr extends baseController{
         billsController.isUsed(req, res);
     }
     /*
+     * 导入标准清单(确定节点结构:深度数组)
+     * */
+    importBills(req, res){
+        let form = new multiparty.Form({uploadDir: './public'});
+        const allowHeader = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
+        let uploadFullName;
+        form.parse(req, async function (err, fields, files) {
+            try {
+                const file = typeof files.file !== 'undefined' ? files.file[0] : null;
+                if (err || !file) {
+                    throw '上传失败。';
+                }
+                if (file.headers['content-type'] === undefined || allowHeader.indexOf(file.headers['content-type']) < 0) {
+                    throw '不支持该类型';
+                }
+                const billsLibId = typeof fields.billsLibId !== 'undefined' && fields.billsLibId.length > 0 ? fields.billsLibId[0] : null;
+                if (!billsLibId) {
+                    throw '请选择一个清单库。';
+                }
+                let hasData = await billsLibDao.hasData(billsLibId);
+                if (hasData) {
+                    throw '请新建一个新的清单库,或删除库中的清单后再导入。';
+                }
+                // 重命名文件名
+                uploadFullName = './public/' + file.originalFilename;
+                fs.renameSync(file.path, uploadFullName);
+                const sheet = excel.parse(uploadFullName);
+                if (sheet[0] === undefined || sheet[0].data === undefined || sheet[0].data.length <= 0) {
+                    throw 'excel没有对应数据';
+                }
+                //插入清单
+                await billsLibDao.importBills(billsLibId, sheet[0].data);
+                // 删除文件
+                if(uploadFullName && fs.existsSync(uploadFullName)){
+                    fs.unlinkSync(uploadFullName);
+                }
+                res.json({error: 0, data: null, msg: ''});
+
+            } catch (err) {
+                console.log(err);
+                // 删除文件
+                if(uploadFullName && fs.existsSync(uploadFullName)){
+                    fs.unlinkSync(uploadFullName);
+                }
+                res.json({error: 1, data: null, msg: err});
+            }
+        });
+    }
+
+    /*
     *上传图片
     * */
     uploadImg(req, res){
@@ -172,7 +224,6 @@ class billsPermContr extends baseController{
             res.json({error: 1, data: {pageCount: 1, currentImgsUrl: []}, message: err});
         }
     }
-
 }
 
 export default billsPermContr;

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

@@ -40,6 +40,9 @@ class billsLibPermContr extends baseController{
     createStdBillsLib(req, res){
         billsController.createStdBillsLib(req, res);
     }
+    copyStdBillsLib(req, res) {
+        billsController.copyStdBillsLib(req, res);
+    }
     deleteStdBillsLib(req, res){
         billsController.deleteStdBillsLib(req, res);
     }

+ 298 - 2
modules/bills_lib/models/bills_lib_interfaces.js

@@ -11,8 +11,94 @@ let ItemCharacter = mongoose.model('std_bills_lib_itemCharacter');
 let moment = require("moment");
 let billsGuidanceLib = mongoose.model('std_billsGuidance_lib');
 const engLibModel = mongoose.model('engineering_lib');
+let uuid = require('uuid');
 let billsLibDao = function(){};
 
+billsLibDao.prototype.copyLib = async function (userName, libName, fromLibId) {
+    const libData = await this.createStdBillsLibSync(userName, libName);
+    const newLibId = libData.billsLibId;
+    //插入工作内容
+    let orgJobs = await JobContent.find({billsLibId: fromLibId}).lean();
+    let jobCounter = await counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_jobs, orgJobs.length);
+    let maxJobId = jobCounter.sequence_value;
+    let jobTask = [],
+        orgNewJobMapping = {};
+    for (let i = 0; i < orgJobs.length; i++) {
+        let jobData = orgJobs[i];
+        delete jobData._id;
+        let newID = (maxJobId - (orgJobs.length - 1) + i);
+        orgNewJobMapping[jobData.id] = newID;
+        jobData.id = newID;
+        jobData.billsLibId = newLibId;
+        jobTask.push({insertOne: {document: jobData}});
+    }
+    if (jobTask.length > 0) {
+        await JobContent.bulkWrite(jobTask);
+    }
+    //插入项目特征
+    let orgItems = await ItemCharacter.find({billsLibId: fromLibId}).lean();
+    let itemCounter = await counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib_items, orgItems.length);
+    let maxItemId = itemCounter.sequence_value;
+    let itemTask = [],
+        orgNewItemMapping = {};
+    for (let i = 0; i < orgItems.length; i++) {
+        let itemData = orgItems[i];
+        delete itemData._id;
+        let newID = (maxItemId - (orgItems.length - 1) + i);
+        orgNewItemMapping[itemData.id] = newID;
+        itemData.id = newID;
+        itemData.billsLibId = newLibId;
+        itemTask.push({insertOne: {document: itemData}});
+    }
+    if (itemTask.length > 0) {
+        await ItemCharacter.bulkWrite(itemTask);
+    }
+    //插入清单
+    let billsTask = [];
+    let bills = await Bills.find({billsLibId: fromLibId}).lean();
+    let IDMapping = {},
+        billsDatas = [];
+    for (let b of bills) {
+        let bData = b;
+        delete bData._id;
+        bData.billsLibId = newLibId;
+        billsDatas.push(bData);
+        IDMapping[bData.ID] = uuid.v1();
+    }
+    for (let bD of billsDatas) {
+        bD.ID = IDMapping[bD.ID];
+        if (IDMapping[bD.NextSiblingID]) {
+            bD.NextSiblingID = IDMapping[bD.NextSiblingID];
+        }
+        if (IDMapping[bD.ParentID]) {
+            bD.ParentID = IDMapping[bD.ParentID];
+        }
+        // 更新sectionInfo数据
+        if (bD.sectionInfo) {
+            const first = IDMapping[bD.sectionInfo.first];
+            const second = IDMapping[bD.sectionInfo.second];
+            const third = IDMapping[bD.sectionInfo.third];
+            bD.sectionInfo.first = first || null;
+            bD.sectionInfo.second = second || null;
+            bD.sectionInfo.third = third || null;
+        }
+        for (let subJob of bD.jobs) {
+            if (orgNewJobMapping[subJob.id]) {
+                subJob.id = orgNewJobMapping[subJob.id];
+            }
+        }
+        for (let subItem of bD.items) {
+            if (orgNewItemMapping[subItem.id]) {
+                subItem.id = orgNewItemMapping[subItem.id];
+            }
+        }
+        billsTask.push({insertOne: {document: bD}});
+    }
+    if (billsTask.length > 0) {
+        await Bills.bulkWrite(billsTask);
+    }
+    return libData;
+};
 
 billsLibDao.prototype.getMaxNumber = function(gData, callback){
     let billsLibId = gData.billsLibId;
@@ -64,6 +150,20 @@ billsLibDao.prototype.getStdBillsLib = function(callback){
     });
 };
 
+billsLibDao.prototype.createStdBillsLibSync = async function (userName, libName) {
+    const counterRst = await counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib, 1);
+    const dateStr = moment().format('YYYY-MM-DD HH:mm:ss');
+    const libData = {
+        creator: userName,
+        createDate: dateStr,
+        recentOpr: [{operator: userName, operateDate: dateStr}],
+        billsLibId: counterRst.sequence_value,
+        billsLibName: libName,
+        deleted: false
+    };
+    await StdBillsLib.create(libData);
+    return libData;
+};
 
 billsLibDao.prototype.createStdBillsLib = function(clibData, callback){
     counter.counterDAO.getIDAfterCount(counter.moduleName.billsLib, 1, function(err, result){
@@ -218,7 +318,7 @@ billsLibDao.prototype.getCurrentUniqId = function(callback){
 }
 //----------------------------Bills---------------------
 billsLibDao.prototype.getBills = function (billsLibId, callback) {
-    Bills.find({billsLibId: billsLibId, deleted: false}, "-_id",  function(err, billsData){
+    Bills.find({billsLibId: billsLibId, deleted: false}, "-_id", {lean: true}, function(err, billsData){
         if(err){
             callback(1, "Error", null);
         }
@@ -3091,7 +3191,203 @@ billsLibDao.prototype.edUpdateItem = function(data, callback){
         }
     });
 };
-//
+
+billsLibDao.prototype.hasData = async function (billsLibId) {
+    let bills = await Bills.findOne({billsLibId: billsLibId});
+    if (bills) {
+        return true;
+    }
+    return false;
+};
+
+billsLibDao.prototype.importBills = async function (billsLibId, sheetData) {
+    //实际节点深度数组,下标等于深度,元素为该为上一个该深度清单数据, 数组长度-1等于最大深度
+    let depthArr = [];
+    const deepest = 10000;
+    //深度的值,并不是真正的深度,只是三种类型节点(顶节点、中间节点、底节点)的深度值,节点根据深度值与深度数组最大深度的比较,对深度数组进行更新,
+    //并且确定父子上下关系
+    function getDepthValue(code){
+        let midReg = /\.{1,}/g;
+        //root
+        if (code.length === 1) {
+            return 0;
+        }
+        if (midReg.test(code)) {
+            return code.match(midReg).length;
+        }
+        return deepest;
+    }
+    let billsDatas = [],
+        jobMapping = {},
+        itemMapping = {};
+    function getDivideData(data){
+        let rst = [];
+        let divideReg = /[\n,\r]/g,
+            prefixReg = /\d+\.{1}/g; //前缀 1. 2.
+        let divideArr = data.split(divideReg);
+        for (let dData of divideArr) {
+            if (dData !== '') {
+                rst.push(dData.replace(prefixReg, ''));
+            }
+        }
+        return rst;
+    }
+    //设置总工作内容/项目特征映射
+    function setBillsSubMapping(subData, mapping){
+        for (let data of subData) {
+            if (!mapping[data]) {
+                let code = Object.keys(mapping).length + 1;
+                mapping[data] = {billsLibId: billsLibId, code: code, content: data, deleted: false};
+            }
+        }
+    }
+    let row = -1;
+    //从表格中获取清单数据
+    for (let rowData of sheetData) {
+        row++;
+        if (row === 0) {
+            continue;
+        }
+        let bills = {
+            deleted: false,
+            billsLibId: billsLibId,
+            parent: null,
+            ID: uuid.v1(),
+            ParentID: -1,
+            NextSiblingID: -1,
+            code: typeof rowData[0] !== 'undefined' ? rowData[0] : '',
+            name: typeof rowData[1] !== 'undefined' ? rowData[1] : '',
+            unit: typeof rowData[2] !== 'undefined' ? rowData[2] : '',
+            ruleText: typeof rowData[3] !== 'undefined' ? rowData[3] : '',
+            recharge: '',
+        };
+        let jobData = typeof rowData[4] !== 'undefined' ? getDivideData(rowData[4]) : [],
+            itemData = typeof rowData[5] !== 'undefined' ? getDivideData(rowData[5]) :[];
+        bills.jobData = jobData;
+        bills.itemData = itemData;
+        setBillsSubMapping(jobData, jobMapping);
+        setBillsSubMapping(itemData, itemMapping);
+        billsDatas.push(bills);
+    }
+    //设置工作内容、项目特征id
+    async function setSubId(moduleName, subMapping) {
+        let idx = 0,
+            subCount = Object.keys(subMapping).length;
+        let subCounter = await counter.counterDAO.getIDAfterCount(moduleName, subCount);
+        for (let mapping in subMapping) {
+            let id = subCounter.sequence_value - (subCount - 1) + idx;
+            let sub = subMapping[mapping];
+            sub.id = id;
+            idx++;
+        }
+    }
+    await setSubId(counter.moduleName.billsLib_jobs, jobMapping);
+    await setSubId(counter.moduleName.billsLib_items, itemMapping);
+    //获得清单、工作内容/项目特征关联数组
+    //subDatas为清单工作内容/项目特征的字符串数组 eg: ['场内运输', '开挖'];
+    //mapping为总工作内容/项目特征字符串映射 eg: {'场内运输': {content: '场内运输', id: 1, code: 1, deleted: false}}
+    function getBillsSubRef(subDatas, mapping) {
+        let rst = [];
+        for (let i = 0; i < subDatas.length; i++) {
+            let data = subDatas[i];
+            if (mapping[data]) {
+                rst.push({id: mapping[data].id, serialNo: i + 1});
+            }
+        }
+        return rst;
+    }
+    //设置完整的清单数据(树结构、工作内容/项目特征)
+    for (let i = 0; i < billsDatas.length; i++) {
+        let bills = billsDatas[i],
+            preBills = billsDatas[i - 1];
+        //树结构相关设置
+        let maxDepth = depthArr.length - 1;
+        let depthV = getDepthValue(bills.code);
+        //前节点为最底层节点,且这个节点为最底层节点,则深度相同
+        let preIsDeepest = preBills && getDepthValue(preBills.code) === deepest ? true : false;
+        if (preIsDeepest && depthV === deepest) {
+            depthV = maxDepth;
+        }
+        if (depthV > maxDepth) {
+            let parent = depthArr[depthArr.length - 1];
+            if (parent) {
+                bills.ParentID = parent.ID;
+                bills.parent = parent;
+            }
+            depthArr.push(bills);
+        } else {
+            let parent = depthArr[depthV -1];
+            if (parent) {
+                bills.ParentID = parent.ID;
+                bills.parent = parent;
+            }
+            depthArr[depthV].NextSiblingID = bills.ID;
+            depthArr.splice(depthV, 1);
+            if (depthV < maxDepth) { //切割
+                depthArr = depthArr.slice(0, depthV);
+            }
+            depthArr.push(bills);
+        }
+        //工作内容项目特征
+        bills.jobs = getBillsSubRef(bills.jobData, jobMapping);
+        bills.items = getBillsSubRef(bills.itemData, itemMapping);
+    }
+    function getSectionInfo(bills){
+        let parentIDs = [];
+        let sectionInfo = {first: null, second: null, third: null};
+        getParent(bills);
+        if(parentIDs[parentIDs.length - 1]){
+            sectionInfo.first = parentIDs[parentIDs.length - 1];
+        }
+        if(parentIDs[parentIDs.length - 2]){
+            sectionInfo.second = parentIDs[parentIDs.length - 2];
+        }
+        if(parentIDs[parentIDs.length - 3]){
+            sectionInfo.third = parentIDs[parentIDs.length - 3];
+        }
+        return sectionInfo;
+        function getParent(bills){
+            if(bills.parent){
+                parentIDs.push(bills.parent.ID);
+                getParent(bills.parent);
+            }
+        }
+    }
+    //设置sectionInfo
+    for (let bills of billsDatas) {
+        bills.sectionInfo = getSectionInfo(bills);
+    }
+    //插入清单
+    let bulks = [];
+    for (let bills of billsDatas) {
+        delete bills.parent;
+        bulks.push({insertOne: {document: bills}});
+    }
+    if (bulks.length > 0) {
+        await Bills.bulkWrite(bulks);
+    }
+    //清除工作内容、项目特征
+    await JobContent.remove({billsLibId: billsLibId});
+    await ItemCharacter.remove({billsLibId: billsLibId});
+    function getSubBulks(subMapping) {
+        let rst = [];
+        for (let mapping in subMapping) {
+            let sub = subMapping[mapping];
+            rst.push({insertOne: {document: sub}});
+        }
+        return rst;
+    }
+    //插入工作内容
+    let jobBulks = getSubBulks(jobMapping);
+    if (jobBulks.length > 0) {
+        await JobContent.bulkWrite(jobBulks);
+    }
+    //插入项目特征
+    let itemBulks = getSubBulks(itemMapping);
+    if (itemBulks.length > 0) {
+        await ItemCharacter.bulkWrite(itemBulks);
+    }
+};
 
 
 module.exports = new billsLibDao();

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

@@ -26,9 +26,12 @@ module.exports =function (app) {
     billsRouter.post('/getABillsLib', billsLibContr.auth, billsLibContr.init, billsLibContr.getABillsLib);
     billsRouter.post("/getStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.getStdBillsLib);
     billsRouter.post("/createStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.createStdBillsLib);
+    billsRouter.post("/copyStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.copyStdBillsLib);
     billsRouter.post("/deleteStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.deleteStdBillsLib);
     billsRouter.post("/renameStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.renameStdBillsLib);
     billsRouter.post("/getStdBillsLibName", billsLibContr.auth, billsLibContr.init, billsLibContr.getStdBillsLibName);
+    //导入清单
+    billsRouter.post('/importBills', billsContr.importBills);
     //上传图片
     billsRouter.post('/uploadImg', billsContr.uploadImg);
     //删除图片

+ 27 - 1
modules/bills_template_lib/controllers/bills_template_controller.js

@@ -9,7 +9,9 @@ import BaseController from "../../common/base/base_controller";
 import billsTemplateFacade from "../facade/bills_template_facade";
 import {default as BillsFixedFlagConst, List as BillsFixedFlagList} from "../../common/const/bills_fixed.js";
 import {default as BillsTypeFlagConst, List as BillsTypeFlagList} from "../../common/const/bills_type.js";
+import CompilationModel from '../../users/models/compilation_model';
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 
 class BillsTemplateController extends BaseController {
 
@@ -21,12 +23,23 @@ class BillsTemplateController extends BaseController {
      * @return {void}
      */
     async main(request, response) {
-        let templateLibs = await billsTemplateFacade.getAllLibs();
+        let filter = request.query.filter ? {compilationId: request.query.filter} : null;
+        let templateLibs = await billsTemplateFacade.getAllLibs(filter);
+        let compilationModel = new CompilationModel();
+        let compilationList = await compilationModel.getCompilationList({_id: 1, name: 1});
+        compilationList.unshift({_id: 'all', name: '所有'});
+        let activeCompilation = compilationList.find(compilation => compilation._id.toString() === request.query.filter);
+        if (activeCompilation) {
+            activeCompilation.active = 'active';
+        } else {
+            compilationList[0].active = 'active'
+        }
         let randerData = {
             title:'清单模板',
             userAccount: request.session.managerData.username,
             userID: request.session.managerData.userID,
             templateLibs:templateLibs,
+            compilationList: compilationList,
             layout: 'maintain/common/html/layout',
             LicenseKey:config.getLicenseKey(process.env.NODE_ENV)
         };
@@ -81,6 +94,7 @@ class BillsTemplateController extends BaseController {
     }
 
     async deleteLibByID(request,response){
+        logger.info(`delete billsTemplateLib ${request.ip}`);
         let result={
             error:0
         };
@@ -139,6 +153,18 @@ class BillsTemplateController extends BaseController {
         }
         response.redirect(request.headers.referer);
     }
+
+    async copyLib(req, res) {
+        try {
+            const data = JSON.parse(req.body.data);
+            const userName = req.session.managerData.username;
+            await billsTemplateFacade.copyLib(data.libID, data.name, userName);
+            res.json({error: 0, data: null, message: 'success'})
+        } catch (err) {
+            console.log(err);
+            res.json({error: 1, data: null, message: 'fail'});
+        }
+    }
 }
 
 export default BillsTemplateController;

+ 21 - 1
modules/bills_template_lib/facade/bills_template_facade.js

@@ -11,6 +11,7 @@ let billTemplateItemsModel = mongoose.model("std_bills_template_items");
 
 let billTemplate={
     addLib:addLib,
+    copyLib: copyLib,
     getAllLibs:getAllLibs,
     getLibByID:getLibByID,
     saveLib:saveLib,
@@ -62,7 +63,10 @@ async function getLibByID(ID) {
     return await billTemplateLibModel.findOne({ID:ID});
 }
 
-async function getAllLibs() {
+async function getAllLibs(filter = null) {
+    if (filter) {
+        return await billTemplateLibModel.find(filter);
+    }
     return await billTemplateLibModel.find();
 }
 
@@ -92,5 +96,21 @@ async function addLib(data){
     }
 }
 
+async function copyLib(libID, name, userName) {
+    const lib = await billTemplateLibModel.findOne({ID: libID}, '-_id').lean();
+    const libItems = await billTemplateItemsModel.find({libID}, '-_id').lean();
+    lib.creator = userName;
+    lib.createDate = Date.now();
+    lib.recentOpr = [{operator: userName, operator: moment(lib.createDate).format('YYYY-MM-D HH:mm:ss')}];
+    lib.name = name;
+    lib.ID = uuidV1();
+    await billTemplateLibModel.create(lib);
+    libItems.forEach(item => {
+        item.libID = lib.ID;
+    });
+    if (libItems.length) {
+        await billTemplateItemsModel.insertMany(libItems);
+    }
+}
 
 export default  billTemplate

+ 1 - 0
modules/bills_template_lib/routes/bills_template_routes.js

@@ -16,6 +16,7 @@ module.exports =function (app) {
     templateRouter.post("/saveLib", billsTemplateController.auth, billsTemplateController.init, billsTemplateController.saveLib);
     templateRouter.post("/deleteLibByID", billsTemplateController.auth, billsTemplateController.init, billsTemplateController.deleteLibByID);
     templateRouter.post("/add-lib", billsTemplateController.auth, billsTemplateController.init, billsTemplateController.addLib);
+    templateRouter.post("/copyLib", billsTemplateController.auth, billsTemplateController.init, billsTemplateController.copyLib);
     templateRouter.post("/updateBillsTemplateItem/:libID", billsTemplateController.auth, billsTemplateController.init, billsTemplateController.updateBillsTemplateItem);
     app.use("/billsTemplate", templateRouter);
 

+ 15 - 1
modules/calc_program_lib/controllers/calc_program_controller.js

@@ -3,16 +3,29 @@
  */
 import BaseController from "../../common/base/base_controller";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 import calcProgramFacade from "../facade/calc_program_facade";
+import CompilationModel from '../../users/models/compilation_model';
 
 class CalcProgramController extends BaseController {
     async main(request, response) {
-        let calcProgramLibs = await calcProgramFacade.findByCondition({}, {templates: 0}, false);
+        let compilationModel = new CompilationModel();
+        let compilationList = await compilationModel.getCompilationList({_id: 1, name: 1});
+        compilationList.unshift({_id: 'all', name: '所有'});
+        let activeCompilation = compilationList.find(compilation => compilation._id.toString() === request.query.filter);
+        if (activeCompilation) {
+            activeCompilation.active = 'active';
+        } else {
+            compilationList[0].active = 'active'
+        }
+        let filter = request.query.filter ? {compilationId: request.query.filter} : {};
+        let calcProgramLibs = await calcProgramFacade.findByCondition(filter, {templates: 0}, false);
         let randerData = {
             title: '计算程序模板库',
             userAccount: request.session.managerData.username,
             userID: request.session.managerData.userID,
             calcProgramLibs: calcProgramLibs,
+            compilationList: compilationList,
             layout: 'maintain/common/html/layout'
         };
         response.render("maintain/calc_program_lib/html/main", randerData);
@@ -59,6 +72,7 @@ class CalcProgramController extends BaseController {
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete calcProgramLib ${request.ip}`);
         let result={
             error:0
         };

+ 38 - 18
modules/common/base/base_controller.js

@@ -7,8 +7,8 @@
  */
 import crypto from "crypto";
 import Url from "url";
-import Moment from "moment";
-import menuData from "../../../config/menu";
+import Moment from 'moment-timezone';
+// import menuData from "../../../config/menu";
 
 class BaseController {
 
@@ -65,35 +65,55 @@ class BaseController {
             console.log('enterINit');
             // 如果不适超级管理员则判断权限
             let sessionManager = request.session.managerData;
+            let MenuPermission = sessionManager.menuData;
             if (sessionManager.superAdmin !== 1) {
-                let currentPermission = sessionManager.permission;
-                // 校验权限
+                let currentPermission = sessionManager.toolPermission;
+                // MenuPermission = sessionManager.menuData;
+                // 校验权限 暂时只检测能否使用该controller名称的总权限,不细分
                 currentPermission = currentPermission.split(',');
                 let withoutPermission = ['login', 'dashboard'];
-                // 工具页面整合
-                let toolPermission = ['rationRepository', 'stdBillsmain', 'stdGljRepository'];
-                let hasToolPermission = false;
-                if (controller === 'tool') {
-                    for (let tmpPermission of toolPermission) {
-                        if (currentPermission.indexOf(tmpPermission) >= 0) {
-                            hasToolPermission = true;
-                            break;
-                        }
+
+                // 工具
+                let toolAllPermission = sessionManager.toolAllPermission;
+                toolAllPermission = toolAllPermission.split(',');
+                // let toolAllPermission = ['stdBillsmain', 'rationRepository', 'rpt_tpl', 'stdGljRepository',
+                //     'billsGuidance', 'clearJunk', 'billsTemplate', 'mainTreeCol',
+                //     'materialReplace', 'projectFeature', 'feeRate', 'calcProgram'];
+                let hasToolPermission = true;
+                if (toolAllPermission.indexOf(controller) >= 0 && currentPermission.indexOf(controller) < 0) {
+                    hasToolPermission = false;
+                }
+
+                let currentControllerPermission = '';
+                // let currentActionPermission = true;
+
+                if(withoutPermission.indexOf(controller) < 0) {
+                    if (MenuPermission.hasOwnProperty(controller)) {
+                        currentControllerPermission = MenuPermission[controller];
+
                     }
+
+                    // if (currentControllerPermission !== '' && action !== 'index') {
+                    //     if (currentControllerPermission.children.hasOwnProperty(action)) {
+                    //         currentActionPermission = true;
+                    //     }
+                    // } else if (action === 'index') {
+                    //     currentActionPermission = true
+                    // }
                 }
 
-                if (!hasToolPermission && withoutPermission.indexOf(controller) < 0 &&
-                    (currentPermission.length <= 0 || currentPermission.indexOf(controller)) < 0) {
+                if (withoutPermission.indexOf(controller) < 0 &&
+                    !(hasToolPermission || currentControllerPermission !== '')) {
 
                     throw '没有权限';
                 }
             }
 
             // 菜单数据
-            response.locals.menu = menuData;
+            response.locals.menu = MenuPermission;
             // 二级菜单数据
-            response.locals.secondMenu = menuData[controller] !== undefined && menuData[controller].children !== undefined ?
-                menuData[controller].children : {};
+            response.locals.secondMenu = MenuPermission[controller] !== undefined && MenuPermission[controller].children !== undefined ?
+                MenuPermission[controller].children : {};
 
             // url相关数据
             response.locals.urlQuery = JSON.stringify(urlInfo.query);

+ 42 - 2
modules/common/const/bills_fixed.js

@@ -42,7 +42,34 @@ const fixedFlag = {
     //工程造价
     ENGINEERINGCOST: 19,
     //增值税
-    ADDED_VALUE_TAX: 20
+    ADDED_VALUE_TAX: 20,
+    //专项技术措施暂估价
+    SPECIAL_TECH_PROVISIONAL: 21,
+    //专业发包工程管理费
+    LET_CONTRACT_MANAGEMENT: 22,
+    //人工
+    LABOUR: 23,
+    //材料
+    MATERIAL: 24,
+    //施工机械
+    MACHINE: 25,
+    //索赔
+    CLAIM: 26,
+    //现场签证
+    VISA: 27,
+    //附加税
+    ADDITIONAL_TAX: 28,
+    //环境保护税
+    ENVIRONMENTAL_PROTECTION_TAX: 29,
+    //建设工程竣工档案编制费
+    PROJECT_COMPLETE_ARCH_FEE:30,
+    //住宅工程质量分户验收费
+    HOUSE_QUALITY_ACCEPT_FEE:31,
+    //组织措施费
+    ORGANIZATION:32,
+    //其他措施费
+    OTHER_MEASURE_FEE:33
+
 };
 const fixedFlagList = [
     {name: "分部分项工程", value: fixedFlag.SUB_ENGINERRING},
@@ -57,14 +84,27 @@ const fixedFlagList = [
     {name: "材料(工程设备)暂估价", value: fixedFlag.MATERIAL_PROVISIONAL},
     {name: "专业工程暂估价", value: fixedFlag.ENGINEERING_ESITIMATE},
     {name: "计日工", value: fixedFlag.DAYWORK},
+    {name: '人工', value: fixedFlag.LABOUR},
+    {name: '材料', value: fixedFlag.MATERIAL},
+    {name: '施工机械', value: fixedFlag.MACHINE},
     {name: "总承包服务费", value: fixedFlag.TURN_KEY_CONTRACT},
     {name: "索赔与现场签证", value: fixedFlag.CLAIM_VISA},
+    {name: "索赔", value: fixedFlag.CLAIM},
+    {name: "现场签证", value: fixedFlag.VISA},
     {name: "规费", value: fixedFlag.CHARGE},
     {name: "社会保险费及住房公积金", value: fixedFlag.SOCIAL_INSURANCE_HOUSING_FUND},
     {name: "工程排污费", value: fixedFlag.POLLUTANTS},
     {name: "税金", value: fixedFlag.TAX},
     {name: "工程造价", value: fixedFlag.ENGINEERINGCOST},
-    {name: "增值税", value: fixedFlag.ADDED_VALUE_TAX}
+    {name: "增值税", value: fixedFlag.ADDED_VALUE_TAX},
+    {name: "附加税", value: fixedFlag.ADDITIONAL_TAX},
+    {name: "环境保护税", value: fixedFlag.ENVIRONMENTAL_PROTECTION_TAX},
+    {name: '专项技术措施暂估价', value: fixedFlag.SPECIAL_TECH_PROVISIONAL},
+    {name: '专业发包工程管理费', value: fixedFlag.LET_CONTRACT_MANAGEMENT},
+    {name: '建设工程竣工档案编制费', value: fixedFlag.PROJECT_COMPLETE_ARCH_FEE},
+    {name: '住宅工程质量分户验收费', value: fixedFlag.HOUSE_QUALITY_ACCEPT_FEE},
+    {name: '组织措施费', value: fixedFlag.ORGANIZATION},
+    {name: '其他措施费', value: fixedFlag.OTHER_MEASURE_FEE}
 ];
 
 export {fixedFlag as default, fixedFlagList as List};

+ 102 - 0
modules/economic_lib/controllers/economic_controller.js

@@ -0,0 +1,102 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+import BaseController from "../../common/base/base_controller";
+let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import economicFacade from "../facade/economic_facade";
+
+class EconomicController extends BaseController{
+    async main(request, response) {
+        let economicLibs = await economicFacade.findByCondition({},{info:0},false);
+        let randerData = {
+            title:'主要经济指标库',
+            userAccount: request.session.managerData.username,
+            userID: request.session.managerData.userID,
+            economicLibs:economicLibs,
+            layout: 'maintain/common/html/layout'
+        };
+        response.render("maintain/economic_lib/html/main", randerData);
+    }
+    async addLib(request, response){
+        try {
+            await economicFacade.addLib(request.body);
+        }catch (error) {
+            console.log(error);
+        }
+        response.redirect(request.headers.referer);
+    }
+    async findLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let conditions={ID:data.ID};
+            let resultData = await economicFacade.findByCondition(conditions);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async saveLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await economicFacade.saveLib(data);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async deleteLibByID(request,response){
+        logger.info(`delete feeRateLib ${request.ip}`);
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await economicFacade.deleteLibByID(data.ID);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async edit(request,response){
+        //先取出替换库信息:
+        let libID = request.params.libID;
+        let economicLib = await economicFacade.findByCondition({'ID':libID});
+        if(economicLib){
+            let randerData = {
+                title:'主要经济指标库',
+                mainURL:'/economic/main',
+                libName:economicLib.name,
+                userAccount: request.session.managerData.username,
+                userID: request.session.managerData.userID,
+                originalInfo:JSON.stringify(economicLib.index),
+                libID:libID,
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                layout: 'maintain/common/html/edit_layout'
+            };
+            response.render("maintain/economic_lib/html/edit", randerData);
+        }else {
+            response.redirect(request.headers.referer);
+        }
+    }
+}
+
+export default EconomicController;

+ 41 - 0
modules/economic_lib/facade/economic_facade.js

@@ -0,0 +1,41 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+import mongoose from "mongoose";
+
+const uuidV1 = require('uuid/v1');
+let moment = require("moment");
+let economicModel = mongoose.model('std_economic_lib');
+
+let economicLib = {
+    findByCondition:async function(conditions,options,single=true){
+        if(single == true){
+            return await economicModel.findOne(conditions,options);
+        }else {
+            return await  economicModel.find(conditions,options);
+        }
+    },
+    addLib : async function (data){
+        let now = new Date().getTime();
+        let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
+        let newLib = {
+            creator: data.userAccount,
+            createDate: now,
+            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+            name: data.name,
+        };
+        newLib.ID = uuidV1();
+        return await economicModel.create(newLib);
+
+
+    },
+    saveLib:async function(param) {
+        return await economicModel.findOneAndUpdate(param.query,param.data,{new:true});
+    },
+    deleteLibByID:async function(ID){
+        return await economicModel.deleteOne({ID:ID});
+    }
+};
+
+export default economicLib

+ 21 - 0
modules/economic_lib/routes/economic_routes.js

@@ -0,0 +1,21 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+let express = require("express");
+let economicRouter =express.Router();
+import EconomicController from "../controllers/economic_controller";
+let economicController = new EconomicController();
+
+module.exports =function (app) {
+
+    economicRouter.get("/main", economicController.auth, economicController.init, economicController.main);
+    economicRouter.post("/addLib", economicController.auth, economicController.init, economicController.addLib);
+    economicRouter.post("/findLib", economicController.auth, economicController.init, economicController.findLib);
+    economicRouter.post("/saveLib", economicController.auth, economicController.init, economicController.saveLib);
+    economicRouter.post("/deleteLibByID", economicController.auth, economicController.init, economicController.deleteLibByID);
+    economicRouter.get("/edit/:libID", economicController.auth, economicController.init, economicController.edit);
+
+
+    app.use("/economic", economicRouter);
+};

+ 102 - 0
modules/engineer_feature_lib/controllers/engineer_feature_controller.js

@@ -0,0 +1,102 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+import BaseController from "../../common/base/base_controller";
+let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import engineerFeatureFacade from "../facade/engineer_feature_facade";
+
+class EngineerFeatureController extends BaseController{
+    async main(request, response) {
+        let engineerFeatureLibs = await engineerFeatureFacade.findByCondition({},{info:0},false);
+        let randerData = {
+            title:'工程特征指标库',
+            userAccount: request.session.managerData.username,
+            userID: request.session.managerData.userID,
+            engineerFeatureLibs:engineerFeatureLibs,
+            layout: 'maintain/common/html/layout'
+        };
+        response.render("maintain/engineer_feature_lib/html/main", randerData);
+    }
+    async addLib(request, response){
+        try {
+            await engineerFeatureFacade.addLib(request.body);
+        }catch (error) {
+            console.log(error);
+        }
+        response.redirect(request.headers.referer);
+    }
+    async findLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let conditions={ID:data.ID};
+            let resultData = await engineerFeatureFacade.findByCondition(conditions);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async saveLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await engineerFeatureFacade.saveLib(data);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async deleteLibByID(request,response){
+        logger.info(`delete feeRateLib ${request.ip}`);
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await engineerFeatureFacade.deleteLibByID(data.ID);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async edit(request,response){
+        //先取出替换库信息:
+        let libID = request.params.libID;
+        let engineerFeatureLib = await engineerFeatureFacade.findByCondition({'ID':libID});
+        if(engineerFeatureLib){
+            let randerData = {
+                title:'工程特征指标库',
+                mainURL:'/engineerFeature/main',
+                libName:engineerFeatureLib.name,
+                userAccount: request.session.managerData.username,
+                userID: request.session.managerData.userID,
+                originalInfo:JSON.stringify(engineerFeatureLib.features),
+                libID:libID,
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                layout: 'maintain/common/html/edit_layout'
+            };
+            response.render("maintain/engineer_feature_lib/html/edit", randerData);
+        }else {
+            response.redirect(request.headers.referer);
+        }
+    }
+}
+
+export default EngineerFeatureController;

+ 41 - 0
modules/engineer_feature_lib/facade/engineer_feature_facade.js

@@ -0,0 +1,41 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+import mongoose from "mongoose";
+
+const uuidV1 = require('uuid/v1');
+let moment = require("moment");
+let engineerFeatureModel = mongoose.model('std_engineer_feature_lib');
+
+let engineerFeatureLib = {
+    findByCondition:async function(conditions,options,single=true){
+        if(single == true){
+            return await engineerFeatureModel.findOne(conditions,options);
+        }else {
+            return await  engineerFeatureModel.find(conditions,options);
+        }
+    },
+    addLib : async function (data){
+        let now = new Date().getTime();
+        let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
+        let newLib = {
+            creator: data.userAccount,
+            createDate: now,
+            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+            name: data.name,
+        };
+        newLib.ID = uuidV1();
+        return await engineerFeatureModel.create(newLib);
+
+
+    },
+    saveLib:async function(param) {
+        return await engineerFeatureModel.findOneAndUpdate(param.query,param.data,{new:true});
+    },
+    deleteLibByID:async function(ID){
+        return await engineerFeatureModel.deleteOne({ID:ID});
+    }
+};
+
+export default engineerFeatureLib

+ 21 - 0
modules/engineer_feature_lib/routes/engineer_feature_routes.js

@@ -0,0 +1,21 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+let express = require("express");
+let engineerFeatureRouter =express.Router();
+import EngineerFeatureController from "../controllers/engineer_feature_controller";
+let engineerFeatureController = new EngineerFeatureController();
+
+module.exports =function (app) {
+
+    engineerFeatureRouter.get("/main", engineerFeatureController.auth, engineerFeatureController.init, engineerFeatureController.main);
+    engineerFeatureRouter.post("/addLib", engineerFeatureController.auth, engineerFeatureController.init, engineerFeatureController.addLib);
+    engineerFeatureRouter.post("/findLib", engineerFeatureController.auth, engineerFeatureController.init, engineerFeatureController.findLib);
+    engineerFeatureRouter.post("/saveLib", engineerFeatureController.auth, engineerFeatureController.init, engineerFeatureController.saveLib);
+    engineerFeatureRouter.post("/deleteLibByID", engineerFeatureController.auth, engineerFeatureController.init, engineerFeatureController.deleteLibByID);
+    engineerFeatureRouter.get("/edit/:libID", engineerFeatureController.auth, engineerFeatureController.init, engineerFeatureController.edit);
+
+
+    app.use("/engineerFeature", engineerFeatureRouter);
+};

+ 102 - 0
modules/engineer_info_lib/controllers/engineer_info_controller.js

@@ -0,0 +1,102 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+import BaseController from "../../common/base/base_controller";
+let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import engineerInfoFacade from "../facade/engineer_info_facade";
+
+class EngineerInfoController extends BaseController{
+    async main(request, response) {
+        let engineerInfoLibs = await engineerInfoFacade.findByCondition({},{info:0},false);
+        let randerData = {
+            title:'工程信息库',
+            userAccount: request.session.managerData.username,
+            userID: request.session.managerData.userID,
+            engineerInfoLibs:engineerInfoLibs,
+            layout: 'maintain/common/html/layout'
+        };
+        response.render("maintain/engineer_info_lib/html/main", randerData);
+    }
+    async addLib(request, response){
+        try {
+            await engineerInfoFacade.addLib(request.body);
+        }catch (error) {
+            console.log(error);
+        }
+        response.redirect(request.headers.referer);
+    }
+    async findLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let conditions={ID:data.ID};
+            let resultData = await engineerInfoFacade.findByCondition(conditions);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async saveLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await engineerInfoFacade.saveLib(data);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async deleteLibByID(request,response){
+        logger.info(`delete feeRateLib ${request.ip}`);
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await engineerInfoFacade.deleteLibByID(data.ID);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async edit(request,response){
+        //先取出替换库信息:
+        let libID = request.params.libID;
+        let engineerInfoLib = await engineerInfoFacade.findByCondition({'ID':libID});
+        if(engineerInfoLib){
+            let randerData = {
+                title:'工程信息库',
+                mainURL:'/engineerInfo/main',
+                libName:engineerInfoLib.name,
+                userAccount: request.session.managerData.username,
+                userID: request.session.managerData.userID,
+                originalInfo:JSON.stringify(engineerInfoLib.info),
+                libID:libID,
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                layout: 'maintain/common/html/edit_layout'
+            };
+            response.render("maintain/engineer_info_lib/html/edit", randerData);
+        }else {
+            response.redirect(request.headers.referer);
+        }
+    }
+}
+
+export default EngineerInfoController;

+ 42 - 0
modules/engineer_info_lib/facade/engineer_info_facade.js

@@ -0,0 +1,42 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+import mongoose from "mongoose";
+
+const uuidV1 = require('uuid/v1');
+let moment = require("moment");
+let engineerInfoModel = mongoose.model('std_engineer_info_lib');
+const _ = require('lodash');
+
+let engineerInfoLib = {
+    findByCondition:async function(conditions,options,single=true){
+        if(single == true){
+            return await engineerInfoModel.findOne(conditions,options);
+        }else {
+            return await  engineerInfoModel.find(conditions,options);
+        }
+    },
+    addLib : async function (data){
+        let now = new Date().getTime();
+        let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
+        let newLib = {
+            creator: data.userAccount,
+            createDate: now,
+            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+            name: data.name,
+        };
+        newLib.ID = uuidV1();
+        return await engineerInfoModel.create(newLib);
+
+
+    },
+    saveLib:async function(param) {
+        return await engineerInfoModel.findOneAndUpdate(param.query,param.data,{new:true});
+    },
+    deleteLibByID:async function(ID){
+        return await engineerInfoModel.deleteOne({ID:ID});
+    },
+};
+
+export default engineerInfoLib

+ 21 - 0
modules/engineer_info_lib/routes/engineer_info_routes.js

@@ -0,0 +1,21 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+let express = require("express");
+let engineerInfoRouter =express.Router();
+import EngineerInfoController from "../controllers/engineer_info_controller";
+let engineerInfoController = new EngineerInfoController();
+
+module.exports =function (app) {
+
+    engineerInfoRouter.get("/main", engineerInfoController.auth, engineerInfoController.init, engineerInfoController.main);
+    engineerInfoRouter.post("/addLib", engineerInfoController.auth, engineerInfoController.init, engineerInfoController.addLib);
+    engineerInfoRouter.post("/findLib", engineerInfoController.auth, engineerInfoController.init, engineerInfoController.findLib);
+    engineerInfoRouter.post("/saveLib", engineerInfoController.auth, engineerInfoController.init, engineerInfoController.saveLib);
+    engineerInfoRouter.post("/deleteLibByID", engineerInfoController.auth, engineerInfoController.init, engineerInfoController.deleteLibByID);
+    engineerInfoRouter.get("/edit/:libID", engineerInfoController.auth, engineerInfoController.init, engineerInfoController.edit);
+
+
+    app.use("/engineerInfo", engineerInfoRouter);
+};

+ 15 - 1
modules/fee_rate_lib/controllers/fee_rate_controller.js

@@ -3,16 +3,29 @@
  */
 import BaseController from "../../common/base/base_controller";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 import feeRateFacade from "../facade/fee_rate_facade";
+import CompilationModel from '../../users/models/compilation_model';
 
 class FeeRateController extends BaseController{
     async main(request, response) {
-        let feeRateLibs = await feeRateFacade.findByCondition({},{rates:0},false);
+        let compilationModel = new CompilationModel();
+        let compilationList = await compilationModel.getCompilationList({_id: 1, name: 1});
+        compilationList.unshift({_id: 'all', name: '所有'});
+        let activeCompilation = compilationList.find(compilation => compilation._id.toString() === request.query.filter);
+        if (activeCompilation) {
+            activeCompilation.active = 'active';
+        } else {
+            compilationList[0].active = 'active'
+        }
+        let filter = request.query.filter ? {compilationId: request.query.filter} : {};
+        let feeRateLibs = await feeRateFacade.findByCondition(filter,{rates:0},false);
         let randerData = {
             title:'费率标准库',
             userAccount: request.session.managerData.username,
             userID: request.session.managerData.userID,
             feeRateLibs:feeRateLibs,
+            compilationList: compilationList,
             layout: 'maintain/common/html/layout'
         };
         response.render("maintain/fee_rate_lib/html/main", randerData);
@@ -59,6 +72,7 @@ class FeeRateController extends BaseController{
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete feeRateLib ${request.ip}`);
         let result={
             error:0
         };

+ 2 - 0
modules/main_col_lib/controllers/main_col_controller.js

@@ -9,6 +9,7 @@
 import BaseController from "../../common/base/base_controller";
 import mainColFacade from "../facade/main_col_facade";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 
 class MainColController extends BaseController {
 
@@ -36,6 +37,7 @@ class MainColController extends BaseController {
     }
 
     async deleteLibByID(request,response){
+        logger.info(`delete colSettingLib ${request.ip}`);
         let result={
             error:0
         };

+ 102 - 0
modules/main_quantity_lib/controllers/quantity_controller.js

@@ -0,0 +1,102 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+import BaseController from "../../common/base/base_controller";
+let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import quantityFacade from "../facade/quantity_facade";
+
+class QuantityController extends BaseController{
+    async main(request, response) {
+        let quantityLibs = await quantityFacade.findByCondition({},{info:0},false);
+        let randerData = {
+            title:'主要工程量指标库',
+            userAccount: request.session.managerData.username,
+            userID: request.session.managerData.userID,
+            quantityLibs:quantityLibs,
+            layout: 'maintain/common/html/layout'
+        };
+        response.render("maintain/main_quantity_lib/html/main", randerData);
+    }
+    async addLib(request, response){
+        try {
+            await quantityFacade.addLib(request.body);
+        }catch (error) {
+            console.log(error);
+        }
+        response.redirect(request.headers.referer);
+    }
+    async findLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let conditions={ID:data.ID};
+            let resultData = await quantityFacade.findByCondition(conditions);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async saveLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await quantityFacade.saveLib(data);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async deleteLibByID(request,response){
+        logger.info(`delete feeRateLib ${request.ip}`);
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await quantityFacade.deleteLibByID(data.ID);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async edit(request,response){
+        //先取出替换库信息:
+        let libID = request.params.libID;
+        let quantityLib = await quantityFacade.findByCondition({'ID':libID});
+        if(quantityLib){
+            let randerData = {
+                title:'主要工程量指标库',
+                mainURL:'/material/main',
+                libName:quantityLib.name,
+                userAccount: request.session.managerData.username,
+                userID: request.session.managerData.userID,
+                originalInfo:JSON.stringify(quantityLib.index),
+                libID:libID,
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                layout: 'maintain/common/html/edit_layout'
+            };
+            response.render("maintain/main_quantity_lib/html/edit", randerData);
+        }else {
+            response.redirect(request.headers.referer);
+        }
+    }
+}
+
+export default QuantityController;

+ 41 - 0
modules/main_quantity_lib/facade/quantity_facade.js

@@ -0,0 +1,41 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+import mongoose from "mongoose";
+
+const uuidV1 = require('uuid/v1');
+let moment = require("moment");
+let quantityModel = mongoose.model('std_main_quantity_lib');
+
+let quantityLib = {
+    findByCondition:async function(conditions,options,single=true){
+        if(single == true){
+            return await quantityModel.findOne(conditions,options);
+        }else {
+            return await  quantityModel.find(conditions,options);
+        }
+    },
+    addLib : async function (data){
+        let now = new Date().getTime();
+        let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
+        let newLib = {
+            creator: data.userAccount,
+            createDate: now,
+            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+            name: data.name,
+        };
+        newLib.ID = uuidV1();
+        return await quantityModel.create(newLib);
+
+
+    },
+    saveLib:async function(param) {
+        return await quantityModel.findOneAndUpdate(param.query,param.data,{new:true});
+    },
+    deleteLibByID:async function(ID){
+        return await quantityModel.deleteOne({ID:ID});
+    }
+};
+
+export default quantityLib

+ 21 - 0
modules/main_quantity_lib/routes/quantity_routes.js

@@ -0,0 +1,21 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+let express = require("express");
+let quantityRouter =express.Router();
+import QuantityController from "../controllers/quantity_controller";
+let quantityController = new QuantityController();
+
+module.exports =function (app) {
+
+    quantityRouter.get("/main", quantityController.auth, quantityController.init, quantityController.main);
+    quantityRouter.post("/addLib", quantityController.auth, quantityController.init, quantityController.addLib);
+    quantityRouter.post("/findLib", quantityController.auth, quantityController.init, quantityController.findLib);
+    quantityRouter.post("/saveLib", quantityController.auth, quantityController.init, quantityController.saveLib);
+    quantityRouter.post("/deleteLibByID", quantityController.auth, quantityController.init, quantityController.deleteLibByID);
+    quantityRouter.get("/edit/:libID", quantityController.auth, quantityController.init, quantityController.edit);
+
+
+    app.use("/mainQuantity", quantityRouter);
+};

+ 102 - 0
modules/material_lib/controllers/material_controller.js

@@ -0,0 +1,102 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+import BaseController from "../../common/base/base_controller";
+let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import materialFacade from "../facade/material_facade";
+
+class MaterialController extends BaseController{
+    async main(request, response) {
+        let materialLibs = await materialFacade.findByCondition({},{info:0},false);
+        let randerData = {
+            title:'主要工料指标库',
+            userAccount: request.session.managerData.username,
+            userID: request.session.managerData.userID,
+            materialLibs:materialLibs,
+            layout: 'maintain/common/html/layout'
+        };
+        response.render("maintain/material_lib/html/main", randerData);
+    }
+    async addLib(request, response){
+        try {
+            await materialFacade.addLib(request.body);
+        }catch (error) {
+            console.log(error);
+        }
+        response.redirect(request.headers.referer);
+    }
+    async findLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let conditions={ID:data.ID};
+            let resultData = await materialFacade.findByCondition(conditions);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async saveLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await materialFacade.saveLib(data);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async deleteLibByID(request,response){
+        logger.info(`delete feeRateLib ${request.ip}`);
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await materialFacade.deleteLibByID(data.ID);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async edit(request,response){
+        //先取出替换库信息:
+        let libID = request.params.libID;
+        let materialLib = await materialFacade.findByCondition({'ID':libID});
+        if(materialLib){
+            let randerData = {
+                title:'主要工料指标库',
+                mainURL:'/material/main',
+                libName:materialLib.name,
+                userAccount: request.session.managerData.username,
+                userID: request.session.managerData.userID,
+                originalInfo:JSON.stringify(materialLib.materials),
+                libID:libID,
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                layout: 'maintain/common/html/edit_layout'
+            };
+            response.render("maintain/material_lib/html/edit", randerData);
+        }else {
+            response.redirect(request.headers.referer);
+        }
+    }
+}
+
+export default MaterialController;

+ 41 - 0
modules/material_lib/facade/material_facade.js

@@ -0,0 +1,41 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+import mongoose from "mongoose";
+
+const uuidV1 = require('uuid/v1');
+let moment = require("moment");
+let materialModel = mongoose.model('std_material_lib');
+
+let materialLib = {
+    findByCondition:async function(conditions,options,single=true){
+        if(single == true){
+            return await materialModel.findOne(conditions,options);
+        }else {
+            return await  materialModel.find(conditions,options);
+        }
+    },
+    addLib : async function (data){
+        let now = new Date().getTime();
+        let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
+        let newLib = {
+            creator: data.userAccount,
+            createDate: now,
+            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+            name: data.name,
+        };
+        newLib.ID = uuidV1();
+        return await materialModel.create(newLib);
+
+
+    },
+    saveLib:async function(param) {
+        return await materialModel.findOneAndUpdate(param.query,param.data,{new:true});
+    },
+    deleteLibByID:async function(ID){
+        return await materialModel.deleteOne({ID:ID});
+    }
+};
+
+export default materialLib

+ 21 - 0
modules/material_lib/routes/material_routes.js

@@ -0,0 +1,21 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+let express = require("express");
+let materialRouter =express.Router();
+import MaterialController from "../controllers/material_controller";
+let materialController = new MaterialController();
+
+module.exports =function (app) {
+
+    materialRouter.get("/main", materialController.auth, materialController.init, materialController.main);
+    materialRouter.post("/addLib", materialController.auth, materialController.init, materialController.addLib);
+    materialRouter.post("/findLib", materialController.auth, materialController.init, materialController.findLib);
+    materialRouter.post("/saveLib", materialController.auth, materialController.init, materialController.saveLib);
+    materialRouter.post("/deleteLibByID", materialController.auth, materialController.init, materialController.deleteLibByID);
+    materialRouter.get("/edit/:libID", materialController.auth, materialController.init, materialController.edit);
+
+
+    app.use("/material", materialRouter);
+};

+ 4 - 0
modules/material_replace_lib/controllers/material_replace_controller.js

@@ -4,6 +4,7 @@
 import BaseController from "../../common/base/base_controller";
 import materialFacade from "../facade/material_replace_facade";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
 
 class ReplaceController extends BaseController{
     /**
@@ -34,6 +35,7 @@ class ReplaceController extends BaseController{
             let gljLib = await  materialFacade.findGLJLibByComID(compilationId);
             let billsList = await materialFacade.findBillsByLibID(libID);
             //let templateDatas = await materialFacade.getTemplateDatasByLibID(libID);
+            //let stdBills = await  materialFacade.getStdBillsByLib(billsLibId);
 
             let randerData = {
                 title:'材料替换库',
@@ -45,6 +47,7 @@ class ReplaceController extends BaseController{
                 billsLibId:billsLibId,
                 gljLibID:gljLib.ID,
                 libID:libID,
+                //stdBills:JSON.stringify(stdBills),
                 LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
                 layout: 'maintain/common/html/edit_layout'
             };
@@ -98,6 +101,7 @@ class ReplaceController extends BaseController{
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete materialLib ${request.ip}`);
         let result={
             error:0
         };

+ 4 - 0
modules/material_replace_lib/facade/material_replace_facade.js

@@ -76,6 +76,10 @@ let materialReplaceLib = {
     },
     getMaterialByBillsID : async function(billsID){
        return  await replaceMaterialModel.find({billsItemID:billsID});
+    },
+    getStdBillsByLib:async function(libID){
+        let bills = await stdBillsModel.find({billsLibId: libID},['ID','code','name','items']);
+        return bills;
     }
 };
 function prepareDatas(data) {//整理数据

+ 102 - 0
modules/over_height_lib/controllers/over_height_controller.js

@@ -0,0 +1,102 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+import BaseController from "../../common/base/base_controller";
+let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import overHeightFacade from "../facade/over_height_facade";
+
+class OverHeightController extends BaseController{
+    async main(request, response) {
+        let overHeightLibs = await overHeightFacade.findByCondition({},{info:0},false);
+        let randerData = {
+            title:'超高降效库',
+            userAccount: request.session.managerData.username,
+            userID: request.session.managerData.userID,
+            overHeightLibs:overHeightLibs,
+            layout: 'maintain/common/html/layout'
+        };
+        response.render("maintain/over_height_lib/html/main", randerData);
+    }
+    async addLib(request, response){
+        try {
+            await overHeightFacade.addLib(request.body);
+        }catch (error) {
+            console.log(error);
+        }
+        response.redirect(request.headers.referer);
+    }
+    async findLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let conditions={ID:data.ID};
+            let resultData = await overHeightFacade.findByCondition(conditions);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async saveLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await overHeightFacade.saveLib(data);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async deleteLibByID(request,response){
+        logger.info(`delete feeRateLib ${request.ip}`);
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await overHeightFacade.deleteLibByID(data.ID);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async edit(request,response){
+        //先取出替换库信息:
+        let libID = request.params.libID;
+        let overHeightLib = await overHeightFacade.findByCondition({'ID':libID});
+        if(overHeightLib){
+            let randerData = {
+                title:'超高降效库',
+                mainURL:'/overHeight/main',
+                libName:overHeightLib.name,
+                userAccount: request.session.managerData.username,
+                userID: request.session.managerData.userID,
+                originalInfo:JSON.stringify(overHeightLib.list),
+                libID:libID,
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                layout: 'maintain/common/html/edit_layout'
+            };
+            response.render("maintain/over_height_lib/html/edit", randerData);
+        }else {
+            response.redirect(request.headers.referer);
+        }
+    }
+}
+
+export default OverHeightController;

+ 41 - 0
modules/over_height_lib/facade/over_height_facade.js

@@ -0,0 +1,41 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+import mongoose from "mongoose";
+
+const uuidV1 = require('uuid/v1');
+let moment = require("moment");
+let overHeightModel = mongoose.model('std_over_height_lib');
+
+let overHeightLib = {
+    findByCondition:async function(conditions,options,single=true){
+        if(single == true){
+            return await overHeightModel.findOne(conditions,options);
+        }else {
+            return await  overHeightModel.find(conditions,options);
+        }
+    },
+    addLib : async function (data){
+        let now = new Date().getTime();
+        let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
+        let newLib = {
+            creator: data.userAccount,
+            createDate: now,
+            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+            name: data.name,
+        };
+        newLib.ID = uuidV1();
+        return await overHeightModel.create(newLib);
+
+
+    },
+    saveLib:async function(param) {
+        return await overHeightModel.findOneAndUpdate(param.query,param.data,{new:true});
+    },
+    deleteLibByID:async function(ID){
+        return await overHeightModel.deleteOne({ID:ID});
+    }
+};
+
+export default overHeightLib

+ 21 - 0
modules/over_height_lib/routes/over_height_routes.js

@@ -0,0 +1,21 @@
+/**
+ * Created by zhang on 2018/9/10.
+ */
+
+let express = require("express");
+let overHeightRouter = express.Router();
+import OverHeightController from "../controllers/over_height_controller";
+let overHeightController = new OverHeightController();
+
+module.exports =function (app) {
+
+    overHeightRouter.get("/main", overHeightController.auth, overHeightController.init, overHeightController.main);
+    overHeightRouter.post("/addLib", overHeightController.auth, overHeightController.init, overHeightController.addLib);
+    overHeightRouter.post("/findLib", overHeightController.auth, overHeightController.init, overHeightController.findLib);
+    overHeightRouter.post("/saveLib", overHeightController.auth, overHeightController.init, overHeightController.saveLib);
+    overHeightRouter.post("/deleteLibByID", overHeightController.auth, overHeightController.init, overHeightController.deleteLibByID);
+    overHeightRouter.get("/edit/:libID", overHeightController.auth, overHeightController.init, overHeightController.edit);
+
+
+    app.use("/overHeight", overHeightRouter);
+};

+ 44 - 1
modules/project_feature_lib/controllers/project_feature_controller.js

@@ -4,15 +4,57 @@
 import BaseController from "../../common/base/base_controller";
 import featureFacade from "../facade/project_feature_facade";
 let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import CompilationModel from '../../users/models/compilation_model';
+let mongoose = require('mongoose');
+let featureLibModel = mongoose.model('std_project_feature_lib');
 
 class FeatureController extends BaseController{
     async main(request, response) {
-        let featureLibs = await featureFacade.findByCondition({},{feature:0},false);
+        //
+        let allLibs = await featureLibModel.find({});
+        for (let lib of allLibs) {
+            if (lib.name.indexOf('重庆2018') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5b52b027fd3bb0000b257cf8', compilationName: '重庆定额(2018)'}}, {multi: true});
+            } else if (lib.name.indexOf('甘肃2013') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5b75146cfa63aa000df7ff3c', compilationName: '甘肃定额(2013)'}}, {multi: true});
+            } else if (lib.name.indexOf('江西2017') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5b754aacfa63aa000df80481', compilationName: '江西定额(2017)'}}, {multi: true});
+            }else if (lib.name.indexOf('浙江2010') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5b85218494c4a2000d3d8f5c', compilationName: '浙江定额(2010)'}}, {multi: true});
+            }else if (lib.name.indexOf('内蒙古2017') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5c1760b489ad9a000dd1e78a', compilationName: '内蒙古定额(2017)'}}, {multi: true});
+            }else if (lib.name.indexOf('浙江2017') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5c246ed917f3a0000dbf7111', compilationName: '浙江定额(2018)'}}, {multi: true});
+            }else if (lib.name.indexOf('广东') !== -1) {
+                await featureLibModel.update({ID: lib.ID},
+                    {$set: {compilationId: '5c66649650da2d000d8d37ba', compilationName: '广东定额(2018)'}}, {multi: true});
+            }
+        }
+        //
+        let compilationModel = new CompilationModel();
+        let compilationList = await compilationModel.getCompilationList({_id: 1, name: 1});
+        compilationList.unshift({_id: 'all', name: '所有'});
+        let activeCompilation = compilationList.find(compilation => compilation._id.toString() === request.query.filter);
+        if (activeCompilation) {
+            activeCompilation.active = 'active';
+        } else {
+            compilationList[0].active = 'active'
+        }
+        let filter = request.query.filter ? {compilationId: request.query.filter} : {};
+        let featureLibs = await featureFacade.findByCondition(filter,{feature:0},false);
         let randerData = {
             title:'工程特征库',
             userAccount: request.session.managerData.username,
             userID: request.session.managerData.userID,
             featureLibs:featureLibs,
+            compilationList: compilationList,
             layout: 'maintain/common/html/layout'
         };
         response.render("maintain/project_feature_lib/html/main", randerData);
@@ -59,6 +101,7 @@ class FeatureController extends BaseController{
         response.json(result);
     }
     async deleteLibByID(request,response){
+        logger.info(`delete projectFeatureLib ${request.ip}`);
         let result={
             error:0
         };

+ 17 - 8
modules/project_feature_lib/facade/project_feature_facade.js

@@ -5,6 +5,7 @@ import mongoose from "mongoose";
 const uuidV1 = require('uuid/v1');
 let moment = require("moment");
 let projectFeatureModel = mongoose.model('std_project_feature_lib');
+let compilationModel = mongoose.model('compilation');
 
 
 let projectFeatureLib = {
@@ -18,14 +19,22 @@ let projectFeatureLib = {
     addLib : async function (data){
         let now = new Date().getTime();
         let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
-        let newLib = {
-            creator: data.userAccount,
-            createDate: now,
-            recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
-            name: data.name,
-        };
-        newLib.ID = uuidV1();
-        return await projectFeatureModel.create(newLib);
+        //取编办信息
+        let compilation = await compilationModel.findOne({_id:data.compilationId});
+        if(compilation){
+            let newLib = {
+                creator: data.userAccount,
+                createDate: now,
+                recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+                name: data.name,
+                compilationId: data.compilationId,
+                compilationName: compilation.name,
+            };
+            newLib.ID = uuidV1();
+            return await projectFeatureModel.create(newLib);
+        }else {
+            throw  new Error("没有找到该编办!");
+        }
     },
     saveLib:async function(param) {
         return await projectFeatureModel.findOneAndUpdate(param.query,param.data,{new:true});

+ 9 - 0
modules/ration_repository/controllers/coe_controller.js

@@ -8,6 +8,15 @@ var callback = function(req,res,err,message, data){
 }
 
 class CoeListController extends BaseController{
+    async getCoeReference(req, res) {
+        try {
+            const { rationRepId, coeID } = JSON.parse(req.body.data);
+            const rst = await coeList.getCoeReference(rationRepId, coeID);
+            res.json({ error: 0, message: 'success', data: rst });
+        } catch (err) {
+            res.json({ error: 1, message: err.message, data: null });
+        }
+    }
     getCoeList(req,res){
         coeList.getCoesByLibID(req.body.libID, function(err,data){
             callback(req, res, err, 'Get coes', data);

+ 20 - 74
modules/ration_repository/controllers/ration_controller.js

@@ -108,79 +108,25 @@ class RationController extends BaseController{
             callback(req, res, err, '', null);
         });
     }
-}
-
-export default RationController;
-
-/*
-module.exports = {
-    getRationItemsBySection: function(req, res){
-        var sectionId = req.body.sectionID;
-        rationItem.getRationItemsBySection(sectionId, function(err, message, rst){
-            if (err) {
-                callback(req, res, err, message, null);
-            } else {
-                callback(req, res, err, message, rst);
-            }
-        });
-    },
-    mixUpdateRationItems: function(req, res){
-        var sectionId = req.body.sectionID,
-            rationLibId = req.body.rationLibId,
-            updateItems = JSON.parse(req.body.updateItems),
-            addItems = JSON.parse(req.body.addItems),
-            removeIds = JSON.parse(req.body.removeIds);
-        rationItem.mixUpdateRationItems(rationLibId, sectionId, updateItems, addItems, removeIds, function(err, message, rst){
-            if (err) {
-                callback(req, res, err, message, null);
-            } else {
-                callback(req, res, err, message, rst);
-            }
-        });
-    },
-    removeRationItems: function(req, res){
-        var rIds = JSON.parse(req.body.updateItems);
-        if (rIds && rIds.length > 0) {
-            rationItem.removeRationItems(rIds, function(err, message, rst){
-                if (err) {
-                    callback(req, res, err, message, null);
-                } else {
-                    callback(req, res, err, message, rst);
-                }
-            });
-        }
-    },
-    updateRationBasePrc: function (req, res) {
+    async updateRationTemplate(req, res){
         let data = JSON.parse(req.body.data);
-        rationItem.updateRationBasePrc(data, function (err, message) {
-            if(err){
-                callback(req, res, err, message, null);
-            }
-            else{
-                callback(req, res, err, message, null);
-            }
-        })
-    },
-    getRationGljIds: function (req, res) {
-        let data = JSON.parse(req.body.data);
-        rationItem.getRationGljIds(data, function (err, message, ids) {
-            if(err){
-                callback(req, res, err, message, null);
-            }
-            else{
-                callback(req, res, err, message, ids);
-            }
-        })
-    },
-    getRationsCodes: function (req, res) {
-        let data = JSON.parse(req.body.data);
-        rationItem.getRationsCodes(data, function (err, message, codes) {
-            if(err){
-                callback(req, res, err, message, null);
-            }
-            else{
-                callback(req, res, err, message, codes);
-            }
-        })
+        try {
+            let newTemplate = await rationItem.updateRationTemplate(data.rationRepId, data.rationID, data.templateData);
+            callback(req, res, 0, 'success', newTemplate);
+        } catch (err) {
+            callback(req, res, 1, err, null);
+        }
     }
-}*/
+    async updateRationBySection(req, res) {
+        const data = JSON.parse(req.body.data);
+        try {
+            const { rationRepId, sectionList, updateData } = data;
+            await rationItem.updateRationBySection(rationRepId, sectionList, updateData);
+            callback(req, res, 0, 'success', null);
+        } catch (err) {
+            callback(req, res, 1, err, null);
+        }
+    }
+}
+
+export default RationController;

+ 48 - 71
modules/ration_repository/controllers/ration_repository_controller.js

@@ -6,6 +6,7 @@ var rationRepository = require("../models/repository_map");
 import baseController from "../../common/base/base_controller";
 import CompilationModel from "../../users/models/compilation_model";
 const gljMapModel = mongoose.model('std_glj_lib_map');
+const compilationModel = mongoose.model('compilation');
 import async from "async";
 var callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
@@ -16,11 +17,25 @@ const fs = require("fs");
 // excel解析
 const excel = require("node-xlsx");
 const rationItem = require("../models/ration_item");
+const rationSectionTree = require('../models/ration_section_tree');
 const rationLibModel = mongoose.model('std_ration_lib_map');
 const rationItemModel = mongoose.model('std_ration_lib_ration_items');
 import STDGLJListModel from '../../std_glj_lib/models/gljModel';
+let logger = require('../../../logs/log_helper').logger;
 
 class RationRepositoryController extends baseController {
+    // 定额页面初始化数据
+    async prepareInitData(req, res) {
+        try {
+            const data = JSON.parse(req.body.data);
+            const rst = await rationItem.prepareInitData(data.rationRepId);
+            res.json({error: 0, message: 'success', data: rst});
+        } catch (err) {
+            console.log(err);
+            res.json({error: 1, message: 'fail', data: null});
+        }
+    }
+
     async getRationLibsByCompilation(req, res){
         try{
             let data = JSON.parse(req.body.data);
@@ -102,7 +117,7 @@ class RationRepositoryController extends baseController {
         });
     }
 
-    getDisPlayRationLibs(req, res) {
+    async getDisPlayRationLibs(req, res) {
         rationRepository.getDisplayRationLibs(function (err, data) {
             if (data) {
                 callback(req, res, err, "has data", data);
@@ -134,6 +149,7 @@ class RationRepositoryController extends baseController {
     }
 
     deleteRationLib(req, res) {
+        logger.info(`deleteRationLib ${req.ip}`);
         let oprtor = req.body.oprtor,
             libId = req.body.libId;
         rationRepository.deleteRationLib(oprtor, libId, function (err, message) {
@@ -161,7 +177,11 @@ class RationRepositoryController extends baseController {
             err: 0,
             msg: ''
         };
-        const allowHeader = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
+        const allowHeader = [
+            'application/vnd.ms-excel', 
+            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+            'application/octet-stream'
+        ];
         const uploadOption = {
             uploadDir: './public'
         };
@@ -180,9 +200,10 @@ class RationRepositoryController extends baseController {
                 if (err || file === null) {
                     throw '上传失败';
                 }
+                console.log(file.headers['content-type']);
                 // 判断类型
                 if (file.headers['content-type'] === undefined || allowHeader.indexOf(file.headers['content-type']) < 0) {
-                    throw '不支持该类型';
+                    throw `不支持该类型:${file.headers['content-type']}`;
                 }
                 // 重命名文件名
                 uploadFullName = uploadOption.uploadDir + '/' + file.originalFilename;
@@ -192,11 +213,23 @@ class RationRepositoryController extends baseController {
                 if (sheet[0] === undefined || sheet[0].data === undefined) {
                     throw 'excel没有对应数据';
                 }
-                const result = type === 'source_file' ?
-                    await rationItem.batchAddFromExcel(rationRepId, sheet[0].data) :
-                    await rationItem.batchUpdateSectionIdFromExcel(sheet[0].data);
-                if (rationItem.failGLJList && rationItem.failGLJList.length > 0) {
-                    responseData.msg = rationItem.failGLJList.join("\r\n");
+                let failGLJList;
+                switch (type) {
+                    // 导入原始数据
+                    case 'source_file':
+                        failGLJList = await rationItem.batchAddFromExcel(rationRepId, sheet[0].data);
+                        break;
+                    // 导入内部数据
+                    case 'import_data':
+                        failGLJList = await rationItem.batchUpdateSectionIdFromExcel(sheet[0].data);
+                        break;
+                    // 导入章节数据(一列文本,生成兄弟节点树)
+                    case 'section_file':
+                        await rationSectionTree.importSection(rationRepId, sheet[0].data);
+                        break;
+                }
+                if (Array.isArray(failGLJList) && failGLJList.length > 0) {
+                    responseData.msg = failGLJList.join("<br/>");
                 }
                 // 删除文件
                 if(uploadFullName && fs.existsSync(uploadFullName)){
@@ -265,13 +298,19 @@ class RationRepositoryController extends baseController {
             let stdGLJList = {};
             let stdGLJListByID = {};
             for (const tmp of stdGLJData) {
+                if (tmp.priceProperty && Object.keys(tmp.priceProperty).length) {
+                    tmp.basePrice = tmp.priceProperty.price1;
+                }
                 stdGLJList[tmp.code.toString()] = tmp.ID;
                 stdGLJListByID[tmp.ID] = tmp;
             }
             //获取所有的定额
             let allRations = await rationItemModel.find({rationRepId: rationRepId, $or: [{isDeleted: false}, {isDeleted: null}]});
+            let compilation = await compilationModel.findOne({_id: mongoose.Types.ObjectId(rationLib.compilationId)});
+            let tempUrl = compilation.overWriteUrl ? req.app.locals.rootDir + compilation.overWriteUrl : req.app.locals.rootDir;
+            let absoluteUrl = fs.existsSync(tempUrl) && fs.statSync(tempUrl).isFile()? tempUrl : null;
             for(let ration of allRations){
-                rationItem.calcForRation(stdGLJListByID, ration);
+                rationItem.calcForRation(stdGLJListByID, ration, absoluteUrl);
                 task.push({
                     updateOne: {
                         filter: {ID: ration.ID},
@@ -292,65 +331,3 @@ class RationRepositoryController extends baseController {
 }
 
 export default RationRepositoryController;
-/*
-module.exports = {
-    addRationRepository:function(req,res){
-        var rationObj = JSON.parse(req.body.rationRepObj);
-        rationRepository.addRationRepository(rationObj,function(err,data){
-            if (data) {
-                callback(req, res, err, "has data", data);
-            } else {
-                callback(req, res, err, "no data", null);
-            }
-        })
-    },
-    getDisPlayRationLibs: function(req, res){
-        rationRepository.getDisplayRationLibs(function(err, data){
-            if (data) {
-                callback(req, res, err, "has data",data);
-            } else {
-                callback(req, res, err, "no data", null);
-            }
-        });
-    },
-    getRealLibName:function(req,res){
-        var libName = req.body.rationName;
-        rationRepository.getRealLibName(libName,function(err,data){
-            if (data) {
-                callback(req, res, err, "has data", data);
-            } else {
-                callback(req, res, err, "no data", null);
-            }
-        })
-    },
-    getLibIDByName:function(req,res){
-        rationRepository.getLibIDByName(req.body.libName, function(err,data){
-            if (data) {
-                callback(req, res, err, "has ID", data);
-            } else {
-                callback(req, res, err, "no ID", null);
-            }
-        })
-    },
-    deleteRationLib:function(req,res){
-        var rationName = req.body.rationName;
-        rationRepository.deleteRationLib(rationName,function(err,data){
-            if (data) {
-                callback(req, res, err, "has data", data);
-            } else {
-                callback(req, res, err, "no data", null);
-            }
-        })
-    },
-    updateRationRepositoryName: function(req, res) {
-        var orgName = req.body.rationName;
-        var newName = req.body.newName;
-        rationRepository.updateName(orgName, newName, function(err, data){
-            if (data) {
-                callback(req, res, err, "has data", data);
-            } else {
-                callback(req, res, err, "no data", null);
-            }
-        });
-    }
-}*/

+ 19 - 39
modules/ration_repository/controllers/ration_section_tree_controller.js

@@ -9,6 +9,25 @@ var callback = function(req,res,err,message, data){
 }
 
 class RationChapterTreeController extends BaseController{
+    //某费用定额下补充定额库章节树模板数据条数
+    async sectionTemplateCount(req, res) {
+        try {
+            let count = await rationChapterTreeData.sectionTemplateCount(req.params.compilationId);
+            callback(req, res, 0, 'success', {count});
+        } catch (err) {
+            callback(req, res, 1, err, {count: 0});
+        }
+    }
+    //将该标准定额库的章节树设置为该费用定额下补充定额章节树的模板
+    async initSectionTemplate(req, res) {
+        try {
+            let data = JSON.parse(req.body.data);
+            await rationChapterTreeData.initSectionTemplate(data.rationLibId, data.compilationId);
+            callback(req, res, 0, 'success', null);
+        } catch (err) {
+            callback(req, res, 1, err, null)
+        }
+    }
     getRationChapterTree(req,res){
         let data = JSON.parse(req.body.data);
         var rationLibId = data.rationLibId;
@@ -97,42 +116,3 @@ class RationChapterTreeController extends BaseController{
 }
 
 export default RationChapterTreeController;
-
-/*
-module.exports ={
-    getRationChapterTree: function(req,res){
-        var rationLibId = req.body.rationLibId;
-        var repId = req.body.rationRepositoryId;
-        if (rationLibId) {
-            rationChapterTreeData.getRationChapterTree(rationLibId,function(err,data){
-                callback(req,res,err, "", data);
-            })
-        } else if (repId) {
-            rationChapterTreeData.getRationChapterTreeByRepId(repId,function(err,data){
-                callback(req,res,err,"", data)
-            })
-        }
-    },
-    createNewNode: function(req, res){
-        var libId = req.body.rationLibId;
-        var lastNodeId = req.body.lastNodeId;
-        var nodeData = JSON.parse(req.body.rawNodeData);
-        rationChapterTreeData.createNewNode(libId, lastNodeId, nodeData, function(err,data){
-            callback(req,res,err,"", data)
-        });
-    },
-    updateNodes: function(req, res) {
-        var nodes = JSON.parse(req.body.nodes);
-        rationChapterTreeData.updateNodes(nodes, function(err,results){
-            callback(req,res, err, "", results)
-        });
-    },
-    deleteNodes: function(req, res) {
-        var nodes = JSON.parse(req.body.nodes);
-        var preNodeId = req.body.preNodeId;
-        var preNodeNextId = req.body.preNodeNextId;
-        rationChapterTreeData.removeNodes(nodes, preNodeId, preNodeNextId, function(err,results){
-            callback(req,res, err, "", results)
-        });
-    }
-}*/

+ 42 - 17
modules/ration_repository/controllers/repository_views_controller.js

@@ -2,24 +2,42 @@
  * Created by Zhong on 2017/8/3.
  */
 import BaseController from "../../common/base/base_controller";
+import CompilationModel from '../../users/models/compilation_model';
 let config = require("../../../config/config.js");
 import mongoose from 'mongoose';
 const compilationModel = mongoose.model('compilation');
 const rationLibModel = mongoose.model('std_ration_lib_map');
 const fs = require('fs');
 class ViewsController extends BaseController{
-    redirectMain(req, res){
+    async redirectMain(req, res){
+        let filter = req.query.filter ? {compilationId: req.query.filter} : null;
+        let allLibs = await rationLibModel.find({}, {_id: 0, recentOpr: 0}),
+            rationLibs = allLibs.filter(lib => filter && lib.compilationId === filter.compilationId || !filter),
+            allNames = allLibs.map(lib => lib.dispName);
+        let compilationModel = new CompilationModel();
+        let compilationList = await compilationModel.getCompilationList({_id: 1, name: 1});
+        compilationList.unshift({_id: 'all', name: '所有'});
+        let activeCompilation = compilationList.find(compilation => compilation._id.toString() === req.query.filter);
+        if (activeCompilation) {
+            activeCompilation.active = 'active';
+        } else {
+            compilationList[0].active = 'active'
+        }
         res.render('maintain/ration_repository/main.html',
             {
+                allNames: allNames,
+                rationLibs: rationLibs,
+                compilationList: compilationList,
                 userAccount: req.session.managerData.username,
                 userID: req.session.managerData.userID
             });
     }
     async redirectRation(req, res){
         const repId = req.query.repository;
-        const redirectGlj = `/rationRepository/lmm?repository=${repId}`;
-        const redirectCoe = `/rationRepository/coeList?repository=${repId}`;
-        const redirectInstallation = `/rationRepository/installation?repository=${repId}`;
+        const locked = req.query.locked || 'true';
+        const redirectGlj = `/rationRepository/lmm?repository=${repId}&locked=${locked}`;
+        const redirectCoe = `/rationRepository/coeList?repository=${repId}&locked=${locked}`;
+        const redirectInstallation = `/rationRepository/installation?repository=${repId}&locked=${locked}`;
         let overWriteUrl = null;
         let priceProperties = [];
         let stdRationLib = await rationLibModel.findOne({ID: repId});
@@ -37,14 +55,16 @@ class ViewsController extends BaseController{
                 redirectCoe: redirectCoe,
                 redirectInstallation: redirectInstallation,
                 LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
-                priceProperties: JSON.stringify(priceProperties)
+                priceProperties: JSON.stringify(priceProperties),
+                overWriteUrl: overWriteUrl
             });
     }
     async redirectGlj(req, res){
         const repId = req.query.repository;
-        const redirectRation = `/rationRepository/ration?repository=${repId}`;
-        const redirectCoe = `/rationRepository/coeList?repository=${repId}`;
-        const redirectInstallation = `/rationRepository/installation?repository=${repId}`;
+        const locked = req.query.locked || 'true';
+        const redirectRation = `/rationRepository/ration?repository=${repId}&locked=${locked}`;
+        const redirectCoe = `/rationRepository/coeList?repository=${repId}&locked=${locked}`;
+        const redirectInstallation = `/rationRepository/installation?repository=${repId}&locked=${locked}`;
         let overWriteUrl = null;
         let priceProperties = [];
         let stdRationLib = await rationLibModel.findOne({ID: repId});
@@ -62,14 +82,16 @@ class ViewsController extends BaseController{
                 redirectCoe: redirectCoe,
                 redirectInstallation: redirectInstallation,
                 LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
-                priceProperties: JSON.stringify(priceProperties)
+                priceProperties: JSON.stringify(priceProperties),
+                rationLib: stdRationLib
             });
     }
     redirectCoeList(req, res){
         const repId = req.query.repository;
-        const redirectGlj = `/rationRepository/lmm?repository=${repId}`;
-        const redirectRation = `/rationRepository/ration?repository=${repId}`;
-        const redirectInstallation = `/rationRepository/installation?repository=${repId}`;
+        const locked = req.query.locked || 'true';
+        const redirectGlj = `/rationRepository/lmm?repository=${repId}&locked=${locked}`;
+        const redirectRation = `/rationRepository/ration?repository=${repId}&locked=${locked}`;
+        const redirectInstallation = `/rationRepository/installation?repository=${repId}&locked=${locked}`;
         res.render('maintain/ration_repository/fuzhu.html',
             {
                 userAccount: req.session.managerData.username,
@@ -80,11 +102,13 @@ class ViewsController extends BaseController{
                 LicenseKey:config.getLicenseKey(process.env.NODE_ENV)
             });
     }
-    redirectInstallation(req, res){
+    async redirectInstallation(req, res){
         const repId = req.query.repository;
-        const redirectGlj = `/rationRepository/lmm?repository=${repId}`;
-        const redirectCoe = `/rationRepository/coeList?repository=${repId}`;
-        const redirectRation = `/rationRepository/ration?repository=${repId}`;
+        const locked = req.query.locked || 'true';
+        const redirectGlj = `/rationRepository/lmm?repository=${repId}&locked=${locked}`;
+        const redirectCoe = `/rationRepository/coeList?repository=${repId}&locked=${locked}`;
+        const redirectRation = `/rationRepository/ration?repository=${repId}&locked=${locked}`;
+        let stdRationLib = await rationLibModel.findOne({ID: repId});
         res.render('maintain/ration_repository/anzhuang.html',
             {
                 userAccount: req.session.managerData.username,
@@ -92,7 +116,8 @@ class ViewsController extends BaseController{
                 redirectGlj: redirectGlj,
                 redirectCoe: redirectCoe,
                 redirectRation: redirectRation,
-                LicenseKey:config.getLicenseKey(process.env.NODE_ENV)
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                rationLib: stdRationLib
             });
     }
 }

+ 9 - 9
modules/ration_repository/controllers/search_controller.js

@@ -8,15 +8,15 @@ var callback = function(req, res, err, message, data){
 };
 
 class SearchController extends BaseController{
-    getRationItem (req, res) {
-        var rId = req.body.rationLibId, code = req.body.code;
-        var rationData = {}
-        rationItem.getRationItem(rId, code).then(function (result) {
-            rationData = result._doc;
-            callback(req, res, null, '', rationData);
-        }).catch(function (err, message) {
-            callback(req, res, err, message, null);
-        })
+    async getRationItem (req, res) {
+        try {
+            let data = JSON.parse(req.body.data);
+            let rId = data.rationLibId, code = data.code;
+            let ration = await rationItem.getRationItem(rId, code);
+            callback(req, res, 0, '', ration);
+        } catch (err) {
+            callback(req, res, 1, err, null);
+        }
     }
     findRation (req, res) {
         var rId = req.body.rationLibId, keyword = req.body.keyword;

+ 5 - 0
modules/ration_repository/models/coe.js

@@ -6,10 +6,15 @@
 const mongoose = require('mongoose');
 const coeListModel = mongoose.model('std_ration_lib_coe_list');
 let counter = require('../../../public/counter/counter');
+const rationModel = mongoose.model('std_ration_lib_ration_items');
 import async from 'async';
 
 let coeListDAO = function(){};
 
+coeListDAO.prototype.getCoeReference = async function (rationRepId, coeID) {
+    return await rationModel.find({rationRepId, 'rationCoeList.ID': coeID}, '-_id code').sort({code: 1});
+};
+
 coeListDAO.prototype.getCoe = function (data, callback) {
     coeListModel.findOne({
             "libID": data.libID,

+ 3 - 2
modules/ration_repository/models/glj_repository.js

@@ -12,6 +12,7 @@ const gljModel = mongoose.model('std_glj_lib_gljList');
 const gljClassModel = mongoose.model('std_glj_lib_gljClass');
 
 var gljItemDAO = function(){};
+
 gljItemDAO.prototype.getGljTypes = function(gljLibID, callback){
     gljClassModel.find({"repositoryId": gljLibID, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
         if(data.length) callback(false,data);
@@ -79,11 +80,11 @@ gljItemDAO.prototype.getStdCompleGljItems = async function (compleGljIds, stdGlj
     try{
         let rst = [];
         if(compleGljIds.length > 0){
-            let compleGlj = await compleGljModel.find({ID: {$in: compleGljIds}, deleteInfo: null}, {ID: 1, gljType: 1, basePrice: 1});
+            let compleGlj = await compleGljModel.find({ID: {$in: compleGljIds}}, {ID: 1, gljType: 1, basePrice: 1});
             rst = rst.concat(compleGlj);
         }
         if(stdGljIds.length > 0){
-            let stdGlj = await gljModel.find({ID: {$in: stdGljIds}, $or: [{deleted: null}, {deleted: false}]}, {ID: 1, gljType: 1, basePrice: 1});
+            let stdGlj = await gljModel.find({ID: {$in: stdGljIds}}, {ID: 1, gljType: 1, basePrice: 1, priceProperty: 1});
             rst = rst.concat(stdGlj);
         }
         callback(0, rst);

+ 32 - 3
modules/ration_repository/models/installation.js

@@ -9,14 +9,43 @@ const installSectionModel = mongoose.model('std_ration_lib_installationSection')
 class InstallationDao{
     async getInstallation(rationRepId, callback){
         try {
-            let feeItems = await installFeeItemModel.find({rationRepId: rationRepId, $or: [{deleted: false}, {deleted: null}]});
+            const feeItems = await installFeeItemModel.find({ rationRepId }).lean();
+            const feeItemMap = {};
+            const sectionIds = [];
+            feeItems.forEach(item => {
+                feeItemMap[item.ID] = item;
+                item.section.forEach(s => sectionIds.push(s.ID));
+                item.section = [];
+            });
+            const sections = await installSectionModel.find({ID: {$in: sectionIds}});
+            sections.forEach(section => {
+                const matchFeeItem = feeItemMap[section.feeItemId];
+                if (matchFeeItem) {
+                    matchFeeItem.section.push(section);
+                }
+            });
+            if (!callback) {
+                return feeItems;
+            }
+            callback(0, feeItems);
+        }
+        catch(err){
+            if (!callback) {
+                return [];
+            }
+            callback(err, null);
+        }
+    }
+    /*async getInstallation(rationRepId, callback){
+        try {
+            let feeItems = await installFeeItemModel.find({rationRepId: rationRepId});
             for(let feeItem of feeItems){
                 let sids = [];
                 for(let sec of feeItem.section){
                     sids.push(sec.ID);
                 }
                 if(sids.length > 0){
-                    let sections = await installSectionModel.find({ID: {$in: sids}, $or: [{deleted: false}, {deleted: null}]});
+                    let sections = await installSectionModel.find({ID: {$in: sids}});
                     feeItem._doc.section = sections;
                 }
             }
@@ -25,7 +54,7 @@ class InstallationDao{
         catch(err){
             callback(err, null);
         }
-    }
+    }*/
 
     async updateSection(updateData, callback){
         try{

+ 318 - 238
modules/ration_repository/models/ration_item.js

@@ -10,11 +10,48 @@ let rationRepositoryDao = require('./repository_map');
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
 const rationItemModel = mongoose.model('std_ration_lib_ration_items');
 const stdRationLibModel = mongoose.model('std_ration_lib_map');
+const stdRationSectionModel = mongoose.model('std_ration_lib_ration_chapter_trees');
 const compleRationModel = mongoose.model('complementary_ration_items');
 import STDGLJListModel from '../../std_glj_lib/models/gljModel';
+import InstallationDao from '../models/installation';
+const installationDao = new InstallationDao();
+import GljDao from "../../std_glj_lib/models/gljModel";
+const stdGljDao = new GljDao();
+import stdgljutil  from "../../../public/cache/std_glj_type_util";
 
 var rationItemDAO = function(){};
 
+rationItemDAO.prototype.prepareInitData = async function (rationRepId) {
+    // 定额库
+    const libTask = stdRationLibModel.findOne({ID: rationRepId}, '-_id ID dispName gljLib');
+    // 定额编码
+    const codesTask = rationItemModel.find({rationRepId}, '-_id code', {lean: true});
+    // 定额章节树
+    const sectionTreeTask = stdRationSectionModel.find({rationRepId}, '-_id', {lean: true});
+    // 安装增加费
+    const installationTask = installationDao.getInstallation(rationRepId);
+    const [libInfo, codesArr, sectionTree, installationList] = await Promise.all([libTask, codesTask, sectionTreeTask, installationTask]);
+    const rationsCodes = codesArr.reduce((acc, cur) => {
+        acc.push(cur.code);
+        return acc;
+    }, []);
+    // 人材机分类树
+    const gljLibId = libInfo.gljLib;
+    const gljTreeTask = stdGljDao.getGljTreeSync(gljLibId);
+    const gljTask = stdGljDao.getGljItemsSync(gljLibId);
+    const [gljTree, gljList] = await Promise.all([gljTreeTask, gljTask]);
+    const gljDistTypeList = stdgljutil.getStdGljTypeCacheObj().toArray();
+    return {
+        libInfo,
+        rationsCodes,
+        sectionTree,
+        installationList,
+        gljTree,
+        gljList,
+        gljDistTypeList
+    };
+};
+
 rationItemDAO.prototype.getRationItemsByLib = async function (rationRepId, showHint = null, returnFields = '') {
     let rationLib = await stdRationLibModel.findOne({ID: rationRepId, deleted: false});
     if(!rationLib){
@@ -101,15 +138,49 @@ rationItemDAO.prototype.sortToNumber = function (datas) {
     }
 };
 
-rationItemDAO.prototype.getRationItemsBySection = function(rationRepId, sectionId,callback){
+rationItemDAO.prototype.getRationItemsBySection = async function(rationRepId, sectionId,callback){
     let me = this;
-    rationItemModel.find({"rationRepId": rationRepId, "sectionId": sectionId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
+    try {
+        let rations = await rationItemModel.find({rationRepId: rationRepId, sectionId: sectionId});
+        me.sortToNumber(rations);
+        let matchRationIDs = [],
+            matchRations = [];
+        for (let ration of rations) {
+            if (ration.rationTemplateList) {
+                for (let rt of ration.rationTemplateList) {
+                    if (rt.rationID) {
+                        matchRationIDs.push(rt.rationID);
+                    }
+                }
+            }
+        }
+        if (matchRationIDs.length > 0) {
+            matchRations = await rationItemModel.find({ID: {$in: matchRationIDs}}, '-_id ID code name');
+        }
+        for (let mr of matchRations) {
+            for (let ration of rations) {
+                if (ration.rationTemplateList) {
+                    for (let rt of ration.rationTemplateList) {
+                        if (rt.rationID && rt.rationID === mr.ID) {
+                            rt.code = mr.code ? mr.code : '';
+                            rt.name = mr.name ? mr.name : '';
+                        }
+                    }
+                }
+            }
+        }
+        callback(false,"Get items successfully", rations);
+    } catch (err) {
+        console.log(err);
+        callback(true, "Fail to get items", "");
+    }
+  /*  rationItemModel.find({"rationRepId": rationRepId, "sectionId": sectionId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
         if(err) callback(true, "Fail to get items", "");
         else {
             me.sortToNumber(data);
             callback(false,"Get items successfully", data);
         }
-    })
+    })*/
 };
 rationItemDAO.prototype.mixUpdateRationItems = function(rationLibId, lastOpr, sectionId, updateItems, addItems, rIds, callback){
     var me = this;
@@ -144,7 +215,16 @@ rationItemDAO.prototype.removeRationItems = function(rationLibId, lastOpr, rIds,
             } else {
                 rationRepositoryDao.updateOprArr({ID: rationLibId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
                     if(!err){
-                        callback(false, "Remove successfully", docs);
+                        rationItemModel.update({rationRepId: rationLibId}, {$pull: {rationTemplateList: {rationID: {$in: rIds}}}}, function (theErr) {
+                            if (!theErr) {
+                                callback(false, "Remove successfully", docs);
+                            } else {
+                                callback(true, "Fail to remove", false);
+                            }
+
+                        });
+                    } else {
+                        callback(true, "Fail to remove", false);
                     }
                 })
             }
@@ -179,20 +259,9 @@ rationItemDAO.prototype.findRation = function (repId, keyword, callback) {
     })
 }
 
-rationItemDAO.prototype.getRationItem = function (repId, code, callback) {
-    if (callback) {
-        rationItemModel.findOne({rationRepId: repId, code: code, "$or": [{"isDeleted": null}, {"isDeleted": false}]}, '-_id').exec()
-            .then(function (result, err) {
-                if (err) {
-                    callback(1, '找不到定额“' + code +'”' , null);
-                } else {
-                    callback(0, '', result);
-                }
-            });
-        return null;
-    } else {
-        return rationItemModel.findOne({rationRepId: repId, code: code, "$or": [{"isDeleted": null}, {"isDeleted": false}]}, '-_id').exec();
-    }
+rationItemDAO.prototype.getRationItem = async function (repId, code) {
+    let ration = await rationItemModel.findOne({rationRepId: repId, code: code});
+    return ration;
 };
 
 rationItemDAO.prototype.addRationItems = function(rationLibId, lastOpr, sectionId, items,callback){
@@ -228,6 +297,7 @@ rationItemDAO.prototype.addRationItems = function(rationLibId, lastOpr, sectionI
 };
 
 rationItemDAO.prototype.updateRationItems = function(rationLibId, lastOpr, sectionId, items,callback){
+    console.log('enter============');
     var functions = [];
     for (var i=0; i < items.length; i++) {
         functions.push((function(doc) {
@@ -268,8 +338,90 @@ function round(v,e){
     return Math.round(v*t)/t;
 }
 
+function calcRation(gljArr) {
+    let labourPrc = [],
+        materialPrc = [],
+        machinePrc = [],
+        managePrc = [],
+        profitPrc = [],
+        riskPrc = [],
+        singlePrc,
+        updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, managePrice: 0, profitPrice: 0, riskPrice: 0, basePrice: 0};
+    gljArr.forEach(function (gljItem) {
+        if(gljItem.gljParentType !== -1){
+            singlePrc = scMathUtil.roundTo(gljItem.basePrice * gljItem.consumeAmt, -3);
+            if(gljItem.gljParentType === 1){
+                labourPrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType ===2){
+                materialPrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType === 3){
+                machinePrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType === 6){
+                managePrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType === 7){
+                profitPrc.push(singlePrc);
+            }
+            else if(gljItem.gljParentType === 8){
+                riskPrc.push(singlePrc);
+            }
+        }
+    });
+    if(labourPrc.length > 0){
+        let sumLaP = 0;
+        for(let i=0; i<labourPrc.length; i++){
+            sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], -6);
+        }
+        updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.labourPrice, -2);
+    }
+    if(materialPrc.length > 0){
+        let sumMtP = 0;
+        for(let i= 0; i<materialPrc.length; i++){
+            sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], -6);
+        }
+        updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.materialPrice, -2);
+    }
+    if(machinePrc.length > 0){
+        let sumMaP = 0;
+        for(let i =0; i< machinePrc.length; i++){
+            sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], -6);
+        }
+        updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.machinePrice, -2);
+    }
+    if(managePrc.length > 0){
+        let sumMgP = 0;
+        for(let i =0; i< managePrc.length; i++){
+            sumMgP = scMathUtil.roundTo(sumMgP + managePrc[i], -6);
+        }
+        updatePrc.managePrice = scMathUtil.roundTo(sumMgP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.managePrice, -2);
+    }
+    if(profitPrc.length > 0){
+        let sumPfP = 0;
+        for(let i =0; i< profitPrc.length; i++){
+            sumPfP = scMathUtil.roundTo(sumPfP + profitPrc[i], -6);
+        }
+        updatePrc.profitPrice = scMathUtil.roundTo(sumPfP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.profitPrice, -2);
+    }
+    if(riskPrc.length > 0){
+        let sumRkP = 0;
+        for(let i =0; i< riskPrc.length; i++){
+            sumRkP = scMathUtil.roundTo(sumRkP + riskPrc[i], -6);
+        }
+        updatePrc.riskPrice = scMathUtil.roundTo(sumRkP, -2);
+        updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.riskPrice, -2);
+    }
+    return updatePrc;
+}
 
-rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
+rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, overWriteUrl, callback) {
     async.each(basePrcArr, function (basePrcObj, finalCb) {
         let adjGljId = basePrcObj.gljId, adjBasePrice = basePrcObj.basePrice, adjGljType = basePrcObj.gljType;
         async.waterfall([
@@ -346,7 +498,6 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                     }
                 }
                 gljDao.getStdCompleGljItems(compleGljIds, stdGljIds, function (err, allGljs) {
-                    const processDecimal = -6;
                     if(err){
                         cb(err);
                     }
@@ -367,36 +518,33 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                                     }
                                     if(theGlj.gljType <= 3){
                                         gljParentType = theGlj.gljType;
-                                    }
-                                    if(theGlj.gljType > 200 && theGlj.gljType < 300){
+                                    } else if(theGlj.gljType > 200 && theGlj.gljType < 300){
                                         gljParentType = 2;
-                                    }
-                                    if(theGlj.gljType > 300 && theGlj.gljType < 400){
+                                    } else if(theGlj.gljType > 300 && theGlj.gljType < 400){
                                         gljParentType = 3;
-                                    }
-                                    //管理费
-                                    if(theGlj.gljType === 6){
+                                    } else if(theGlj.gljType === 6){   //管理费
                                         gljParentType = 6;
-                                    }
-                                    //利润
-                                    if(theGlj.gljType === 7){
+                                    } else if(theGlj.gljType === 7){    //利润
                                         gljParentType = 7;
-                                    }
-                                    //风险费
-                                    if(theGlj.gljType === 8){
+                                    } else if(theGlj.gljType === 8){    //风险费
                                         gljParentType = 8;
                                     }
                                     if(theGlj)
                                     if(theGlj.ID === adjGljId){
-                                        gljArr.push({gljId: theGlj.ID, basePrice: adjBasePrice, gljParentType: gljParentType});
-                                    }
-                                    else {
+                                        gljArr.push({gljId: theGlj.ID, basePrice: adjBasePrice, gljParentType: gljParentType, unit: theGlj.unit});
+                                    } else {
                                         if(theGlj.priceProperty && Object.keys(theGlj.priceProperty).length > 0){
-                                            let priceKeys = Object.keys(theGlj.priceProperty);
-                                            gljArr.push({gljId: theGlj.ID, basePrice: parseFloat(theGlj.priceProperty[priceKeys[0]]), gljParentType: gljParentType});
-                                        }
-                                        else {
-                                            gljArr.push({gljId: theGlj.ID, basePrice: parseFloat(theGlj.basePrice), gljParentType: gljParentType});
+                                            gljArr.push({
+                                                gljId: theGlj.ID,
+                                                basePrice: parseFloat(theGlj.priceProperty.price1),
+                                                gljParentType: gljParentType,
+                                                unit: theGlj.unit});
+                                        } else {
+                                            gljArr.push({
+                                                gljId: theGlj.ID,
+                                                basePrice: parseFloat(theGlj.basePrice),
+                                                gljParentType: gljParentType,
+                                                unit: theGlj.unit});
                                         }
                                     }
                                 }
@@ -408,82 +556,18 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                                     }
                                 })
                             });
-                            //recalculate the price of ration
-                            let labourPrc = [],
-                                materialPrc = [],
-                                machinePrc = [],
-                                managePrc = [],
-                                profitPrc = [],
-                                riskPrc = [],
-                                singlePrc,
-                                updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, managePrice: 0, profitPrice: 0, riskPrice: 0, basePrice: 0};
-                            gljArr.forEach(function (gljItem) {
-                                if(gljItem.gljParentType !== -1){
-                                    singlePrc = scMathUtil.roundTo(gljItem.basePrice * gljItem.consumeAmt, -3);
-                                    if(gljItem.gljParentType === 1){
-                                        labourPrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType ===2){
-                                        materialPrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType === 3){
-                                        machinePrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType === 6){
-                                        managePrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType === 7){
-                                        profitPrc.push(singlePrc);
-                                    }
-                                    else if(gljItem.gljParentType === 8){
-                                        riskPrc.push(singlePrc);
-                                    }
-                                }
-                            });
-                            if(labourPrc.length > 0){
-                                let sumLaP = 0;
-                                for(let i=0; i<labourPrc.length; i++){
-                                    sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], processDecimal);
-                                }
-                                updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
-                            }
-                            if(materialPrc.length > 0){
-                                let sumMtP = 0;
-                                for(let i= 0; i<materialPrc.length; i++){
-                                    sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], processDecimal);
+                            let updatePrc = null;
+                            let overWriteCalc = false;  //需要重写算法
+                            if (overWriteUrl) {
+                                let overWriteExports = require(overWriteUrl);
+                                if (typeof overWriteExports.calcRation !== 'undefined') {
+                                    overWriteCalc = true;
+                                    updatePrc = overWriteExports.calcRation(gljArr, scMathUtil);
                                 }
-                                updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
                             }
-                            if(machinePrc.length > 0){
-                                let sumMaP = 0;
-                                for(let i =0; i< machinePrc.length; i++){
-                                    sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], processDecimal);
-                                }
-                                updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
-                            }
-                            if(managePrc.length > 0){
-                                let sumMgP = 0;
-                                for(let i =0; i< managePrc.length; i++){
-                                    sumMgP = scMathUtil.roundTo(sumMgP + managePrc[i], processDecimal);
-                                }
-                                updatePrc.managePrice = scMathUtil.roundTo(sumMgP, -2);
-                            }
-                            if(profitPrc.length > 0){
-                                let sumPfP = 0;
-                                for(let i =0; i< profitPrc.length; i++){
-                                    sumPfP = scMathUtil.roundTo(sumPfP + profitPrc[i], processDecimal);
-                                }
-                                updatePrc.profitPrice = scMathUtil.roundTo(sumPfP, -2);
+                            if (!overWriteCalc) {
+                                updatePrc = calcRation(gljArr);
                             }
-                            if(riskPrc.length > 0){
-                                let sumRkP = 0;
-                                for(let i =0; i< riskPrc.length; i++){
-                                    sumRkP = scMathUtil.roundTo(sumRkP + riskPrc[i], processDecimal);
-                                }
-                                updatePrc.riskPrice = scMathUtil.roundTo(sumRkP, -2);
-                            }
-                            updatePrc.basePrice = scMathUtil.roundTo(
-                                updatePrc.labourPrice + updatePrc.materialPrice + updatePrc.machinePrice + updatePrc.managePrice + updatePrc.profitPrice + updatePrc.riskPrice, -2);
                             let task = {
                                 updateOne: {
                                     filter: {
@@ -632,127 +716,89 @@ rationItemDAO.prototype.updateAnnotation = function (lastOpr, repId, updateArr,
     });
 };
 
-//计算导入数据的价格
-rationItemDAO.prototype.calcForRation = function (stdGljList, ration) {
-    const processDecimal = -6;
-    //根据工料机类型划分价格
-    const labour = [1],
-        material = [201, 202, 203, 204, 205, 206, 207],
-        machine = [301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312],
-        manage = [6],
-        profit = [7],
-        risk = [8];
-    let labourPrc = [], materialPrc = [], machinePrc = [], managePrc = [], profitPrc = [], riskPrc = [],
-        singlePrc, updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, basePrice: 0, managePrice: 0, profitPrice: 0, riskPrice: 0};
-    let rationGljList = ration.rationGljList;
-    for(let rationGlj of rationGljList){
-        let glj = stdGljList[rationGlj.gljId];
-        let prcType = isDef(glj) ? getParentType(glj.gljType) : null;
-        if(isDef(prcType)){
-            singlePrc = scMathUtil.roundTo(parseFloat(glj.basePrice) * parseFloat(rationGlj.consumeAmt), -3);
-            if(prcType === 'labour'){
-                labourPrc.push(singlePrc);
-            }
-            else if(prcType === 'material'){
-                materialPrc.push(singlePrc);
-            }
-            else if(prcType === 'machine'){
-                machinePrc.push(singlePrc);
-            }
-            else if(prcType === 'manage'){
-                managePrc.push(singlePrc);
-            }
-            else if(prcType === 'profit'){
-                profitPrc.push(singlePrc);
-            }
-            else if(prcType === 'risk'){
-                riskPrc.push(singlePrc);
-            }
+//更新定额下模板关联
+rationItemDAO.prototype.updateRationTemplate = async function (rationRepId, rationID, templateData) {
+    //自动匹配定额
+    let matachCodes = [],
+        matchRations = [];
+    //要保存的数据
+    let saveData = [];
+    for (let data of templateData) {
+        if (data.code) {
+            matachCodes.push(data.code);
         }
     }
-    //计算人工费
-    if(labourPrc.length > 0){
-        let sumLaP = 0;
-        for(let i = 0, len  = labourPrc.length; i < len; i++){
-            sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], processDecimal);
-        }
-        updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
+    matachCodes = Array.from(new Set(matachCodes));
+    if (matachCodes.length > 0) {
+        matchRations = await rationItemModel.find({rationRepId: rationRepId, code: {$in: matachCodes}}, '-_id ID code name');
     }
-    //材料费
-    if(materialPrc.length > 0){
-        let sumMtP = 0;
-        for(let i = 0, len  = materialPrc.length; i < len; i++){
-            sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], processDecimal);
+    let validData = [];
+    //设置展示数据
+    for (let data of templateData) {
+        let match = false;
+        for (let ration of matchRations) {
+            if (data.code && data.code === ration.code) {
+                match = true;
+                data.name = ration.name;
+                data.rationID = ration.ID;
+                break;
+            }
         }
-        updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
-    }
-    //机械费
-    if(machinePrc.length > 0){
-        let sumMaP = 0;
-        for(let i = 0, len  = machinePrc.length; i < len; i++){
-            sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], processDecimal);
+        if (!match) {
+            data.code = '';
+            data.name = '';
         }
-        updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
-    }
-    //管理费
-    if(managePrc.length > 0){
-        let sumMgP = 0;
-        for(let i = 0, len  = managePrc.length; i < len; i++){
-            sumMgP = scMathUtil.roundTo(sumMgP + managePrc[i], processDecimal);
+        if (data.type || data.code || data.name || data.billsLocation) {
+            validData.push(data);
         }
-        updatePrc.managePrice = scMathUtil.roundTo(sumMgP, -2);
     }
-    //利润
-    if(profitPrc.length > 0){
-        let sumPfP = 0;
-        for(let i = 0, len  = profitPrc.length; i < len; i++){
-            sumPfP = scMathUtil.roundTo(sumPfP + profitPrc[i], processDecimal);
-        }
-        updatePrc.profitPrice = scMathUtil.roundTo(sumPfP, -2);
+    for (let data of validData) {
+        saveData.push({rationID: data.rationID ? data.rationID : null, type: data.type, billsLocation: data.billsLocation});
     }
-    //风险费
-    if(riskPrc.length > 0){
-        let sumRkP = 0;
-        for(let i = 0, len  = riskPrc.length; i < len; i++){
-            sumRkP = scMathUtil.roundTo(sumRkP + riskPrc[i], processDecimal);
+    //更新
+    await rationItemModel.update({ID: rationID}, {$set: {rationTemplateList: saveData}});
+    return validData;
+};
+
+// 根据章节列表批量更新定额
+rationItemDAO.prototype.updateRationBySection = async function (rationRepId, sectionList, updateData) {
+    await rationItemModel.updateMany({rationRepId, sectionId: {$in: sectionList}}, updateData);
+}
+
+//计算导入数据的价格
+rationItemDAO.prototype.calcForRation = function (stdGljList, ration, overWriteUrl) {
+    let rationGljList = ration.rationGljList,
+        gljArr = [];
+    for(let rationGlj of rationGljList) {
+        let glj = stdGljList[rationGlj.gljId];
+        let gljPType = parseInt(glj.gljType.toString().match(/\d+?/)[0]);
+        let newGlj = {
+            gljId: glj.ID,
+            consumeAmt: rationGlj.consumeAmt,
+            gljParentType: gljPType,
+            unit: glj.unit
+        };
+        newGlj.basePrice = glj.priceProperty && Object.keys(glj.priceProperty).length > 0
+            ? parseFloat(glj.priceProperty.price1)
+            : parseFloat(glj.basePrice);
+        gljArr.push(newGlj);
+    }
+    let updatePrc = null;
+    let overWriteCalc = false;  //需要重写算法
+    if (overWriteUrl) {
+        let overWriteExports = require(overWriteUrl);
+        if (typeof overWriteExports.calcRation !== 'undefined') {
+            overWriteCalc = true;
+            updatePrc = overWriteExports.calcRation(gljArr, scMathUtil);
         }
-        updatePrc.riskPrice = scMathUtil.roundTo(sumRkP, -2);
     }
-    //基价
-    updatePrc.basePrice = scMathUtil.roundTo(
-        updatePrc.labourPrice + updatePrc.materialPrice + updatePrc.machinePrice + updatePrc.managePrice + updatePrc.profitPrice + updatePrc.riskPrice, -2);
-    //更新定额数据
+    if (!overWriteCalc) {
+        updatePrc = calcRation(gljArr);
+    }
     ration.labourPrice = updatePrc.labourPrice.toString();
     ration.materialPrice = updatePrc.materialPrice.toString();
     ration.machinePrice = updatePrc.machinePrice.toString();
     ration.basePrice = updatePrc.basePrice.toString();
-
-    function isDef(v){
-        return v !== undefined && v !== null;
-    }
-    //是否属于人工、材料、机械类型
-    function getParentType(type){
-        if(labour.includes(type)){
-            return 'labour';
-        }
-        if(material.includes(type)){
-            return 'material';
-        }
-        if(machine.includes(type)){
-            return 'machine';
-        }
-        if(manage.includes(type)){
-            return 'manage';
-        }
-        if(profit.includes(type)){
-            return 'profit';
-        }
-        if(risk.includes(type)){
-            return 'risk'
-        }
-        return null;
-    }
-
 };
 
 /**
@@ -806,12 +852,14 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
         stdGLJListByID[tmp.ID] = tmp;
     }
     let lastData = {};
+    // 定额xx下提示的次数
+    let lastFailCount = 0;
     const rationData = [];
     // 编码列表,用于查找库中是否有对应数据
     let rationCodeList = [];
     let gljCodeList = [];
     // 插入失败的工料机列表(用于提示)
-    this.failGLJList = [];
+    let failGLJList = [];
     for (const tmp of data) {
         if (tmp.length <= 0) {
             continue;
@@ -820,8 +868,12 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
         if (tmp[0] === undefined && Object.keys(lastData).length > 0) {
             // 如果不存在对应的工料机库数据则跳过
             if (stdGLJList[tmp[1]] === undefined) {
-                const failString = '定额' + lastData.code + '下的' + tmp[1];
-                this.failGLJList.push(failString);
+                if (lastFailCount === 0) {
+                    failGLJList.push('定额' + lastData.code + '下的');
+                    lastFailCount++;
+                }
+                //const failString = '定额' + lastData.code + '下的' + tmp[1];
+                failGLJList.push(tmp[1]);
                 continue;
             }
             const tmpRationGlj = {
@@ -839,7 +891,7 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
         if (tmp[0] === '定额' && Object.keys(lastData).length > 0) {
             rationData.push(lastData);
         }
-
+        lastFailCount = 0;
         // 组装数据
         lastData = {
             code: tmp[1],
@@ -897,7 +949,7 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
     }
     // 如果都已经存在,直接返回
     if (insertData.length <= 0) {
-        return true;
+        return failGLJList;
     }
     //计算价格
     for(let ration of insertData){
@@ -915,8 +967,8 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
         count++;
     }
     // 插入数据库
-    const result = await rationItemModel.create(insertData);
-    return result.length > 0;
+    await rationItemModel.create(insertData);
+    return failGLJList;
 };
 
 /**
@@ -929,17 +981,20 @@ rationItemDAO.prototype.exportExcelData = async function(rationRepId) {
     const condition = {
         rationRepId: rationRepId
     };
-    // @todo 限制导出的数量以防内存溢出
-    const rationDataList = await this.getRationItemByCondition(condition, ['name', 'code', 'ID', 'sectionId', 'feeType', 'caption', 'basePrice']);
+    const rationDataList = await this.getRationItemByCondition(condition, ['name', 'code', 'ID', 'sectionId', 'feeType', 'caption', 'basePrice', 'jobContent', 'annotation']);
 
     // 整理数据
     let rationData = [];
     for (const tmp of rationDataList) {
         const sectionId = tmp.sectionId <= 0 || tmp.sectionId === undefined ? null : tmp.sectionId;
         const feeType = tmp.feeType === '' || tmp.feeType === undefined ? null : tmp.feeType;
-        const ration = [sectionId, feeType, tmp.ID, tmp.code, tmp.name, tmp.caption, tmp.basePrice];
+        const ration = [sectionId, feeType, tmp.ID, tmp.code, tmp.name, tmp.caption, tmp.basePrice, tmp.jobContent, tmp.annotation];
         rationData.push(ration);
     }
+    const excelData = [['树ID', '取费专业', '定额ID', '定额编码', '定额名', '定额显示名称', '基价', '工作内容', '附注']];
+    excelData.push.apply(excelData, rationData);
+
+    return excelData;
     //根据编号排序,优先级:number-number-..., number, Anumber....
     /*let regConnector = /-/g,
         regLetter = /[a-z,A-Z]/g,
@@ -1003,10 +1058,10 @@ rationItemDAO.prototype.exportExcelData = async function(rationRepId) {
         }
         return rst;
     });*/
-    const excelData = [['树ID', '取费专业', '定额ID', '定额编码', '定额名', '定额显示名称', '基价']];
+    /*const excelData = [['树ID', '取费专业', '定额ID', '定额编码', '定额名', '定额显示名称', '基价']];
     excelData.push.apply(excelData, rationData);
 
-    return excelData;
+    return excelData;*/
 };
 
 /**
@@ -1020,12 +1075,17 @@ rationItemDAO.prototype.batchUpdateSectionIdFromExcel = async function(data) {
         return false;
     }
     // 批量执行update
-    let bulkOprs = [];
+    let bulkOprs = [],
+        sectionIDs = [];
     for (const tmp of data) {
         let rationId = parseInt(tmp[2]);
         rationId = isNaN(rationId) || rationId <= 0 ? 0 : rationId;
         let sectionId = parseInt(tmp[0]);
         sectionId = isNaN(sectionId) || sectionId <= 0 ? 0 : sectionId;
+        if (sectionId <= 0 || rationId <= 0) {
+            continue;
+        }
+        sectionIDs.push(sectionId);
         // 取费专业
         let feeType = tmp[1] ? parseInt(tmp[1]) : null;
         feeType = isNaN(feeType) || feeType <= 0 ? null : feeType;
@@ -1033,15 +1093,35 @@ rationItemDAO.prototype.batchUpdateSectionIdFromExcel = async function(data) {
         name = name ? name : '';
         let caption = tmp[5];
         caption = caption ? caption : '';
-        if (sectionId <= 0 || rationId <= 0) {
-            continue;
-        }
-        bulkOprs.push({updateOne: {filter: {ID: rationId}, update: {$set: {sectionId: sectionId, feeType: feeType, name: name, caption: caption}}}});
+        let jobContent = tmp[7] ? tmp[7] : '';
+        let annotation = tmp[8] ? tmp[8] : '';
+        bulkOprs.push({updateOne: {
+            filter: {ID: rationId},
+            update: {$set: {
+                sectionId,
+                feeType,
+                name,
+                caption,
+                jobContent,
+                annotation
+            }}}
+        });
     }
     if(bulkOprs.length <= 0){
         throw '无有效数据(树ID、定额ID不为空、且为数值)';
     }
     await rationItemModel.bulkWrite(bulkOprs);
+    // 更新章节树工作内容、附注节点选项(全设置为ALL)
+    sectionIDs = Array.from(new Set(sectionIDs));
+    if (sectionIDs.length) {
+        await stdRationSectionModel.updateMany(
+            {ID: {$in: sectionIDs}},
+            {$set: {
+                jobContentSituation: 'ALL',
+                annotationSituation: 'ALL'
+            }}
+        )
+    }
 };
 
 module.exports = new rationItemDAO();

+ 43 - 0
modules/ration_repository/models/ration_section_tree.js

@@ -8,8 +8,51 @@ let counter = require('../../../public/counter/counter');
 let rationRepositoryDao = require('./repository_map');
 const rationChapterTreeModel = mongoose.model('std_ration_lib_ration_chapter_trees');
 const rationModel = mongoose.model('std_ration_lib_ration_items');
+const compleRationSectionTemp = mongoose.model('complementary_ration_section_templates');
 var rationChapterTreeDAO = function(){};
 
+rationChapterTreeDAO.prototype.importSection = async function (rationRepId, sheetData) {
+    const counterRst = await counter.counterDAO.getIDAfterCount(counter.moduleName.rationTree, sheetData.length);
+    const insertData = [];
+    const beginID = counterRst.sequence_value - (sheetData.length - 1);
+    for (let i = 0; i < sheetData.length; i++) {
+        const curData = sheetData[i];
+        const nextData = sheetData[i + 1];
+        const curID = beginID + i;
+        const nextID = nextData ? curID + 1 : -1;
+        const name = curData[0];
+        insertData.push({
+            rationRepId,
+            name,
+            ID: curID,
+            NextSiblingID: nextID,
+            ParentID: -1
+        });
+    }
+    await rationChapterTreeModel.insertMany(insertData);
+};
+
+rationChapterTreeDAO.prototype.sectionTemplateCount = async function (compilationId) {
+    return await compleRationSectionTemp.find({compilationId}).count();
+};
+
+rationChapterTreeDAO.prototype.initSectionTemplate = async function (rationLibId, compilationId) {
+    let sectionTempCount = await compleRationSectionTemp.find({compilationId}).count();
+    if (sectionTempCount > 0) {
+        await compleRationSectionTemp.remove({compilationId});
+    }
+    let bulks = [];
+    let stdRationSection = await rationChapterTreeModel.find({rationRepId: rationLibId});
+    for (let data of stdRationSection) {
+        delete data._doc._id;
+        data._doc.compilationId = compilationId;
+        bulks.push({insertOne: {document: data}});
+    }
+    if (bulks.length > 0) {
+        await compleRationSectionTemp.bulkWrite(bulks);
+    }
+};
+
 rationChapterTreeDAO.prototype.getRationChapterTree = function(rationLibId,callback){
     rationChapterTreeModel.find({"rationRepId": rationLibId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
         if(data.length) callback(0,data);

+ 6 - 2
modules/ration_repository/models/repository_map.js

@@ -18,6 +18,7 @@ const engLibModel = mongoose.model('engineering_lib');
 function createNewLibModel(rationLibObj){
     var rst = {};
     rst.dispName = rationLibObj.dispName;
+    rst.libCode = rationLibObj.libCode;
     rst.appType = rationLibObj.appType?rationLibObj.appType:'construct';
     rst.compilationId = rationLibObj.compilationId;
     rst.compilationName = rationLibObj.compilationName;
@@ -136,6 +137,9 @@ rationRepositoryDao.prototype.getRepositoryById = function(repId,callback = null
 
 rationRepositoryDao.prototype.addRationRepository = function( rationLibObj,callback){
     counter.counterDAO.getIDAfterCount(counter.moduleName.rationMap, 1, function(err, result){
+        if (!result) {
+            callback('获取不到新的库ID,创建失败', null);
+        }
         var rMap = createNewLibModel(rationLibObj);
         rMap.ID = result.sequence_value;
         new rationRepository(rMap).save(function(err, result) {
@@ -173,7 +177,7 @@ rationRepositoryDao.prototype.getRationLib = function(libId, callback) {
 };
 
 rationRepositoryDao.prototype.getDisplayRationLibs = function(callback) {
-    rationRepository.find({"deleted": false}, function(err, data){
+    rationRepository.find(filter, function(err, data){
         if (err) {
             callback( 'Error', null);
         } else {
@@ -183,7 +187,7 @@ rationRepositoryDao.prototype.getDisplayRationLibs = function(callback) {
 };
 
 rationRepositoryDao.prototype.updateName = function(oprtor, renameObj, callback){
-    rationRepository.update({ID: renameObj.ID, deleted: false}, {$set: {dispName: renameObj.newName}}, function (err) {
+    rationRepository.update({ID: renameObj.ID, deleted: false}, {$set: {dispName: renameObj.newName, libCode: renameObj.newLibCode}}, function (err) {
         if(err){
             callback(err, '重命名失败!');
         }

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

@@ -30,10 +30,11 @@ module.exports =  function (app) {
     app.get('/rationRepository/coeList', viewsController.auth, viewsController.init, viewsController.redirectCoeList);
     app.get('/rationRepository/installation', viewsController.auth, viewsController.init, viewsController.redirectInstallation);
 
+    apiRouter.post("/prepareInitData", rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.prepareInitData);
     apiRouter.post("/getCompilationList", rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.getCompilationList);
     apiRouter.post("/getRationLibsByCompilation", rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.getRationLibsByCompilation);
-
     apiRouter.post("/getRationLib",rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.getRationLib);
+
     apiRouter.post("/getRationDisplayNames",rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.getDisPlayRationLibs);
     apiRouter.post("/editRationLibs",rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.updateRationRepositoryName);
     apiRouter.post("/addRationRepository",rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.addRationRepository);
@@ -41,6 +42,8 @@ module.exports =  function (app) {
     apiRouter.post("/getRealLibName",rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.getRealLibName);
     apiRouter.post("/getLibIDByName",rationRepositoryController.auth, rationRepositoryController.init, rationRepositoryController.getLibIDByName);
 
+    apiRouter.get('/sectionTemplateCount/:compilationId', rationChapterTreeController.auth, rationChapterTreeController.init, rationChapterTreeController.sectionTemplateCount);
+    apiRouter.post('/initSectionTemplate', rationChapterTreeController.auth, rationChapterTreeController.init, rationChapterTreeController.initSectionTemplate);
     apiRouter.post("/getRationTree",rationChapterTreeController.auth, rationChapterTreeController.init, rationChapterTreeController.getRationChapterTree);
     apiRouter.post("/getNewRationTreeID",rationChapterTreeController.auth, rationChapterTreeController.init, rationChapterTreeController.getNewRationTreeID);
     apiRouter.post("/createNewNode",rationChapterTreeController.auth, rationChapterTreeController.init, rationChapterTreeController.createNewNode);
@@ -59,6 +62,8 @@ module.exports =  function (app) {
     apiRouter.post("/getRationsCodes",rationController.auth, rationController.init, rationController.getRationsCodes);
     apiRouter.post("/updateJobContent",rationController.auth, rationController.init, rationController.updateJobContent);
     apiRouter.post("/updateAnnotation",rationController.auth, rationController.init, rationController.updateAnnotation);
+    apiRouter.post("/updateRationTemplate",rationController.auth, rationController.init, rationController.updateRationTemplate);
+    apiRouter.post("/updateRationBySection",rationController.auth, rationController.init, rationController.updateRationBySection);
 
     apiRouter.post("/createNewGljTypeNode",repositoryGljController.auth, gljController.init, gljController.createNewGljTypeNode);
     apiRouter.post("/updateGljNodes",repositoryGljController.auth, gljController.init, gljController.updateGljNodes);
@@ -70,6 +75,7 @@ module.exports =  function (app) {
     apiRouter.post("/getGljItemsByIds",repositoryGljController.auth, gljController.init, gljController.getGljItemsByIds);
     apiRouter.post("/getGljItemsByCodes",repositoryGljController.auth, gljController.init, gljController.getGljItemsByCodes);
 
+    apiRouter.post("/getCoeReference",coeListController.auth, coeListController.init, coeListController.getCoeReference);
     apiRouter.post("/getCoeList",coeListController.auth, coeListController.init, coeListController.getCoeList);
     apiRouter.post("/saveCoeList",coeListController.auth, coeListController.init, coeListController.saveCoeList);
     apiRouter.post("/getCoeItemsByIDs",coeListController.auth, coeListController.init, coeListController.getCoeItemsByIDs);

+ 2 - 2
modules/reports/rpt_component/helper/jpc_helper_common.js

@@ -133,7 +133,7 @@ let JpcCommonHelper = {
         }
         return rst;
     },
-    getStringLinesInArea: function(area, strVal, pdfDoc, chnW, otherW) {
+    getStringLinesInArea: function(area, strVal, chnW, otherW) {
         //备注: 因后台的pdf kit判断字符串长度与前端的不一样,需要做些调整,不一次性地判断字符串长度。
         //      分2种字符:中文与非中文,按照各种字符的数量分别乘以相关一个字符的宽度再累计。
         //      另判断行数还不能直接用总长度除以宽度来计算,因每一行都会有不同的余量,所以得一行行走过来判断。
@@ -157,7 +157,7 @@ let JpcCommonHelper = {
         return rst;
         //备注: 其实是想用canvas的,但node canvas装起来麻烦,暂时用PDF Kit来顶用一下,以后有更好的再换
     },
-    splitString: function (area, strVal, pdfDoc, chnW, otherW) {
+    splitString: function (area, strVal, chnW, otherW) {
         let rst = [];
         if (strVal) {
             let areaWidth = area[JV.PROP_RIGHT] - area[JV.PROP_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT] - 1;

+ 5 - 1
modules/reports/rpt_component/helper/jpc_helper_common_output.js

@@ -2,7 +2,7 @@ let JV = require('../jpc_value_define');
 let JpcFieldHelper = require('./jpc_helper_field');
 
 let JpcCommonOutputHelper = {
-    createCommonOutputWithoutDecorate: function (node, value) {
+    createCommonOutputWithoutDecorate: function (node, value, forceCombine) {
         let me = this, rst = {};
         //1. font/style/control
         rst[JV.PROP_FONT] = node[[JV.PROP_FONT]];
@@ -14,9 +14,13 @@ let JpcCommonOutputHelper = {
         // innerFormat(node[JV.PROP_FORMAT], rst);
         if (node[JV.PROP_PREFIX] && rst[JV.PROP_VALUE] !== null) {
             rst[JV.PROP_VALUE] = node[JV.PROP_PREFIX] + rst[JV.PROP_VALUE];
+        } else if (node[JV.PROP_PREFIX] && forceCombine) {
+            rst[JV.PROP_VALUE] = node[JV.PROP_PREFIX];
         }
         if (node[JV.PROP_SUFFIX] && rst[JV.PROP_VALUE] !== null) {
             rst[JV.PROP_VALUE] = rst[JV.PROP_VALUE] + node[JV.PROP_SUFFIX];
+        } else if (node[JV.PROP_SUFFIX] && forceCombine) {
+            rst[JV.PROP_VALUE] = node[JV.PROP_SUFFIX];
         }
         return rst;
     },

+ 39 - 7
modules/reports/rpt_component/helper/jpc_helper_cross_tab.js

@@ -1,4 +1,5 @@
 let JV = require('../jpc_value_define');
+let JE = require('../jpc_rte');
 let JpcCommonHelper = require('./jpc_helper_common');
 
 let JpcCrossTabHelper = {
@@ -27,7 +28,7 @@ let JpcCrossTabHelper = {
     },
     sortFieldValue: function(sIDX, eIDX, sortOrder, dataField, dataValSeq) {
         let tmpSeq = [];
-        if ((sortOrder) && (sortOrder != JV.TAB_FIELD_PROP_SORT_VAL_NOSORT)) {
+        if ((sortOrder) && (sortOrder !== JV.TAB_FIELD_PROP_SORT_VAL_NOSORT)) {
             if (sIDX >= 0 && eIDX >= sIDX && dataValSeq.length > eIDX) {
                 let reversed = 1;
                 if (sortOrder === JV.TAB_FIELD_PROP_SORT_VAL_DESC) {
@@ -38,7 +39,8 @@ let JpcCrossTabHelper = {
                 }
                 tmpSeq.sort(function(idx1, idx2) {
                     let rst = 0;
-                    if (isNaN(parseFloat(dataField[idx1])) || isNaN(parseFloat(dataField[idx1]))) {
+                    // if (isNaN(parseFloat(dataField[idx1])) || isNaN(parseFloat(dataField[idx1]))) {
+                    if (typeof (dataField[idx1]) === 'string' || typeof (dataField[idx1]) === 'string' ) {
                         if (dataField[idx1] > dataField[idx2]) {
                             rst = reversed;
                         } else if (dataField[idx1] < dataField[idx2]) {
@@ -72,12 +74,12 @@ let JpcCrossTabHelper = {
         }
         return rst;
     },
-    sortTabFields: function(tabFields, fieldSeqs, data_details, dataSeq) {
+    sortTabFields: function(tabFields, fieldSeqs, data_details, dataSeq, $CURRENT_RPT) {
         let me = this;
         let sIDX = 0, eIDX = -1, isFirstSort = true;
         for (let i = 0; i < tabFields.length; i++) {
             let tabField = tabFields[i];
-            if (tabField[JV.TAB_FIELD_PROP_SORT] != JV.TAB_FIELD_PROP_SORT_VAL_NOSORT) {
+            if (tabField[JV.TAB_FIELD_PROP_SORT] !== JV.TAB_FIELD_PROP_SORT_VAL_NOSORT) {
                 if (isFirstSort) {
                     isFirstSort = false;
                     //first field, should sort all data items
@@ -85,14 +87,34 @@ let JpcCrossTabHelper = {
                         sIDX = 0;
                         eIDX = dataSeq[j].length - 1;
                         //sort the field value here
-                        me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                        if (typeof(fieldSeqs[i]) === "object") {
+                            let exFirstField = JE.F(fieldSeqs[i][JV.PROP_ID], $CURRENT_RPT);
+                            if (exFirstField) {
+                                me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT], exFirstField[JV.PROP_AD_HOC_DATA], dataSeq[j]);
+                            } else {
+                                //不排序(健壮性)
+                            }
+                        } else {
+                            me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                        }
+                        // me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
                     }
                 } else {
                     //then sort the rest fields one by one
                     for (let j = 0; j < dataSeq.length; j++) {
                         let chkFields = [];
                         for (let k = 0; k < i; k++) {
-                            chkFields.push(data_details[fieldSeqs[k]]);
+                            if (typeof(fieldSeqs[k]) === "object") {
+                                let exField = JE.F(fieldSeqs[k][JV.PROP_ID], $CURRENT_RPT);
+                                if (exField) {
+                                    chkFields.push(exField[JV.PROP_AD_HOC_DATA]);
+                                } else {
+                                    chkFields.push(null);
+                                }
+                            } else {
+                                chkFields.push(data_details[fieldSeqs[k]]);
+                            }
+                            // chkFields.push(data_details[fieldSeqs[k]]);
                         }
                         sIDX = 0, eIDX = -1;
                         for (let m = 1; m < dataSeq[j].length; m++) {
@@ -103,7 +125,17 @@ let JpcCrossTabHelper = {
                             };
                             if (eIDX >= sIDX) {
                                 if (eIDX != sIDX) {
-                                    me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                                    if (typeof(fieldSeqs[i]) === "object") {
+                                        let exOtherField = JE.F(fieldSeqs[i][JV.PROP_ID], $CURRENT_RPT);
+                                        if (exOtherField) {
+                                            me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT], exOtherField[JV.PROP_AD_HOC_DATA], dataSeq[j]);
+                                        } else {
+                                            //不排序(健壮性)
+                                        }
+                                    } else {
+                                        me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                                    }
+                                    // me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
                                 }
                                 sIDX = m;
                                 eIDX = m - 1; //for protection purpose

+ 1 - 1
modules/reports/rpt_component/helper/jpc_helper_discrete.js

@@ -60,7 +60,7 @@ let JpcDiscreteHelper = {
                                 let param = JE.P(df[JV.PROP_PARAM_ID], $CURRENT_RPT);
                                 value = param[JV.PROP_DFT_VALUE];
                             }
-                            let item = JpcCommonOutputHelper.createCommonOutputWithoutDecorate(df, value, null);
+                            let item = JpcCommonOutputHelper.createCommonOutputWithoutDecorate(df, value, true);
                             //position
                             item[JV.PROP_AREA] = JpcAreaHelper.outputArea(df[JV.PROP_AREA], band, unitFactor, 1, 0, 1, 0, multiCols, multiColIdx, false, false);
                             rst.push(item);

+ 0 - 0
modules/reports/rpt_component/helper/jpc_helper_field.js


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است