Browse Source

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

Conflicts:
	web/users/views/compilation/engineering.html
zhangweicheng 7 years ago
parent
commit
acf949de78
100 changed files with 17940 additions and 1150 deletions
  1. 12557 0
      lib/lodash/lodash.js
  2. 62 0
      lib/spreadjs/sheets/gc.spread.sheets.all.11.1.0.min.js
  3. 62 0
      lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js
  4. 4 0
      lib/ztree/css/zTreeStyle.css
  5. 2 0
      modules/all_models/compilation.js
  6. 5 0
      modules/all_models/engineering_lib.js
  7. 2 1
      modules/all_models/stdRation_ration.js
  8. 26 0
      modules/all_models/std_billsGuidance_items.js
  9. 27 0
      modules/all_models/std_billsGuidance_lib.js
  10. 9 9
      modules/bills_lib/models/bills_lib_interfaces.js
  11. 4 0
      modules/common/base/base_controller.js
  12. 10 0
      modules/ration_repository/controllers/ration_controller.js
  13. 10 0
      modules/ration_repository/controllers/ration_repository_controller.js
  14. 33 4
      modules/ration_repository/controllers/repository_views_controller.js
  15. 8 2
      modules/ration_repository/models/installation.js
  16. 17 11
      modules/ration_repository/models/ration_item.js
  17. 20 1
      modules/ration_repository/models/ration_section_tree.js
  18. 37 5
      modules/ration_repository/models/repository_map.js
  19. 2 0
      modules/ration_repository/routes/ration_rep_routes.js
  20. 13 5
      modules/reports/controllers/rpt_tpl_controller.js
  21. 0 24
      modules/reports/rpt_component/helper/jpc_helper_common.js
  22. 10 5
      modules/reports/rpt_component/jpc_flow_tab.js
  23. 218 58
      modules/reports/util/rpt_construct_data_util.js
  24. 94 0
      modules/reports/util/rpt_svg_util.js
  25. 103 0
      modules/std_billsGuidance_lib/controllers/libController.js
  26. 27 0
      modules/std_billsGuidance_lib/controllers/viewController.js
  27. 239 0
      modules/std_billsGuidance_lib/facade/facades.js
  28. 29 0
      modules/std_billsGuidance_lib/routes/routes.js
  29. 33 5
      modules/std_glj_lib/models/gljMapModel.js
  30. 20 32
      modules/std_glj_lib/models/gljModel.js
  31. 19 0
      modules/users/controllers/compilation_controller.js
  32. 0 1
      modules/users/controllers/login_controller.js
  33. 43 2
      modules/users/controllers/user_controller.js
  34. 13 1
      modules/users/models/compilation_model.js
  35. 5 0
      modules/users/models/engineering_lib_model.js
  36. 68 0
      modules/users/models/user_model.js
  37. 1 0
      modules/users/routes/compilation_route.js
  38. 1 0
      modules/users/routes/user_route.js
  39. 11 8
      operation.js
  40. 8 7
      package.json
  41. 37 1
      public/stringUtil.js
  42. 27 1
      public/web/common_ajax.js
  43. 49 0
      public/web/ration_glj_units.js
  44. 4 1
      public/web/rpt_value_define.js
  45. 2 0
      public/web/sheet/sheet_common.js
  46. 21 4
      public/web/treeDataHelper.js
  47. 42 1
      public/web/tree_sheet/tree_sheet_controller.js
  48. 2 0
      public/web/tree_sheet/tree_sheet_helper.js
  49. 285 0
      web/maintain/billsGuidance_lib/css/main.css
  50. 147 0
      web/maintain/billsGuidance_lib/html/main.html
  51. 116 0
      web/maintain/billsGuidance_lib/html/zhiyin.html
  52. 796 0
      web/maintain/billsGuidance_lib/js/billsGuidance.js
  53. 46 0
      web/maintain/billsGuidance_lib/js/global.js
  54. 224 0
      web/maintain/billsGuidance_lib/js/main.js
  55. 62 57
      web/maintain/bills_lib/css/main.css
  56. 15 2
      web/maintain/bills_lib/html/main.html
  57. 24 2
      web/maintain/bills_lib/html/neirong.html
  58. 29 3
      web/maintain/bills_lib/html/qingdan.html
  59. 23 2
      web/maintain/bills_lib/html/tezheng.html
  60. 28 0
      web/maintain/bills_lib/scripts/bills_lib_ajax.js
  61. 10 2
      web/maintain/bills_lib/scripts/db_controller.js
  62. 12 3
      web/maintain/bills_lib/scripts/set_sheets.js
  63. 25 6
      web/maintain/ration_repository/anzhuang.html
  64. 91 63
      web/maintain/ration_repository/dinge.html
  65. 9 8
      web/maintain/ration_repository/fuzhu.html
  66. 9 8
      web/maintain/ration_repository/gongliao.html
  67. 4 16
      web/maintain/ration_repository/js/coe.js
  68. 333 0
      web/maintain/ration_repository/js/gljSelect.js
  69. 95 67
      web/maintain/ration_repository/js/installation.js
  70. 21 1
      web/maintain/ration_repository/js/main.js
  71. 73 36
      web/maintain/ration_repository/js/ration.js
  72. 0 49
      web/maintain/ration_repository/js/rationUnits.js
  73. 8 8
      web/maintain/ration_repository/js/ration_assist.js
  74. 13 13
      web/maintain/ration_repository/js/ration_coe.js
  75. 137 39
      web/maintain/ration_repository/js/ration_glj.js
  76. 5 17
      web/maintain/ration_repository/js/repository_glj.js
  77. 22 3
      web/maintain/ration_repository/js/section_tree.js
  78. 53 0
      web/maintain/ration_repository/js/sheetsOpr.js
  79. 4 4
      web/maintain/ration_repository/main.html
  80. 7 2
      web/maintain/report/js/cfg_const.js
  81. 1 1
      web/maintain/report/js/rpt_tpl_band.js
  82. 1 0
      web/maintain/report/js/rpt_tpl_calculation.js
  83. 231 78
      web/maintain/report/js/rpt_tpl_data_map.js
  84. 21 21
      web/maintain/report/js/rpt_tpl_field_map.js
  85. 339 193
      web/maintain/report/js/rpt_tpl_main.js
  86. 344 144
      web/maintain/report/js/rpt_tpl_pre_handle.js
  87. 2 2
      web/maintain/report/rpt_tpl_detail_calculation.html
  88. 13 22
      web/maintain/report/rpt_tpl_detail_field_location.html
  89. 2 2
      web/maintain/report/rpt_tpl_detail_mapping_fields.html
  90. 12 14
      web/maintain/report/rpt_tpl_main.html
  91. 10 7
      web/maintain/report/rpt_tpl_tree.html
  92. 26 5
      web/maintain/std_glj_lib/html/gongliao.html
  93. 12 10
      web/maintain/std_glj_lib/html/main.html
  94. 59 30
      web/maintain/std_glj_lib/js/glj.js
  95. 10 5
      web/maintain/std_glj_lib/js/gljClassTree.js
  96. 3 2
      web/maintain/std_glj_lib/js/gljComponent.js
  97. 28 9
      web/maintain/std_glj_lib/js/main.js
  98. 47 5
      web/users/js/compilation.js
  99. 17 0
      web/users/js/user.js
  100. 0 0
      web/users/views/compilation/add.html

File diff suppressed because it is too large
+ 12557 - 0
lib/lodash/lodash.js


File diff suppressed because it is too large
+ 62 - 0
lib/spreadjs/sheets/gc.spread.sheets.all.11.1.0.min.js


File diff suppressed because it is too large
+ 62 - 0
lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js


+ 4 - 0
lib/ztree/css/zTreeStyle.css

@@ -70,12 +70,16 @@ website:	http://code.google.com/p/jquerytree/
 .ztree li span.button.bottom_docu{background-position:-56px -36px}
 .ztree li span.button.noline_docu{ background:none;}
 
+.ztree li span.button.star {margin-right:2px; background-position:-126px -64px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.blue_core {margin-right:2px; background-position:-126px -16px; vertical-align:top; *vertical-align:middle}
+
 .ztree li span.button.ico_open{margin-right:2px; background-position:-110px -16px; vertical-align:top; *vertical-align:middle}
 .ztree li span.button.ico_close{margin-right:2px; background-position:-110px 0; vertical-align:top; *vertical-align:middle}
 .ztree li span.button.ico_docu{margin-right:2px; background-position:-110px -32px; vertical-align:top; *vertical-align:middle}
 .ztree li span.button.edit {margin-right:2px; background-position:-110px -48px; vertical-align:top; *vertical-align:middle}
 .ztree li span.button.remove {margin-right:2px; background-position:-110px -64px; vertical-align:top; *vertical-align:middle}
 
+
 .ztree li span.button.ico_loading{margin-right:2px; background:url(img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
 
 ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}

+ 2 - 0
modules/all_models/compilation.js

@@ -63,6 +63,8 @@ let modelSchema = {
     create_time: Number,
     // 创建者id
     creator: String,
+    //描述
+    description: String,
     // 发布时间
     release_time: {
         type: Number,

+ 5 - 0
modules/all_models/engineering_lib.js

@@ -25,6 +25,11 @@ let modelSchema = {
         type: Schema.Types.Mixed,
         default: []
     },
+    //清单指引库
+    billsGuidance_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
     // 列设置
     main_tree_col: {
         type: Schema.Types.Mixed,

+ 2 - 1
modules/all_models/stdRation_ration.js

@@ -43,7 +43,8 @@ const rationItemSchema = new Schema({
     rationGljList: [rationGljItemSchema],
     rationCoeList: Array,
     rationAssList: [rationAssItemSchema],
-    rationInstList: [rationInstSchema]
+    rationInstList: [rationInstSchema],
+    isDeleted: {type: Boolean, default: false}
 });
 
 mongoose.model('std_ration_lib_ration_items', rationItemSchema, 'std_ration_lib_ration_items');

+ 26 - 0
modules/all_models/std_billsGuidance_items.js

@@ -0,0 +1,26 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+//清单指引条目
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+
+const stdBillsGuidanceItems = new Schema({
+    libID: String,
+    ID: String, //uuid
+    ParentID: String,
+    NextSiblingID: String,
+    billsID: String, //关联清单的ID
+    name: String,
+    type: Number, //0:工作内容 1:定额
+    rationID: {type: Number, default: null}, //定额类型时
+    deleted: {type: Boolean, default: false}
+}, {versionKey: false});
+
+mongoose.model('std_billsGuidance_items', stdBillsGuidanceItems, 'std_billsGuidance_items');

+ 27 - 0
modules/all_models/std_billsGuidance_lib.js

@@ -0,0 +1,27 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+//清单指引库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+
+const stdBillsGuidanceLib = new Schema({
+    ID: String, //uuid
+    compilationId: String,
+    compilationName: String,
+    billsLibId: Number,
+    billsLibName: String,
+    name: String,
+    creator: String,
+    createDate: String,
+    deleted: {type: Boolean, default: false},
+}, {versionKey: false});
+
+mongoose.model('std_billsGuidance_lib', stdBillsGuidanceLib, 'std_billsGuidance_lib');
+

+ 9 - 9
modules/bills_lib/models/bills_lib_interfaces.js

@@ -139,7 +139,7 @@ billsLibDao.prototype.deleteStdBillsLib = function(data, callback){
                 else{
                     if(result.length > 0 ){
                         let newRecentOpr = getNewOprArr(result[0].recentOpr, lastOperator, lastOperateDate);
-                        StdBillsLib.update({billsLibId: billsLibId}, {$set: {recentOpr: newRecentOpr, deleted: true}}, function(err){
+                        StdBillsLib.remove({billsLibId: billsLibId}, function(err){
                             if(err){
                                 cb(err);
                             }
@@ -152,17 +152,17 @@ billsLibDao.prototype.deleteStdBillsLib = function(data, callback){
             });
         },
         function(cb){
-            Bills.update({billsLibId: billsLibId, deleted: false}, {$set: {deleted: true}}, {upsert: false, multi: true}, function(err){
+            Bills.remove({billsLibId: billsLibId}, function(err){
                 cb(null);
             });
         },
         function(cb){
-            JobContent.update({billsLibId: billsLibId, deleted: false}, {$set: {deleted: true}}, {upsert: false, multi: true}, function(err, result){
+            JobContent.remove({billsLibId: billsLibId}, function(err, result){
                 cb(null);
             });
         },
         function(cb){
-            ItemCharacter.update({billsLibId: billsLibId, deleted: false}, {$set: {deleted: true}}, {upsert: false, multi: true}, function(err){
+            ItemCharacter.remove({billsLibId: billsLibId}, function(err){
                 cb(null);
             })
         }
@@ -844,7 +844,7 @@ billsLibDao.prototype.removeTotal = function (data, callback) {
         delJobs: function () {
             return function (cb) {
                 async.each(delIds, function (delJobId, ecb) {
-                    JobContent.update({billsLibId: billsLibId, id: delJobId, deleted: false}, {$set: {deleted: true}}, function (err, result) {
+                    JobContent.remove({billsLibId: billsLibId, id: delJobId}, function (err, result) {
                         if(err){
                             ecb(err);
                         }
@@ -865,7 +865,7 @@ billsLibDao.prototype.removeTotal = function (data, callback) {
         delJobsArr: function () {
             return function (cb) {
                 async.each(delArr, function (delObj, ecb) {
-                    Bills.update({billsLibId: billsLibId, ID: delObj.updateId, deleted: false}, {$pull: {jobs: {id: delObj.delId}}}, function (err) {
+                    Bills.update({billsLibId: billsLibId, ID: delObj.updateID, deleted: false}, {$pull: {jobs: {id: delObj.delId}}}, function (err) {
                         if(err){
                             ecb(err);
                         }else{
@@ -885,7 +885,7 @@ billsLibDao.prototype.removeTotal = function (data, callback) {
         delItems: function () {
             return function (cb) {
                 async.each(delIds, function (delItemId, ecb) {
-                    ItemCharacter.update({billsLibId: billsLibId, id: delItemId, deleted: false}, {$set: {deleted: true}}, function (err) {
+                    ItemCharacter.remove({billsLibId: billsLibId, id: delItemId}, function (err) {
                         if(err){
                             ecb(err);
                         }
@@ -906,7 +906,7 @@ billsLibDao.prototype.removeTotal = function (data, callback) {
         delItemsArr: function () {
             return function (cb) {
                 async.each(delArr, function (delObj, ecb) {
-                    Bills.update({billsLibId: billsLibId, ID: delObj.updateId, deleted:false}, {$pull: {items: {id: delObj.delId}}}, function(err){
+                    Bills.update({billsLibId: billsLibId, ID: delObj.updateID, deleted:false}, {$pull: {items: {id: delObj.delId}}}, function(err){
                         if(err){
                             ecb(err);
                         }
@@ -1770,7 +1770,7 @@ billsLibDao.prototype.deleteBills = function(delData, callback){
         async.parallel([
             function(cb){
                 async.each(deleteIds, function(delId, ecb){
-                    Bills.update({billsLibId: billsLibId, ID: delId, deleted: false}, {$set: {deleted: true}}, function(err){
+                    Bills.remove({billsLibId: billsLibId, ID: delId}, function(err){
                         if(err){
                             ecb(err);
                         }

+ 4 - 0
modules/common/base/base_controller.js

@@ -62,6 +62,7 @@ class BaseController {
         }
 
         try {
+            console.log('enterINit');
             // 如果不适超级管理员则判断权限
             let sessionManager = request.session.managerData;
             if (sessionManager.superAdmin !== 1) {
@@ -105,6 +106,7 @@ class BaseController {
             // moment工具
             response.locals.moment = Moment;
         } catch (error) {
+            console.log('enterAURE');
             console.log(error);
             response.redirect('/dashboard');
             return;
@@ -125,6 +127,7 @@ class BaseController {
         // 判断session
         let mangerData = request.session.managerData;
         try {
+            console.log('enterAuth');
             if (typeof mangerData !== 'object' || Object.keys(mangerData).length < 0) {
                 throw 'err data';
             }
@@ -140,6 +143,7 @@ class BaseController {
             }
 
         } catch (error) {
+            console.log('enterAURE');
             response.redirect('/login');
             return;
         }

+ 10 - 0
modules/ration_repository/controllers/ration_controller.js

@@ -9,6 +9,16 @@ var callback = function(req, res, err, message, data){
 };
 
 class RationController extends BaseController{
+    async getRationItemsByLib(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let rationItems = await rationItem.getRationItemsByLib(data.rationLibId);
+            callback(req, res, 0, '', rationItems);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
     getRationItemsBySection(req, res){
         let sectionId = req.body.sectionID;
         let rationRepId = req.body.rationRepId;

+ 10 - 0
modules/ration_repository/controllers/ration_repository_controller.js

@@ -18,6 +18,16 @@ const excel = require("node-xlsx");
 const rationItem = require("../models/ration_item");
 
 class RationRepositoryController extends baseController {
+    async getRationLibsByCompilation(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let rationLibs = await rationRepository.getRationLibsByCompilation(data.compilationId);
+            callback(req, res, 0, '', rationLibs);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
     async getCompilationList(req, res) {
         try {
             let compilationModel = new CompilationModel(), rst = [];

+ 33 - 4
modules/ration_repository/controllers/repository_views_controller.js

@@ -10,32 +10,61 @@ class ViewsController extends BaseController{
                 userID: req.session.managerData.userID
             });
     }
+    //rationRepository/lmm rationRepository/coeList rationRepository/installation
     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}`;
         res.render('maintain/ration_repository/dinge.html',
             {
                 userAccount: req.session.managerData.username,
-                userID: req.session.managerData.userID
+                userID: req.session.managerData.userID,
+                redirectGlj: redirectGlj,
+                redirectCoe: redirectCoe,
+                redirectInstallation: redirectInstallation
             });
     }
     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}`;
         res.render('maintain/ration_repository/gongliao.html',
             {
                 userAccount: req.session.managerData.username,
-                userID: req.session.managerData.userID
+                userID: req.session.managerData.userID,
+                redirectRation: redirectRation,
+                redirectCoe: redirectCoe,
+                redirectInstallation: redirectInstallation
             });
     }
     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}`;
         res.render('maintain/ration_repository/fuzhu.html',
             {
                 userAccount: req.session.managerData.username,
-                userID: req.session.managerData.userID
+                userID: req.session.managerData.userID,
+                redirectGlj: redirectGlj,
+                redirectRation: redirectRation,
+                redirectInstallation: redirectInstallation
             });
     }
     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}`;
         res.render('maintain/ration_repository/anzhuang.html',
             {
                 userAccount: req.session.managerData.username,
-                userID: req.session.managerData.userID
+                userID: req.session.managerData.userID,
+                redirectGlj: redirectGlj,
+                redirectCoe: redirectCoe,
+                redirectRation: redirectRation
             });
     }
 }

+ 8 - 2
modules/ration_repository/models/installation.js

@@ -33,9 +33,12 @@ class InstallationDao{
                 if(data.updateType === 'new'){
                     await installSectionModel.create(data.updateData);
                 }
-                else if(data.updateType === 'update'){
+                else if(data.updateType === 'update' && !data.updateData.deleted){
                     await installSectionModel.update({ID: data.updateData.ID}, data.updateData);
                 }
+                else {
+                    await installSectionModel.remove({ID: data.updateData.ID});
+                }
             }
             callback(0, null);
         }
@@ -50,9 +53,12 @@ class InstallationDao{
                 if(data.updateType === 'new'){
                     await installFeeItemModel.create(data.updateData);
                 }
-                else if(data.updateType === 'update'){
+                else if(data.updateType === 'update' && !data.updateData.deleted){
                     await installFeeItemModel.update({ID: data.updateData.ID}, data.updateData);
                 }
+                else{
+                    await installFeeItemModel.remove({ID: data.updateData.ID});
+                }
             }
             callback(0, null);
         }

+ 17 - 11
modules/ration_repository/models/ration_item.js

@@ -14,6 +14,10 @@ import STDGLJListModel from '../../std_glj_lib/models/gljModel';
 
 var rationItemDAO = function(){};
 
+rationItemDAO.prototype.getRationItemsByLib = async function (rationRepId) {
+    return await rationItemModel.find({rationRepId: rationRepId, $or: [{isDeleted: null}, {isDeleted: false}]});
+};
+
 rationItemDAO.prototype.sortToNumber = function (datas) {
     for(let i = 0, len = datas.length; i < len; i++){
         let data = datas[i]._doc;
@@ -288,6 +292,7 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                     }
                 }
                 gljDao.getStdCompleGljItems(compleGljIds, stdGljIds, function (err, allGljs) {
+                    const processDecimal = -6;
                     if(err){
                         cb(err);
                     }
@@ -349,21 +354,21 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                             if(labourPrc.length > 0){
                                 let sumLaP = 0;
                                 for(let i=0; i<labourPrc.length; i++){
-                                    sumLaP += labourPrc[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 += materialPrc[i];
+                                    sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], processDecimal);
                                 }
                                 updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
                             }
                             if(machinePrc.length > 0){
                                 let sumMaP = 0;
                                 for(let i =0; i< machinePrc.length; i++){
-                                    sumMaP += machinePrc[i];
+                                    sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], processDecimal);
                                 }
                                 updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
                             }
@@ -458,7 +463,7 @@ rationItemDAO.prototype.getRationGljIds = function (data, callback) {
 
 rationItemDAO.prototype.getRationsCodes = function (data, callback) {
     let repId = data.repId;
-    rationItemModel.find({rationRepId: repId}, function (err, result) {
+    rationItemModel.find({rationRepId: repId, isDeleted: false}, function (err, result) {
         if(err){
             callback(err, 'Error', null);
         }
@@ -518,6 +523,7 @@ 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], machine = [301, 302, 303];
     let labourPrc = [], materialPrc = [], machinePrc = [], singlePrc, updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, basePrice: 0};
@@ -542,25 +548,25 @@ rationItemDAO.prototype.calcForRation = function (stdGljList, ration) {
     if(labourPrc.length > 0){
         let sumLaP = 0;
         for(let i = 0, len  = labourPrc.length; i < len; i++){
-            sumLaP += labourPrc[i];
+            sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], processDecimal);
         }
         updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
     }
     //材料费
     if(materialPrc.length > 0){
-        let sumLaP = 0;
+        let sumMtP = 0;
         for(let i = 0, len  = materialPrc.length; i < len; i++){
-            sumLaP += materialPrc[i];
+            sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], processDecimal);
         }
-        updatePrc.materialPrice = scMathUtil.roundTo(sumLaP, -2);
+        updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
     }
     //机械费
     if(machinePrc.length > 0){
-        let sumLaP = 0;
+        let sumMaP = 0;
         for(let i = 0, len  = machinePrc.length; i < len; i++){
-            sumLaP += machinePrc[i];
+            sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], processDecimal);
         }
-        updatePrc.machinePrice = scMathUtil.roundTo(sumLaP, -2);
+        updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
     }
     //基价
     updatePrc.basePrice = scMathUtil.roundTo(updatePrc.labourPrice + updatePrc.materialPrice + updatePrc.machinePrice, -2);

+ 20 - 1
modules/ration_repository/models/ration_section_tree.js

@@ -7,6 +7,7 @@ let moment = require('moment');
 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');
 var rationChapterTreeDAO = function(){};
 
 rationChapterTreeDAO.prototype.getRationChapterTree = function(rationLibId,callback){
@@ -169,7 +170,7 @@ rationChapterTreeDAO.prototype.updateNodes = function(lastOpr, updateData,callba
         //md.isNew = false;
         functions.push((function(doc) {
             return function(cb) {
-                if(doc.updateType === 'update'){
+                if(doc.updateType === 'update' && !doc.updateData.isDeleted){
                     rationChapterTreeModel.update({rationRepId: doc.updateData.rationRepId, ID: doc.updateData.ID}, doc.updateData, function (err) {
                         if(err){
                             cb(err);
@@ -179,6 +180,24 @@ rationChapterTreeDAO.prototype.updateNodes = function(lastOpr, updateData,callba
                         }
                     });
                 }
+                else if(doc.updateType === 'update' && doc.updateData.isDeleted){
+                    rationChapterTreeModel.remove({rationRepId: doc.updateData.rationRepId, ID: doc.updateData.ID}, function (err) {
+                        if(err){
+                            cb(err);
+                        }
+                        else {
+                            rationModel.remove({sectionId: doc.updateData.ID}, function(err){
+                                if(err){
+                                    cb(err);
+                                }
+                                else {
+                                    cb(null);
+                                }
+                            });
+
+                        }
+                    });
+                }
                 else if(doc.updateType === 'new'){
                     rationChapterTreeModel.create(doc.updateData, function (err) {
                         if(err){

+ 37 - 5
modules/ration_repository/models/repository_map.js

@@ -9,7 +9,10 @@ let counter = require('../../../public/counter/counter');
 const gljMapModel = mongoose.model('std_glj_lib_map');
 const rationRepository = mongoose.model('std_ration_lib_map');
 const rationChapterTreeModel = mongoose.model('std_ration_lib_ration_chapter_trees');
-const rationItemModel = mongoose.model('complementary_ration_items');
+const rationItemModel = mongoose.model('std_ration_lib_ration_items');
+const rationCoeModel = mongoose.model('std_ration_lib_coe_list');
+const rationInstallFeeItem = mongoose.model('std_ration_lib_installation');
+const rationInstallSection = mongoose.model('std_ration_lib_installationSection');
 
 function createNewLibModel(rationLibObj){
     var rst = {};
@@ -27,6 +30,10 @@ function createNewLibModel(rationLibObj){
 
 var rationRepositoryDao = function(){};
 
+rationRepositoryDao.prototype.getRationLibsByCompilation = async function (compilationId) {
+    return await rationRepository.find({compilationId: compilationId, deleted: false});
+};
+
 rationRepositoryDao.prototype.updateGljLib = function (gljLibId, callback) {
     rationRepository.update({gljLib: gljLibId}, {$set: {gljLib: -1}}, {multi: true}, function (err) {
         if(err){
@@ -203,9 +210,9 @@ rationRepositoryDao.prototype.deleteRationLib = function(oprtor, libId, callback
                    callback(err, "没有数据!");
                }
                 else{
-                   rationRepository.update({ID: libId, deleted: false}, {$set: {deleted: true}}, function (err) {
+                   rationRepository.remove({ID: libId}, function (err) {
                        if(err){
-                           callback(err, '移除工料机库失败!');
+                           callback(err, '移除定额库失败!');
                        }
                        else{
                            async.parallel([
@@ -222,17 +229,42 @@ rationRepositoryDao.prototype.deleteRationLib = function(oprtor, libId, callback
                                },
                                //删除库下定额
                                function (cb) {
-                                   rationItemModel.update({rationRepId: libId}, {$set: {isDeleted: true}}, {upsert: true, multi: true}, function (err) {
+                                   rationItemModel.remove({rationRepId: libId}, function (err) {
                                        if(err)cb(err);
                                        else cb(null);
                                    });
                                },
                                //删除库下章节树
                                function (cb) {
-                                   rationChapterTreeModel.update({rationRepId: libId}, {$set: {isDeleted: true}}, {upsert: true, multi: true}, function (err) {
+                                   rationChapterTreeModel.remove({rationRepId: libId}, function (err) {
                                        if(err)cb(err);
                                        else cb(null);
                                    })
+                               },
+                               //删除子目换算
+                               function (cb) {
+                                   rationCoeModel.remove({libID: libId}, function (err) {
+                                       if(err)cb(err);
+                                       else cb(null);
+                                   });
+                               },
+                               //删除安装
+                               async function (cb) {
+                                    try{
+                                        let feeItems = await rationInstallFeeItem.find({rationRepId: libId});
+                                        let sectionIDs = [];
+                                        for(let item of feeItems){
+                                            for(let section of item.section){
+                                                sectionIDs.push(section.ID);
+                                            }
+                                        }
+                                        await rationInstallFeeItem.remove({rationRepId: libId});
+                                        await rationInstallSection.remove({ID: {$in: sectionIDs}});
+                                        cb(null);
+                                    }
+                                    catch (err){
+                                        cb(err);
+                                    }
                                }
                            ], function (err) {
                                if(err) callback(err, 'fail');

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

@@ -31,6 +31,7 @@ module.exports =  function (app) {
     app.get('/rationRepository/installation', viewsController.auth, viewsController.init, viewsController.redirectInstallation);
 
     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);
@@ -51,6 +52,7 @@ module.exports =  function (app) {
     apiRouter.post("/updateAnnoSituation",rationChapterTreeController.auth, rationChapterTreeController.init, rationChapterTreeController.updateAnnoSituation);
 
     apiRouter.post("/getRationItems",rationController.auth, rationController.init, rationController.getRationItemsBySection);
+    apiRouter.post("/getRationItemsByLib",rationController.auth, rationController.init, rationController.getRationItemsByLib);
     apiRouter.post("/mixUpdateRationItems",rationController.auth, rationController.init, rationController.mixUpdateRationItems);
     apiRouter.post("/updateRationBasePrc",rationController.auth, rationController.init, rationController.updateRationBasePrc);
     apiRouter.post("/getRationGljIds",rationController.auth, rationController.init, rationController.getRationGljIds);

+ 13 - 5
modules/reports/controllers/rpt_tpl_controller.js

@@ -95,13 +95,21 @@ let mExport = {
         let params = JSON.parse(req.body.params),
             compilationId = params.compilationId,
             userId = params.userId,
+            sessionUserId = null,
             engineerId = params.engineerId;
-        if (req.session.sessionUser && req.session.sessionUser.id) userId = req.session.sessionUser.id;
-        let userIds = [];
-        userIds.push(userId);
-        if (userId != "-100") {
-            userIds.push("-100");
+        let userIds = ["-100"];
+        if (req.session.sessionUser && req.session.sessionUser.id) sessionUserId = req.session.sessionUser.id;
+        if (userId !== null) {
+            if (typeof userId === "string") {
+                if (userIds.indexOf(userId) < 0) userIds.push(userId);
+            } else if (userId instanceof Array) {
+                for (let uid of userId) {
+                    userIds.push(uid);
+                }
+            }
+        } else {
         }
+        if (sessionUserId && userIds.indexOf(sessionUserId) < 0) userIds.push(sessionUserId);
         if (!compilationId) {
             compilationId = req.session.sessionCompilation._id;
         }

+ 0 - 24
modules/reports/rpt_component/helper/jpc_helper_common.js

@@ -74,30 +74,6 @@ let JpcCommonHelper = {
         }
         return arrDPI;
     },
-    // getBrowerScreenDPI: function() {
-    //     let me = this, arrDPI = [];
-    //     if (!me.commonConstant.resolution) {
-    //         if (window) {
-    //             if (window.screen.deviceXDPI != undefined) {
-    //                 arrDPI.push(window.screen.deviceXDPI);
-    //                 arrDPI.push(window.screen.deviceYDPI);
-    //             } else {
-    //                 let tmpNode = document.createElement("DIV");
-    //                 tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
-    //                 document.body.appendChild(tmpNode);
-    //                 arrDPI.push(parseInt(tmpNode.offsetWidth));
-    //                 arrDPI.push(parseInt(tmpNode.offsetHeight));
-    //                 tmpNode.parentNode.removeChild(tmpNode);
-    //             }
-    //         } else {
-    //             arrDPI = [96,96];
-    //         }
-    //         me.commonConstant.resolution = arrDPI;
-    //     } else {
-    //         arrDPI = me.commonConstant.resolution;
-    //     }
-    //     return arrDPI;
-    // },
     getUnitFactor: function(rptTpl) {
         let me = this;
         return me.translateUnit(rptTpl[JV.NODE_MAIN_INFO][JV.PROP_UNITS]);

+ 10 - 5
modules/reports/rpt_component/jpc_flow_tab.js

@@ -52,8 +52,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         let private_inner_add_grp_rec = function(vi) {
             let hasFullGrp = true, couldBreak = false;
             for (let i = 0; i < grp_lines; i++) {
-                // if ( ((vi + insertedGrpAmt * grp_lines) + i + 1) >= (maxRecPerPage - preAmt)) {
-                if ( (vIdx.length + i ) >= maxRecPerPage) {
+                if (vIdx.length >= maxRecPerPage) {
                     for (let j = i; j < grp_lines; j++) {
                         grpPageInfo[JV.PROP_PRE_ADD_GRP_REC_INFO].push(j);
                     }
@@ -108,10 +107,16 @@ JpcFlowTabSrv.prototype.createNew = function(){
                     if (couldBreak) break;
                 } else {
                     //备注: 在有group的情况下,如果grpPageInfo[JV.PROP_SEG_GRP_IDX] 范围大于 grpSequenceInfo.length,则表示已经到最后了,不要再加空白数据了
+                    //      !!!但这是在有ex数据的情况下!!!
                     if (grpPageInfo[JV.PROP_SEG_GRP_IDX] < grpSequenceInfo.length) {
                         if (private_normal_add_rec(vi)) break;
                     } else {
-                        break;
+                        //还得判断是否是普通的流水数据情况,这里可以用isFollow来进行判断,暂时不需要特意加新参数(以后如isFollow的意义有变化则需要调整)
+                        if (!isFollow) {
+                            if (private_normal_add_rec(vi)) break;
+                        } else {
+                            break;
+                        }
                     }
                 }
             } else {
@@ -198,7 +203,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 }
                 let sumV = 0;
                 for (let si = preGrpIdx; si <= nexGrpIdx; si++) {
-                    sumV += JpcFieldHelper.getValue(data_field, segDataIdx[si]);
+                    sumV += parseFloat(JpcFieldHelper.getValue(data_field, segDataIdx[si]));
                 }
                 // me.group_sum_values[segIdx][j].push(sumV);
                 me.group_sum_values[segIdx][me.group_sum_fields[j][JV.PROP_SUM_KEY]].push(sumV);
@@ -588,7 +593,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                             }
                             //add page info
                             pageStatus[JV.STATUS_SEGMENT_END] = true;
-                            pageStatus[JV.STATUS_REPORT_END] = true;
+                            pageStatus[JV.STATUS_REPORT_END] = (segIdx === me.segments.length - 1);
                             private_addPage(segIdx, grpSeqInfo, false, false, -1);
                         } else {
                             private_addPage(segIdx, grpSeqInfo, false, false, -1);

+ 218 - 58
modules/reports/util/rpt_construct_data_util.js

@@ -12,6 +12,8 @@ let stringUtil = require("../../../public/stringUtil");
 let treeUtil = require('../../../public/treeUtil');
 let projectConst = consts.projectConst;
 let projectConstList = consts.projectConstList;
+const gljUtil = require('../../../public/gljUtil');
+
 
 const GLJ_TYPE = {
     Labour: 1,
@@ -134,11 +136,25 @@ class Rpt_Data_Extractor {
                             if (key === projectConst.RATION_GLJ && (rst.indexOf(projectConst.PROJECTGLJ) < 0)) {
                                 rst.push(projectConst.PROJECTGLJ);
                             }
-                            if (key === projectConst.PROJECTGLJ && (rst.indexOf(projectConst.RATION_GLJ) < 0)) {
-                                rst.push(projectConst.RATION_GLJ);
+                            if (key === projectConst.PROJECTGLJ) {
+                                if (rst.indexOf(projectConst.RATION_GLJ) < 0) rst.push(projectConst.RATION_GLJ);
+                                if (field[JV.PROP_FIELD_EXP_MAP].indexOf("'quantity'") > 0 ||
+                                    field[JV.PROP_FIELD_EXP_MAP].indexOf("'subdivisionQuantity'") > 0 ||
+                                    field[JV.PROP_FIELD_EXP_MAP].indexOf("'techQuantity'") > 0 ) {
+                                    if (rst.indexOf(projectConst.RATION) < 0) rst.push(projectConst.RATION);
+                                    if (rst.indexOf(projectConst.BILLS) < 0) rst.push(projectConst.BILLS);
+                                }
                             }
                         }
                     }
+                } else if (key === projectConst.PROJECTGLJ) {
+                    if (rst.indexOf(projectConst.RATION_GLJ) < 0) rst.push(projectConst.RATION_GLJ);
+                    if (field[JV.PROP_FIELD_EXP_MAP].indexOf("'quantity'") > 0 ||
+                        field[JV.PROP_FIELD_EXP_MAP].indexOf("'subdivisionQuantity'") > 0 ||
+                        field[JV.PROP_FIELD_EXP_MAP].indexOf("'techQuantity'") > 0 ) {
+                        if (rst.indexOf(projectConst.RATION) < 0) rst.push(projectConst.RATION);
+                        if (rst.indexOf(projectConst.BILLS) < 0) rst.push(projectConst.BILLS);
+                    }
                 }
             }
         };
@@ -202,6 +218,14 @@ class Rpt_Data_Extractor {
         for (let item of rawDataObj.prjData) {
             setupFunc($PROJECT.DETAIL, item.moduleName, item);
         }
+        let projectGLJDatas = getModuleDataByKey(rawDataObj.prjData, "projectGLJ");
+        let rationGLJDatas = getModuleDataByKey(rawDataObj.prjData, "ration_glj");
+        let rationDatas = getModuleDataByKey(rawDataObj.prjData, "ration");
+        let billsDatas = getModuleDataByKey(rawDataObj.prjData, "bills");
+        if (projectGLJDatas && rationGLJDatas && rationDatas && billsDatas) {
+            gljUtil.calcProjectGLJQuantity(projectGLJDatas.data, rationGLJDatas.data, rationDatas.data, billsDatas.data, 4);
+        }
+
         if (tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
             for (let preHandle of tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
                 let srcData = getModuleDataByKey(rawDataObj.prjData, preHandle[JV.PROP_DATA_KEY]);
@@ -292,13 +316,46 @@ function getModuleDataByKey(prjData, key) {
 function summaryData(sourceData, handleCfg, prjData){
     let rstArr = [], tempRstArr = [];
     let curParentPrjData = {};
-    for (let item of sourceData.data) {
+    for (let item of getActDataArr(sourceData)) {
         if (item._doc) {
             tempRstArr.push(item._doc);
         } else {
             tempRstArr.push(item);
         }
     }
+    let private_cal_before_sum = function () {
+        for (let calcAheadObj of handleCfg[JV.PROP_SUM_CALC_AHEAD]) {
+            if (!curParentPrjData[calcAheadObj["seeking_parent"]]) curParentPrjData[calcAheadObj["seeking_parent"]] = getModuleDataByKey(prjData, calcAheadObj["seeking_parent"]);
+            for (let idxP = 0; idxP < curParentPrjData[calcAheadObj["seeking_parent"]].data.length; idxP++) {
+                let pDataItem = curParentPrjData[calcAheadObj["seeking_parent"]].data[idxP];
+                let data = (pDataItem._doc)?pDataItem._doc:pDataItem;
+                for (let idx = 0; idx < tempRstArr.length; idx++) {
+                    let dtlItem = tempRstArr[idx];
+                    if (dtlItem[calcAheadObj["seeking_key"]] === data[calcAheadObj["parent_key"]]) {
+                        for (let sumKey of handleCfg[JV.PROP_SUM_SUM_KEYS]) {
+                            switch (calcAheadObj[JV.PROP_SUM_CACL_TYPE]) {
+                                case "+":
+                                    dtlItem[sumKey] = parseFloat(dtlItem[sumKey]) + parseFloat(data[calcAheadObj["calc_property"]]);
+                                    break;
+                                case "-":
+                                    dtlItem[sumKey] = parseFloat(dtlItem[sumKey]) - parseFloat(data[calcAheadObj["calc_property"]]);
+                                    break;
+                                case "*":
+                                    dtlItem[sumKey] = dtlItem[sumKey] * parseFloat(data[calcAheadObj["calc_property"]]).toFixed(4);
+                                    break;
+                                case "/":
+                                    dtlItem[sumKey] = dtlItem[sumKey] / parseFloat(data[calcAheadObj["calc_property"]]).toFixed(4);
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                        // break;
+                    }
+                }
+            }
+        }
+    };
     let private_get_grp_key = function (item) {
         let keys = [];
         for (let cfg of handleCfg[JV.PROP_SUM_GROUP_KEYS]) {
@@ -318,6 +375,9 @@ function summaryData(sourceData, handleCfg, prjData){
         return ( "grp_key_" + keys.join('_'));
     };
     let sumObj = {};
+    if (handleCfg[JV.PROP_SUM_CALC_AHEAD] && handleCfg[JV.PROP_SUM_CALC_AHEAD].length > 0) {
+        private_cal_before_sum();
+    }
     for (let dtl of tempRstArr) {
         let grpKey = private_get_grp_key(dtl);
         if (sumObj[grpKey] === null || sumObj[grpKey] === undefined) {
@@ -332,14 +392,13 @@ function summaryData(sourceData, handleCfg, prjData){
             }
         }
     }
-    delete sourceData.data;
-    sourceData.data = rstArr;
+    replaceActDataArr(sourceData, rstArr);
     // fsUtil.writeObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/sumRst.jsp");
 }
 
 function filterData(sourceData, handleCfg, prjData) {
     let rstArr = [], tempRstArr = [];
-    for (let item of sourceData.data) {
+    for (let item of getActDataArr(sourceData)) {
         if (item._doc) {
             tempRstArr.push(item._doc);
         } else {
@@ -378,9 +437,9 @@ function filterData(sourceData, handleCfg, prjData) {
                     rst = compVal.indexOf(src) >= 0;
                 } else {
                     //string,需要转类型
-                    let newCv = JSON.parse(compVal);
-                    if (newCv instanceof Array) {
-                        rst = newCv.indexOf(src) >= 0;
+                    let newInCv = JSON.parse(compVal);
+                    if (newInCv instanceof Array) {
+                        rst = newInCv.indexOf(src) >= 0;
                     } else {
                         rst = false;
                     }
@@ -391,9 +450,9 @@ function filterData(sourceData, handleCfg, prjData) {
                     rst = compVal.indexOf(src) < 0;
                 } else {
                     //string,需要转类型
-                    let newCv = JSON.parse(compVal);
-                    if (newCv instanceof Array) {
-                        rst = newCv.indexOf(src) < 0;
+                    let newNotInCv = JSON.parse(compVal);
+                    if (newNotInCv instanceof Array) {
+                        rst = (newNotInCv.indexOf(src) < 0);
                     } else {
                         rst = true;
                     }
@@ -406,32 +465,74 @@ function filterData(sourceData, handleCfg, prjData) {
     };
     let private_chkArrVal = function(arr, key, compVal, compStr){
         let rst = false;
-        for (let arrItem of arr) {
-            if (arrItem[key]) {
-                rst = private_chkVal(arrItem[key], compVal, compStr);
+        if (arr.length > 0) {
+            for (let arrItem of arr) {
+                if (arrItem[key]) {
+                    rst = private_chkVal(arrItem[key], compVal, compStr);
+                }
+                if (rst) {
+                    break;
+                }
             }
-            if (rst) {
-                break;
+        } else {
+            //在某些判断条件下(含有'非'判断),如arr没有数组项,默认结果反而是true
+            switch (compStr) {
+                case "!=" :
+                case "!==" :
+                case "not in":
+                    rst = true;
+                    break;
+                default:
+                    break;
             }
         }
         return rst;
     };
-    let compareObj = {};
-    for (let item of tempRstArr) {
+    let private_filter_compare = function (item, filterCfg) {
+        let compareObj = {};
         let compRst = true;
         let curComparePrjData = null;
         let startIdx = 0;
-        for (let cfg of handleCfg[JV.PROP_FILTER_KEYS]) {
+        let private_ref_join = function(refKey, targetDataKey, targetPropertyKey) {
+            let rst = null, objDataArr = null;
+            curComparePrjData = getModuleDataByKey(prjData, targetDataKey);
+            try {
+                if (curComparePrjData !== null) {
+                    objDataArr = getActDataArr(curComparePrjData);
+                    for (let dtl of objDataArr) {
+                        if (item[refKey] === dtl[targetPropertyKey]) {
+                            rst = dtl;
+                            break;
+                        }
+                    }
+                }
+            } finally {
+                curComparePrjData = null;
+            }
+            return rst;
+        };
+        for (let cfg of filterCfg[JV.PROP_FILTER_KEYS]) {
             if (cfg[JV.PROP_FILTER_COMPARE_VAL]) {
                 //比较key值
                 let keys = cfg.key.split(".");
                 if (keys.length > 1) {
                     let lastObj = item;
                     for (let i = 0; i < keys.length - 1; i++) {
-                        lastObj = item[keys[i]];
-                        if (!(lastObj)) {
-                            compRst = false;
-                            break;
+                        if (keys[i].indexOf("ref_join(") === 0) {
+                            let params = keys[i].slice(9, keys[i].length - 1).split(",");
+                            if (params.length === 3) {
+                                lastObj = private_ref_join(params[0], params[1], params[2]);
+                            }
+                            if (!(lastObj)) {
+                                compRst = false;
+                                break;
+                            }
+                        } else {
+                            lastObj = item[keys[i]];
+                            if (!(lastObj)) {
+                                compRst = false;
+                                break;
+                            }
                         }
                     }
                     if (lastObj) {
@@ -454,7 +555,7 @@ function filterData(sourceData, handleCfg, prjData) {
                     if (!compareObj.hasOwnProperty(cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY] + startIdx.toString())) {
                         compareObj[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY] + startIdx.toString()] = [];
                         compareArr = compareObj[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY] + startIdx.toString()];
-                        for (let data of curComparePrjData.data) {
+                        for (let data of getActDataArr(curComparePrjData)) {
                             if (compareArr.indexOf(data[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]]) < 0) {
                                 compareArr.push(data[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]]);
                             }
@@ -464,26 +565,57 @@ function filterData(sourceData, handleCfg, prjData) {
                     }
                     compRst = private_chkVal(item[cfg.key], compareArr, cfg[JV.PROP_FILTER_CONDITION]);
                 } else {
-                    for (let data of curComparePrjData.data) {
+                    for (let data of getActDataArr(curComparePrjData)) {
                         compRst = private_chkVal(item[cfg.key], data[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]], cfg[JV.PROP_FILTER_CONDITION]);
                         if (compRst) break;
                     }
                 }
             }
             startIdx++;
+            if (!compRst) {
+                break; //有不符合条件的数据则退出(这里的判断条件是and关系)
+            }
+        }
+        return compRst;
+    };
+    let private_sub_filter_compare = function (dtlItem, subFilters) {
+        let cmpRst = false;
+        for (let dtlCfg of subFilters) {
+            cmpRst = private_filter_compare(dtlItem, dtlCfg);
+            if (cmpRst) {
+                if (dtlCfg[JV.PROP_OTHER_SUB_FILTER] && dtlCfg[JV.PROP_OTHER_SUB_FILTER].length > 0) {
+                    cmpRst = private_sub_filter_compare(dtlItem, dtlCfg[JV.PROP_OTHER_SUB_FILTER]);
+                    if (cmpRst) break;
+                } else {
+                    break;
+                }
+            }
         }
-        if (compRst) {
+        return cmpRst;
+    };
+
+    for (let item of tempRstArr) {
+        if (private_filter_compare(item, handleCfg)) {
             rstArr.push(item);
         }
     }
-    delete sourceData.data;
-    sourceData.data = rstArr;
-    // fsUtil.writeObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/filteredRst.js");
+    if (handleCfg[JV.PROP_OTHER_SUB_FILTER] && handleCfg[JV.PROP_OTHER_SUB_FILTER].length > 0) {
+        let newRstArr = [];
+        for (let dtlItem of rstArr) {
+            let cmpRst = private_sub_filter_compare(dtlItem, handleCfg[JV.PROP_OTHER_SUB_FILTER]);
+            if (cmpRst) {
+                newRstArr.push(dtlItem);
+            }
+        }
+        rstArr = newRstArr;
+    }
+    replaceActDataArr(sourceData, rstArr);
+    // fsUtil.writeObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/filteredRst.jsp");
 }
 
 function adjustData(sourceData, adjustCfg) {
     let rstArr = [];
-    for (let item of sourceData.data) {
+    for (let item of getActDataArr(sourceData)) {
         if (item._doc) {
             rstArr.push(item._doc);
         } else {
@@ -499,8 +631,7 @@ function adjustData(sourceData, adjustCfg) {
             }
         }
     }
-    delete sourceData.data;
-    sourceData.data = rstArr;
+    replaceActDataArr(sourceData, rstArr);
 }
 
 function moveRationData(rationData, rawDataObj) {
@@ -509,7 +640,7 @@ function moveRationData(rationData, rawDataObj) {
         let rationGljData = getModuleDataByKey(rawDataObj.prjData, projectConst.RATION_GLJ);
         let prjGljData = getModuleDataByKey(rawDataObj.prjData, projectConst.PROJECTGLJ);
         let dummyCode = " ", dummyPRJID = 10101010;
-        for (let rationItem of rationData.data) {
+        for (let rationItem of getActDataArr(rationData)) {
             if (rationItem.type === 2 || rationItem.type === 3) {
                 //2: 量材(人工/材料/机械/主材/设备) 3:材料(材料/主材/设备)
                 let copyItem = {};
@@ -586,7 +717,7 @@ function getDupGrpKeyVals(sourceData, segKeys) {
 
 function addDummyData(sourceData, addCfg) {
     let rstArr = [], tempRstArr = [];
-    for (let item of sourceData.data) {
+    for (let item of getActDataArr(sourceData)) {
         if (item._doc) {
             tempRstArr.push(item._doc);
         } else {
@@ -619,8 +750,7 @@ function addDummyData(sourceData, addCfg) {
         }
     }
     rstArr = rstArr.concat(tempRstArr);
-    delete sourceData.data;
-    sourceData.data = rstArr;
+    replaceActDataArr(sourceData, rstArr);
 }
 
 function getGLJBizType(orgType, orgCode, orgName) {
@@ -660,9 +790,10 @@ function getGLJBizType(orgType, orgCode, orgName) {
 }
 
 function sortData(sourceData, sortCfg, prjData) {
-    let rst = sourceData.data, tempRstArr = [];
+    let rst = getActDataArr(sourceData), tempRstArr = [];
     let sortType = sortCfg[JV.PROP_SORT_TYPE];
-    for (let item of sourceData.data) {
+    let srcData = getActDataArr(sourceData);
+    for (let item of srcData) {
         if (item._doc) {
             tempRstArr.push(item._doc);
         } else {
@@ -763,14 +894,12 @@ function sortData(sourceData, sortCfg, prjData) {
             }
             let destArr = [];
             treeUtil.getFlatArray(newTopArr, destArr);
-            delete sourceData.data;
-            sourceData.data = destArr;
+            replaceActDataArr(sourceData, destArr);
             // fsUtil.writeObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/sortedAndFlattedRst.jsp");
             break;
         case "normal":
             private_normal_sort(tempRstArr, sortCfg[JV.PROP_SORT_KEYS]);
-            delete sourceData.data;
-            sourceData.data = tempRstArr;
+            replaceActDataArr(sourceData, tempRstArr);
             // fsUtil.writeObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/normalSortedRst.jsp");
             break;
         case "accord_to_parent":
@@ -778,7 +907,7 @@ function sortData(sourceData, sortCfg, prjData) {
             let parentSrcData = getModuleDataByKey(prjData, pcKey[JV.PROP_PARENT_DATA_KEY]);
             if (parentSrcData) {
                 let tempParentArr = [];
-                for (let item of parentSrcData.data) {
+                for (let item of getActDataArr(parentSrcData)) {
                     if (item._doc) {
                         tempParentArr.push(item._doc);
                     } else {
@@ -810,8 +939,7 @@ function sortData(sourceData, sortCfg, prjData) {
                     }
                 }
             }
-            delete sourceData.data;
-            sourceData.data = tempRstArr;
+            replaceActDataArr(sourceData, tempRstArr);
             break;
         case "self_define":
             if (sortCfg[JV.PROP_SORT_TYPE_SELF_DEFINE_LOGIC]) {
@@ -819,8 +947,7 @@ function sortData(sourceData, sortCfg, prjData) {
                 eval('selfDefFunc = ' + sortCfg[JV.PROP_SORT_TYPE_SELF_DEFINE_LOGIC]);
                 tempRstArr.sort(selfDefFunc);
             }
-            delete sourceData.data;
-            sourceData.data = tempRstArr;
+            replaceActDataArr(sourceData, tempRstArr);
             break;
         default:
             //
@@ -924,9 +1051,10 @@ function ext_getPropety(propKey) {
     let rst = [], parentObj = this;
     let dtObj = parentObj["myOwnRawDataObj"];
     if (propKey && dtObj) {
-        for (let dItem of dtObj.data) {
+        for (let dItem of getActDataArr(dtObj)) {
             let doc = (dItem._doc === null || dItem._doc === undefined)?dItem:dItem._doc;
             if (propKey instanceof Array) {
+                //备注:这里的key数组表示取value的优先级
                 for (let pi = 0; pi < propKey.length; pi++) {
                     if (doc.hasOwnProperty("property")) {
                         if (doc["property"].hasOwnProperty(propKey[pi])) {
@@ -936,6 +1064,16 @@ function ext_getPropety(propKey) {
                     } else if (doc.hasOwnProperty(propKey[pi])) {
                         rst.push(doc[propKey[pi]]);
                         break;
+                    } else {
+                        let lenBefore = rst.length;
+                        getDeepProperty(propKey[pi], doc, rst);
+                        if (rst.length === (lenBefore + 1)) {
+                            if (rst[lenBefore] !== null && rst[lenBefore] !== undefined && rst[lenBefore] !== "") {
+                                break;
+                            } else {
+                                rst.splice(-1, 1); //删除末尾一条数据,给后面留空间
+                            }
+                        }
                     }
                     if (pi === propKey.length - 1) rst.push('');
                 }
@@ -945,7 +1083,8 @@ function ext_getPropety(propKey) {
                 } else if (doc.hasOwnProperty(propKey)) {
                     rst.push(doc[propKey]);
                 } else {
-                    rst.push('');
+                    // rst.push('');
+                    getDeepProperty(propKey, doc, rst);
                 }
             }
         }
@@ -958,7 +1097,7 @@ function ext_getPropertyByRefId(baseKey, refIDKey, propertyKey){
     let dtObj = parentObj["myOwnRawDataObj"];
     let orgDtObj = parentObj["myOwnOrgRawDataObj"];
     if (baseKey && refIDKey && propertyKey && dtObj) {
-        for (let dItem of dtObj.data) {
+        for (let dItem of getActDataArr(dtObj)) {
             let doc = (dItem._doc === null || dItem._doc === undefined)?dItem:dItem._doc;
             let tmpRst = doc[baseKey];
             if (typeof tmpRst === "string" && tmpRst[0] === "@") {
@@ -1012,7 +1151,7 @@ function ext_getFee(feeKey, dtlFeeKey) {
     let rst = [], parentObj = this;
     let dtObj = parentObj["myOwnRawDataObj"];
     if (feeKey && dtObj) {
-        for (let dItem of dtObj.data) {
+        for (let dItem of getActDataArr(dtObj)) {
             rst.push(pri_getFee(dItem, feeKey, dtlFeeKey));
         }
     }
@@ -1123,7 +1262,7 @@ function ext_getArrayValues(itemKey) {
     let rst = [], parentObj = this;
     let dtObj = parentObj["myOwnRawDataObj"];
     let keysArr = itemKey.split(".");
-    for (let dataItem of dtObj.data) {
+    for (let dataItem of getActDataArr(dtObj)) {
         let itemArr = [];
         if (keysArr.length <= 2) {
             if (dataItem[keysArr[0]] instanceof Array) {
@@ -1183,7 +1322,8 @@ function ext_getBlank(dftVal) {
     let rst = [], parentObj = this;
     let dtObj = parentObj["myOwnRawDataObj"];
     if (dtObj) {
-        for (let i = 0; i < dtObj.data.length; i++) {
+        let dtData = getActDataArr(dtObj);
+        for (let i = 0; i < dtData.length; i++) {
             if (dftVal !== null && dftVal !== undefined) {
                 rst.push(dftVal)
             } else rst.push('');
@@ -1197,7 +1337,7 @@ function ext_getPropertyByFlag(flagVal, rstKey, dftValIfEmpty) {
     let dtObj = parentObj["myOwnRawDataObj"];
     if (flagVal && rstKey && dtObj) {
         let isArr = (flagVal instanceof Array);
-        for (let dItem of dtObj.data) {
+        for (let dItem of getActDataArr(dtObj)) {
             let doc = (dItem._doc)?dItem._doc:dItem;
             if (doc.hasOwnProperty("flags")) {
                 let bFlag = false;
@@ -1239,8 +1379,7 @@ function ext_getPropertyByForeignId(foreignIdVal, adHocIdKey, propKey, dftValIfN
         if (foreignIdVal instanceof Array) {
             for (let idVal of foreignIdVal) {
                 isFound = false;
-                let dataArr = dtObj.data;
-                if (dtObj.moduleName === "projectGLJ") dataArr = dtObj.data.gljList;
+                let dataArr = getActDataArr(dtObj);
                 for (let i = 0; i < dataArr.length; i++) {
                     let item = (dataArr[i]._doc)?dataArr[i]._doc:dataArr[i];
                     if (item[IdKey] === idVal) {
@@ -1271,7 +1410,7 @@ function ext_getPropertyByForeignId(foreignIdVal, adHocIdKey, propKey, dftValIfN
                 }
             }
         } else {
-            for (let item of dtObj.data) {
+            for (let item of getActDataArr(dtObj)) {
                 if (item[IdKey] === foreignIdVal) {
                     rst.push(item[propKey]);
                     isFound = true;
@@ -1286,4 +1425,25 @@ function ext_getPropertyByForeignId(foreignIdVal, adHocIdKey, propKey, dftValIfN
     return rst;
 }
 
+function getActDataArr(dtObj) {
+    let rst = null;
+    if (dtObj) {
+        rst = dtObj.data;
+        if (dtObj.moduleName === "projectGLJ") {
+            rst = dtObj.data.gljList;
+        }
+    }
+    return rst;
+}
+
+function replaceActDataArr(dtObj, newArr) {
+    if (dtObj.moduleName === "projectGLJ") {
+        delete dtObj.data.gljList;
+        dtObj.data.gljList = newArr;
+    } else {
+        delete dtObj.data;
+        dtObj.data = newArr;
+    }
+}
+
 export default Rpt_Data_Extractor;

+ 94 - 0
modules/reports/util/rpt_svg_util.js

@@ -0,0 +1,94 @@
+/**
+ * Created by Tony on 2018/6/27.
+ * 报表直接打印需要
+ */
+
+let JV = require('../rpt_component/jpc_value_define');
+const SCREEN_DPI = [96,96];
+
+module.exports = {
+    exportSvgStr: function (pagesData, callback) {
+        let styles = pagesData[JV.NODE_STYLE_COLLECTION],
+            fonts = pagesData[JV.NODE_FONT_COLLECTION],
+            controls = pagesData[JV.NODE_CONTROL_COLLECTION]
+        ;
+        for (let page of pagesData.items) {
+            let svgPageArr = [], pixelSize = getPixelSize(pagesData);
+            svgPageArr.push("<svg width='" + pixelSize[0] + "' height='" + pixelSize[1] + "'>");
+            for (let cell of page.cells) {
+                svgPageArr.push(buildCellSvg(cell, fonts, styles, controls, page[JV.PROP_PAGE_MERGE_BORDER]));
+            }
+            svgPageArr.push("</svg>");
+        }
+    }
+}
+
+function buildCellSvg(cell, fonts, styles, controls, mergeBorder) {
+    let rst = [];
+    let style = styles[cell[JV.PROP_STYLE]];
+    if (style) {
+        if (style[JV.PROP_LEFT] && parseFloat(style[JV.PROP_LEFT][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + cell[JV.PROP_AREA][JV.PROP_LEFT] + "' y1='" + cell[JV.PROP_AREA][JV.PROP_TOP] +
+                "' x2='" + cell[JV.PROP_AREA][JV.PROP_LEFT] + "' y2='" + cell[JV.PROP_AREA][JV.PROP_BOTTOM] +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_RIGHT] && parseFloat(style[JV.PROP_RIGHT][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + cell[JV.PROP_AREA][JV.PROP_RIGHT] + "' y1='" + cell[JV.PROP_AREA][JV.PROP_TOP] +
+                "' x2='" + cell[JV.PROP_AREA][JV.PROP_RIGHT] + "' y2='" + cell[JV.PROP_AREA][JV.PROP_BOTTOM] +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_TOP] && parseFloat(style[JV.PROP_TOP][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + cell[JV.PROP_AREA][JV.PROP_LEFT] + "' y1='" + cell[JV.PROP_AREA][JV.PROP_TOP] +
+                "' x2='" + cell[JV.PROP_AREA][JV.PROP_RIGHT] + "' y2='" + cell[JV.PROP_AREA][JV.PROP_TOP] +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_BOTTOM] && parseFloat(style[JV.PROP_BOTTOM][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + cell[JV.PROP_AREA][JV.PROP_LEFT] + "' y1='" + cell[JV.PROP_AREA][JV.PROP_BOTTOM] +
+                "' x2='" + cell[JV.PROP_AREA][JV.PROP_RIGHT] + "' y2='" + cell[JV.PROP_AREA][JV.PROP_BOTTOM] +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+    }
+    let font = cell[JV.PROP_FONT];
+    if (typeof font === 'string') {
+        font = fonts[cell[JV.PROP_FONT]];
+    }
+    let fontsize = parseInt(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]]);
+    let left = parseInt(cell[JV.PROP_AREA][JV.PROP_LEFT]),
+        right = parseInt(cell[JV.PROP_AREA][JV.PROP_RIGHT]),
+        top = parseInt(cell[JV.PROP_AREA][JV.PROP_TOP]),
+        bottom = parseInt(cell[JV.PROP_AREA][JV.PROP_BOTTOM]),
+        x = left, y = top,
+        text_anchor = "start"
+    ;
+    let control = controls[cell[JV.PROP_CONTROL]];
+    if (control) {
+        if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "left") {
+            text_anchor = "start";
+            x = left + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "right") {
+            text_anchor = "end";
+            x = right - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "center") {
+            text_anchor = "middle";
+            x = Math.round((left + right) / 2);
+        }
+        if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "top") {
+            y = top + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "bottom") {
+            y = bottom - fontsize - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "center") {
+            y = Math.round((top + bottom + fontsize) / 2 );
+        }
+    }
+    rst.push("<text style='fill:black;font-size:" + fontsize + "pt' x='" + x +"' y='" + y + "'>" + cell[JV.PROP_VALUE] + "</text>");
+    return rst.join();
+}
+
+function getPixelSize(pagesData) {
+    let rst = [793,1122];
+    if (pagesData[JV.NODE_PAGE_INFO] && pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE]) {
+        rst[0] = Math.round(SCREEN_DPI[0] * pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][0]);
+        rst[1] = Math.round(SCREEN_DPI[1] * pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][1]);
+    }
+    return rst;
+}

+ 103 - 0
modules/std_billsGuidance_lib/controllers/libController.js

@@ -0,0 +1,103 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+import BaseController from '../../common/base/base_controller';
+import mongoose from 'mongoose';
+import CompilationModel from "../../users/models/compilation_model";
+import moment from 'moment';
+const uuidV1 = require('uuid/v1');
+const billsLibModel = mongoose.model('std_bills_lib_list');
+const billsGuideLibModel = mongoose.model('std_billsGuidance_lib');
+const billsGuideItemsModel = mongoose.model('std_billsGuidance_items');
+const stdBillsLibModel = mongoose.model('std_bills_lib_list');
+const stdBillsModel = mongoose.model('std_bills_lib_bills');
+const stdBillsJobsModel = mongoose.model('std_bills_lib_jobContent');
+const stdRationModel = mongoose.model('std_ration_lib_ration_items');
+const _ = require('lodash');
+const billsGuidanceFacade = require('../facade/facades');
+let callback = function (req, res, err, msg, data) {
+    res.json({error: err, message: msg, data: data});
+};
+
+class BillsGuideLibController extends BaseController{
+    //获取编办及编办清单库信息
+    async getComBillsLibInfo(req, res){
+        try{
+            let comBillsLibInfo = await billsGuidanceFacade.getComBillsLibInfo();
+            callback(req, res, 0, '', comBillsLibInfo);
+        }
+        catch(err) {
+            callback(req, res, 1, err, null);
+        }
+    }
+
+    async getBillsGuideLibs(req, res){
+        try{
+            let libs = await billsGuidanceFacade.getBillsGuideLibs({deleted: false});
+            callback(req, res, 0, '', libs);
+        }
+        catch(err){
+            callback(req, res, 1, '获取清单指引库数据错误', null);
+        }
+    }
+
+    async updateBillsGuideLib(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            if(data.updateType === 'create'){
+                data.updateData.createDate = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
+                data.updateData.creator = req.session.managerData.username;
+                await billsGuidanceFacade.initBillsGuideLib(data.updateData);
+            }
+            else{
+                await billsGuidanceFacade.updateBillsGuideLib(data);
+            }
+            callback(req, res, 0, '', data.updateData);
+        }
+        catch(err){
+            callback(req, res, 1, '更新失败', null);
+        }
+    }
+    //获取清单指引库和该库引用的清单
+    async getLibWithBills(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let rst = await billsGuidanceFacade.getLibWithBills(data.libID);
+            callback(req, res, 0, '', rst);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
+
+    async getItemsByBills(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let items = await billsGuidanceFacade.getItemsBybills(data.guidanceLibID, data.billsID);
+            callback(req, res, 0, '', items);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
+
+    async updateItems(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let updateDatas = data.updateDatas;
+            await billsGuidanceFacade.updateItems(updateDatas);
+            callback(req, res, 0, '', null);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
+}
+
+export default BillsGuideLibController;

+ 27 - 0
modules/std_billsGuidance_lib/controllers/viewController.js

@@ -0,0 +1,27 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+import BaseController from "../../common/base/base_controller";
+
+class ViewsController extends BaseController{
+    redirectMain(req, res){
+        res.render('maintain/billsGuidance_lib/html/main.html',
+            {
+                userAccount: req.session.managerData.username
+            });
+    }
+    redirectGuidance(req, res){
+        res.render('maintain/billsGuidance_lib/html/zhiyin.html',
+            {
+                userAccount: req.session.managerData.username
+            });
+    }
+}
+
+export default ViewsController;

+ 239 - 0
modules/std_billsGuidance_lib/facade/facades.js

@@ -0,0 +1,239 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/6/1
+ * @version
+ */
+import mongoose from 'mongoose';
+import CompilationModel from "../../users/models/compilation_model";
+import moment from 'moment';
+const uuidV1 = require('uuid/v1');
+const billsLibModel = mongoose.model('std_bills_lib_list');
+const billsGuideLibModel = mongoose.model('std_billsGuidance_lib');
+const billsGuideItemsModel = mongoose.model('std_billsGuidance_items');
+const stdBillsLibModel = mongoose.model('std_bills_lib_list');
+const stdBillsModel = mongoose.model('std_bills_lib_bills');
+const stdBillsJobsModel = mongoose.model('std_bills_lib_jobContent');
+const stdRationModel = mongoose.model('std_ration_lib_ration_items');
+const _ = require('lodash');
+
+module.exports = {
+    getComBillsLibInfo,
+    getBillsGuideLibs,
+    initBillsGuideLib,
+    updateBillsGuideLib,
+    getLibWithBills,
+    getItemsBybills,
+    updateItems
+};
+
+async function getCompilationList() {
+    let compilationModel = new CompilationModel();
+    return await compilationModel.getCompilationList();
+}
+
+async function getComBillsLibInfo() {
+    let rst = [];
+    let compilationList = await getCompilationList();
+    if(compilationList.length <= 0){
+        throw '没有数据';
+    }
+    else{
+        for(let compilation of compilationList){
+            let billsLibs = await billsLibModel.find({compilationId: compilation._id, deleted: false}, '-_id billsLibId billsLibName');
+            rst.push({_id: compilation._id, name: compilation.name, billsLibs: billsLibs});
+        }
+        return rst;
+    }
+}
+
+async function getBillsGuideLibs(findData) {
+    return await billsGuideLibModel.find(findData);
+}
+
+//拷贝工作内容并转化为树结构,形成项目指引数据
+async function genGuidanceItems(guidanceLibId, billsLibId){
+    let bills = await stdBillsModel.find({billsLibId: billsLibId, deleted: false, 'jobs.0': {$exists: true}});
+    //设置工作内容数据
+    let jobIds = [];
+    let totalJobs = [];
+    for(let bill of bills){
+        for(let job of bill.jobs){
+            jobIds.push(job.id);
+        }
+    }
+    jobIds = Array.from(new Set(jobIds));
+    if(jobIds.length > 0){
+        totalJobs = await stdBillsJobsModel.find({deleted: false, id: {$in: jobIds}});
+    }
+    if(totalJobs.length > 0){
+        let jobIdIndex = {};//id索引
+        for(let job of totalJobs){
+            jobIdIndex[job.id] = job;
+        }
+        let insertArr = [];
+        for(let bill of bills){
+            //排序后根据serialNo转换成NextSiblingID,倒序
+            bill.jobs.sort(function (a, b) {
+                let rst = 0;
+                if(a.serialNo > b.serialNo){
+                    rst = -1;
+                }
+                else if(a.serialNo < b.serialNo){
+                    rst = 1;
+                }
+                return rst;
+            });
+            let jobNoIndex = {};//下标索引
+            for(let i = 0; i < bill.jobs.length; i++){
+                let newItem = {libID: guidanceLibId, ID: uuidV1(), ParentID: -1, NextSiblingID: jobNoIndex[i - 1] ? jobNoIndex[i - 1]['ID'] : -1,
+                    name: jobIdIndex[bill.jobs[i]['id']]['content'], type: 0, billsID: bill.ID};
+                jobNoIndex[i] = newItem;
+                insertArr.push({insertOne: {document: newItem}});
+            }
+        }
+        await billsGuideItemsModel.bulkWrite(insertArr);
+    }
+}
+
+async function initBillsGuideLib(updateData){
+    await billsGuideLibModel.create(updateData);
+    await genGuidanceItems(updateData.ID, updateData.billsLibId);
+}
+
+async function updateBillsGuideLib(data) {
+    if(data.updateType === 'delete'){
+        //删除所有条目
+        await billsGuideLibModel.remove(data.findData);
+        await billsGuideItemsModel.remove({libID: data.findData.ID});
+    }
+    else {
+        await billsGuideLibModel.update(data.findData, {$set: data.updateData});
+    }
+}
+
+async function getLibWithBills(libID){
+    let guidanceLib = await getBillsGuideLibs({ID: libID, deleted: false});
+    if(guidanceLib.length === 0){
+        throw '不存在此指引库!';
+    }
+    let billsLib = await stdBillsLibModel.findOne({billsLibId: guidanceLib[0].billsLibId, deleted: false});
+    if(!billsLib){
+        throw '引用的清单规则库不存在!';
+    }
+    let bills = await stdBillsModel.find({billsLibId: billsLib.billsLibId, deleted: false}, '-_id code name ID NextSiblingID ParentID');
+    return {guidanceLib: guidanceLib[0], bills};
+}
+
+function getAttrs(field, datas){
+    let rst = [];
+    for(let data of datas){
+        if(data[field]){
+            rst.push(data[field]);
+        }
+    }
+    return rst;
+}
+
+//定额项目指所引用定额是否被删除
+function rationAllExist(rationItems, stdRationIdx) {
+    for(let item of rationItems){
+        if(!stdRationIdx[item.rationID]){
+            return false;
+        }
+    }
+    return true;
+}
+
+//将同层树结构转为顺序数组
+function chainToArr(nodes){
+    let rst = [];
+    let tempIdx = {};
+    let nodeIdx = {};
+    //建索引
+    for(let node of nodes){
+        tempIdx[node.ID] = {ID: node.ID, NextSiblingID: node.NextSiblingID, preSibling: null, nextSibling: null};
+        nodeIdx[node.ID] = node;
+    }
+    //建链
+    for(let i in tempIdx){
+        let temp = tempIdx[i];
+        if(temp.NextSiblingID != -1){
+            let next = tempIdx[temp.NextSiblingID];
+            temp.nextSibling = next;
+            next.preSibling = temp;
+        }
+    }
+    let firstNode = null;
+    for(let i in tempIdx){
+        if(!tempIdx[i].preSibling){
+            firstNode = tempIdx[i];
+            break;
+        }
+    }
+    //获得顺序队列
+    while(firstNode){
+        rst.push(nodeIdx[firstNode.ID]);
+        firstNode = firstNode.nextSibling;
+    }
+    return rst;
+}
+
+async function getItemsBybills(guidanceLibID, billsID){
+    const type = {job: 0, ration: 1};
+    let items = await billsGuideItemsModel.find({libID: guidanceLibID, billsID: billsID, deleted: false});
+    let rationItems = _.filter(items, {type: type.ration});
+    let rationIds = getAttrs('rationID', rationItems);
+    let stdRations = await stdRationModel.find({ID: {$in: rationIds}, $or: [{isDeleted: null}, {isDeleted: false}]});
+    let stdRationIndex = {};
+    for(let stdRation of stdRations){
+        stdRationIndex[stdRation.ID] = stdRation;
+    }
+    //判断定额完整性
+    if(!rationAllExist(rationItems, stdRationIndex)){
+        //建定额链, 排序后再清除不存在的定额,保证顺序正确性
+        rationItems = chainToArr(rationItems);
+        //清除已被删除的定额
+        let removeIds = [];
+        _.remove(rationItems, function (item) {
+            if(!stdRationIndex[item.rationID]){
+                removeIds.push(item.ID);
+                return true;
+            }
+            return false;
+        });
+        _.remove(items, function (item) {
+           return removeIds.includes(item.ID);
+        });
+        await billsGuideItemsModel.remove({ID: {$in: removeIds}});
+        //重组树结构
+        let bulkArr = [];
+        for(let i = 0, len = rationItems.length; i < len; i++){
+            rationItems[i].NextSiblingID = rationItems[i + 1] ? rationItems[i + 1].ID : -1;
+            bulkArr.push({updateOne: {filter: {ID: rationItems[i].ID}, update: {$set: {NextSiblingID: rationItems[i].NextSiblingID}}}});
+        }
+        await billsGuideItemsModel.bulkWrite(bulkArr);
+    }
+    return items;
+}
+
+async function updateItems(updateDatas) {
+    let bulkArr = [];
+    for(let updateData of updateDatas){
+        if(updateData.updateType === 'create'){
+            bulkArr.push({insertOne: {document: updateData.updateData}});
+        }
+        else if(updateData.updateType === 'update'){
+            bulkArr.push({updateOne: {filter: updateData.findData, update: {$set: updateData.updateData}}});
+        }
+        else{
+            bulkArr.push({deleteOne: {filter: updateData.findData}});
+        }
+    }
+    if(bulkArr.length > 0){
+        await billsGuideItemsModel.bulkWrite(bulkArr);
+    }
+}

+ 29 - 0
modules/std_billsGuidance_lib/routes/routes.js

@@ -0,0 +1,29 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+import express from 'express';
+import BillsGuideLibController from '../controllers/libController';
+import ViewsController from '../controllers/viewController';
+const router = express.Router();
+const billsGuideLibController = new BillsGuideLibController();
+const viewsController = new ViewsController();
+
+module.exports = function (app) {
+  app.get('/billsGuidance/main', viewsController.auth, viewsController.init, viewsController.redirectMain);
+  app.get('/billsGuidance/guidance', viewsController.auth, viewsController.init, viewsController.redirectGuidance);
+  router.post('/getComBillsLibInfo', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.getComBillsLibInfo);
+  router.post('/getBillsGuideLibs', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.getBillsGuideLibs);
+  router.post('/updateBillsGuideLib', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.updateBillsGuideLib);
+  router.post('/getLibWithBills', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.getLibWithBills);
+  router.post('/getItemsByBills', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.getItemsByBills);
+  router.post('/updateItems', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.updateItems);
+
+
+  app.use('/billsGuidance/api', router);
+};

+ 33 - 5
modules/std_glj_lib/models/gljMapModel.js

@@ -5,6 +5,7 @@ const mongoose = require('mongoose');
 const gljMapModel = mongoose.model('std_glj_lib_map');
 const gljModel = mongoose.model('std_glj_lib_gljList');
 const gljClassModel = mongoose.model('std_glj_lib_gljClass');
+const gljClassTemplateModel = mongoose.model('std_glj_lib_gljClassTemplate');
 const rationRepository = mongoose.model('std_ration_lib_map');
 import moment from "moment";
 import counter from "../../../public/counter/counter";
@@ -119,7 +120,34 @@ class GljMapDao extends OprDao{
                         callback(err, '创建新工料机库失败!', null);
                     }
                     else{
-                        callback(null, '创建成功!', result);
+                        //创建分类模板
+                        gljClassTemplateModel.find({'$or': [{isDeleted: null}, {isDeleted: false}, {deleted: false}]}, function (err, datas) {
+                            if(err){
+                                callback(err, "获取工料机类型错误!", null);
+                            }
+                            else{
+                                let rst = [];
+                                async.each(datas, function (data, cb) {
+                                    let newClassObj = {};
+                                    newClassObj.ID = data.ID;
+                                    newClassObj.ParentID = data.ParentID;
+                                    newClassObj.NextSiblingID = data.NextSiblingID;
+                                    newClassObj.Name = data.Name;
+                                    newClassObj.repositoryId = newGljLib.ID;
+                                    newClassObj.deleted = false;
+                                    gljClassModel.create(newClassObj, function(err){
+                                        if(err)cb(err);
+                                        else{
+                                            rst.push(newClassObj);
+                                            cb(null);
+                                        }
+                                    });
+                                }, function (err) {
+                                    if(err) callback(err, "新增工料机类型错误!", null);
+                                    else callback(null, '创建成功', result);
+                                });
+                            }
+                        });
                     }
                 });
             }
@@ -154,12 +182,12 @@ class GljMapDao extends OprDao{
                     }
                     else{
                         if(result[0].rationLibs.length > 0){//已被引用
-                            callback(null, '此工料机库已被引用!');
+                            callback(null, '此人材机库已被引用!');
                         }
                         else{
                             async.parallel([
                                 function (cb) {
-                                    gljMapModel.update({ID: libId, deleted: false}, {$set: {deleted: true}}, function (err) {
+                                    gljMapModel.remove({ID: libId}, function (err) {
                                         if(err){
                                             cb(err);
                                         }
@@ -169,7 +197,7 @@ class GljMapDao extends OprDao{
                                     });
                                 },
                                 function (cb) {
-                                    gljModel.update({repositoryId: libId}, {$set: {deleted: true}}, {upsert: true, multi: true}, function (err) {
+                                    gljModel.remove({repositoryId: libId}, function (err) {
                                         if(err){
                                             cb(err);
                                         }
@@ -179,7 +207,7 @@ class GljMapDao extends OprDao{
                                     });
                                 },
                                 function (cb) {
-                                    gljClassModel.update({repositoryId: libId}, {$set: {deleted: true}}, {upsert: true, multi: true}, function (err) {
+                                    gljClassModel.remove({repositoryId: libId}, function (err) {
                                         if(err){
                                             cb(err);
                                         }

+ 20 - 32
modules/std_glj_lib/models/gljModel.js

@@ -14,38 +14,9 @@ import async from "async";
 class GljDao  extends OprDao{
     getGljTypes (gljLibId, callback){
         gljClassModel.find({"repositoryId": gljLibId, "$or": [{"isDeleted": null}, {"isDeleted": false}, {deleted: false} ]},function(err,data){
-            if(data.length) {
-                callback(0, data);
-            }
-            else  if(err) callback("获取工料机类型错误!",false)
+            if(err) callback("获取工料机类型错误!",false)
             else {
-                gljClassTemplateModel.find({'$or': [{isDeleted: null}, {isDeleted: false}, {deleted: false}]}, function (err, datas) {
-                    if(err){
-                        callback("获取工料机类型错误!", false);
-                    }
-                    else{
-                        let rst = [];
-                        async.each(datas, function (data, cb) {
-                            let newClassObj = {};
-                            newClassObj.ID = data.ID;
-                            newClassObj.ParentID = data.ParentID;
-                            newClassObj.NextSiblingID = data.NextSiblingID;
-                            newClassObj.Name = data.Name;
-                            newClassObj.repositoryId = gljLibId;
-                            newClassObj.deleted = false;
-                            gljClassModel.create(newClassObj, function(err){
-                                if(err)cb(err);
-                                else{
-                                    rst.push(newClassObj);
-                                    cb(null);
-                                }
-                            });
-                        }, function (err) {
-                            if(err) callback("新增工料机类型错误!", false);
-                            else callback(0, rst);
-                        });
-                    }
-                });
+                callback(0, data);
             }
         })
     }
@@ -351,7 +322,7 @@ class GljDao  extends OprDao{
         for (let i = 0, len = updateData.length; i < len; i++) {
             functions.push((function(doc) {
                 return function(cb) {
-                    if(doc.updateType === 'update'){
+                    if(doc.updateType === 'update' && !doc.updateData.deleted){
                         gljClassModel.update({repositoryId: doc.updateData.repositoryId, ID: doc.updateData.ID}, doc.updateData, function (err) {
                             if(err){
                                 cb(err);
@@ -361,6 +332,23 @@ class GljDao  extends OprDao{
                             }
                         });
                     }
+                    else if(doc.updateType === 'update' && doc.updateData.deleted){
+                        gljClassModel.remove({repositoryId: doc.updateData.repositoryId, ID: doc.updateData.ID}, function (err) {
+                            if(err){
+                                cb(err);
+                            }
+                            else {
+                                gljModel.remove({repositoryId: doc.updateData.repositoryId, gljClass: doc.updateData.ID}, function (err) {
+                                    if(err){
+                                        cb(err);
+                                    }
+                                    else{
+                                        cb(null);
+                                    }
+                                });
+                            }
+                        });
+                    }
                     else if(doc.updateType === 'new'){
                         gljClassModel.create(doc.updateData, function (err) {
                             if(err){

+ 19 - 0
modules/users/controllers/compilation_controller.js

@@ -18,6 +18,7 @@ import {default as BillsTypeFlagConst, List as BillsTypeFlagList} from "../../co
 import EngineeringLibModel from "../models/engineering_lib_model";
 import STDLabourCoesModel from "../../common/std/std_labour_coes_model";
 import STDCalcProgramModel from "../../common/std/std_calc_program_model";
+const billsGuidanceFc = require('../../std_billsGuidance_lib/facade/facades');
 
 class CompilationController extends BaseController {
 
@@ -188,6 +189,7 @@ class CompilationController extends BaseController {
         let valuationList = {};
         let artificialCoefficientList = [];
         let calculationList = [];
+        let billsGuidanceList = [];
         try {
             let compilationModel = new CompilationModel();
             compilationList = await compilationModel.getCompilationList();
@@ -230,6 +232,9 @@ class CompilationController extends BaseController {
             let billsTemplateModel = new BillsTemplateModel();
             billsTemplateData = await billsTemplateModel.getTemplateData(valuationId, engineering);
 
+            //获取清单指引数据
+            billsGuidanceList = await billsGuidanceFc.getBillsGuideLibs({compilationId: selectedCompilation._id, $or: [{deleted: null}, {deleted: false}]});
+
         } catch (error) {
             console.log(error);
         }
@@ -250,6 +255,7 @@ class CompilationController extends BaseController {
             mainTreeCol: JSON.stringify(libData.main_tree_col),
             gljCol:JSON.stringify(libData.glj_col),
             calculationList: JSON.stringify(calculationList),
+            billsGuidanceList: JSON.stringify(billsGuidanceList),
             layout: 'users/views/layout/layout'
         };
         response.render('users/views/compilation/engineering', renderData);
@@ -443,6 +449,19 @@ class CompilationController extends BaseController {
         response.json(responseData);
     }
 
+    async setDescription(request, response){
+        let compilationId = request.body.id;
+        let description = request.body.description;
+        try{
+            let compilationModel = new CompilationModel();
+            await compilationModel.setDescription(compilationId, description);
+            response.json({err: 0, msg: '', data: null});
+        }
+        catch (err){
+            response.json({err: 1, msg: err, data: null});
+        }
+    }
+
     /**
      * 模板设置页面
      *

+ 0 - 1
modules/users/controllers/login_controller.js

@@ -82,7 +82,6 @@ class LoginController extends BaseController {
             responseData.error = error.code;
             responseData.msg = error.err;
         }
-
         response.json(responseData);
     }
 

+ 43 - 2
modules/users/controllers/user_controller.js

@@ -23,9 +23,18 @@ class UserController extends BaseController {
         let total = 0;
         let pageData = {};
         let userList = [];
+        let filter = request.query;
         try {
+            let condition = userModel.getFilterCondition(request);
+
+            //获取注册时间
+            let regtime = request.query.regtime;
+            if(regtime !== '' && regtime !== undefined){
+                filter.regtimeMsg = userModel.getDayMsg(regtime);
+            }
+
             // 获取用户总数
-            total = await userModel.count();
+            total = await userModel.count(condition);
 
             // 分页数据
             let page = request.query.page === undefined ? 1 : request.query.page;
@@ -36,7 +45,7 @@ class UserController extends BaseController {
             };
 
             // 获取用户列表
-            userList = await userModel.getList(null, page, Config.pageSize);
+            userList = await userModel.getList(condition, page, Config.pageSize);
         } catch (error) {
             console.log(error);
         }
@@ -46,12 +55,44 @@ class UserController extends BaseController {
             userList: userList,
             pages: pageData,
             total: total,
+            filter: filter,
             model: userModel,
             layout: 'users/views/layout/layout'
         };
         response.render('users/views/user/index', renderData);
     }
 
+
+    /**
+     * 获取搜索用户json
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {string}
+     */
+    async search(request, response) {
+        let userModel = new UserModel();
+        let responseData = {
+            error: 0,
+            msg: '',
+            data: null
+        };
+        try{
+            let keyword = request.query.keyword;
+            if(keyword === undefined || keyword === '') {
+                throw { code: 1, err: '参数有误或为空'};
+            }
+            let condition = userModel.getFilterCondition(request);
+            let userList = await userModel.getList(condition);
+            responseData.data = userList;
+        } catch (error) {
+            console.log(error);
+            responseData.error = error.code;
+            responseData.msg = error.err;
+        }
+
+        response.json(responseData);
+    }
 }
 
 export default UserController;

+ 13 - 1
modules/users/models/compilation_model.js

@@ -35,7 +35,7 @@ class CompilationModel extends BaseModel {
      */
     async getCompilationList() {
         // 筛选字段
-        let field = {_id: 1, name: 1, is_release: 1, "ration_valuation._id": 1, "ration_valuation.name": 1, "ration_valuation.enable": 1,
+        let field = {_id: 1, name: 1, is_release: 1, description: 1, "ration_valuation._id": 1, "ration_valuation.name": 1, "ration_valuation.enable": 1,
             "bill_valuation._id": 1, "bill_valuation.name": 1, "bill_valuation.enable": 1};
         let compilationData = await this.findDataByCondition({name: {$ne: ''}}, field, false);
 
@@ -77,6 +77,18 @@ class CompilationModel extends BaseModel {
         return result;
     }
 
+    /*
+    * 设置版本描述
+    *
+    * @param {String} compilationId
+    * @param {String} description
+    * @return {Promise}
+    * */
+    async setDescription(compilationId, description){
+        return await this.updateById(compilationId, {description: description});
+    }
+
+
     /**
      * 新增计价规则
      *

+ 5 - 0
modules/users/models/engineering_lib_model.js

@@ -85,6 +85,8 @@ class EngineeringLibModel extends BaseModel {
                 delete data.id;
                 delete data.section;
                 delete data.engineering;
+                console.log(`data==============================================`);
+                console.log(data);
                 // 存在则直接更新
                 let condition = {_id: engineeringLib.engineering_id};
                 result = await this.db.update(condition, data);
@@ -148,6 +150,9 @@ class EngineeringLibModel extends BaseModel {
         // 判断工料机库
         data.glj_lib = this._validLib(data.glj_lib);
 
+        // 判断清单指引库
+        data.billsGuidance_lib = this._validLib(data.billsGuidance_lib);
+
         // 判断费率标准
         data.fee_lib = this._validLib(data.fee_lib);
 

+ 68 - 0
modules/users/models/user_model.js

@@ -32,6 +32,13 @@ class UserModel extends BaseModel {
     companyScale = ['1-20', '20-50', '50-100', '100+'];
 
     /**
+     * 最近天数
+     *
+     * @var
+     */
+    dayMsg = ['所有', '最近24小时', '最近3天', '最近7天', '最近30天'];
+
+    /**
      * 构造函数
      *
      * @return {void}
@@ -61,6 +68,67 @@ class UserModel extends BaseModel {
         return userList;
     }
 
+    /**
+     * 获取过滤条件
+     *
+     * @return {Object}
+     */
+    getFilterCondition(request) {
+        let condition = {};
+        let regtime = request.query.regtime;
+        regtime = regtime !== '' && regtime !== undefined ? parseInt(regtime) : 0;
+        if (regtime !== 0) {
+            condition.create_time = this.getTimestamp(regtime);
+        }
+
+        let version = request.query.version;
+        if(version !== '' && version !== undefined) {
+            condition.version = version;
+        }
+
+        let keyword = request.query.keyword;
+        if (keyword !== '' && keyword !== undefined) {
+            condition.$or = [{real_name : {$regex: keyword}},{email : {$regex: keyword}},{mobile : {$regex: keyword}},{company : {$regex: keyword}}];
+        }
+
+        return condition;
+    }
+
+    /**
+     * 获取时间戳区间
+     *
+     * @return {Object}
+     */
+    getTimestamp(type) {
+        let startTime = '';
+        switch (type) {
+            case 1 :
+                startTime = Date.parse(new Date())-86400*1000;
+                break;
+            case 2 :
+                startTime = Date.parse(new Date())-86400*1000*3;
+                break;
+            case 3 :
+                startTime = Date.parse(new Date())-86400*1000*7;
+                break;
+            case 4 :
+                startTime = Date.parse(new Date())-86400*1000*30;
+                break;
+            default :
+                break;
+        }
+        let endTime =  Date.parse(new Date());
+        return startTime === '' ? '' : {'$gte': startTime, '$lt': endTime};
+    }
+
+    /**
+     * 获取daymsg
+     *
+     */
+    getDayMsg(index){
+        return this.dayMsg[index];
+    }
+
 }
 
 export default UserModel;

+ 1 - 0
modules/users/routes/compilation_route.js

@@ -21,6 +21,7 @@ module.exports = function (app) {
 
     router.post('/release', compilationController.auth, compilationController.init, compilationController.release);
     router.post('/add', compilationController.auth, compilationController.init, compilationController.addCompilation);
+    router.post('/setDescription', compilationController.auth, compilationController.init, compilationController.setDescription);
     router.post('/add-valuation', compilationController.auth, compilationController.init, compilationController.addValuation);
     router.post('/save-valuation', compilationController.auth, compilationController.init, compilationController.saveValuation);
     router.post('/save-lib', compilationController.auth, compilationController.init, compilationController.saveEngineering);

+ 1 - 0
modules/users/routes/user_route.js

@@ -14,6 +14,7 @@ const userController = new UserController();
 module.exports =function (app) {
     // action定义区域
     router.get('/', userController.auth, userController.init, userController.lastRegister);
+    router.get('/search', userController.auth, userController.init, userController.search);
 
     app.use("/user", router);
 };

+ 11 - 8
operation.js

@@ -34,6 +34,8 @@ cfgCacheUtil.setupDftCache();
 log.use(app);
 app.use(express.static(_rootDir));
 
+app.disable('view cache');
+
 app.set('views', path.join(__dirname, 'web'));
 app.engine('.html', require('ejs').__express);
 app.set('view engine', 'html');
@@ -50,7 +52,7 @@ app.use(bodyParser.json({limit: '3mb'}));
 app.use(session({
     name: 'usersSession',
     secret: 'session users secret',
-    cookie: {maxAge: 1000*60*30},
+    cookie: {maxAge: 3600 * 6 * 1000},
     resave: false,
     rolling: true,
     saveUninitialized: true
@@ -61,16 +63,17 @@ app.use(session({
     //*/
 }));
 
+
 app.use(function (req, res, next) {
     let referer = '';
     if (!/^\/login/.test(req.originalUrl) && !req.session.managerData) {
-        if (/\/api/.test(req.originalUrl)) {
-            console.log(`req.originalUrl`);
-            console.log(req.originalUrl);
-            referer = URL.parse(req.headers.referer);
-            return res.redirect('/login' + '?referer=' + referer.path);
-        } else {
-            return res.redirect("/login" + '?referer=' + req.originalUrl);
+        if (req.headers["x-requested-with"] != null
+            && req.headers["x-requested-with"] == "XMLHttpRequest"
+            && req.url != "/login") {
+            return res.json({ret_code: 99, ret_msg: '登录信息失效,请您重新登录'});
+        }
+        else{
+            return res.redirect('/login');
         }
     }
     next();

+ 8 - 7
package.json

@@ -3,22 +3,23 @@
   "version": "0.2.0",
   "description": "Smart Soft - Construct Cost",
   "devDependencies": {
-    "body-parser": "^1.13.2",
+    "async": "^2.1.5",
     "babel-preset-es2015": "^6.24.1",
     "babel-preset-stage-2": "^6.24.1",
-    "express": "^4.13.1",
-    "express-partials": "^0.3.0",
-    "mongoose": "~4.13.12",
-    "async": "^2.1.5",
+    "body-parser": "^1.13.2",
     "connect-mongo": "^1.3.2",
     "cookie-parser": "~1.4.3",
     "debug": "~2.6.0",
     "ejs": "~2.5.5",
+    "express": "^4.13.1",
+    "express-partials": "^0.3.0",
     "express-session": "^1.15.1",
+    "glob": "~4.0.5",
+    "lodash": "^3.10.1",
     "moment": "^2.18.1",
+    "mongoose": "~4.13.12",
     "request": "^2.79.0",
-    "tape": "^4.6.3",
-    "glob": "~4.0.5"
+    "tape": "^4.6.3"
   },
   "dependencies": {
     "babel-core": "^6.26.0",

+ 37 - 1
public/stringUtil.js

@@ -227,5 +227,41 @@ module.exports = {
     },
     getPinYinCamelChars: function(value) {
         return pinyin.getCamelChars(value);
+    },
+    formatNumber: function(formatStr, val) {
+        let rst = val;
+        if (formatStr) {
+            if (!(isNaN(parseFloat(val)))) {
+                function comdify(numStr){
+                    let re = /\d{1,3}(?=(\d{3})+$)/g;
+                    return numStr.replace(/^(\d+)((\.\d+)?)$/,function(s,s1,s2){return s1.replace(re,"$&,")+s2;});
+                }
+                let dotIdx = formatStr.indexOf(".");
+                if (dotIdx >= 0) {
+                    let tmpStr = parseFloat(val).toFixed(formatStr.length - dotIdx - 1);
+                    let digStr = formatStr.substr(dotIdx + 1, formatStr.length - dotIdx);
+                    for (let sIdx = digStr.length - 1; sIdx >= 0; sIdx--) {
+                        if (digStr[sIdx] === '#') {
+                            if (tmpStr.length > 0 && tmpStr[tmpStr.length - 1] === '0') {
+                                tmpStr = tmpStr.substr(0, tmpStr.length - 1);
+                            } else {
+                                break;
+                            }
+                        } else {
+                            break;
+                        }
+                    }
+                    if (tmpStr[tmpStr.length - 1] === '.') tmpStr = tmpStr.substr(0, tmpStr.length - 1);
+                    rst = tmpStr;
+                } else {
+                    rst = parseFloat(val).toFixed(0);
+                }
+                let commaIdx = formatStr.indexOf(",");
+                if (commaIdx >= 0) {
+                    rst = comdify(val.toString());
+                }
+            }
+        }
+        return rst;
     }
-};
+}

+ 27 - 1
public/web/common_ajax.js

@@ -2,6 +2,32 @@
  * Created by Mai on 2017/4/20.
  */
 
+/**
+ * 设置全局的AJAX请求默认选项
+ * 主要设置了AJAX请求遇到Session过期的情况
+ */
+$.ajaxSetup({
+    complete: function (data) {
+        if (data.responseJSON&&data.responseJSON.ret_code && data.responseJSON.ret_code == 99) {
+            alert(data.responseJSON.ret_msg);
+            var top = getTopWindow();
+            setTimeout('top.location.href = "/login";', 300);
+        }
+    }
+});
+
+/**
+ * 在页面中任何嵌套层次的窗口中获取顶层窗口
+ * @return 当前页面的顶层窗口对象
+ */
+function getTopWindow() {
+    var p = window;
+    while (p != p.parent) {
+        p = p.parent;
+    }
+    return p;
+}
+
 var CommonAjax = {
     post: function (url, data, successCallback, errorCallback) {
         $.ajax({
@@ -19,7 +45,7 @@ var CommonAjax = {
                 } else {
                     alert('error: ' + result.message);
                     if (errorCallback) {
-                        errorCallback();
+                        errorCallback(result.message);
                     }
                 }
             },

+ 49 - 0
public/web/ration_glj_units.js

@@ -0,0 +1,49 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/6/4
+ * @version
+ */
+//定额与工料机公用单位
+const rationAndGljUnits =[
+    'm',
+    'm2',
+    'm3',
+    '台班',
+    '工日',
+    't',
+    'kg',
+    '座',
+    '组',
+    '宗',
+    '元',
+    '套',
+    '台',
+    '千米',
+    '千克',
+    '辆',
+    '块',
+    '公斤',
+    '付',
+    '部',
+    '10t',
+    '10m',
+    '10 m2',
+    '10 m3',
+    '100m',
+    '100 m2',
+    '100 m3',
+    '1000m',
+    '1000 m2',
+    '1000 m3',
+    '10000块',
+    '立方米',
+    '平方米',
+    '株',
+    '棵',
+    '项',
+    '樘'
+];

+ 4 - 1
public/web/rpt_value_define.js

@@ -52,6 +52,7 @@ const JV = {
     PROP_PARENT_SORT_KEYS: "父排序键值集",
     PROP_CHILD_SORT_KEYS: "子排序键值集",
     PROP_OTHER_SUB_SORT: "其他子排序",
+    PROP_OTHER_SUB_FILTER: "其他子过滤",
     PROP_HANDLE_TYPE: "预处理类型",
     PROP_FILTER_KEYS: "过滤键值集",
     PROP_FILTER_TOP_BILLS_NODES: "清单顶节点集",
@@ -79,6 +80,8 @@ const JV = {
     PROP_SORT_KEYS: "排序键值集",
     PROP_SUM_GROUP_KEYS: "分组键值集",
     PROP_SUM_SUM_KEYS: "统计键值集",
+    PROP_SUM_CALC_AHEAD: "统计前计算",
+    PROP_SUM_CACL_TYPE: "计算类型",
     PROP_FIELD_EXP_MAP: "mapExpression",
 
     NODE_FONT_COLLECTION: "font_collection",
@@ -186,7 +189,7 @@ const JV = {
     PROP_SEG_GRP_IDX: "segGrpRecStartIdx",
     PROP_PRE_ADD_GRP_REC_INFO: "preAddPageGrpInfo",
     PROP_INSERTED_GRP_REC: "insertedGrpRecAmt",
-    PROP_GRP_LINES: "me.group_lines_amt",
+    PROP_GRP_LINES: "group_lines_amt",
 
     RUN_TYPE_BEFORE_PAGING: "before_paging",
     RUN_TYPE_BEFORE_OUTPUT: "before_output",

+ 2 - 0
public/web/sheet/sheet_common.js

@@ -13,6 +13,7 @@ var sheetCommonObj = {
         //spreadBook.options.showHorizontalScrollbar = false;
         spreadBook.options.allowUserDragDrop = false;
         spreadBook.options.scrollbarMaxAlign = true;
+        spreadBook.options.allowContextMenu = false;
         spreadBook.options.allowUndo = false;
         spreadBook.options.cutCopyIndicatorVisible = false;
         return spreadBook;
@@ -49,6 +50,7 @@ var sheetCommonObj = {
         spreadBook.options.allowExtendPasteRange = true;
         spreadBook.options.allowUserDragDrop = false;
         spreadBook.options.allowUndo = false;
+        spreadBook.options.allowContextMenu = false;
         var spreadNS = GC.Spread.Sheets;
         var sheet = spreadBook.getSheet(0);
         sheet.suspendPaint();

+ 21 - 4
public/web/treeDataHelper.js

@@ -1,7 +1,8 @@
 /**
  * Created by Tony on 2017/1/23.
  */
-const NODE_ID = "ID", P_ID = "ParentID", NEXT_ID = "NextSiblingID", ADHOC_PRE_ID="Previous_ID", CHILDREN_NODE = "items", SUB_ID = "sub_ids", EMPTY_ID_VAL = -1, TREE_LEVEL = 'treeLevel';
+const NODE_ID = "ID", P_ID = "ParentID", NEXT_ID = "NextSiblingID", ADHOC_PRE_ID="Previous_ID", CHILDREN_NODE = "items", SUB_ID = "sub_ids",
+      EMPTY_ID_VAL = -1, TREE_LEVEL = 'treeLevel', TOP_BILL_ID = "topBillID";
 
 let tree_Data_Helper = {
     buildTreeNodeDirectly: function(data, addLevel) {
@@ -16,7 +17,7 @@ let tree_Data_Helper = {
             }
             return tmpNodeRst;
         };
-        let private_buildNodeData = function(parentItem, idArr, treeLevel) {
+        let private_buildNodeData = function(parentItem, idArr, treeLevel, tbID) {
             let iter = [], nextNode = private_getStartNode(idArr);
             while (nextNode !== null && nextNode !== undefined ) {
                 if (parentItem) {
@@ -25,11 +26,27 @@ let tree_Data_Helper = {
                     rst.push(nextNode);
                 }
                 iter.push(nextNode);
+                nextNode[TOP_BILL_ID] = tbID;
+                if (parentItem === null) {
+                    nextNode[TOP_BILL_ID] = nextNode[NODE_ID];
+                    if (nextNode.flags && nextNode.flags.length > 0) {
+                        for (let flag of nextNode.flags) {
+                            if (flag.fieldName === "fixed") {
+                                nextNode[TOP_BILL_ID] = flag.flag;
+                                break;
+                            }
+                        }
+                    }
+                }
                 if (addLevel) nextNode[TREE_LEVEL] = treeLevel;
                 nextNode = tmpNodes[prefix + nextNode[NEXT_ID]];
             }
             for (let i = 0; i < iter.length; i++) {
-                private_buildNodeData(iter[i], iter[i][SUB_ID], (treeLevel + 1));
+                let rtbID = tbID;
+                if (parentItem === null) {
+                    rtbID = iter[i][TOP_BILL_ID];
+                }
+                private_buildNodeData(iter[i], iter[i][SUB_ID], (treeLevel + 1), rtbID);
             }
         };
 
@@ -52,7 +69,7 @@ let tree_Data_Helper = {
                 tmpNodes[prefix + data[i][P_ID]][SUB_ID].push(data[i][NODE_ID]);
             }
         }
-        private_buildNodeData(null, topArr, 0);
+        private_buildNodeData(null, topArr, 0, -1);
         //try to release and return
         tmpNodes = null;
         topArr.length = 0;

+ 42 - 1
public/web/tree_sheet/tree_sheet_controller.js

@@ -60,6 +60,47 @@ var TREE_SHEET_CONTROLLER = {
                     });
                 }
             }
+            return newNode;
+        };
+        controller.prototype.insertByIDS = function (ID, ParentID, NexSiblingID) {
+            var newNode = null, that = this,  sels = this.sheet.getSelections();
+            if (this.tree) {
+                if (this.tree.selected) {
+                    newNode = this.tree.insertByID(ID, ParentID, NexSiblingID);
+                } else {
+                    newNode = this.tree.insertByID(ID);
+                }
+                if (newNode) {
+                    TREE_SHEET_HELPER.massOperationSheet(this.sheet, function () {
+                        that.sheet.addRows(newNode.serialNo(), 1);
+                        TREE_SHEET_HELPER.refreshTreeNodeData(that.setting, that.sheet, [newNode], false);
+                        that.setTreeSelected(newNode);
+                        that.sheet.setSelection(newNode.serialNo(), sels[0].col, 1, 1);
+                        //that.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                    });
+                }
+            }
+            return newNode;
+        };
+        controller.prototype.insertToChild = function (ID, ParentID, NextSiblingID) {
+            var newNode = null, that = this,  sels = this.sheet.getSelections();
+            if (this.tree) {
+                if (this.tree.selected) {
+                    newNode = this.tree.insertByID(ID, ParentID, NextSiblingID);
+                } else {
+                    newNode = this.tree.insertByID(ID);
+                }
+                if (newNode) {
+                    TREE_SHEET_HELPER.massOperationSheet(this.sheet, function () {
+                        that.sheet.addRows(newNode.serialNo(), 1);
+                        TREE_SHEET_HELPER.refreshTreeNodeData(that.setting, that.sheet, [newNode], false);
+                        that.setTreeSelected(newNode);
+                        that.sheet.setSelection(newNode.serialNo(), sels[0].col, 1, 1);
+                        //that.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                    });
+                }
+            }
+            return newNode;
         };
         controller.prototype.delete = function () {
             var that = this, sels = this.sheet.getSelections();
@@ -67,7 +108,7 @@ var TREE_SHEET_CONTROLLER = {
                 if (this.tree.delete(this.tree.selected)) {
                     TREE_SHEET_HELPER.massOperationSheet(this.sheet, function () {
                         that.sheet.deleteRows(sels[0].row, that.tree.selected.posterityCount() + 1);
-                        that.setTreeSelected(that.tree.items[sels[0].row]);
+                        that.setTreeSelected(that.tree.items[sels[0].row] ? that.tree.items[sels[0].row] : that.tree.items[that.tree.items.length - 1]);
                     });
                 }
             }

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

@@ -30,6 +30,7 @@ var TREE_SHEET_HELPER = {
         spread.options.cutCopyIndicatorVisible = false;
         spread.options.allowCopyPasteExcelStyle = false;
         spread.options.allowUserDragDrop = false;
+        spread.options.allowContextMenu = false;
         spread.getActiveSheet().setRowCount(3);
         return spread;
     },
@@ -265,6 +266,7 @@ var TREE_SHEET_HELPER = {
             };
             // Draw Text
             x = x + (node.depth() + 1) * indent;
+            w = w - (node.depth() + 1) * indent;
             GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
         };
         TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {

+ 285 - 0
web/maintain/billsGuidance_lib/css/main.css

@@ -0,0 +1,285 @@
+/*building SAAS 0.1*/
+/*bootstrap 初始化*/
+body {
+    font-size: 0.9rem
+}
+.dropdown-menu {
+    font-size: 0.9rem
+}
+/*自定义css*/
+.header {
+    background: #e1e1e1
+}
+.header .header-logo {
+    background: #ff6501;
+    color: #fff;
+    float: left;
+    padding-top: .25rem;
+    padding-bottom: .25rem;
+    margin-right: 1rem;
+    font-size: 1.25rem;
+    line-height: inherit
+}
+.top-msg{
+  position: fixed;
+  top:0;
+  width:100%;
+  z-index: 999
+}
+.in-1{padding-left:0rem!important}
+.in-2{padding-left:1rem!important}
+.in-3{padding-left:1.5rem!important}
+.in-4{padding-left:2rem!important}
+.in-5{padding-left:2.5rem!important}
+.in-6{padding-left:3rem!important}
+.main {
+    position: relative;
+    background: #f7f7f9;
+}
+.main-nav {
+    position: absolute;
+    text-align: center;
+    z-index: 999;
+    padding: 2px 0 0 2px
+}
+.main-nav .nav a {
+    display: block;
+    width: 28px;
+    text-align: center;
+    line-height: 18px;
+    color: #999;
+    padding: 10px 0;
+    border-right: 1px solid #ccc;
+}
+.main-nav .nav a:hover {
+    background: #fff;
+    color: #333;
+    text-decoration: none;
+}
+.main-nav .nav a.active {
+    border: 1px solid #ccc;
+    border-right: 1px solid #fff;
+    background: #fff;
+    color: #333
+}
+.content {
+    background: #fff
+}
+.tools-btn {
+    height: 30px;
+    line-height: 30px;
+}
+.toolsbar .tools-btn.btn:hover {
+    background: #f7f7f9;
+}
+.main-side {
+    border-right: 1px solid #ccc;
+    border-left: 1px solid #ccc;
+    overflow:hidden;
+}
+.main-side .tab-bar {
+    padding:5px 10px;
+    height:38px;
+    position:fixed;
+}
+.main-side .tab-content {
+    margin-top: 38px
+}
+.top-content, .fluid-content {
+    overflow: hidden;
+    border-bottom: 1px solid #ccc;
+}
+.warp-p2 {
+    padding: 2px
+}
+.bottom-content .nav,.top-content .nav {
+    background: #f7f7f9;
+    padding:0 0 0 2px
+}
+.bottom-content .nav-tabs .nav-link, .side-tabs .nav-tabs .nav-link,.top-content .nav-tabs .nav-link {
+    border-radius: 0;
+    padding: 0.2em 0.5em
+}
+.side-tabs .nav-tabs .nav-item {
+  z-index: 999
+}
+.side-tabs .nav-tabs {
+    border-bottom: none;
+    margin-bottom: -1px
+}
+.side-tabs .nav-tabs .nav-link {
+    border-radius: 0;
+    padding: 0em 0.5em;
+    line-height: 30px;
+    z-index: 999
+}
+.bottom-content .nav-tabs .nav-link.active {
+    border-top: 1px solid #f7f7f9
+}
+.side-tabs .nav-tabs .nav-link.active {
+    border-top: none;
+    border-bottom:1px solid #fff
+}
+.side-tabs a.active, .sub-nav a.active {
+    background: #ccc
+}
+.poj-manage {
+    background: #fff
+}
+.slide-sidebar {
+    border-left: 1px solid #E1E1E1;
+    box-shadow: 0px 15px 15px rgba(0, 0, 0, 0.1);
+    background: none repeat scroll 0% 0% #ffffff;
+    overflow: hidden;
+    position: absolute;
+    right: 0px;
+    top: 0;
+    z-index: 999;
+    width: 0px;
+}
+.new-msg {
+    -webkit-animation: tada 1s infinite .2s ease both;
+    -moz-animation: tada 1s infinite .2s ease both;
+}
+@-webkit-keyframes tada {
+    0% {
+        -webkit-transform: scale(1)
+    }
+    10%, 20% {
+        -webkit-transform: scale(0.9) rotate(-3deg)
+    }
+    30%, 50%, 70%, 90% {
+        -webkit-transform: scale(1.1) rotate(3deg)
+    }
+    40%, 60%, 80% {
+        -webkit-transform: scale(1.1) rotate(-3deg)
+    }
+    100% {
+        -webkit-transform: scale(1) rotate(0)
+    }
+}
+@-moz-keyframes tada {
+    0% {
+        -moz-transform: scale(1)
+    }
+    10%, 20% {
+        -moz-transform: scale(0.9) rotate(-3deg)
+    }
+    30%, 50%, 70%, 90% {
+        -moz-transform: scale(1.1) rotate(3deg)
+    }
+    40%, 60%, 80% {
+        -moz-transform: scale(1.1) rotate(-3deg)
+    }
+    100% {
+        -moz-transform: scale(1) rotate(0)
+    }
+}
+.has-danger {
+    -webkit-animation: shake 1s .2s ease both;
+    -moz-animation: shake 1s .2s ease both;
+    animation: shake 1s .2s ease both;
+}
+@-webkit-keyframes shake {
+    0%, 100% {
+        -webkit-transform: translateX(0);
+    }
+    10%, 30%, 50%, 70%, 90% {
+        -webkit-transform: translateX(-10px);
+    }
+    20%, 40%, 60%, 80% {
+        -webkit-transform: translateX(10px);
+    }
+}
+@-moz-keyframes shake {
+    0%, 100% {
+        -moz-transform: translateX(0);
+    }
+    10%, 30%, 50%, 70%, 90% {
+        -moz-transform: translateX(-10px);
+    }
+    20%, 40%, 60%, 80% {
+        -moz-transform: translateX(10px);
+    }
+}
+@keyframes shake {
+    0%, 100% {
+        transform: translateX(0);
+    }
+    10%, 30%, 50%, 70%, 90% {
+        transform: translateX(-10px);
+    }
+    20%, 40%, 60%, 80% {
+        transform: translateX(10px);
+    }
+}
+.bottom-content {
+    height: 370px;
+    overflow: hidden;
+}
+.bottom-content .tab-content .main-data-bottom{
+    height: 340px;
+    overflow: auto;
+}
+.form-signin {
+    max-width: 500px;
+    margin: 150px auto;
+}
+.poj-list, .side-content {
+    overflow: auto;
+}
+.poj-list span.poj-icon {
+  padding-right:10px;
+  color:#ccc
+}
+.print-toolsbar{
+  padding:5px
+}
+.print-toolsbar .panel {
+  display:inline-block;
+  vertical-align:top;
+  background:#f7f7f9
+}
+.print-toolsbar .panel .panel-foot{
+  text-align: center;
+  font-size: 12px
+}
+.print-list {
+  border-right:1px solid #ccc
+}
+.print-list .form-list {
+  overflow: auto
+}
+.print-list .list-tools{
+  height:50px;
+  padding:10px 0;
+  border-bottom:1px solid #f2f2f2
+}
+.pageContainer {
+  background: #ededed;
+  text-align: center
+}
+.pageContainer .page{
+  border:9px solid transparent;
+  display: inline-block;
+}
+.pageContainer .page img{
+  width:inherit;
+  height: inherit;
+}
+.codeList{
+    max-height: 200px;
+    overflow:auto;
+}
+.main-data-top,.main-data-bottom,.main-data,.main-side,.main-data-side-q{
+  overflow: hidden;
+}
+.modal-fixed-height {
+    height:400px;
+    overflow-y:auto;
+}
+.btn.disabled, .btn:disabled {
+    cursor: not-allowed;
+    opacity: .65;
+    color:#666
+}

+ 147 - 0
web/maintain/billsGuidance_lib/html/main.html

@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>清单指引编辑器</title>
+    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/web/maintain/billsGuidance_lib/css/main.css">
+    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
+</head>
+
+<body>
+    <div class="header">
+        <nav class="navbar navbar-toggleable-lg navbar-light bg-faded p-0 ">
+            <span class="header-logo px-2">清单指引编辑器</span>
+            <div class="navbar-text"></div>
+        </nav>
+        <nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0">
+          <ul class="nav navbar-nav px-1">
+              <li class="nav-item">
+                  <a class="nav-link" href="javacript:void(0);" aria-haspopup="true" aria-expanded="false" data-toggle="modal" data-target="#add">新建清单指引库</a>
+              </li>
+          </ul>
+        </nav>
+    </div>
+    <div class="main">
+        <div class="content">
+            <div class="container-fluid">
+                <div class="row">
+                  <div class="col-md-8">
+                    <div class="warp-p2 mt-3">
+                      <table class="table table-hover table-bordered">
+                        <thead><tr><th>清单指引名称</th><th>编办</th><th>清单规则</th><th width="160">添加时间</th><th width="90">操作</th></tr></thead>
+                        <tbody>
+                        </tbody>
+                      </table>
+                    </div>
+                  </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!--弹出添加-->
+    <div class="modal fade" id="add" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                  <h5 class="modal-title">添加清单指引</h5>
+                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                  </button>
+                </div>
+                <div class="modal-body">
+                  <form>
+                    <div class="form-group">
+                      <label>清单指引名称</label>
+                      <input id="createName" class="form-control" placeholder="输入清单指引名称" type="text">
+                    </div>
+                    <div class="form-group">
+                      <label>编办</label>
+                      <select id="comSels" class="form-control"><option>重庆2018</option></select>
+                    </div>
+                    <div class="form-group">
+                      <label>清单规则</label>
+                      <select id="billsLibSels" class="form-control"><option>重庆清单规则-2013</option></select>
+                    </div>
+                  </form>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                    <a href="javascript:void(0);" id="addY" class="btn btn-primary">新建</a>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!--弹出编辑-->
+    <div class="modal fade" id="edit" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                  <h5 class="modal-title">编辑清单指引</h5>
+                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                  </button>
+                </div>
+                <div class="modal-body">
+                  <form>
+                    <div class="form-group">
+                      <label>清单指引名称</label>
+                      <input id="edName" class="form-control" placeholder="输入清单指引名称" type="text" value="XXX清单指引">
+                    </div>
+                    <div class="form-group">
+                      <label>编办</label>
+                      <select id="edComSels" class="form-control" disabled><option>重庆2018</option></select>
+                    </div>
+                    <div class="form-group">
+                      <label>清单规则</label>
+                      <select id="edBillsLibSels" class="form-control" disabled><option>重庆清单规则-2013</option></select>
+                    </div>
+                  </form>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                    <a href="javascript:void(0);" id="editY" class="btn btn-primary">确定</a>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!--弹出删除-->
+    <div class="modal fade" id="del" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                  <h5 class="modal-title">删除确认</h5>
+                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                  </button>
+                </div>
+                <div class="modal-body">
+                    <h5 class="text-danger">删除后无法恢复,确认是否删除?</h5>
+                </div>
+                <div class="modal-footer">
+                    <a id="delY" href="javascript:void(0);" class="btn btn-danger">确认</a>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!-- JS. -->
+    <script src="/lib/jquery/jquery.min.js"></script>
+    <script src="/lib/tether/tether.min.js"></script>
+    <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/lib/lodash/lodash.js"></script>
+    <script src="/public/web/PerfectLoad.js"></script>
+    <script src="/web/maintain/billsGuidance_lib/js/global.js"></script>
+    <script src="/public/web/uuid.js"></script>
+    <script src="/public/web/common_ajax.js"></script>
+    <script src="/web/maintain/billsGuidance_lib/js/main.js"></script>
+
+</body>
+<script type="text/javascript">
+    autoFlashHeight();
+</script>
+
+</html>

File diff suppressed because it is too large
+ 116 - 0
web/maintain/billsGuidance_lib/html/zhiyin.html


+ 796 - 0
web/maintain/billsGuidance_lib/js/billsGuidance.js

@@ -0,0 +1,796 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/6/1
+ * @version
+ */
+
+const billsGuidance = (function () {
+    //自执行函数全局变量定义
+    const libID = getQueryString('libID');
+    const bills = {
+        dom: $('#billsSpread'),
+        workBook: null,
+        cache: [],
+        tree: null,
+        controller: null,
+        treeSetting: {
+            treeCol: 0,
+            emptyRows: 0,
+            headRows: 1,
+            headRowHeight: [40],
+            defaultRowHeight: 21,
+            cols: [{
+                width: 200,
+                readOnly: true,
+                head: {
+                    titleNames: ["项目编码"],
+                    spanCols: [1],
+                    spanRows: [1],
+                    vAlign: [1],
+                    hAlign: [1],
+                    font: ["Arial"]
+                },
+                data: {
+                    field: "code",
+                    vAlign: 1,
+                    hAlign: 0,
+                    font: "Arial"
+                }
+            }, {
+                width: 200,
+                readOnly: true,
+                head: {
+                    titleNames: ["项目名称"],
+                    spanCols: [1],
+                    spanRows: [1],
+                    vAlign: [1],
+                    hAlign: [1],
+                    font: ["Arial"]
+                },
+                data: {
+                    field: "name",
+                    vAlign: 1,
+                    hAlign: 0,
+                    font: "Arial"
+                }
+            }]
+        },
+        headers: [
+            {name: '项目编码', dataCode: 'code', width: 200, vAlign: 'center', hAlign: 'left', formatter: '@'},
+            {name: '项目名称', dataCode: 'name', width: 200, vAlign: 'center', hAlign: 'left', formatter: '@'}
+        ],
+        events: {
+            SelectionChanged: function (sender, info) {
+                billsInitSel(info.newSelections[0].row);
+            }
+        }
+    };
+    //项目指引类型
+    const itemType = {
+        job: 0,
+        ration: 1
+    };
+    const updateType = {
+        create: 'create',
+        update: 'update',
+        del: 'delete'
+    };
+    const guideItem = {
+        dom: $('#guideItemSpread'),
+        workBook: null,
+        tree: null,
+        controller: null,
+        treeSetting: {
+            treeCol: 0,
+            emptyRows: 0,
+            headRows: 1,
+            headRowHeight: [40],
+            defaultRowHeight: 21,
+            cols: [{
+                width: 400,
+                readOnly: false,
+                head: {
+                    titleNames: ["项目指引"],
+                    spanCols: [1],
+                    spanRows: [1],
+                    vAlign: [1],
+                    hAlign: [1],
+                    font: ["Arial"]
+                },
+                data: {
+                    field: "name",
+                    vAlign: 1,
+                    hAlign: 0,
+                    font: "Arial"
+                }
+            }]
+        },
+        headers: [
+            {name: '项目指引', dataCode: 'name', width: 400, vAlign: 'center', hAlign: 'left', formatter: '@'},
+        ],
+        events: {
+            SelectionChanged: function (sender, info) {
+                guideItemInitSel(info.newSelections[0].row)
+            },
+            EditEnded: function (sender, args) {
+                edit(args.sheet, [{row: args.row, col: args.col}]);
+            },
+            RangeChanged: function (sender, args) {
+                edit(args.sheet, args.changedCells);
+            }
+        }
+    };
+    const ration = {
+        dom: $('#rationSpread'),
+        workBook: null,
+        datas: [],
+        cache: [],
+        headers: [
+            {name: '选择', dataCode: 'select', width: 50, vAlign: 'center', hAlign: 'center'},
+            {name: '编码', dataCode: 'code', width: 110, vAlign: 'center', hAlign: 'left', formatter: '@'},
+            {name: '名称', dataCode: 'name', width: 250, vAlign: 'center', hAlign: 'left', formatter: '@'},
+            {name: '单位', dataCode: 'unit', width: 100, vAlign: 'center', hAlign: 'left', formatter: '@'}
+        ],
+        events: {
+            ButtonClicked: function (sender, args) {
+                if(args.sheet.isEditing()){
+                    args.sheet.endEdit(true);
+                }
+            },
+            CellDoubleClick: function (sender, args) {
+                if(ration.headers[args.col].dataCode === 'name'){
+                    let insertDatas = getInsertRations([args.row]);
+                    if(insertDatas.length > 0){
+                        insert(insertDatas);
+                    }
+                }
+            }
+        }
+    };
+    const options = {
+        workBook: {
+            tabStripVisible:  false,
+            allowContextMenu: false,
+            allowCopyPasteExcelStyle : false,
+            allowExtendPasteRange: false,
+            allowUserDragDrop : false,
+            allowUserDragFill: false,
+            scrollbarMaxAlign : true
+        },
+        sheet: {
+            protectionOptions: {allowResizeRows: true, allowResizeColumns: true},
+            clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values
+        }
+    };
+
+    //渲染时方法,停止渲染
+    //@param {Object}sheet {Function}func @return {void}
+    function renderSheetFunc(sheet, func){
+        sheet.suspendEvent();
+        sheet.suspendPaint();
+        if(func){
+            func();
+        }
+        sheet.resumeEvent();
+        sheet.resumePaint();
+    }
+    //设置表选项
+    //@param {Object}workBook {Object}opts @return {void}
+    function setOptions (workBook, opts) {
+        for(let opt in opts.workBook){
+            workBook.options[opt] = opts.workBook[opt];
+        }
+        for(let opt in opts.sheet){
+            workBook.getActiveSheet().options[opt] = opts.sheet[opt];
+        }
+    }
+    //建表头
+    //@param {Object}sheet {Array}headers @return {void}
+    function buildHeader(sheet, headers) {
+        let fuc = function () {
+            sheet.setColumnCount(headers.length);
+            sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
+            for(let i = 0, len = headers.length; i < len; i++){
+                sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
+                sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
+                if(headers[i].formatter){
+                    sheet.setFormatter(-1, i, headers[i].formatter);
+                }
+                sheet.getRange(-1, i, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[i]['hAlign']]);
+                sheet.getRange(-1, i, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[i]['vAlign']]);
+            }
+        };
+        renderSheetFunc(sheet, fuc);
+    }
+    //表监听事件
+    //@param {Object}workBook @return {void}
+    function bindEvent(workBook, events) {
+        if(Object.keys(events).length === 0){
+            return;
+        }
+        const Events = GC.Spread.Sheets.Events;
+        let sheet = workBook.getActiveSheet();
+        for(let event in events){
+            workBook.bind(Events[event], events[event]);
+        }
+    }
+    //建表
+    //@param {Object}module @return {void}
+    function buildSheet(module) {
+        if(!module.workBook){
+            module.workBook = new GC.Spread.Sheets.Workbook(module.dom[0], {sheetCount: 1});
+            let sheet = module.workBook.getActiveSheet();
+            if(module === bills){
+                //默认初始可控制焦点在清单表中
+                module.workBook.focus();
+                sheet.options.isProtected = true;
+            }
+            if(module === ration){
+                sheet.options.isProtected = true;
+                sheet.getRange(-1, 0, -1, 1).locked(false);
+                sheet.getRange(-1, 1, -1, -1).locked(true);
+            }
+            setOptions(module.workBook, options);
+            buildHeader(module.workBook.getActiveSheet(), module.headers);
+            bindEvent(module.workBook, module.events);
+        }
+    }
+    //清空表数据
+    //@param {Object}sheet {Array}headers {Number}rowCount @return {void}
+    function cleanData(sheet, headers, rowCount){
+        renderSheetFunc(sheet, function () {
+            sheet.clear(-1, 0, -1, headers.length, GC.Spread.Sheets.SheetArea.viewport, GC.Spread.Sheets.StorageType.data);
+            if (rowCount > 0) {
+                sheet.setRowCount(rowCount);
+            }
+        });
+    }
+    //根据清单获取项目指引
+    //@param {String}guidanceLibID {Number}billsID {Function}callback @return {void}
+    function getItemsByBills(guidanceLibID, billsID, callback){
+        CommonAjax.post('/billsGuidance/api/getItemsByBills', {guidanceLibID: guidanceLibID, billsID: billsID}, function (rstData) {
+            if(callback){
+                callback(rstData);
+            }
+        });
+    }
+    //清单表焦点控制
+    //@param {Number}row @return {void}
+    function billsInitSel(row){
+        let guideSheet = guideItem.workBook.getActiveSheet();
+        cleanData(guideSheet, guideItem.headers, -1);
+        let node = bills.tree.items[row];
+        if(!node){
+            return;
+        }
+        bills.tree.selected = node;
+        if(!node.guidance.tree){
+            getItemsByBills(libID, node.data.ID, function (rstData) {
+                initTree(node.guidance, guideSheet, guideItem.treeSetting, rstData);
+                //项目指引初始焦点
+                guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
+            });
+        }
+        else{
+            node.guidance.controller.showTreeData();
+            //项目指引初始焦点
+            guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
+        }
+    }
+    //节点子项是否全是工作内容
+    //@param {Object}node @return {Boolean}
+    function allJobChildren(node){
+        for(let c of node.children){
+            if(c.data.type === itemType.ration){
+                return false;
+            }
+        }
+        return true;
+    }
+    //节点子项是否全是定额
+    //@param {Object}node @return {Boolean}
+    function allRationChildren(node){
+        for(let c of node.children){
+            if(c.data.type === itemType.job){
+                return false;
+            }
+        }
+        return true;
+    }
+    //刷新按钮有效性
+    //@param {Object}node @return {void}
+    function refreshBtn(node){
+        //全部设为无效
+        $('.tools-btn').children().addClass('disabled');
+        $('#insertRation').addClass('disabled');
+        //插入
+        if(bills.tree.selected && bills.tree.selected.guidance.tree){
+            $('#insert').removeClass('disabled');
+            if(node && node.data.type === itemType.ration){
+                $('#insert').addClass('disabled');
+            }
+        }
+        //删除
+        if(node){
+            $('#del').removeClass('disabled');
+        }
+        if(node && node.data.type === itemType.job){
+            //升级
+            if(node.parent){
+                $('#upLevel').removeClass('disabled');
+                if(node.nextSibling && node.children.length > 0 && !allJobChildren(node)){
+                    $('#upLevel').addClass('disabled');
+                }
+            }
+            //降级
+            if(node.preSibling){
+                $('#downLevel').removeClass('disabled');
+                if(node.preSibling.children.length > 0 && !allJobChildren(node.preSibling)){
+                    $('#downLevel').addClass('disabled');
+                }
+            }
+        }
+        //上移
+        if(node && node.preSibling){
+            $('#upMove').removeClass('disabled')
+        }
+        //下移
+        if(node && node.nextSibling){
+            $('#downMove').removeClass('disabled');
+        }
+        //插入定额
+        if(node && (node.children.length === 0 || allRationChildren(node))){
+            $('#insertRation').removeClass('disabled');
+        }
+    }
+    //项目指引表焦点控制
+    //@param {Number}row @return {void}
+    function guideItemInitSel(row){
+        let billsNode = bills.tree.selected;
+        let node = null;
+        if(billsNode && billsNode.guidance.tree){
+            node = billsNode.guidance.tree.items[row];
+            if(node){
+                billsNode.guidance.tree.selected = node;
+            }
+        }
+        refreshBtn(node);
+    }
+    //初始化当前库名
+    //@param {String} @return {void}
+    function initLibName(libName) {
+        $('#libName')[0].outerHTML = $('#libName')[0].outerHTML.replace("XXX清单指引", libName);
+    }
+    //初始化各工作表
+    //@param {Array}modules @return {void}
+    function initWorkBooks(modules){
+        for(let module of modules){
+            buildSheet(module);
+        }
+    }
+    //输出表数据(定额表)
+    //@param {Object}sheet {Array}headers {Array}datas @return {void}
+    function showData(sheet, headers, datas){
+        let fuc = function () {
+            sheet.setRowCount(datas.length);
+            //复选框
+            let checkBoxType = new GC.Spread.Sheets.CellTypes.CheckBox();
+            sheet.setCellType(-1, 0, checkBoxType);
+            for(let col = 0, cLen = headers.length; col < cLen; col++){
+                for(let row = 0, rLen = datas.length; row < rLen; row++){
+                    sheet.setValue(row, col, datas[row][headers[col]['dataCode']]);
+                }
+            }
+        };
+        renderSheetFunc(sheet, fuc);
+    }
+    //初始化定额条目
+    //@param {Number}rationLibId @return {void}
+    function initRationItems(rationLibId){
+        $.bootstrapLoading.start();
+        CommonAjax.post('/rationRepository/api/getRationItemsByLib', {rationLibId: rationLibId}, function (rstData) {
+            rstData.sort(function (a, b) {
+                let rst = 0;
+                if(a.code > b.code){
+                    rst = 1;
+                }
+                else if(a.code < b.code){
+                    rst = -1;
+                }
+                return rst;
+            });
+            ration.datas = rstData;
+            ration.cache = rstData;
+            showData(ration.workBook.getActiveSheet(), ration.headers, rstData);
+            $.bootstrapLoading.end();
+        });
+    }
+    //初始化定额库选择
+    //@param {String}compilationId @return {void}
+    function initRationLibs(compilationId){
+        CommonAjax.post('/rationRepository/api/getRationLibsByCompilation', {compilationId: compilationId}, function (rstData) {
+            $('#rationLibSel').empty();
+            for(let rationLib of rstData){
+                let opt = `<option value="${rationLib.ID}">${rationLib.dispName}</option>`;
+                $('#rationLibSel').append(opt);
+            }
+            //初始选择
+            initRationItems(parseInt($('#rationLibSel').select().val()));
+            $('#rationLibSel').change(function () {
+                let rationLibId = parseInt($(this).select().val());
+                initRationItems(rationLibId);
+            })
+        });
+    }
+    //获取指引库信息及关联的清单
+    //@param {Number}libID {Function}callback @return {Object}
+    function getLibWithBills(libID, callback){
+        CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function (rstData) {
+            initRationLibs(rstData.guidanceLib.compilationId);
+            bills.cache = rstData.bills;
+            initLibName(rstData.guidanceLib.name);
+            initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, bills.cache);
+            //每一棵项目指引树挂在清单节点上
+            for(let node of bills.tree.items){
+                node.guidance = {tree: null, controller: null};
+            }
+            //默认初始节点
+            billsInitSel(0);
+            if(callback){
+                callback(rstData);
+            }
+        }, function (msg) {
+            window.location.href = '/billsGuidance/main';
+        });
+    }
+    //初始化并输出树
+    //@param {Object}module {Object}sheet {Object}treeSetting {Array}datas
+    function initTree(module, sheet, treeSetting, datas){
+        module.tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
+        module.controller = TREE_SHEET_CONTROLLER.createNew(module.tree, sheet, treeSetting);
+        module.tree.loadDatas(datas);
+        module.controller.showTreeData();
+    }
+    //更新项目指引
+    //@param {Array}updateDatas {Function}callback @return {void}
+    function updateGuideItems(updateDatas, callback){
+        CommonAjax.post('/billsGuidance/api/updateItems', {updateDatas: updateDatas}, function (rstData) {
+            if(callback){
+                callback(rstData);
+            }
+        });
+    }
+    //项目指引编辑
+    //@param {Object}sheet {Array}cells
+    function edit(sheet, cells){
+        let updateDatas = [];
+        //同步节点数据
+        let syncDatas = [];
+        for(let cell of cells){
+            let text = sheet.getValue(cell.row, cell.col);
+            text = text ? text : '';
+            let node = bills.tree.selected.guidance.tree.items[cell.row];
+            if(node.data.name != text){
+                syncDatas.push({node: node, text: text});
+                updateDatas.push({updateType: updateType.update, findData: {ID: node.getID()}, updateData: {name: text}});
+            }
+        }
+        if(updateDatas.length > 0){
+            updateGuideItems(updateDatas, function () {
+                for(let syncData of syncDatas){
+                    syncData.node.data.name = syncData.text;
+                }
+            }, function () {
+                //失败恢复
+                renderSheetFunc(sheet, function () {
+                    for(let syncData of syncDatas){
+                        sheet.setValue(syncData.node.serialNo(), 0, syncData.node.data.name ? syncData.node.data.name : '');
+                    }
+                });
+            });
+        }
+    }
+    //项目指引插入,支持一次插入多条数据
+    //@param {Array}datas {Function}callback @return {void}
+    function insert(datas, callback = null){
+        $.bootstrapLoading.start();
+        let sheet = guideItem.workBook.getActiveSheet();
+        let controller = bills.tree.selected.guidance.controller;
+        let selected = bills.tree.selected.guidance.tree.selected;
+        let updateDatas = [];
+        //建立数组下标索引
+        let newDataIndex = {};
+        for(let i = 0; i < datas.length; i++){
+            let newNodeData = {
+                libID: libID, ID: uuid.v1(), ParentID: selected ? selected.getParentID() : -1, NextSiblingID: selected ? selected.getNextSiblingID() : -1,
+                billsID: bills.tree.selected.getID()
+            };
+            //定额类型插入当前工作内容焦点行,
+            if(selected && selected.data.type === itemType.job && datas[i].type === itemType.ration){
+                newNodeData.ParentID = selected.getID();
+                newNodeData.NextSiblingID = -1;
+            }
+            Object.assign(newNodeData, datas[i]);
+            newDataIndex[i] = newNodeData;
+        }
+        for(let i = 0; i < datas.length; i++){
+            //第一个节点
+            if(i === 0){
+                //非插入成子节点,更新选中节点NestSiblingID
+                if(selected && !(selected.data.type === itemType.job && datas[i].type === itemType.ration)){
+                    updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {NextSiblingID: newDataIndex[i].ID}});
+                }
+            }
+            //非最后一个节点
+            if(i !== datas.length - 1){
+                newDataIndex[i].NextSiblingID = newDataIndex[i + 1].ID;
+            }
+            updateDatas.push({updateType: updateType.create, updateData: newDataIndex[i]});
+        }
+        updateGuideItems(updateDatas, function () {
+            for(let updateData of updateDatas){
+                if(updateData.updateType === updateType.create){
+                    let newNode = controller.insertByIDS(updateData.updateData.ID, updateData.updateData.ParentID, updateData.updateData.NextSiblingID);
+                    //同步data
+                    Object.assign(newNode.data, updateData.updateData);
+                    sheet.setValue(newNode.serialNo(), 0, newNode.data.name);
+                    refreshBtn(newNode);
+                }
+            }
+            if(callback){
+                callback();
+            }
+            $.bootstrapLoading.end();
+        });
+    }
+    //项目指引删除操作
+    //@return {void}
+    function del(){
+        $.bootstrapLoading.start();
+        let controller = bills.tree.selected.guidance.controller;
+        let selected = bills.tree.selected.guidance.tree.selected;
+        let updateDatas = [];
+        function getDelDatas(node){
+            updateDatas.push({updateType: updateType.del, findData: {ID: node.getID()}, updateData: {deleted: true}});
+            if(node.children.length > 0){
+                for(let c of node.children){
+                    getDelDatas(c);
+                }
+            }
+        }
+        getDelDatas(selected);
+        updateGuideItems(updateDatas, function () {
+            controller.delete();
+            refreshBtn(bills.tree.selected.guidance.tree.selected);
+            $.bootstrapLoading.end();
+        });
+    }
+    //项目指引升级
+    //@return {void}
+    function upLevel(){
+        $.bootstrapLoading.start();
+        let controller = bills.tree.selected.guidance.controller;
+        let selected = bills.tree.selected.guidance.tree.selected;
+        let updateDatas = [];
+        //更新父节点
+        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getParentID()}, updateData: {NextSiblingID: selected.getID()}});
+        //更新选中节点
+        updateDatas.push({udpateType: updateType.update, findData: {ID: selected.getID()},
+            updateData: {ParentID: selected.parent.getParentID(), NextSiblingID: selected.parent.getNextSiblingID()}});
+        if(selected.nextSibling && selected.children.length > 0){
+            //更新选中节点最末子节点
+            let lastChild = selected.children[selected.children.length - 1];
+            updateDatas.push({updateType: updateType.update, findData: {ID: lastChild.getID()}, updateData: {NextSiblingID: selected.getNextSiblingID()}});
+        }
+        updateGuideItems(updateDatas, function () {
+            controller.upLevel();
+            refreshBtn(bills.tree.selected.guidance.tree.selected);
+            $.bootstrapLoading.end();
+        });
+    }
+    //项目指引降级
+    //@return {void}
+    function downLevel(){
+        $.bootstrapLoading.start();
+        let controller = bills.tree.selected.guidance.controller;
+        let selected = bills.tree.selected.guidance.tree.selected;
+        let updateDatas = [];
+        //更新前兄弟节点
+        updateDatas.push({updateType: updateType.update, findData: {ID: selected.preSibling.getID()}, updateData: {NextSiblingID: selected.getNextSiblingID()}});
+        //更新前兄弟节点最末子节点
+        if(selected.preSibling.children.length > 0){
+            let lastChild = selected.preSibling.children[selected.preSibling.children.length - 1];
+            updateDatas.push({updateType: updateType.update, findData: {ID: lastChild.getID()}, updateData: {NextSiblingID: selected.getID()}});
+        }
+        //更新选中节点
+        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {ParentID: selected.preSibling.getID(), NextSiblingID: -1}});
+        updateGuideItems(updateDatas, function () {
+            controller.downLevel();
+            refreshBtn(bills.tree.selected.guidance.tree.selected);
+            $.bootstrapLoading.end();
+        });
+    }
+    //项目指引上移
+    //@return {void}
+    function upMove(){
+        $.bootstrapLoading.start();
+        let controller = bills.tree.selected.guidance.controller;
+        let selected = bills.tree.selected.guidance.tree.selected;
+        let updateDatas = [];
+        //更新前节点
+        updateDatas.push({updateType: updateType.update, findData: {ID: selected.preSibling.getID()}, updateData: {NextSiblingID: selected.getNextSiblingID()}});
+        //更新前前节点
+        if(selected.preSibling.preSibling){
+            updateDatas.push({udpateType: updateType.update, findData: {ID: selected.preSibling.preSibling.getID()}, updateData: {NextSiblingID: selected.getID()}});
+        }
+        //更新选中节点
+        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {NextSiblingID: selected.preSibling.getID()}});
+        updateGuideItems(updateDatas, function () {
+            controller.upMove();
+            refreshBtn(bills.tree.selected.guidance.tree.selected);
+            $.bootstrapLoading.end();
+        });
+    }
+    //项目指引下移
+    //@return {void}
+    function downMove(){
+        $.bootstrapLoading.start();
+        let controller = bills.tree.selected.guidance.controller;
+        let selected = bills.tree.selected.guidance.tree.selected;
+        let updateDatas = [];
+        //更新下节点
+        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getNextSiblingID()}, updateData: {NextSiblingID: selected.getID()}});
+        //更新前节点
+        if(selected.preSibling){
+            updateDatas.push({updateType: updateType.update, findData: {ID: selected.preSibling.getID()}, updateData: {NextSiblingID: selected.getNextSiblingID()}});
+        }
+        //更新选中节点
+        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {NextSiblingID: selected.nextSibling.getNextSiblingID()}});
+        updateGuideItems(updateDatas, function () {
+            controller.downMove();
+            refreshBtn(bills.tree.selected.guidance.tree.selected);
+            $.bootstrapLoading.end();
+        });
+    }
+    //获取定额类型的项目指引名称,通过定额转换
+    //@param {Object}ration @return {String}
+    function getRationItemName(ration){
+        let arr = [];
+        arr.push(ration.code ? ration.code : '');
+        arr.push(ration.name ? ration.name : '');
+        arr.push(ration.basePrice ? ration.basePrice : '');
+        let rst = arr.join(' ');
+        rst += `/${ration.unit ? ration.unit : ''}`;
+        return rst;
+    }
+    //获取选中的定额表行
+    //@return {Array}
+    function getCheckedRationRows(){
+        let rst = [];
+        let sheet = ration.workBook.getActiveSheet();
+        for(let i = 0; i < sheet.getRowCount(); i++){
+            let checked = sheet.getValue(i, 0);
+            if(checked){
+                rst.push(i);
+            }
+        }
+        return rst;
+    }
+    //清空选中定额表行
+    //@param {Array}rows @return {void}
+    function clearCheckedRation(rows) {
+        let sheet = ration.workBook.getActiveSheet();
+        renderSheetFunc(sheet, function () {
+            for(let row of rows){
+                sheet.setValue(row, 0, 0);
+            }
+        });
+    }
+    //获取要插入的定额数据
+    //@param {Array}rows @return {Array}
+    function getInsertRations(rows){
+        let rst = [];
+        //当前已存在定额
+        let curRationIems = [];
+        let selected = bills.tree.selected.guidance.tree.selected;
+        if(selected){
+            if(selected.data.type === itemType.job){
+                curRationIems = selected.children;
+            }
+            else {
+                curRationIems = selected.parent ? selected.parent.children : selected.tree.roots;
+            }
+        }
+        for(let row of rows){
+            let selRation = ration.cache[row];
+            if(selRation){
+                //添加的定额是否已存在,不重复添加
+                let isExist = false;
+                for(let curRation of curRationIems){
+                    if(curRation.data.rationID == selRation.ID){
+                        isExist = true;
+                        break;
+                    }
+                }
+                if(!isExist){
+                    rst.push({type: itemType.ration, name: getRationItemName(selRation), rationID: selRation.ID});
+                }
+            }
+        }
+        return rst;
+    }
+    //初始化个按钮点击
+    //@return {void}
+    function initBtn(){
+        $('#insert').click(function () {
+            insert([{type: itemType.job, name: ''}]);
+        });
+        $('#delConfirm').click(function () {
+            del();
+            $('#delAlert').modal('hide');
+        });
+        $('#del').click(function () {
+            $('#delAlert').modal('show');
+        });
+        $('#upLevel').click(function () {
+            upLevel();
+        });
+        $('#downLevel').click(function () {
+            downLevel();
+        });
+        $('#upMove').click(function () {
+            upMove();
+        });
+        $('#downMove').click(function () {
+            downMove();
+        });
+        $('#insertRation').click(function () {
+            let checkedRows = getCheckedRationRows();
+            let insertDatas = getInsertRations(checkedRows);
+            if(insertDatas.length > 0){
+                insert(insertDatas, function () {
+                    //清空选择
+                    clearCheckedRation(checkedRows);
+                });
+            }
+            else {
+                clearCheckedRation(checkedRows);
+            }
+        });
+        //搜索定额
+        $('#searchBtn').click(function () {
+            let searchStr = $('#searchText').val();
+            if(!searchStr || searchStr === ''){
+                ration.cache = ration.datas;
+            }
+            else{
+                ration.cache = _.filter(ration.datas, function (data) {
+                    return data.code.includes(searchStr);
+                });
+            }
+            let rationSheet = ration.workBook.getActiveSheet();
+            renderSheetFunc(rationSheet, function () {
+                showData(rationSheet, ration.headers, ration.cache);
+            })
+        });
+    }
+    //初始化视图
+    //@param {void} @return {void}
+    function initViews(){
+        let modules = [bills, guideItem, ration];
+        initWorkBooks(modules);
+        getLibWithBills(libID);
+        initBtn();
+    }
+
+
+    return {initViews};
+})();
+
+$(document).ready(function () {
+    billsGuidance.initViews();
+});

+ 46 - 0
web/maintain/billsGuidance_lib/js/global.js

@@ -0,0 +1,46 @@
+/*全局自适应高度*/
+function autoFlashHeight(){
+    var headerHeight = $(".header").height();
+    var bottomContentHeight = $(".bottom-content").height();
+    var toolsBar = $(".toolsbar").height();
+    var toolsBarHeightQ = $(".tools-bar-height-q").height();
+    $(".content").height($(window).height()-headerHeight);
+    $(".main-side").height($(window).height()-headerHeight-2);
+    $(".fluid-content").height($(window).height()-headerHeight-1);
+    $(".side-content").height($(window).height()-headerHeight );
+    $(".poj-list").height($(window).height()-headerHeight);
+    $(".form-list").height($(window).height()-headerHeight-50 );
+    $(".main-data-top").height($(window).height()-headerHeight-toolsBar-bottomContentHeight-2);
+    $(".main-data").height($(window).height()-headerHeight-toolsBar);
+    $(".main-data-full").height($(window).height()-headerHeight);
+    $(".main-data-side-q").height($(window).height()-headerHeight-toolsBarHeightQ-2);
+
+};
+$(window).resize(autoFlashHeight);
+/*全局自适应高度结束*/
+$(function(){
+/*侧滑*/
+$(".open-sidebar").click(function(){
+    $(".slide-sidebar").animate({width:"800"}).addClass("open");
+});
+$("body").click(function(event){
+        var e = event || window.event; //浏览器兼容性
+        if(!$(event.target).is('a')) {
+            var elem = event.target || e.srcElement;
+            while (elem) { //循环判断至跟节点,防止点击的是div子元素
+                if (elem.className == "open-sidebar" || elem.className == 'slide-sidebar open') {
+                    return false;
+                }
+                elem = elem.parentNode;
+            }
+            $(".slide-sidebar").animate({width:"0"}).removeClass("open")// 关闭处理
+        }
+
+    });
+/*侧滑*/
+/*工具提示*/
+$('*[data-toggle=tooltip]').mouseover(function() {
+ $(this).tooltip('show');
+  });
+/*工具提示*/
+});

+ 224 - 0
web/maintain/billsGuidance_lib/js/main.js

@@ -0,0 +1,224 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+
+const billsGuidanceMain = (function () {
+    const updateType = {create: 'create', update: 'update', delete: 'delete'};
+    let guidanceLibs = [];
+    let curLib = null;
+    //上一个选择的库(三次确认删除同一库时用)
+    let preLib = null;
+    let deleteCount = 0;
+
+    //获取编办及编办下清单库
+    //@return {void}
+    function getComBillsLibInfo(){
+        CommonAjax.post('/billsGuidance/api/getComBillsLibInfo', {}, function (rstData) {
+            const comSels = $('#comSels');
+            const billsLibSels = $('#billsLibSels');
+            //设置编办及清单规则库选择
+            comSels.empty();
+            function setBillsLib(libs){
+                billsLibSels.empty();
+                for(let lib of libs){
+                    let libOpt = `<option value="${lib.billsLibId}">${lib.billsLibName}</option>`;
+                    billsLibSels.append(libOpt);
+                }
+            }
+            let comIndex = {};
+            for(let i = 0; i < rstData.length; i++){
+                let compilation = rstData[i];
+                comIndex[compilation._id] = compilation;
+                let comOpt = `<option value = "${compilation._id}">${compilation.name}</option>`;
+                comSels.append(comOpt);
+                //设置初始选择的清单规则库
+                if(i === 0){
+                    setBillsLib(compilation.billsLibs);
+                }
+            }
+            //变更编办选择
+            comSels.on('change', function () {
+                let curComId = $(this).select().val();
+                let curCom = comIndex[curComId];
+                setBillsLib(curCom.billsLibs);
+            });
+        });
+    }
+    //html新增库
+    //@param {Object}tbody {Object}lib @return {void}
+    function addLibToView(tbody, lib){
+        let tr = `<tr id="${lib.ID}">
+            <td><a href="/billsGuidance/guidance/?libID=${lib.ID}">${lib.name}</a>
+            <td>${lib.compilationName}</td><td>${lib.billsLibName}</td>
+            <td>${lib.createDate.split(' ')[0]}</td>
+            <td><a href="javascript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a>
+            <a href="javascript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>`;
+        tbody.append(tr);
+    }
+    //获取清单指引库
+    //@return {void}
+    function getLibs(){
+        CommonAjax.post('/billsGuidance/api/getBillsGuideLibs', {}, function (rstData) {
+            guidanceLibs = rstData;
+            const tbody = $('.main').find('tbody');
+            tbody.empty();
+            for(let lib of rstData){
+                addLibToView(tbody, lib);
+            }
+        });
+    }
+    //是否已存在此库
+    //@param {Object}findSet {Array}libs @return {Object}
+    function existLib(findSet, libs) {
+        for(let lib of libs){
+            if(lib[findSet.k] === findSet.v){
+                return lib;
+            }
+        }
+        return null;
+    }
+    //监听事件
+    //@return {void}
+    function eventListener(){
+        //新建库确认按钮事件
+        $('#addY').click(function () {
+            try{
+                let cName = $('#createName').val();
+                if(!cName || cName.trim() === ''){
+                    throw '请输入名称!';
+                }
+                if(existLib({k: 'name', v: cName}, guidanceLibs)){
+                    throw '已存在此库!';
+                }
+                let compilationId = $('#comSels').select().val();
+                let compilationName = $('#comSels').select().children('option:selected').text();
+                if(!compilationId){
+                    throw '请选择编办!';
+                }
+                let billsLibId = $('#billsLibSels').select().val();
+                let billsLibName = $('#billsLibSels').select().children('option:selected').text();
+                if(!billsLibId){
+                    throw '请选择清单规则库';
+                }
+                //新建
+                $.bootstrapLoading.start();
+                let createData = {ID: uuid.v1(), name: cName, compilationId: compilationId, compilationName: compilationName, billsLibId: parseInt(billsLibId), billsLibName:billsLibName};
+                let updateData = {updateType: updateType.create, updateData: createData};
+                CommonAjax.post('/billsGuidance/api/updateBillsGuideLib', updateData, function (rstData) {
+                    guidanceLibs.push(rstData);
+                    addLibToView($('.main').find('tbody'), rstData);
+                    $('#add').modal('hide');
+                    $.bootstrapLoading.end();
+                }, function () {
+                    $.bootstrapLoading.end();
+                });
+            }
+            catch(err){
+                alert(err);
+                $('#createName').focus();
+            }
+        });
+        //新建模态框
+        $('#add').on('hidden.bs.modal', function () {
+           $('#createName').val('');
+        });
+        $('#add').on('shown.bs.modal', function () {
+            $('#createName').focus();
+        });
+        //所有编辑按钮
+        $('.main').find('tbody').on('click', '[data-target="#edit"]', function () {
+            let tr = $(this).parent().parent();
+            let selLib = existLib({k: 'ID', v: tr.attr('id')}, guidanceLibs);
+            curLib = selLib;
+            $('#edName').val(curLib.name);
+            $('#edComSels').select().children('option:selected').text(curLib.compilationName);
+            $('#edBillsLibSels').select().children('option:selected').text(curLib.billsLibName);
+        });
+        //编辑确认
+        $('#editY').click(function(){
+            try{
+                let newName = $('#edName').val();
+                if(newName.trim() === curLib.name){
+                    $('#edit').modal('hide');
+                    return;
+                }
+                if(!newName || newName.trim() === ''){
+                    throw '名称不能为空!';
+                }
+                if(existLib({k: 'name', v: newName}, guidanceLibs)){
+                    throw '该库已存在!';
+                }
+                let updateData = {updateType: updateType.update, findData: {ID: curLib.ID}, updateData: {name: newName}};
+                CommonAjax.post('/billsGuidance/api/updateBillsGuideLib', updateData, function (rstData) {
+                    curLib.name = newName;
+                    $(`#${curLib.ID} td:first a`).text(newName);
+                    $('#edit').modal('hide');
+                });
+            }
+            catch(err){
+                alert(err);
+                $('#edName').focus();
+            }
+        });
+        //编辑模态框
+        $('#edit').on('shown.bs.modal', function () {
+            $('#edName').focus();
+        });
+        //所有删除按钮
+        $('.main').find('tbody').on('click', '[data-target="#del"]', function () {
+            let tr = $(this).parent().parent();
+            curLib = existLib({k: 'ID', v: tr.attr('id')}, guidanceLibs);
+            console.log(curLib);
+        });
+        //删除确认
+        $('#delY').click(function () {
+            try{
+                if(!curLib){
+                    throw '不存在该库!';
+                }
+                if(preLib && preLib.ID !== curLib.ID){
+                    deleteCount = 0;
+                }
+                deleteCount++;
+                preLib = curLib;
+                if(deleteCount === 3){
+                    $('#del').modal('hide');
+                    $.bootstrapLoading.start();
+                    let updateData = {updateType: updateType.delete, findData: {ID: curLib.ID}, updateData: {deleted: true}};
+                    CommonAjax.post('/billsGuidance/api/updateBillsGuideLib', updateData, function (rstData) {
+                        $(`#${curLib.ID}`).remove();
+                        curLib = null;
+                        _.remove(guidanceLibs, function (lib) {
+                            return lib.ID === updateData.findData.ID;
+                        });
+                        $.bootstrapLoading.end();
+                    }, function () {
+                        $.bootstrapLoading.end();
+                    });
+                }
+            }
+            catch(err){
+                alert(err);
+            }
+        });
+        //删除确认窗口关闭,重新计数
+        $('#del').on('hidden.bs.modal', function () {
+            deleteCount = 0;
+        });
+
+    }
+
+    return {getComBillsLibInfo, getLibs, eventListener};
+})();
+
+$(document).ready(function () {
+    billsGuidanceMain.getComBillsLibInfo();
+    billsGuidanceMain.getLibs();
+    billsGuidanceMain.eventListener();
+});

+ 62 - 57
web/maintain/bills_lib/css/main.css

@@ -1,8 +1,7 @@
 /*building SAAS 0.1*/
 /*bootstrap 初始化*/
 body {
-    font-size: 0.9rem;
-    overflow: hidden;
+    font-size: 0.9rem
 }
 .dropdown-menu {
     font-size: 0.9rem
@@ -22,17 +21,17 @@ body {
     line-height: inherit
 }
 .top-msg{
-  position: fixed;
-  top:0;
-  width:100%;
-  z-index: 999
-}
-.in-1{padding-left:0px!important}
-.in-2{padding-left:21px!important}
-.in-3{padding-left:42px!important}
-.in-4{padding-left:63px!important}
-.in-5{padding-left:84px!important}
-.in-6{padding-left:105px!important}
+    position: fixed;
+    top:0;
+    width:100%;
+    z-index: 999
+}
+.in-1{padding-left:0rem!important}
+.in-2{padding-left:1rem!important}
+.in-3{padding-left:1.5rem!important}
+.in-4{padding-left:2rem!important}
+.in-5{padding-left:2.5rem!important}
+.in-6{padding-left:3rem!important}
 .main {
     position: relative;
     background: #f7f7f9;
@@ -63,12 +62,7 @@ body {
     background: #fff;
     color: #333
 }
-.main-nav .nav-tabs{
-  border-bottom: none
-}
 .content {
-    border-left: 1px solid #ccc;
-    margin-left: 29px;
     background: #fff
 }
 .tools-btn {
@@ -79,27 +73,34 @@ body {
     background: #f7f7f9;
 }
 .main-side {
-    border-top: 1px solid #ccc;
-    border-left: 1px solid #ccc;
-    overflow-y: hidden;
+    border-right: 1px solid #ccc;
+    overflow:hidden;
 }
-.sidebar-bottom,.sidebar-bottom .col-lg-6,.sidebar-bottom .col-lg-12 {
-  height:200px
+.main-side .tab-bar {
+    padding:5px 10px;
+    height:38px;
+    position:fixed;
+}
+.main-side .tab-content {
+    margin-top: 38px
 }
 .top-content, .fluid-content {
-    overflow: auto;
+    overflow: hidden;
     border-bottom: 1px solid #ccc;
 }
-.bottom-content .nav {
+.warp-p2 {
+    padding: 2px
+}
+.bottom-content .nav,.top-content .nav {
     background: #f7f7f9;
     padding:0 0 0 2px
 }
-.bottom-content .nav-tabs .nav-link, .side-tabs .nav-tabs .nav-link {
+.bottom-content .nav-tabs .nav-link, .side-tabs .nav-tabs .nav-link,.top-content .nav-tabs .nav-link {
     border-radius: 0;
     padding: 0.2em 0.5em
 }
 .side-tabs .nav-tabs .nav-item {
-  z-index: 999
+    z-index: 999
 }
 .side-tabs .nav-tabs {
     border-bottom: none;
@@ -211,13 +212,14 @@ body {
         transform: translateX(10px);
     }
 }
+.bottom-content {
+    height: 370px;
+    overflow: hidden;
+}
 .bottom-content .tab-content .main-data-bottom{
-    height: 200px;
+    height: 340px;
     overflow: auto;
 }
-.bottom-content .tab-content .ovf-hidden{
-    overflow: hidden;
-}
 .form-signin {
     max-width: 500px;
     margin: 150px auto;
@@ -226,49 +228,52 @@ body {
     overflow: auto;
 }
 .poj-list span.poj-icon {
-  padding-right:7px;
-  color:#ccc
-}
-.poj-list a.tree-open,.poj-list a.tree-close{
-  width:15px;
-  display: inline-block;
+    padding-right:10px;
+    color:#ccc
 }
 .print-toolsbar{
-  padding:5px
+    padding:5px
 }
 .print-toolsbar .panel {
-  display:inline-block;
-  vertical-align:top;
-  background:#f7f7f9
+    display:inline-block;
+    vertical-align:top;
+    background:#f7f7f9
 }
 .print-toolsbar .panel .panel-foot{
-  text-align: center;
-  font-size: 12px
+    text-align: center;
+    font-size: 12px
 }
 .print-list {
-  border-right:1px solid #ccc
+    border-right:1px solid #ccc
 }
 .print-list .form-list {
-  overflow: auto
+    overflow: auto
 }
 .print-list .list-tools{
-  height:50px;
-  padding:10px 0;
-  border-bottom:1px solid #f2f2f2
+    height:50px;
+    padding:10px 0;
+    border-bottom:1px solid #f2f2f2
 }
 .pageContainer {
-  background: #ededed;
-  text-align: center
+    background: #ededed;
+    text-align: center
 }
 .pageContainer .page{
-  border:9px solid transparent;
-  display: inline-block;
+    border:9px solid transparent;
+    display: inline-block;
 }
 .pageContainer .page img{
-  width:inherit;
-  height: inherit;
+    width:inherit;
+    height: inherit;
 }
-.modal-fixed-height {
-  height: 400px;
-  overflow-y: auto;
+.codeList{
+    max-height: 200px;
+    overflow:auto;
 }
+.main-data-top,.main-data-bottom,.main-data{
+    overflow: hidden;
+}
+.modal-fixed-height {
+    height:400px;
+    overflow-y:auto;
+}

+ 15 - 2
web/maintain/bills_lib/html/main.html

@@ -114,8 +114,8 @@
                     <h5 class="text-danger">删除后无法恢复,确认是否删除?</h5>
                 </div>
                 <div class="modal-footer">
+                    <a id="deleteA" href="javascript:void(0);" class="btn btn-danger" deleteId="">确认</a>
                     <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a id="deleteA" href="javascript:void(0);" class="btn btn-danger" data-dismiss="modal" deleteId="">删除</a>
                 </div>
             </div>
         </div>
@@ -134,6 +134,8 @@
 </script>
 <script>
     let userAccount = '<%= userAccount %>';
+    let deleteCount = 0;
+    let preDeleteId = null;
     mainAjax.getCompilationList();
     mainAjax.getStdBillsLib();
     $(document).ready(function(){
@@ -160,7 +162,18 @@
        });
         $("#deleteA").click(function(){
             let deleteId = $(this).attr("deleteId");
-            mainAjax.deleteStdBillsLib(userAccount, deleteId);
+            if(preDeleteId && preDeleteId !== deleteId){
+                deleteCount = 0;
+            }
+            preDeleteId = deleteId;
+            deleteCount++;
+            if(deleteCount === 3){
+                mainAjax.deleteStdBillsLib(userAccount, deleteId);
+                deleteCount = 0;
+            }
+        });
+        $('#del').on('hidden.bs.modal', function () {
+            deleteCount = 0;
         });
 
        $("#showArea").on("click", "[data-target = '#edit']", function(){

File diff suppressed because it is too large
+ 24 - 2
web/maintain/bills_lib/html/neirong.html


File diff suppressed because it is too large
+ 29 - 3
web/maintain/bills_lib/html/qingdan.html


File diff suppressed because it is too large
+ 23 - 2
web/maintain/bills_lib/html/tezheng.html


+ 28 - 0
web/maintain/bills_lib/scripts/bills_lib_ajax.js

@@ -1,6 +1,33 @@
 /**
  * Created by vian on 2017/3/27.
  */
+
+/**
+ * 设置全局的AJAX请求默认选项
+ * 主要设置了AJAX请求遇到Session过期的情况
+ */
+$.ajaxSetup({
+    complete: function (data) {
+        console.log(data);
+        if (data.responseJSON&&data.responseJSON.ret_code && data.responseJSON.ret_code == 99) {
+            alert(data.responseJSON.ret_msg);
+            var top = getTopWindow();
+            setTimeout('top.location.href = "/login";', 300);
+        }
+    }
+});
+
+/**
+ * 在页面中任何嵌套层次的窗口中获取顶层窗口
+ * @return 当前页面的顶层窗口对象
+ */
+function getTopWindow() {
+    var p = window;
+    while (p != p.parent) {
+        p = p.parent;
+    }
+    return p;
+}
 var mainAjax = {
     //获取编办
     getCompilationList: function () {
@@ -114,6 +141,7 @@ var mainAjax = {
                 if(!result.error){
                     var jqSel = "#"+billsLibId;
                     $(jqSel).remove();
+                    $('#del').modal('hide');
                 }
             }
         });

+ 10 - 2
web/maintain/bills_lib/scripts/db_controller.js

@@ -401,15 +401,19 @@ var createObj = {
             if(nodes){
                 nodes.forEach(function(node){
                     node.jobs = new Array();
+                    let spliceArr = [];
                     node.data.jobs.forEach(function(obj){
                         if(me.jobs[me.prefix + obj.id]){
                             node.jobs.push({job: me.jobs[me.prefix + obj.id], serialNo: obj.serialNo});
                             me.jobs[me.prefix + obj.id].count ++;
                         }
                         else {
-                            node.data.jobs.splice(node.data.jobs.indexOf(obj), 1);
+                            spliceArr.push(obj);
                         }
                     });
+                    for(let sItem of spliceArr){
+                        node.data.jobs.splice(node.data.jobs.indexOf(sItem), 1);
+                    }
                 });
             }
         };
@@ -458,15 +462,19 @@ var createObj = {
             if(nodes){
                 nodes.forEach(function(node){
                     node.items = new Array();
+                    let spliceArr = [];
                     node.data.items.forEach(function(obj){
                         if(me.items[me.prefix + obj.id]){
                             node.items.push({item: me.items[me.prefix + obj.id], serialNo: obj.serialNo});
                             me.items[me.prefix + obj.id].count ++;
                         }
                         else {
-                            node.data.items.splice(node.data.items.indexOf(obj), 1);
+                            spliceArr.push(obj);
                         }
                     });
+                    for(let sItem of spliceArr){
+                        node.data.items.splice(node.data.items.indexOf(sItem), 1);
+                    }
                 });
             }
         };

+ 12 - 3
web/maintain/bills_lib/scripts/set_sheets.js

@@ -12,6 +12,7 @@ var setSheet = {
         spread.options.allowCopyPasteExcelStyle = false;
         spread.options.allowExtendPasteRange = isExtendPaste? true : false;
         spread.options.allowUserDragDrop = false;
+        spread.options.allowContextMenu = false;
         spread.getActiveSheet().options.allowCellOverflow = false;
         spread.getActiveSheet().options.clipBoardOptions = GC.Spread.Sheets.ClipboardPasteOptions.values;
         sheet.showRowOutline(false);
@@ -163,8 +164,7 @@ var myKey = {
         }
 
         function bindTotalJobDel(spread, billsIds, totalJobs, setting){
-            var sheet = spread.getActiveSheet();
-            spread.commandManager().register('myJobDelete', function(){
+            $('#delConfirm').click(function () {
                 spread.suspendEvent();
                 var ids = tools.delIds(sheet);
                 if(ids.length > 0){
@@ -183,6 +183,11 @@ var myKey = {
                     billsAjax.removeTotal(userAccount, billsLibId, billsIds, ids, 'jobs');
                 }
                 spread.resumeEvent();
+                $('#delAlert').modal('hide');
+            });
+            var sheet = spread.getActiveSheet();
+            spread.commandManager().register('myJobDelete', function(){
+                $('#delAlert').modal('show');
             });
             spread.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
             spread.commandManager().setShortcutKey('myJobDelete', GC.Spread.Commands.Key.del, false, false, false, false)
@@ -190,7 +195,7 @@ var myKey = {
 
         function bindTotalItemDel(spread, valSheet, billsIds, totalItems, setting){
             var sheet = spread.getActiveSheet();
-            spread.commandManager().register('myItemDelete', function(){
+            $('#delConfirm').click(function () {
                 spread.suspendEvent();
                 var ids = tools.delIds(sheet);
                 if(ids.length > 0){
@@ -217,6 +222,10 @@ var myKey = {
                     }
                 }
                 spread.resumeEvent();
+                $('#delAlert').modal('hide');
+            });
+            spread.commandManager().register('myItemDelete', function(){
+                $('#delAlert').modal('show');
             });
             spread.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
             spread.commandManager().setShortcutKey('myItemDelete', GC.Spread.Commands.Key.del, false, false, false, false)

File diff suppressed because it is too large
+ 25 - 6
web/maintain/ration_repository/anzhuang.html


File diff suppressed because it is too large
+ 91 - 63
web/maintain/ration_repository/dinge.html


File diff suppressed because it is too large
+ 9 - 8
web/maintain/ration_repository/fuzhu.html


File diff suppressed because it is too large
+ 9 - 8
web/maintain/ration_repository/gongliao.html


+ 4 - 16
web/maintain/ration_repository/js/coe.js

@@ -8,18 +8,6 @@ var pageObj = {
     libID: null,
     gljLibID: null,
     initPage: function (){
-        $("#drirect-dinge").click(function(){
-            $(this).attr('href', "/rationRepository/ration" + "?repository=" + getQueryString("repository"))
-        });
-
-        $("#gongliao").click(function(){
-            $(this).attr('href', "/rationRepository/lmm" + "?repository=" + getQueryString("repository"))
-        });
-
-        $("#anzhuang").click(function(){
-            $(this).attr('href', "/rationRepository/installation" + "?repository=" + getQueryString("repository"))
-        });
-
         var libID = getQueryString("repository");
         var libName = storageUtil.getSessionCache("RationGrp","repositoryID_" + libID);
         if (libName) {
@@ -77,9 +65,9 @@ let coeOprObj = {
     currentMaxNo: null,
     setting: {
         header: [
-            {headerName:"编号", headerWidth:60, dataCode:"serialNo", dataType: "String", hAlign: "center", vAlign: "center", readOnly: false},
+            {headerName:"编号", headerWidth:50, dataCode:"serialNo", dataType: "String", hAlign: "center", vAlign: "center", readOnly: false},
             {headerName:"名称", headerWidth:280, dataCode:"name", dataType: "String", hAlign: "left", vAlign: "center", readOnly: false},
-            {headerName:"内容", headerWidth:250, dataCode:"content", dataType: "String", hAlign: "left", vAlign: "center", readOnly: false},
+            {headerName:"内容", headerWidth:150, dataCode:"content", dataType: "String", hAlign: "left", vAlign: "center", readOnly: false},
         ]
     },
     buildSheet: function (container) {
@@ -375,8 +363,8 @@ let gljAdjOprObj = {
     gljList: [],//只含编号和名称的总工料机列表
     setting: {
         header: [
-            {headerName:"调整类型", headerWidth:100, dataCode:"coeType", dataType: "String", hAlign: "center", vAlign: "center", readOnly: false},
-            {headerName:"工料机编码", headerWidth:100, dataCode:"gljCode", dataType: "String", formatter: '@', hAlign: "center", vAlign: "center", readOnly: false},
+            {headerName:"调整类型", headerWidth:80, dataCode:"coeType", dataType: "String", hAlign: "center", vAlign: "center", readOnly: false},
+            {headerName:"人材机编码", headerWidth:80, dataCode:"gljCode", dataType: "String", formatter: '@', hAlign: "center", vAlign: "center", readOnly: false},
             {headerName:"名称", headerWidth:100, dataCode:"gljName", dataType: "String", hAlign: "center", vAlign: "center", readOnly: true},
             {headerName:"操作符", headerWidth:60, dataCode:"operator", dataType: "String", hAlign: "center", vAlign: "center", readOnly: false},
             {headerName:"数量", headerWidth:80, dataCode:"amount", dataType: "String", hAlign: "center", vAlign: "center" , readOnly: false},

+ 333 - 0
web/maintain/ration_repository/js/gljSelect.js

@@ -0,0 +1,333 @@
+/**
+ * Created by Zhong on 2017/8/25.
+ */
+
+let gljSelOprObj = {
+    parentNodeIds: {},
+    treeObj:null,
+    rootNode: null,//分类树根节点
+    radiosSelected: null,//allGljs, stdGljs, complementaryGljs
+    workBook: null,
+    selectedList: [],//选中的工料机
+    setting: {
+        header: [
+            {headerName:"选择", headerWidth: 40, dataCode: "select", hAlign: "center", vAlign: "center"},
+            {headerName:"编码",headerWidth:80,dataCode:"code", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
+            {headerName:"名称",headerWidth:120,dataCode:"name", dataType: "String", hAlign: "left", vAlign: "center"},
+            {headerName:"规格型号",headerWidth:80,dataCode:"specs", dataType: "String", hAlign: "center", vAlign: "center"},
+            {headerName:"单位",headerWidth:80,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
+            {headerName:"单价",headerWidth:80,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right", vAlign: "center"},
+            {headerName:"类型",headerWidth:80,dataCode:"gljType", dataType: "String",  hAlign: "center", vAlign: "center"}
+        ]
+    },
+    setProp: function (prop, value, gljList) {
+        for(let i = 0, len = gljList.length; i < len; i++){
+            gljList[i][prop] = value;
+        }
+    },
+    sortGlj: function(gljList) {
+        gljList.sort(function(a, b){
+            let rst = 0;
+            if (a.code > b.code) rst = 1
+            else if (a.code < b.code) rst = -1;
+            return rst;
+        });
+    },
+    switchToGljId: function (gljList) {
+        for(let glj of gljList){
+            glj.gljId = glj.ID;
+            delete glj.ID;
+        }
+    },
+    getSelGljItems: function(stdGljLibId, callback) {
+        let me = this;
+        $.ajax({
+            type:"POST",
+            url:"/stdGljRepository/api/getGljItems",
+            data:{"repositoryId": stdGljLibId},
+            dataType:"json",
+            cache:false,
+            timeout:20000,
+            success:function(result){
+                if(!result.error) {
+                    me.stdGljList = result.data;
+                    me.switchToGljId(me.stdGljList);
+                    me.sortGlj(me.stdGljList);
+                    if(callback){
+                        callback();
+                    }
+                }
+            },
+            error:function(err){
+                alert(err.responseJSON.error);
+            }
+        });
+    },
+    getGljClassTree: function (gljLibId, callback) {
+        let me = this;
+        let url = '/stdGljRepository/api/getGljTree';
+        let postData = {gljLibId: gljLibId};
+        let sucFunc = function (rstData) {
+            zTreeHelper.createTree(rstData, gljSelTreeOprObj.setting, "selGljTree", gljSelOprObj);
+            let rootNode = gljSelOprObj.treeObj.getNodes()[0];
+            if(rootNode && rootNode.isParent && rootNode.isFirstNode){
+                gljSelOprObj.rootNode = rootNode;
+            }
+            gljSelOprObj.buildSheet($('#gljSelSheet')[0]);
+            if(callback){
+                callback();
+            }
+        };
+        let errFunc = function () {
+
+        };
+        CommonAjax.post(url, postData, sucFunc, errFunc);
+    },
+    buildSheet: function (container) {
+        let me = gljSelOprObj;
+        me.workBook = sheetCommonObj.buildSheet(container, me.setting, 30);
+        me.workBook.getSheet(0).setColumnWidth(0, 20, GC.Spread.Sheets.SheetArea.rowHeader);
+        me.workBook.getSheet(0).setFormatter(-1, 1, "@", GC.Spread.Sheets.SheetArea.viewport);
+        me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EditStarting, me.onCellEditStart);
+        me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
+        me.workBook.bind(GC.Spread.Sheets.Events.ButtonClicked, me.onButtonClicked);//复选框点击事件
+        me.bindBtnOpr($('#gljSelY'));
+        me.radiosChange();
+    },
+    onClipboardPasting: function (sender, args) {
+        args.cancel = true;
+    },
+    onCellEditStart: function (sender, args) {
+        args.cancel = true;
+    },
+    onButtonClicked: function (sender, args) {
+        let me = gljSelOprObj;
+        let val = args.sheet.getValue(args.row, args.col);
+        let thisGlj = me.currentCache[args.row];
+        thisGlj.isChecked = val;
+        if(args.sheet.isEditing()){
+            args.sheet.endEdit(true);
+        }
+        else{
+            //设置选中
+            if(val === true){
+                let isExist = false;
+                for(let i = 0, len = me.selectedList.length; i < len; i++){
+                    if(me.selectedList[i].gljId === thisGlj.gljId){
+                        isExist = true;
+                        break;
+                    }
+                }
+                if(!isExist){
+                    thisGlj.consumeAmt = 0;
+                    me.selectedList.push(thisGlj);
+                }
+            }
+            else if(val === false){
+                for(let i = 0, len = me.selectedList.length; i < len; i++){
+                    if(me.selectedList[i].gljId === thisGlj.gljId){
+                        me.selectedList.splice(i, 1);
+                        break;
+                    }
+                }
+            }
+        }
+    },
+    setShowGljList: function (gljList, clearChecked) {
+        //初始为所有工料机
+        let  me = this;
+        let curRationGlj = rationGLJOprObj.cache['_GLJ_' + rationGLJOprObj.currentRationItem.ID];
+        for(let i = 0; i < gljList.length; i++){
+            //去除与已添加的组成物重复的条目
+            let isExist = false;
+            for(let j = 0; j < curRationGlj.length; j++){
+                if(curRationGlj[j].gljId === gljList[i].gljId){
+                    isExist = true;
+                    break;
+                }
+            }
+            if(!isExist){
+                if(clearChecked){
+                    gljList[i].isChecked = false;
+                }
+            }
+            else {
+                gljList[i].isChecked = true;
+            }
+            me.showGljList.push(gljList[i]);
+        }
+    },
+    //初始默认radio
+    initRadio: function () {
+        let me = gljSelOprObj;
+        $('#gljSearchKeyword').val('');//恢复搜索文本
+        me.selectedList = [].concat(rationGLJOprObj.cache['_GLJ_' + rationGLJOprObj.currentRationItem.ID]);
+        //默认radio所有工料机
+        if(typeof $("input[name='glj']:checked")[0] !== 'undefined'){
+            $("input[name='glj']:checked")[0].checked = false;
+        }
+        $("input[value = 'allGljs']")[0].checked = true;
+        me.radiosSelected = 'allGljs';
+        //初始为所有工料机
+        me.showGljList = [];
+        if(me.radiosSelected === 'allGljs'){
+            me.setShowGljList(me.stdGljList, true);
+            me.sortGlj(me.showGljList);
+        }
+    },
+    filterDatasAndShow: function () {
+        let me = gljSelOprObj;
+        let val = $("input[name='glj']:checked").val();
+        me.radiosSelected = val;
+        //选择改变,数据重新筛选显示
+        me.showGljList = [];
+        if(me.radiosSelected === 'allGljs'){
+            me.setShowGljList(me.stdGljList);
+        }
+        //搜索匹配
+        let searchStr = $('#gljSearchKeyword').val();
+        if(searchStr && searchStr.trim() != ''){
+            let reg = new RegExp(searchStr);
+            me.showGljList = _.filter(me.showGljList, function (data) {
+                return reg.test(data.code) || reg.test(data.name);
+            });
+        }
+        me.sortGlj(me.showGljList);
+        //重新显示
+        me.showGljItems(me.showGljList, me.gljCurTypeId);
+        //切换radio后更新cache
+        if (me.currentOprParent = 1) {
+            if(me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]){
+                me.currentCache = me.getParentCache(me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]);
+            }
+            else{
+                me.currentCache = [];
+            }
+        } else {
+            me.currentCache = me.getCache();
+        }
+    },
+    //监听radios选择事件
+    radiosChange: function () {
+        let me = gljSelOprObj;
+        $('.glj-radio').change(function () {
+            me.filterDatasAndShow();
+        });
+    },
+
+    getParentCache: function (nodes) {
+        let me = gljSelOprObj, rst = [];
+        for(let i = 0; i < me.showGljList.length; i++){
+            if(nodes.indexOf(me.showGljList[i].gljClass) !== -1){
+                rst.push(me.showGljList[i]);
+            }
+        }
+        rst.sort(function (a, b) {
+            let rst = 0;
+            if(a.code > b.code) rst = 1;
+            else if(a.code < b.code)rst = -1;
+            return rst;
+        });
+        return rst;
+    },
+    getCache: function() {
+        let me = gljSelOprObj, rst = [];
+        for (let i = 0; i < me.showGljList.length; i++) {
+            if (me.showGljList[i].gljClass == me.gljCurTypeId) {
+                rst.push(me.showGljList[i]);
+            }
+        }
+        return rst;
+    },
+    showGljItems: function(data, type) {
+        let me = gljSelOprObj;
+        if (me.workBook) {
+            let cacheSection = [];
+            let pArr = me.parentNodeIds["_pNodeId_" + type];
+            for (let i = 0; i < data.length; i++) {
+                if (pArr && pArr.indexOf(data[i].gljClass) >= 0) {
+                    cacheSection.push(data[i]);
+                } else if (type == data[i].gljClass) {
+                    cacheSection.push(data[i]);
+                }
+            }
+            sheetCommonObj.cleanSheet(me.workBook.getSheet(0), me.setting, -1);
+            sheetsOprObj.showDataForGljSel(me.workBook.getSheet(0), me.setting, cacheSection, rationGLJOprObj.distTypeTree);
+            me.workBook.getSheet(0).setRowCount(cacheSection.length);
+            cacheSection = null;
+        }
+    },
+    //组成物窗口按钮操作
+    bindBtnOpr: function (conf) {//确定、取消、关闭按钮
+        let me = gljSelOprObj, that = rationGLJOprObj;
+        conf.click(function () {
+            that.cache['_GLJ_' + that.currentRationItem.ID] = me.selectedList;
+            that.updateRationItem(function () {
+                that.sheet.getParent().focus();
+                sheetCommonObj.cleanData(that.sheet, that.setting, -1);
+                that.showGljItems(that.currentRationItem.ID);
+                $('#selGlj').modal('hide');
+            });
+        });
+    }
+};
+
+let gljSelTreeOprObj = {
+     setting: {
+        view: {
+            expandSpeed: "",
+            selectedMulti: false
+        },
+        edit: {
+            enable: false,
+            editNameSelectAll: true,
+            showRemoveBtn: true,
+            showRenameBtn: true,
+            removeTitle: "删除节点",
+            renameTitle: "更改名称"
+        },
+        data: {
+            keep: {
+                parent:true,
+                leaf:true
+            },
+            key: {
+                children: "items",
+                name: "Name"
+            },
+            simpleData: {
+                enable: false,
+                idKey: "ID",
+                pIdKey: "ParentID",
+                rootPId: -1
+            }
+        },
+        callback:{
+            onClick: function(event,treeId,treeNode) {
+                let me = gljSelOprObj, gljTypeId = treeNode.ID;
+                if(me.gljCurTypeId !== treeNode.ID){
+                    me.gljCurTypeId = treeNode.ID;
+                    if (me.parentNodeIds["_pNodeId_" + treeNode.ID]) {
+                        me.currentOprParent = 1;
+                        me.currentCache = me.getParentCache(me.parentNodeIds["_pNodeId_" + treeNode.ID]);
+                    } else {
+                        me.currentCache = me.getCache();
+                    }
+                }
+                me.showGljItems(me.showGljList, gljTypeId);
+            }
+        }
+    }
+};
+
+$(document).ready(function () {
+    $('#gljSearchKeyword').change(function () {
+        gljSelOprObj.filterDatasAndShow();
+    });
+    $('#gljSearchKeyword').bind('keypress', function (e) {
+        if(e.keyCode === 13){
+            $(this).blur();
+            return false;
+        }
+    });
+});

+ 95 - 67
web/maintain/ration_repository/js/installation.js

@@ -1,17 +1,6 @@
 /**
  * Created by Zhong on 2018/1/19.
  **/
-$("#gongliao").click(function(){
-    $(this).attr('href', "/rationRepository/lmm" + "?repository=" + getQueryString("repository"))
-});
-
-$("#fuzhu").click(function(){
-    $(this).attr('href', "/rationRepository/coeList" + "?repository=" + getQueryString("repository"))
-});
-
-$("#dinge").click(function(){
-    $(this).attr('href', "/rationRepository/ration" + "?repository=" + getQueryString("repository"))
-});
 
 $(document).ready(function () {
     feeItemObj.buildSheet();
@@ -23,7 +12,92 @@ $(document).ready(function () {
     $('#sectionTreeModal').on('hidden.bs.modal', function () {
         batchSectionObj.clearChecked();
     });
+    $('#delConfirm').click(function () {
+        if(curDeleteType === feeItemObj.deleteType){
+            let me = feeItemObj, se = sectionObj, fr = feeRuleObj;
+            let fiPostData = [], sePostData = [];
+            let sels = me.workBook.getSheet(0).getSelections();
+            for(let i = 0, len = sels.length; i < len; i++){
+                let sel = sels[i];
+                //delete
+                if(sel.colCount === me.setting.header.length){
+                    for(let j = 0, jLen = sel.rowCount; j < jLen; j++){
+                        let row = sel.row + j;
+                        let feeItem = me.cache[row];
+                        //有数据,删除数据
+                        if(me.isDef(feeItem)){
+                            fiPostData.push({updateType: me.updateType.update, updateData: {ID: feeItem.ID, deleted: true}});
+                            //delete feeItem section
+                            for(let section of feeItem.section){
+                                sePostData.push({updateType: me.updateType.update, updateData: {ID: section.ID, deleted: true}});
+                            }
+                        }
+                    }
+                    //front delete
+                    me.cache.splice(sel.row, sel.rowCount);
+                }
+            }
+            //update currentFeeItem
+            me.currentFeeItem = me.getCurrentData(me.sheet, me.cache);
+            se.cache = me.isDef(me.currentFeeItem) ? me.currentFeeItem.section : [];
+            if(fiPostData.length > 0){
+                me.updateFeeItem(fiPostData, function () {
+                    me.sheet.setRowCount(me.cache.length + 10);
+                    sheetCommonObj.showData(me.sheet, me.setting, me.cache);
+                    $('#delAlert').modal('hide');
+                });
+                if(sePostData.length > 0){
+                    se.updateSection(sePostData);
+                }
+                sheetCommonObj.cleanData(se.sheet, se.setting, 10);
+                sheetCommonObj.cleanData(fr.sheet, fr.setting, 10);
+            }
+            else {
+                $('#delAlert').modal('hide');
+            }
+        }
+        else if(curDeleteType === sectionObj.deleteType){
+            let me = sectionObj, fi = feeItemObj, fr = feeRuleObj;
+            let sePostData = [], fiPostData = [];
+            let sels = me.workBook.getSheet(0).getSelections();
+            for(let i = 0, len = sels.length; i < len; i++){
+                let sel = sels[i];
+                //delete
+                if(sel.colCount === me.setting.header.length){
+                    for(let j = 0, jLen = sel.rowCount; j < jLen; j++){
+                        let row = sel.row + j;
+                        let section = me.cache[row];
+                        //有数据,删除数据
+                        if(me.isDef(section)){
+                            sePostData.push({updateType: me.updateType.update, updateData: {ID: section.ID, deleted: true}});
+                            fiPostData.push({updateType: me.updateType.update, updateData: {ID: fi.currentFeeItem.ID, $pull: {section: {ID: section.ID}}}});
+                        }
+                    }
+                    //front delete
+                    me.cache.splice(sel.row, sel.rowCount);
+                }
+            }
+            //update currentSection
+            me.currentSection = fi.getCurrentData(me.sheet, me.cache);
+            fr.cache = me.isDef(me.currentSection) ? me.currentSection.feeRule : [];
+            if(sePostData.length > 0){
+                me.updateSection(sePostData, function () {
+                    me.sheet.setRowCount(me.cache.length + 5);
+                    sheetCommonObj.showData(me.sheet, me.setting, me.cache);
+                    $('#delAlert').modal('hide');
+                });
+                if(fiPostData.length > 0){
+                    fi.updateFeeItem(fiPostData);
+                }
+                sheetCommonObj.cleanData(fr.sheet, fr.setting, 10);
+            }
+            else{
+                $('#delAlert').modal('hide');
+            }
+        }
+    });
 });
+let curDeleteType = null;
 //费用项
 let feeItemObj = {
     rationRepId: null,
@@ -33,6 +107,7 @@ let feeItemObj = {
     currentFeeItem: null,
     feeType: {ZM: '子目费用', FX: '分项费用', CS: '措施费用'},
     updateType: {update: 'update', new: 'new'},
+    deleteType: 'feeItem',
     setting: {
         header:[
             {headerName:"费用项",headerWidth:300,dataCode:"feeItem", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
@@ -236,43 +311,17 @@ let feeItemObj = {
         }
     },
     feeItemDelOpr: function () {
-        let me = feeItemObj, se = sectionObj, fr = feeRuleObj;
-        let fiPostData = [], sePostData = [];
+        let me = this;
         me.workBook.commandManager().register('feeItemDel', function () {
+            curDeleteType = me.deleteType;
             let sels = me.workBook.getSheet(0).getSelections();
             for(let i = 0, len = sels.length; i < len; i++){
                 let sel = sels[i];
                 //delete
                 if(sel.colCount === me.setting.header.length){
-                    for(let j = 0, jLen = sel.rowCount; j < jLen; j++){
-                        let row = sel.row + j;
-                        let feeItem = me.cache[row];
-                        //有数据,删除数据
-                        if(me.isDef(feeItem)){
-                            fiPostData.push({updateType: me.updateType.update, updateData: {ID: feeItem.ID, deleted: true}});
-                            //delete feeItem section
-                            for(let section of feeItem.section){
-                                sePostData.push({updateType: me.updateType.update, updateData: {ID: section.ID, deleted: true}});
-                            }
-                        }
-                    }
-                    //front delete
-                    me.cache.splice(sel.row, sel.rowCount);
-                }
-            }
-            //update currentFeeItem
-            me.currentFeeItem = me.getCurrentData(me.sheet, me.cache);
-            se.cache = me.isDef(me.currentFeeItem) ? me.currentFeeItem.section : [];
-            if(fiPostData.length > 0){
-                me.updateFeeItem(fiPostData, function () {
-                    me.sheet.setRowCount(me.cache.length + 10);
-                    sheetCommonObj.showData(me.sheet, me.setting, me.cache);
-                });
-                if(sePostData.length > 0){
-                    se.updateSection(sePostData);
+                    $('#delAlert').modal('show');
+                    break;
                 }
-                sheetCommonObj.cleanData(se.sheet, se.setting, 10);
-                sheetCommonObj.cleanData(fr.sheet, fr.setting, 10);
             }
         });
         me.workBook.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
@@ -324,6 +373,7 @@ let sectionObj = {
     cache: [],
     currentSection: null,
     updateType: {update: 'update', new: 'new'},
+    deleteType: 'section',
     setting: {
         header:[
             {headerName:"分册章节",headerWidth:600,dataCode:"name", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"}
@@ -521,39 +571,17 @@ let sectionObj = {
         }
     },
     sectionDelOpr: function () {
-        let me = sectionObj, fi = feeItemObj, fr = feeRuleObj;
-        let sePostData = [], fiPostData = [];
+        let me = this;
         me.workBook.commandManager().register('sectionDel', function () {
+            curDeleteType = me.deleteType;
             let sels = me.workBook.getSheet(0).getSelections();
             for(let i = 0, len = sels.length; i < len; i++){
                 let sel = sels[i];
                 //delete
                 if(sel.colCount === me.setting.header.length){
-                    for(let j = 0, jLen = sel.rowCount; j < jLen; j++){
-                        let row = sel.row + j;
-                        let section = me.cache[row];
-                        //有数据,删除数据
-                        if(me.isDef(section)){
-                            sePostData.push({updateType: me.updateType.update, updateData: {ID: section.ID, deleted: true}});
-                            fiPostData.push({updateType: me.updateType.update, updateData: {ID: fi.currentFeeItem.ID, $pull: {section: {ID: section.ID}}}});
-                        }
-                    }
-                    //front delete
-                    me.cache.splice(sel.row, sel.rowCount);
-                }
-            }
-            //update currentSection
-            me.currentSection = fi.getCurrentData(me.sheet, me.cache);
-            fr.cache = me.isDef(me.currentSection) ? me.currentSection.feeRule : [];
-            if(sePostData.length > 0){
-                me.updateSection(sePostData, function () {
-                    me.sheet.setRowCount(me.cache.length + 5);
-                    sheetCommonObj.showData(me.sheet, me.setting, me.cache);
-                });
-                if(fiPostData.length > 0){
-                    fi.updateFeeItem(fiPostData);
+                    $('#delAlert').modal('show');
+                    break;
                 }
-                sheetCommonObj.cleanData(fr.sheet, fr.setting, 10);
             }
         });
         me.workBook.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);

+ 21 - 1
web/maintain/ration_repository/js/main.js

@@ -4,6 +4,11 @@
 
 $(function () {
     let dispNameArr;
+    let preDeleteId = null;
+    let deleteCount = 0;
+    $('#del').on('hidden.bs.modal', function () {
+        deleteCount = 0;
+    });
     getAllRationLib(function (dispNames) {
         dispNameArr = dispNames;
         //添加
@@ -68,9 +73,18 @@ $(function () {
         });
         $("#deleteA").click(function(){
             let deleteId = $(this).attr("deleteId");
+            if(preDeleteId && preDeleteId !== deleteId){
+                deleteCount = 0;
+            }
+            preDeleteId = deleteId;
+            deleteCount++;
             let jqSel = "#" + deleteId + " td:first" + " a";
             let libName = $(jqSel).text();
-            removeRationLib({libId: deleteId, libName: libName}, dispNameArr);
+            if(deleteCount === 3){
+                deleteCount = 0;
+                removeRationLib({libId: deleteId, libName: libName}, dispNameArr);
+                $('#del').modal('hide');
+            }
         });
 
 
@@ -312,6 +326,7 @@ function renameRationLib(renameObj, dispNames){
     })
 }
 function removeRationLib(delObj, dispNames){
+    $.bootstrapLoading.start();
     $.ajax({
         type: 'post',
         url: 'api/deleteRationLibs',
@@ -325,6 +340,11 @@ function removeRationLib(delObj, dispNames){
                 dispNames.splice(index, 1);
                 $('#delCancelBtn').click();
             }
+            $.bootstrapLoading.end();
+        },
+        error: function () {
+            alert('删除失败');
+            $.bootstrapLoading.end();
         }
     })
 }

+ 73 - 36
web/maintain/ration_repository/js/ration.js

@@ -2,18 +2,6 @@
  * Created by Tony on 2017/4/28.
  */
 
-$("#gongliao").click(function(){
-    $(this).attr('href', "/rationRepository/lmm" + "?repository=" + getQueryString("repository"))
-});
-
-$("#fuzhu").click(function(){
-    $(this).attr('href', "/rationRepository/coeList" + "?repository=" + getQueryString("repository"))
-});
-
-$("#anzhuang").click(function(){
-    $(this).attr('href', "/rationRepository/installation" + "?repository=" + getQueryString("repository"))
-});
-
 const digital = {
     gljPrc: -3,//计算定额基价时单个工料机价格取三位
     rationBasePrc: -2,
@@ -27,15 +15,15 @@ let rationOprObj = {
     rationsCodes: [],
     setting: {
         header:[
-            {headerName:"编码",headerWidth:120,dataCode:"code", dataType: "String", formatter: "@"},
-            {headerName:"名称",headerWidth:280,dataCode:"name", dataType: "String"},
-            {headerName:"计量单位",headerWidth:120,dataCode:"unit", dataType: "String", hAlign: "center"},
-            {headerName:"人工费",headerWidth:120,dataCode:"labourPrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
-            {headerName:"材料费",headerWidth:120,dataCode:"materialPrice", dataType: "Number", formatter: "0.00",  hAlign: "right"},
-            {headerName:"机械费",headerWidth:120,dataCode:"machinePrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
-            {headerName:"基价",headerWidth:120,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
-            {headerName:"显示名称(以%s表示参数)",headerWidth:280,dataCode:"caption", dataType: "String"},
-            {headerName:"取费专业",headerWidth:100,dataCode:"feeType", dataType: "Number", hAlign: "center"}
+            {headerName:"编码",headerWidth:70,dataCode:"code", dataType: "String", formatter: "@"},
+            {headerName:"名称",headerWidth:240,dataCode:"name", dataType: "String"},
+            {headerName:"计量单位",headerWidth:70,dataCode:"unit", dataType: "String", hAlign: "center"},
+            {headerName:"人工费",headerWidth:80,dataCode:"labourPrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
+            {headerName:"材料费",headerWidth:80,dataCode:"materialPrice", dataType: "Number", formatter: "0.00",  hAlign: "right"},
+            {headerName:"机械费",headerWidth:80,dataCode:"machinePrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
+            {headerName:"基价",headerWidth:80,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right"},
+            {headerName:"显示名称(以%s表示参数)",headerWidth:240,dataCode:"caption", dataType: "String"},
+            {headerName:"取费专业",headerWidth:70,dataCode:"feeType", dataType: "Number", hAlign: "center"}
         ],
         view:{
             comboBox:[
@@ -54,6 +42,7 @@ let rationOprObj = {
         let me = rationOprObj;
         me.workBook = sheetCommonObj.buildSheet(container, me.setting, 30);
         me.getRationsCodes(rationRepId);
+        me.onContextmenuOpr();
         me.rationDelOpr();
         me.setCombo(me.workBook.getSheet(0), 'dynamic');
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
@@ -70,7 +59,7 @@ let rationOprObj = {
         sheet.suspendEvent();
         if(combo){
             combo = sheetCommonObj.getDynamicCombo();
-            combo.items(rationUnits).itemHeight(10).editable(true);
+            combo.items(rationAndGljUnits).itemHeight(10).editable(true);
         }
         sheet.getRange(-1, me.setting.view.comboBox[0].col, -1, 1).cellType(combo);
         sheet.resumePaint();
@@ -160,6 +149,50 @@ let rationOprObj = {
         }
         return cacheSection;
     },
+    onContextmenuOpr: function () {//右键菜单
+        let me = this;
+        $.contextMenu({
+            selector: '#rationItemsSheet',
+            build: function($triggerElement, e){
+                //控制允许右键菜单在哪个位置出现
+                let target = SheetDataHelper.safeRightClickSelection($triggerElement, e, me.workBook);
+                let sheet = me.workBook.getSheet(0);
+                let  delDis = false;
+                let cacheSection = me.getCache();
+                let ration = cacheSection[target.row];
+                if(target.hitTestType === 3){//在表格内&& typeof target.row !== 'undefined' && typeof target.col !== 'undefined'
+                    if(typeof target.row !== 'undefined'){
+                        //控制按钮是否可用
+                        sheet.setActiveCell(target.row, target.col);
+                        if(!cacheSection ||target.row >= cacheSection.length){//右键定位在有数据的行,删除键才显示可用
+                            delDis = true;
+                        }
+                        else{//有数据
+                            if(typeof target.col === 'undefined'){//定位不在表格内
+                                delDis = true;
+                            }
+                        }
+                    }
+                    else{
+                        delDis = true;
+                    }
+                    return {
+                        callback: function(){},
+                        items: {
+                            "delete": {name: "删除", disabled: delDis, icon: "fa-remove", callback: function (key, opt) {
+                                me.rationsCodes.splice(me.rationsCodes.indexOf(ration.code.toString()), 1);
+                                me.mixDel = 1;
+                                me.mixUpdateRequest([], [], [ration.ID]);
+                            }}
+                        }
+                    };
+                }
+                else{
+                    return false;
+                }
+            }
+        });
+    },
     rationDelOpr: function () {
         let me = rationOprObj;
         me.workBook.commandManager().register('rationDelete', function () {
@@ -173,7 +206,7 @@ let rationOprObj = {
                             for(let i = 0; i < sels[sel].rowCount; i++){
                                 if(sels[sel].row + i < cacheSection.length){
                                     removeArr.push(cacheSection[sels[sel].row + i].ID);
-                                    me.rationsCodes.splice(me.rationsCodes.indexOf(cacheSection[sels[sel].row + i].code), 1);
+                                    me.rationsCodes.splice(me.rationsCodes.indexOf(cacheSection[sels[sel].row + i].code.toString()), 1);
                                 }
                             }
                         }
@@ -276,6 +309,10 @@ let rationOprObj = {
         }
     },
     onCellEditEnd: function(sender, args) {
+        let edV = args.sheet.getValue(args.row, args.col);
+        if(edV){
+            args.sheet.setValue(args.row, args.col, edV.toString().trim());
+        }
         let me = rationOprObj, rObj = sheetsOprObj.combineRationRowData(me.workBook.getSheet(0), me.setting, args.row),
             updateArr = [], addArr = [];
         let dataCode = me.setting.header[args.col].dataCode;
@@ -289,9 +326,9 @@ let rationOprObj = {
                 if(me.currentEditingRation[dataCode] !== rObj[dataCode]){
                     me.addRationItem = rObj;
                     if(dataCode === 'code'){
-                        if(me.rationsCodes.indexOf(rObj.code) === -1){
-                            me.rationsCodes.splice(me.rationsCodes.indexOf(rObj.code), 1);
-                            me.rationsCodes.push(rObj.code);
+                        if(me.rationsCodes.indexOf(rObj.code.toString()) === -1){
+                            me.rationsCodes.splice(me.rationsCodes.indexOf(rObj.code.toString()), 1);
+                            me.rationsCodes.push(rObj.code.toString());
                             updateArr.push(rObj);
                         }
                         else{
@@ -320,7 +357,7 @@ let rationOprObj = {
                 //addArr.push(rObj);
                 me.addRationItem = rObj;
                 if(rObj.code && rObj.code.toString().trim().length > 0){
-                    if(me.rationsCodes.indexOf(rObj.code) === -1){
+                    if(me.rationsCodes.indexOf(rObj.code.toString()) === -1){
                         //jobContent
                         if(jobContentOprObj && jobContentOprObj.currentSituation === jobContentOprObj.situations.ALL){
                             rObj.jobContent = jobContentOprObj.currentJobContent ? jobContentOprObj.currentJobContent : '';
@@ -330,7 +367,7 @@ let rationOprObj = {
                         }
                         me.setInitPrc(rObj);
                         addArr.push(rObj);
-                        me.rationsCodes.push(rObj.code);
+                        me.rationsCodes.push(rObj.code.toString());
                         me.addRationItem = null;
                     }
                     else{
@@ -372,11 +409,11 @@ let rationOprObj = {
         for (let i = 0; i < items.length; i++) {
             let rowIdx = info.cellRange.row + i;
             if (cacheSection) {
-                if(!me.isValidUnit(items[i], rationUnits)){//无效单位
+              /*  if(!me.isValidUnit(items[i], rationUnits)){//无效单位
                     items[i].unit = rowIdx < cacheSection.length  && typeof cacheSection[rowIdx].unit !== 'undefined' ? cacheSection[rowIdx].unit : '';
-                }
+                }*/
                 if(!cacheSection[rowIdx] && info.cellRange.col === 0 ){
-                    if(me.rationsCodes.indexOf(items[i].code) === -1){
+                    if(me.rationsCodes.indexOf(items[i].code.toString()) === -1){
                         //jobConten
                         if(jobContentOprObj && jobContentOprObj.currentSituation === jobContentOprObj.situations.ALL){
                             items[i].jobContent = jobContentOprObj.currentJobContent ? jobContentOprObj.currentJobContent : '';
@@ -386,7 +423,7 @@ let rationOprObj = {
                         }
                         me.setInitPrc(items[i]);
                         addArr.push(items[i]);
-                        me.rationsCodes.push(items[i].code);
+                        me.rationsCodes.push(items[i].code.toString());
                     }
                     else{
                         me.workBook.getSheet(0).setValue(rowIdx, 0, '');
@@ -403,7 +440,7 @@ let rationOprObj = {
                         me.workBook.getSheet(0).setValue(rowIdx, 8, '');
                     }
                     if(info.cellRange.col === 0){
-                        if(me.rationsCodes.indexOf(items[i].code) === -1){
+                        if(me.rationsCodes.indexOf(items[i].code.toString()) === -1){
                             items[i].ID = cacheSection[rowIdx].ID;
                             updateArr.push(items[i]);
                         }
@@ -418,13 +455,13 @@ let rationOprObj = {
                 }
 
             } else {
-                if(!me.isValidUnit(items[i], rationUnits)){//无效单位
+               /* if(!me.isValidUnit(items[i], rationUnits)){//无效单位
                     items[i].unit = '';
-                }
+                }*/
                 //add
                 if(info.cellRange.col === 0){
                     //是否含有已存在的编号
-                        if(me.rationsCodes.indexOf(items[i].code) === -1){
+                        if(me.rationsCodes.indexOf(items[i].code.toString()) === -1){
                             //jobConten
                             if(jobContentOprObj && jobContentOprObj.currentSituation === jobContentOprObj.situations.ALL){
                                 items[i].jobContent = jobContentOprObj.currentJobContent ? jobContentOprObj.currentJobContent : '';

+ 0 - 49
web/maintain/ration_repository/js/rationUnits.js

@@ -1,49 +0,0 @@
-/**
- * Created by Zhong on 2017/9/8.
- * 定额列表单位下拉表
- */
-let rationUnits =[
-    'm',
-    'km',
-    'm2',
-    'm3',
-    'kg',
-    't',
-    '10m',
-    '10m2',
-    '10m3',
-    '100m',
-    '100m2',
-    '100m3',
-    '1000m2',
-    '1000m3',
-    'à·km',
-    '总额',
-    '月',
-    '项',
-    '处',
-    '个',
-    '根',
-    '棵',
-    '块',
-    '每一试桩',
-    '桥长米',
-    '公路公里',
-    '株',
-    '组',
-    '座',
-    '元',
-    '工日',
-    '套',
-    '台班',
-    '艘班',
-    'm/处',
-    'm/道',
-    'm/座',
-    'm2/m',
-    'm3/m',
-    'm3/处',
-    '根/米',
-    '亩',
-    'm3/m2'
-];

+ 8 - 8
web/maintain/ration_repository/js/ration_assist.js

@@ -7,14 +7,14 @@ var rationAssistOprObj = {
     ration: null,
     setting: {
         header:[
-            {headerName:"调整名称",headerWidth:200,dataCode:"name", dataType: "String", hAlign: "left"},
-            {headerName:"辅助定额号",headerWidth:120,dataCode:"assistCode", dataType: "String", hAlign: "center"},
-            {headerName:"标准值",headerWidth:100,dataCode:"stdValue", dataType: "String", hAlign: "right"},
-            {headerName:"步距",headerWidth:100,dataCode:"stepValue", dataType: "String", hAlign: "right"},
-            {headerName:"精度",headerWidth:80,dataCode:"decimal",  dataType: "String", hAlign: "right"},
-            {headerName:"进位方式",headerWidth:100,dataCode:"carryBit", dataType: "String", hAlign: "center"},
-            {headerName:"最小值",headerWidth:100,dataCode:"minValue", dataType: "String", hAlign: "right"},
-            {headerName:"最大值",headerWidth:100,dataCode:"maxValue", dataType: "String", hAlign: "right"}
+            {headerName:"调整名称",headerWidth:110,dataCode:"name", dataType: "String", hAlign: "left"},
+            {headerName:"辅助定额号",headerWidth:90,dataCode:"assistCode", dataType: "String", hAlign: "center"},
+            {headerName:"标准值",headerWidth:60,dataCode:"stdValue", dataType: "String", hAlign: "right"},
+            {headerName:"步距",headerWidth:60,dataCode:"stepValue", dataType: "String", hAlign: "right"},
+            {headerName:"精度",headerWidth:60,dataCode:"decimal",  dataType: "String", hAlign: "right"},
+            {headerName:"进位方式",headerWidth:80,dataCode:"carryBit", dataType: "String", hAlign: "center"},
+            {headerName:"最小值",headerWidth:70,dataCode:"minValue", dataType: "String", hAlign: "right"},
+            {headerName:"最大值",headerWidth:70,dataCode:"maxValue", dataType: "String", hAlign: "right"}
         ],
         view:{},
         comboItems: ["四舍五入", "进一"]

+ 13 - 13
web/maintain/ration_repository/js/ration_coe.js

@@ -10,9 +10,9 @@ var rationCoeOprObj = {
     cache: {},
     setting: {
         header:[
-            {headerName:"编号",headerWidth:120,dataCode:"serialNo", dataType: "Number", hAlign: 'left'},
-            {headerName:"名称",headerWidth:400,dataCode:"name", dataType: "String", hAlign: 'left'},
-            {headerName:"内容",headerWidth:300,dataCode:"content", dataType: "String", hAlign: 'left'}
+            {headerName:"编号",headerWidth:50,dataCode:"serialNo", dataType: "Number", hAlign: 'center'},
+            {headerName:"名称",headerWidth:280,dataCode:"name", dataType: "String", hAlign: 'left'},
+            {headerName:"内容",headerWidth:150,dataCode:"content", dataType: "String", hAlign: 'left'}
         ],
         view:{
             comboBox:[],
@@ -32,7 +32,7 @@ var rationCoeOprObj = {
         me.sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStarting);
         me.sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
         //右键
-        me.onContextmenuOpr();
+        //me.onContextmenuOpr();
     },
 
     isDef: function (v) {
@@ -40,18 +40,18 @@ var rationCoeOprObj = {
     },
 
     onContextmenuOpr: function () {
-        let me = rationCoeOprObj;
+        let raCoe = rationCoeOprObj;
         $.contextMenu({
             selector: '#rdSpread',
             build: function($triggerElement, e){
                 //控制允许右键菜单在哪个位置出现
-                let sheet = me.sheet;
+                let sheet = raCoe.sheet;
                 let offset = $("#rdSpread").offset(),
                     x = e.pageX - offset.left,
                     y = e.pageY - offset.top;
                 let target = sheet.hitTest(x, y);
                 if(sheet.getParent().getActiveSheetIndex() === 2 && target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){//在表格内
-                    let currentCache = me.isDef(me.cache["_Coe_" + me.curRation.ID])  ? me.cache["_Coe_" + me.curRation.ID] : [];
+                    let currentCache = raCoe.isDef(raCoe.cache["_Coe_" + raCoe.curRation.ID])  ? raCoe.cache["_Coe_" + raCoe.curRation.ID] : [];
                     sheet.setActiveCell(target.row, target.col);
                     //控制按钮是否可用
                     let upDis = false,
@@ -63,10 +63,10 @@ var rationCoeOprObj = {
                         refDis = true;
                     }
                     else {
-                        if(!me.isDef(currentCache[target.row - 1])){
+                        if(!raCoe.isDef(currentCache[target.row - 1])){
                             upDis = true;
                         }
-                        if(!me.isDef(currentCache[target.row + 1])){
+                        if(!raCoe.isDef(currentCache[target.row + 1])){
                             downDis = true;
                         }
                     }
@@ -74,13 +74,13 @@ var rationCoeOprObj = {
                         callback: function(){},
                         items: {
                             "upMove": {name: "上移", disabled: upDis, icon: "fa-arrow-up", callback: function (key, opt) {
-                                me.upMove(currentCache[target.row], currentCache[target.row - 1], {row: target.row - 1, col: target.col});
+                                raCoe.upMove(currentCache[target.row], currentCache[target.row - 1], {row: target.row - 1, col: target.col});
                             }},
                             "downMove": {name: "下移", disabled: downDis, icon: "fa-arrow-down", callback: function (key, opt) {
-                                me.downMove(currentCache[target.row], currentCache[target.row + 1], {row: target.row + 1, col: target.col});
+                                raCoe.downMove(currentCache[target.row], currentCache[target.row + 1], {row: target.row + 1, col: target.col});
                             }},
                             "ref": {name: "添加到本节其他定额", disabled: refDis, icon: "fa-arrow-left", callback: function (key, opt) {
-                                me.updateSectionRation(rationOprObj.currentRations["_SEC_ID_" + rationOprObj.currentSectionId], currentCache[target.row], function (updateArr) {
+                                raCoe.updateSectionRation(rationOprObj.currentRations["_SEC_ID_" + rationOprObj.currentSectionId], currentCache[target.row], function (updateArr) {
                                     for(let i = 0, len = updateArr.length; i < len; i++){
                                         let ration = updateArr[i];
                                         let rationCoeList = updateArr[i].rationCoeList;
@@ -90,7 +90,7 @@ var rationCoeOprObj = {
                                                 newNo = rationCoeList[j].no + 1;
                                             }
                                         }
-                                        let theCache = me.cache["_Coe_" + ration.ID];
+                                        let theCache = raCoe.cache["_Coe_" + ration.ID];
                                         if(theCache !== undefined && theCache !== null){
                                             let newCoe = {};
                                             for(let attr in currentCache[target.row]){

+ 137 - 39
web/maintain/ration_repository/js/ration_glj.js

@@ -2,6 +2,7 @@
  * Created by Tony on 2017/4/28.
  */
 var rationGLJOprObj = {
+    processDecimal: -6,
     sheet: null,
     currentRationItem: null,
     distTypeTree: null,
@@ -10,13 +11,13 @@ var rationGLJOprObj = {
     cache: {},
     setting: {
         header:[
-            {headerName:"编码",headerWidth:120,dataCode:"code", dataType: "String", formatter: "@"},
-            {headerName:"名称",headerWidth:400,dataCode:"name", dataType: "String"},
-            {headerName:"规格型号",headerWidth:120,dataCode:"specs", dataType: "String"},
-            {headerName:"单位",headerWidth:160,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
-            {headerName:"基价单价",headerWidth:160, dataCode:"basePrice", dataType: "Number", formatter:"0.00",  precision: 2},
-            {headerName:"定额消耗",headerWidth:160, dataCode:"consumeAmt", dataType: "Number", formatter: "0.000", precision: 3},
-            {headerName:"类型",headerWidth:160,dataCode:"gljType", dataType: "String", hAlign: "center", vAlign: "center"}
+            {headerName:"编码",headerWidth:80,dataCode:"code", dataType: "String", formatter: "@"},
+            {headerName:"名称",headerWidth:160,dataCode:"name", dataType: "String"},
+            {headerName:"规格型号",headerWidth:100,dataCode:"specs", dataType: "String"},
+            {headerName:"单位",headerWidth:60,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
+            {headerName:"定额价",headerWidth:80, dataCode:"basePrice", dataType: "Number", formatter:"0.00",  precision: 2},
+            {headerName:"定额消耗",headerWidth:80, dataCode:"consumeAmt", dataType: "Number", formatter: "0.000", precision: 3},
+            {headerName:"类型",headerWidth:70,dataCode:"gljType", dataType: "String", hAlign: "center", vAlign: "center"}
         ],
         view:{
             comboBox:[],
@@ -78,13 +79,17 @@ var rationGLJOprObj = {
         var me = this;
         me.sheet = sheet;
         me.getGljDistType(function () {
-           // me.onContextmenuOpr();
-            sheetCommonObj.initSheet(me.sheet, me.setting, 30);
-            me.bindRationGljDelOpr();
-            me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
-            me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
-            me.sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStarting);
-            me.sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onCellEditEnd);
+            gljSelOprObj.getGljClassTree(pageOprObj.gljLibId, function () {
+                gljSelOprObj.getSelGljItems(pageOprObj.gljLibId, function () {
+                    sheetCommonObj.initSheet(me.sheet, me.setting, 30);
+                    me.onContextmenuOpr();
+                    me.bindRationGljDelOpr();
+                    me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
+                    me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
+                    me.sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStarting);
+                    me.sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onCellEditEnd);
+                });
+            });
         });
     },
     bindRationGljDelOpr: function () {
@@ -250,7 +255,7 @@ var rationGLJOprObj = {
                         }
                     }
                     if (isExist) {
-                        alert("该工料机已存在!");
+                        alert("该人材机已存在!");
                         args.sheet.setValue(args.row, args.col, typeof cacheArr[args.row] !== 'undefined' ? cacheArr[args.row].code + '' : '');
                     }
                     else {
@@ -281,37 +286,120 @@ var rationGLJOprObj = {
             args.sheet.setValue(args.row, args.col, '');
         }
     },
-    onContextmenuOpr: function () {
-        let me = rationGLJOprObj;
+    onContextmenuOpr: function () {//右键菜单
+        let me = this;
+        let raCoe = rationCoeOprObj;
         $.contextMenu({
             selector: '#rdSpread',
-            build: function ($triggerElement, e) {
+            build: function($triggerElement, e){
                 //控制允许右键菜单在哪个位置出现
+                let target = SheetDataHelper.safeRightClickSelection($triggerElement, e, me.sheet.getParent());
                 let sheet = me.sheet;
-                let offset = $triggerElement.offset(),
-                    x = e.pageX - offset.left,
-                    y = e.pageY - offset.top;
-                let target = sheet.hitTest(x, y);
-                if(sheet.parent.getActiveSheetIndex() === 0 && target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){
-                    let delDis = true, cacheSection;
-                    sheet.setActiveCell(target.row, target.col);
-                    if(me.currentRationItem){
-                        let cacheSection = me.cache["_GLJ_" + me.currentRationItem.ID];
-                        if(target.row < cacheSection.length){
-                            delDis = false;
+                let addDis = false, delDis = false;
+                let rationGlj = [];
+                if(me.sheet.getParent().getActiveSheetIndex() === 0 && target.hitTestType === 3){//在表格内&& typeof target.row !== 'undefined' && typeof target.col !== 'undefined'
+                    //rationGlj表
+                    if(typeof target.row !== 'undefined'){
+                        //控制按钮是否可用
+                        sheet.setActiveCell(target.row, target.col);
+                        if(me.currentRationItem){
+                            rationGlj =  me.cache['_GLJ_' + me.currentRationItem.ID];
+                            if(!rationGlj ||target.row >= rationGlj.length){//右键定位在有数据的行,删除键才显示可用
+                                delDis = true;
+                            }
+                            else{//有数据
+                                if(typeof target.col === 'undefined'){//定位不在表格内
+                                    delDis = true;
+                                }
+                            }
                         }
+                        else{
+                            addDis = true;
+                            delDis = true;
+                        }
+                    }
+                    else{
+                        addDis = true;
+                        delDis = true;
                     }
                     return {
-                        callback: function(key, options) {
-                        },
+                        callback: function(){},
                         items: {
-                            "delete": {name: "删除", icon: 'fa-remove', disabled: delDis, callback: function (key, opt) {
-                                cacheSection.splice(target.row, 1);
-                                me.updateRationItem(function () {
-                                    me.sheet.getParent().focus(true);
+                            "add": {name: "添加人材机", disabled: addDis, icon: "fa-plus", callback: function (key, opt) {
+                                //默认radio所有工料机
+                                gljSelOprObj.initRadio();
+                                gljSelOprObj.gljCurTypeId = null;
+                                //默认点击树根节点
+                                if(gljSelOprObj.rootNode){
+                                    gljSelOprObj.treeObj.selectNode(gljSelOprObj.rootNode);
+                                    gljSelTreeOprObj.setting.callback.onClick(null, 'componentTree', gljSelOprObj.rootNode);
+                                }
+                                //弹出窗口
+                                $('#selGlj').modal('show');
+                            }},
+                            "delete": {name: "删除人材机", disabled: delDis, icon: "fa-remove", callback: function (key, opt) {
+                                rationGlj.splice(target.row, 1);
+                                me.updateRationItem(function(){
+                                    me.sheet.getParent().focus();
                                 });
                                 sheetCommonObj.cleanData(me.sheet, me.setting, -1);
                                 me.showGljItems(me.currentRationItem.ID);
+                            }},
+                        }
+                    };
+                }
+                //rationCoe表
+                else if(me.sheet.getParent().getActiveSheetIndex() === 2 && target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){
+                    let currentCache = raCoe.isDef(raCoe.cache["_Coe_" + raCoe.curRation.ID])  ? raCoe.cache["_Coe_" + raCoe.curRation.ID] : [];
+                    sheet.setActiveCell(target.row, target.col);
+                    //控制按钮是否可用
+                    let upDis = false,
+                        downDis = false,
+                        refDis = false;
+                    if(target.row >= currentCache.length){
+                        upDis = true;
+                        downDis = true;
+                        refDis = true;
+                    }
+                    else {
+                        if(!raCoe.isDef(currentCache[target.row - 1])){
+                            upDis = true;
+                        }
+                        if(!raCoe.isDef(currentCache[target.row + 1])){
+                            downDis = true;
+                        }
+                    }
+                    return {
+                        callback: function(){},
+                        items: {
+                            "upMove": {name: "上移", disabled: upDis, icon: "fa-arrow-up", callback: function (key, opt) {
+                                raCoe.upMove(currentCache[target.row], currentCache[target.row - 1], {row: target.row - 1, col: target.col});
+                            }},
+                            "downMove": {name: "下移", disabled: downDis, icon: "fa-arrow-down", callback: function (key, opt) {
+                                raCoe.downMove(currentCache[target.row], currentCache[target.row + 1], {row: target.row + 1, col: target.col});
+                            }},
+                            "ref": {name: "添加到本节其他定额", disabled: refDis, icon: "fa-arrow-left", callback: function (key, opt) {
+                                raCoe.updateSectionRation(rationOprObj.currentRations["_SEC_ID_" + rationOprObj.currentSectionId], currentCache[target.row], function (updateArr) {
+                                    for(let i = 0, len = updateArr.length; i < len; i++){
+                                        let ration = updateArr[i];
+                                        let rationCoeList = updateArr[i].rationCoeList;
+                                        let newNo = 1;
+                                        for(let j = 0, jLen = rationCoeList.length; j < jLen; j++){
+                                            if(rationCoeList[j].no >= newNo){
+                                                newNo = rationCoeList[j].no + 1;
+                                            }
+                                        }
+                                        let theCache = raCoe.cache["_Coe_" + ration.ID];
+                                        if(theCache !== undefined && theCache !== null){
+                                            let newCoe = {};
+                                            for(let attr in currentCache[target.row]){
+                                                newCoe[attr] = currentCache[target.row][attr];
+                                            }
+                                            newCoe.no = newNo;
+                                            theCache.push(newCoe);
+                                        }
+                                    }
+                                });
                             }}
                         }
                     };
@@ -403,7 +491,7 @@ var rationGLJOprObj = {
                             return rst;
                         });
                         $('#alertModalBtn').click();
-                        $('#alertText').text("工料机"+ codes + "不存在,请查找你所需要的工料机,或新增工料机");
+                        $('#alertText').text("人材机"+ codes + "不存在,请查找你所需要的人材机,或新增人材机");
                         $('#alertModalCls').click(function () {
                             me.showGljItems(me.currentRationItem.ID);
                         });
@@ -443,7 +531,7 @@ var rationGLJOprObj = {
             if(price.gljType1.length > 0){
                 let labourPrice = 0;
                 price.gljType1.forEach(function (singlePrc) {
-                    labourPrice += singlePrc;
+                    labourPrice = scMathUtil.roundTo(labourPrice + singlePrc, me.processDecimal);
                 });
                 let roundPrice = scMathUtil.roundTo(labourPrice, -2);
                 rst.labourPrice = roundPrice;
@@ -452,7 +540,7 @@ var rationGLJOprObj = {
             if(price.gljType2.length > 0){
                 let materialPrice = 0;
                 price.gljType2.forEach(function (singlePrc) {
-                    materialPrice += singlePrc;
+                    materialPrice = scMathUtil.roundTo(materialPrice + singlePrc, me.processDecimal);
                 });
                 let roundPrice = scMathUtil.roundTo(materialPrice, -2);
                 rst.materialPrice = roundPrice;
@@ -461,7 +549,7 @@ var rationGLJOprObj = {
             if(price.gljType3.length > 0){
                 let machinePrice = 0;
                 price.gljType3.forEach(function (singlePrc) {
-                    machinePrice += singlePrc;
+                    machinePrice = scMathUtil.roundTo(machinePrice + singlePrc, me.processDecimal);
                 });
                 let roundPrice = scMathUtil.roundTo(machinePrice, -2);
                 rst.machinePrice = roundPrice;
@@ -568,6 +656,16 @@ var rationGLJOprObj = {
         var me = this;
         if (me.cache["_GLJ_" + rationID]) {
             sheetCommonObj.cleanData(me.sheet, me.setting, -1);
+            me.cache["_GLJ_" + rationID].sort(function (a, b) {
+                let rst = 0;
+                if(a.code > b.code){
+                    rst = 1;
+                }
+                else if(a.code < b.code){
+                    rst = -1;
+                }
+                return rst;
+            });
             sheetsOprObj.showData(me.sheet, me.setting, me.cache["_GLJ_" + rationID], me.distTypeTree);
         }
     }

+ 5 - 17
web/maintain/ration_repository/js/repository_glj.js

@@ -2,18 +2,6 @@
  * Created by Tony on 2017/5/5.
  */
 
-$("#drirect-dinge").click(function(){
-    $(this).attr('href', "/rationRepository/ration" + "?repository=" + getQueryString("repository"))
-});
-
-$("#fuzhu").click(function(){
-    $(this).attr('href', "/rationRepository/coeList" + "?repository=" + getQueryString("repository"))
-});
-
-$("#anzhuang").click(function(){
-    $(this).attr('href', "/rationRepository/installation" + "?repository=" + getQueryString("repository"))
-});
-
 var pageOprObj = {
     rationLibName : null,
     rationLibId: null,
@@ -219,15 +207,15 @@ repositoryGljObj = {
                 let focusToCol;
                 function getFocusToCol (me){
                     if(!me.addGljObj[me.setting.header[0].dataCode]){
-                        $('#alertGljTxt').text('编号不能为空,是否取消增加工料机?');
+                        $('#alertGljTxt').text('编号不能为空,是否取消增加人材机?');
                         return 0;
                     }
                     else if(!me.addGljObj[me.setting.header[1].dataCode]){
-                        $('#alertGljTxt').text('名称不能为空,是否取消增加工料机?');
+                        $('#alertGljTxt').text('名称不能为空,是否取消增加人材机?');
                         return 1;
                     }
                     else if(!me.addGljObj[me.setting.header[5].dataCode]){
-                        $('#alertGljTxt').text('类型不能为空,是否取消增加工料机?');
+                        $('#alertGljTxt').text('类型不能为空,是否取消增加人材机?');
                         return 5;
                     }
                     else {
@@ -426,14 +414,14 @@ repositoryGljObj = {
                 if(refGljCodes.length > 0){
                     let alertText;
                     if(refGljCodes.length > 3){
-                        alertText = "编号: " + refGljCodes[0]+" 、" + refGljCodes[1] + " 、" + refGljCodes[2] + "...等工料机已有定额引用,删除失败!";
+                        alertText = "编号: " + refGljCodes[0]+" 、" + refGljCodes[1] + " 、" + refGljCodes[2] + "...等人材机已有定额引用,删除失败!";
                     }
                     else {
                         let alertCode = " ";
                         for(let i=0; i< refGljCodes.length; i++){
                             alertCode += refGljCodes[i] + " 、";
                         }
-                        alertText = "编号:" + alertCode + "工料机已有定额引用,删除失败!"
+                        alertText = "编号:" + alertCode + "人材机已有定额引用,删除失败!"
                     }
                     $('#alertText').text(alertText);
                     $('#codeAlertBtn').click();

+ 22 - 3
web/maintain/ration_repository/js/section_tree.js

@@ -12,7 +12,7 @@ let pageOprObj = {
                 me.rationLibName = rstData[0].dispName;
                 me.gljLibId = rstData[0].gljLib;
                 if(!me.gljLibId || typeof me.gljLibId === 'undefined' || me.gljLibId == -1){
-                    alert("没有引用工料机库!");
+                    alert("没有引用人材机库!");
                     window.location.href = "/rationRepository/main";
                 }
                 if (me.rationLibName) {
@@ -87,6 +87,7 @@ let sectionTreeObj = {
         },
         options: {
             tabStripVisible:  false,
+            allowContextMenu: false,
             allowCopyPasteExcelStyle : false,
             allowExtendPasteRange: false,
             allowUserDragDrop : false,
@@ -269,8 +270,11 @@ let sectionTreeObj = {
         me.insertBtn.click(function () {
             me.insert();
         });
+        $('#delConfirm').click(function () {
+            me.remove(me.tree.selected);
+        });
         me.removeBtn.click(function () {
-           me.remove(me.tree.selected);
+            $('#delAlert').modal('show');
         });
         me.upLevelBtn.click(function () {
             me.upLevel(me.tree.selected);
@@ -287,7 +291,7 @@ let sectionTreeObj = {
     },
     
     insert: function () {
-        let me = this;
+        let me = sectionTreeObj;
         me.insertBtn.addClass('disabled');
         let postData = [];
         CommonAjax.post('api/getNewRationTreeID', {}, function (newID) {
@@ -314,6 +318,7 @@ let sectionTreeObj = {
                     //fresh tools
                     me.initTools(me.tree.selected);
                     me.workBook.focus();
+                    me.initSelection(me.tree.selected);
                 });
             }
         });
@@ -349,13 +354,21 @@ let sectionTreeObj = {
         if(postData.length > 0){
             //ajax
             me.sectionTreeAjax(postData, function (rstData) {
+                $('#delAlert').modal('hide');
+                me.removeRationsCodes(rationOprObj.currentRations["_SEC_ID_" + selected.data.ID]);
                 me.controller.delete();
                 me.refreshBtn(me.tree.selected);
                 me.initTools(me.tree.selected);
+                me.initSelection(me.tree.selected);
                 me.workBook.focus();
             });
         }
     },
+    removeRationsCodes: function (rations) {
+        for(let ration of rations){
+            rationOprObj.rationsCodes.splice(rationOprObj.rationsCodes.indexOf(ration.code), 1);
+        }
+    },
     getSameDepthNodes: function(){
         let rst = [];
         let sel = this.sheet.getSelections()[0];
@@ -552,8 +565,14 @@ let sectionTreeObj = {
     initSelection: function (node) {
         let me = this;
         if(!me.isDef(node)){
+            sheetCommonObj.cleanSheet(rationOprObj.workBook.getActiveSheet(), rationOprObj.setting, -1);
+            sheetCommonObj.cleanSheet(rationGLJOprObj.sheet, rationGLJOprObj.setting, -1);
+            sheetCommonObj.cleanSheet(rationAssistOprObj.sheet, rationAssistOprObj.setting, -1);
+            sheetCommonObj.cleanSheet(rationCoeOprObj.sheet, rationCoeOprObj.setting, -1);
+            sheetCommonObj.cleanSheet(rationInstObj.sheet, rationInstObj.setting, -1);
             return;
         }
+        me.workBook.getActiveSheet().setActiveCell(node.serialNo(), 0);
         me.initTools(node);
         me.refreshBtn(node);
         if(!me.isDef(node.children) || node.children.length === 0){

+ 53 - 0
web/maintain/ration_repository/js/sheetsOpr.js

@@ -80,6 +80,59 @@ let sheetsOprObj = {
         sheet.resumePaint();
         //me.shieldAllCells(sheet);
     },
+    showDataForGljSel: function(sheet, setting, data, distTypeTree) {
+        var me = this, ch = GC.Spread.Sheets.SheetArea.viewport;
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        let checkBoxType = new GC.Spread.Sheets.CellTypes.CheckBox();
+        if(typeof setting.owner !== 'undefined' && setting.owner === 'gljComponent'){
+            sheet.setRowCount(data.length + 5);
+        }
+        else{
+            sheet.setRowCount(typeof repositoryGljObj !== 'undefined' && repositoryGljObj.currentOprParent === 1 ? data.length : data.length + 10);
+        }
+        for (var col = 0; col < setting.header.length; col++) {
+            var hAlign = "left", vAlign = "center";
+            if (setting.header[col].hAlign) {
+                hAlign = setting.header[col].hAlign;
+            } else if (setting.header[col].dataType !== "String"){
+                hAlign = "right";
+            }
+            vAlign = setting.header[col].vAlign?setting.header[col].vAlign:vAlign;
+            me.setAreaAlign(sheet.getRange(-1, col, -1, 1), hAlign, vAlign);
+            if (setting.header[col].formatter) {
+                sheet.setFormatter(-1, col, setting.header[col].formatter, GC.Spread.Sheets.SheetArea.viewport);
+            }
+            for (var row = 0; row < data.length; row++) {
+                if(setting.header[col].dataCode === 'gljType' && data[row].gljType){
+                    let distTypeVal =  distTypeTree.distTypes[distTypeTree.prefix + data[row].gljType].data.fullName;
+                    sheet.setValue(row, col, distTypeVal, ch);
+                }
+                else {
+                    sheet.setValue(row, col, data[row][setting.header[col].dataCode], ch);
+                    sheet.setTag(row, 0, data[row].ID, ch);
+                }
+                //复选框
+                if(setting.header[col].dataCode === 'isComplementary'){
+                    sheet.setCellType(row, col, checkBoxType);
+                    sheet.getCell(row, col).value(1);
+                }
+                //新增组成物表,选择复选框
+                if(setting.header[col].dataCode === 'select'){
+                    sheet.setCellType(row, col, checkBoxType)
+                    if(data[row].isChecked === true){
+                        sheet.getCell(row, col).value(1);
+                    }
+                }
+            }
+            for(let i = data.length; i < sheet.getRowCount(); i++){
+                sheet.setCellType(i, 6, null);
+            }
+        }
+        sheet.resumeEvent();
+        sheet.resumePaint();
+        //me.shieldAllCells(sheet);
+    },
     combineRowData: function(sheet, setting, row, repositoryGljObj) {
         let me = this;
         var rst = {};

+ 4 - 4
web/maintain/ration_repository/main.html

@@ -90,7 +90,7 @@
                             <select id="compilationSels" class="form-control"></select>
                         </div>
                         <div class="form-group">
-                            <label>工料机库</label>
+                            <label>人材机库</label>
                             <select id="gljLibSels" class="form-control"></select>
                         </div>
                     </form>
@@ -145,10 +145,8 @@
                     <h5 class="text-danger">删除后无法恢复,确认是否删除?</h5>
                 </div>
                 <div class="modal-footer">
-                    <!--<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a href="" id="deleteLib" class="btn btn-danger">删除</a>-->
+                    <a id="deleteA" href="javascript: void(0);" class="btn btn-danger">确认</a>
                     <button id="delCancelBtn" type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a id="deleteA" href="javascript: void(0);" class="btn btn-danger">删除</a>
                 </div>
             </div>
         </div>
@@ -214,7 +212,9 @@
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/tether/tether.min.js"></script>
     <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/public/web/PerfectLoad.js"></script>
     <script src="/web/maintain/ration_repository/js/global.js"></script>
+    <script src="/public/web/common_ajax.js"></script>
     <!-- zTree -->
     <script type="text/javascript" src="/public/web/date_util.js"></script>
   	<script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>

+ 7 - 2
web/maintain/report/js/cfg_const.js

@@ -74,6 +74,7 @@ let setting = {
     },
     callback:{
         onClick: zTreeOprObj.onClick,
+        beforeEditName: zTreeOprObj.beforeEditName,
         beforeRename: zTreeOprObj.beforeRename,
         beforeRemove: zTreeOprObj.onBeforeRemove,
         onRemove: zTreeOprObj.onRemove,
@@ -305,7 +306,8 @@ let rptDataInfoSetting = {
         expandSpeed: "",
         selectedMulti: false,
         addHoverDom: dataInfoMapTreeOprObj.addHoverDom,
-        removeHoverDom: dataInfoMapTreeOprObj.removeHoverDom
+        removeHoverDom: dataInfoMapTreeOprObj.removeHoverDom,
+        addDiyDom: dataInfoMapTreeOprObj.addDiyDom
     },
     edit: {
         enable: true,
@@ -432,7 +434,9 @@ let preHandleSetting = {
     view: {
         showIcon: true,
         expandSpeed: "",
-        selectedMulti: false
+        selectedMulti: false,
+        addHoverDom: preHandleObj.addHoverDom,
+        removeHoverDom: preHandleObj.removeHoverDom
     },
     edit: {
         enable: true,
@@ -462,6 +466,7 @@ let preHandleSetting = {
     callback:{
         onClick: preHandleObj.onPreHandleClick,
         beforeRemove: preHandleObj.onBeforeRemove,
+        beforeDrag: preHandleObj.onBeforeDrag,
         beforeDrop: preHandleObj.onBeforeDrop
     }
 };

+ 1 - 1
web/maintain/report/js/rpt_tpl_band.js

@@ -9,7 +9,7 @@ let bandTreeOprObj = {
         let me = bandTreeOprObj;
         let bandList = rptTpl[JV.NODE_BAND_COLLECTION];
         me.buildTreeData(bandList);
-        let rootNode = {Name: "布局框", isParent: true};
+        let rootNode = {Name: "布局框(勾选表示:此布局框是报表外框,受报表边框属性影响)", isParent: true};
         rootNode[JV.BAND_PROP_SUB_BANDS] = bandList;
         // me.treeObj = $.fn.zTree.init($("#band_tree_reversed"), bandSetting, bandList);
         me.treeObj = $.fn.zTree.init($("#band_tree_reversed"), bandSetting, rootNode);

File diff suppressed because it is too large
+ 1 - 0
web/maintain/report/js/rpt_tpl_calculation.js


+ 231 - 78
web/maintain/report/js/rpt_tpl_data_map.js

@@ -6,7 +6,6 @@
 
 let dataInfoMapTreeOprObj = {
     treeObj : null,
-    bandTreeObj: null,
     selectedTreeObj: null,
     currentNode: null,
     dataTypeDef: ['string', 'int32', 'int64', 'double', 'currency', 'date', 'image'],
@@ -25,8 +24,6 @@ let dataInfoMapTreeOprObj = {
     iniDataMap: function () {
         let me = this, bandList = bandTreeOprObj.copyBandList(false);
         if (bandList) {
-            me.bandTreeObj = $.fn.zTree.init($("#band_tree2_reversed"), bandSetting2, bandList);
-            me.bandTreeObj.expandAll(true);
             let selectedFieldList = fieldMapTreeOprObj.copySelectedFieldList();
             if (me.selectedTreeObj) {
                 let nodes = me.selectedTreeObj.getNodes();
@@ -35,9 +32,49 @@ let dataInfoMapTreeOprObj = {
                 }
                 me.selectedTreeObj.refresh();
             }
-            // me.selectedTreeObj = $.fn.zTree.init(document.getElementById("tpl_data_selected_field_map_reversed"), selectedFieldMapSetting, selectedFieldList);
             me.selectedTreeObj = $.fn.zTree.init($("#tpl_data_selected_field_map_reversed"), selectedFieldMapSetting, selectedFieldList);
             me.selectedTreeObj.expandAll(true);
+            me.refreshBandSelection();
+        }
+    },
+    refreshBandSelection: function () {
+        let me = dataInfoMapTreeOprObj;
+        let tplNodes = me.treeObj.getNodes();
+        let bandList = bandTreeOprObj.copyBandList(false);
+        let currentIdx = 0;
+
+        let private_addBandOption = function(prefix, bandObj, selector, nodeBandName) {
+            selector.append("<option value='" + bandObj[JV.PROP_NAME] + "'>" + prefix + bandObj[JV.PROP_NAME] + "</option>");
+            currentIdx++;
+            if (nodeBandName === bandObj[JV.PROP_NAME]) {
+                selector[0].selectedIndex = currentIdx;
+            }
+            //selector.selectedIndex
+            if (bandObj.items && bandObj.items.length > 0) {
+                for (let subItem of bandObj.items) {
+                    private_addBandOption(prefix + "&nbsp&nbsp", subItem, selector, nodeBandName);
+                }
+            }
+        };
+        let private_refresh_node_selection = function (treeNode) {
+            if (me.checkIfCanAddBand(treeNode)) {
+                //准备加selection
+                let selectObj = $("#diySelect_" +treeNode.tId);
+                selectObj.empty();
+                selectObj.append("<option value='none'>请选择</option>");
+                currentIdx = 0;
+                for (let band of bandList) {
+                    private_addBandOption("", band, selectObj, treeNode[JV.PROP_BAND_NAME]);
+                }
+            }
+            if (treeNode.items && treeNode.items.length > 0) {
+                for (let subItem of treeNode.items) {
+                    private_refresh_node_selection(subItem);
+                }
+            }
+        };
+        for (let i = 0; i < tplNodes.length; i++) {
+            private_refresh_node_selection(tplNodes[i]);
         }
     },
     buildTreeData: function (rptTpl) {
@@ -91,6 +128,7 @@ let dataInfoMapTreeOprObj = {
         me.private_build_column_data(rootColumnNode, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_COLUMN]);
         me.private_build_sum_data(rootChapterSumNode, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_SEG_SUM], rptTpl);
         me.private_build_sum_data(rootPageSumNode, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_PAGE_SUM], rptTpl);
+        me.private_build_grp_data(rootGroupSumNode, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP], rptTpl);
         return rst;
     },
     buildBillData: function(rptTpl) {
@@ -104,6 +142,56 @@ let dataInfoMapTreeOprObj = {
 
         return rst;
     },
+    private_build_grp_data: function (grpNode, grpData, rptTpl) {
+        let me = this;
+        grpNode.items = [];
+        grpNode.sum_field_s = [];
+        if (grpData.sum_field_s && grpData.sum_field_s.length > 0) {
+            for (let sumF of grpData.sum_field_s) {
+                let sf = {};
+                sf[JV.PROP_FIELD_ID] = sumF[JV.PROP_FIELD_ID];
+                sf[JV.PROP_SUM_KEY] = sumF[JV.PROP_SUM_KEY];
+                grpNode.sum_field_s.push(sf);
+            }
+        }
+        let grp_fields = {Name: "分组判断指标集", items: [], Title: "", isParent: true};
+        let grp_lines = {Name: "分组行", items: [], Title: "", isParent: true};
+        grpNode.items.push(grp_fields);
+        grpNode.items.push(grp_lines);
+        if (grpData[JV.PROP_GROUP_FIELDS]) {
+            for (let grpItem of grpData[JV.PROP_GROUP_FIELDS]) {
+                grp_fields.items.push(me.private_build_field_node(grpItem, rptTpl));
+            }
+        }
+        if (grpData[JV.PROP_GROUP_LINES] && grpData[JV.PROP_GROUP_LINES].length > 0) {
+            for (let grpline of grpData[JV.PROP_GROUP_LINES]) {
+                let gl = {Name: "行", items:[], isParent: true}, sumKeys = {Name:"分组字段集", items:[], Title: "", isParent: true}, texts = {Name:"文本集", items:[], Title: "", isParent: true};
+                gl.items.push(sumKeys);
+                gl.items.push(texts);
+                grp_lines.items.push(gl);
+                if (grpline[JV.PROP_GROUP_SUM_KEYS]) {
+                    for (let fieldItem of grpline[JV.PROP_GROUP_SUM_KEYS]) {
+                        let item = me.private_build_field_node(fieldItem, rptTpl);
+                        item[JV.PROP_SUM_KEY] = fieldItem[JV.PROP_SUM_KEY];
+                        item[JV.PROP_NAME] = fieldItem[JV.PROP_SUM_KEY];
+                        for (let gsi of grpNode.sum_field_s) {
+                            if (gsi[JV.PROP_SUM_KEY] === item[JV.PROP_SUM_KEY]) {
+                                item[JV.PROP_FIELD_ID] = gsi[JV.PROP_FIELD_ID];
+                                break;
+                            }
+                        }
+                        sumKeys.items.push(item);
+                    }
+                }
+                if (grpline[JV.PROP_TEXTS]) {
+                    for (let txt of grpline[JV.PROP_TEXTS]) {
+                        texts.items.push(me.private_build_text_node(txt));
+                    }
+                }
+            }
+        }
+        //then group lines
+    },
     private_build_sum_data: function(sumNode, sumData, rptTpl) {
         let me = this;
         sumNode.items = [];
@@ -126,7 +214,8 @@ let dataInfoMapTreeOprObj = {
         let me = this;
         if (columnData[JV.PROP_TEXTS] && columnData[JV.PROP_TEXTS].length > 0) {
             columnNode.items = [];
-            columnNode.Title = "所在区域: " + columnNode[JV.PROP_BAND_NAME];
+            // columnNode.Title = "区域: " + columnNode[JV.PROP_BAND_NAME];
+            columnNode.Title = "";
             for (let txt of columnData[JV.PROP_TEXTS]) {
                 columnNode.items.push(me.private_build_text_node(txt));
             }
@@ -152,7 +241,8 @@ let dataInfoMapTreeOprObj = {
         discreteNode.items = [];
         for (let i = 0; i < discreteData.length; i++) {
             let dtl = discreteData[i];
-            let item = {"Name": "子项(所在区域:" + dtl[JV.PROP_BAND_NAME] + ")", "items":[], Title: ""};
+            // let item = {"Name": "子项(区域:" + dtl[JV.PROP_BAND_NAME] + ")", "items":[], Title: ""};
+            let item = {"Name": "子项", "items":[], Title: ""};
             item[JV.PROP_BAND_NAME] = dtl[JV.PROP_BAND_NAME];
             let discreteFieldsNode = {"Name": "离散字段集", "items": [], "isParent": true, Title: ""};
             let discreteTextsNode = {"Name": "离散文本集", "items": [], "isParent": true, Title: ""};
@@ -238,16 +328,20 @@ let dataInfoMapTreeOprObj = {
         if (source[JV.PROP_FORMAT]) destination[JV.PROP_FORMAT] = source[JV.PROP_FORMAT];
         if (source[JV.PROP_IS_AUTO_HEIGHT]) destination[JV.PROP_IS_AUTO_HEIGHT] = true
         else destination[JV.PROP_IS_AUTO_HEIGHT] = false;
-        destination[JV.PROP_AREA] = {};
-        me.private_copy_area(source[JV.PROP_AREA], destination[JV.PROP_AREA]);
+        if (source[JV.PROP_AREA]) {
+            destination[JV.PROP_AREA] = {};
+            me.private_copy_area(source[JV.PROP_AREA], destination[JV.PROP_AREA]);
+        }
     },
     private_copy_area: function (orgArea, destArea) {
-        destArea[JV.PROP_LEFT] = orgArea[[JV.PROP_LEFT]];
-        destArea[JV.PROP_RIGHT] = orgArea[[JV.PROP_RIGHT]];
-        destArea[JV.PROP_TOP] = orgArea[[JV.PROP_TOP]];
-        destArea[JV.PROP_BOTTOM] = orgArea[[JV.PROP_BOTTOM]];
-        destArea[JV.PROP_H_CALCULATION] = orgArea[[JV.PROP_H_CALCULATION]];
-        destArea[JV.PROP_V_CALCULATION] = orgArea[[JV.PROP_V_CALCULATION]];
+        if (orgArea) {
+            destArea[JV.PROP_LEFT] = orgArea[[JV.PROP_LEFT]];
+            destArea[JV.PROP_RIGHT] = orgArea[[JV.PROP_RIGHT]];
+            destArea[JV.PROP_TOP] = orgArea[[JV.PROP_TOP]];
+            destArea[JV.PROP_BOTTOM] = orgArea[[JV.PROP_BOTTOM]];
+            destArea[JV.PROP_H_CALCULATION] = orgArea[[JV.PROP_H_CALCULATION]];
+            destArea[JV.PROP_V_CALCULATION] = orgArea[[JV.PROP_V_CALCULATION]];
+        }
     },
     private_build_param_node: function (param, rptTpl) {
         let me = this, rst = null;
@@ -307,10 +401,11 @@ let dataInfoMapTreeOprObj = {
         me.private_copy_area(source[JV.PROP_AREA], destination[JV.PROP_AREA]);
     },
 
-    private_get_dummy_text_node: function() {
+    private_get_dummy_text_node: function(treeNode) {
         let me = this, rst = {};
         rst[JV.PROP_NAME] = "文本";
         rst[JV.PROP_LABEL] = "文本";
+        rst.Title = "";
         rst[JV.PROP_FONT] = "Content";
         rst[JV.PROP_CONTROL] = "Default";
         rst[JV.PROP_STYLE] = "Default_None";
@@ -321,10 +416,17 @@ let dataInfoMapTreeOprObj = {
         rst[JV.PROP_AREA][JV.PROP_BOTTOM] = 100;
         rst[JV.PROP_AREA][JV.PROP_H_CALCULATION] = JV.CAL_TYPE[0];
         rst[JV.PROP_AREA][JV.PROP_V_CALCULATION] = JV.CAL_TYPE[0];
+        if (treeNode) {
+            if (treeNode[JV.PROP_NAME].indexOf("_列") >= 0) {
+                rst[JV.PROP_FONT] = "HeaderColumn";
+                rst[JV.PROP_CONTROL] = "Column";
+                rst[JV.PROP_STYLE] = "Default_Normal";
+            }
+        }
         return rst;
     },
 
-    private_setup_dummy_field_node: function(node) {
+    private_setup_dummy_field_node: function(node, targetNode) {
         if (!node[JV.PROP_PARAM_ID]) {
             node[JV.PROP_FIELD_ID] = node[JV.PROP_ID];
         }
@@ -338,63 +440,19 @@ let dataInfoMapTreeOprObj = {
         node[JV.PROP_AREA][JV.PROP_BOTTOM] = 100;
         node[JV.PROP_AREA][JV.PROP_H_CALCULATION] = JV.CAL_TYPE[0];
         node[JV.PROP_AREA][JV.PROP_V_CALCULATION] = JV.CAL_TYPE[0];
+        if (targetNode[JV.PROP_NAME].indexOf("_数据") >= 0) {
+            node[JV.PROP_FONT] = "Content";
+            node[JV.PROP_CONTROL] = "Content_Left";
+            node[JV.PROP_STYLE] = "Default_Normal";
+        }
     },
 
     checkIfShouldHaveBand: function(treeNode) {
         return treeNode.hasOwnProperty(JV.PROP_BAND_NAME);
     },
     onTabDataClick: function (event,treeId,treeNode) {
-        let me = dataInfoMapTreeOprObj, matchedBandNode = null;
-        let bandChked = false;
+        let me = dataInfoMapTreeOprObj;
         me.currentNode = treeNode;
-        function checkBandNode(bNode, bandName) {
-            if (bNode[JV.PROP_NAME] === bandName) {
-                bandChked = true;
-                matchedBandNode = bNode;
-            } else if (bNode.items){
-                for (let subNode of bNode.items) {
-                    checkBandNode(subNode, bandName);
-                    if (bandChked) {
-                        break;
-                    }
-                }
-            }
-        }
-        let nodes = me.bandTreeObj.getNodes();
-        function setDisabledBandSelect(disabled) {
-            for (let node of nodes) {
-                me.bandTreeObj.setChkDisabled(node, disabled, true, true);
-            }
-        }
-        function cleanBandSelect(parentNode) {
-            me.bandTreeObj.checkNode(parentNode, false, false, false);
-            if (parentNode.items && parentNode.items.length > 0) {
-                for (let subNode of parentNode.items) {
-                    cleanBandSelect(subNode);
-                }
-            }
-        }
-        if (treeNode[JV.PROP_BAND_NAME]) {
-            for (let node of nodes) {
-                checkBandNode(node, treeNode[JV.PROP_BAND_NAME]);
-                if (bandChked) {
-                    break;
-                }
-            }
-        }
-        if (bandChked) {
-            setDisabledBandSelect(false);
-            me.bandTreeObj.checkNode(matchedBandNode, true, true);
-        } else {
-            if (me.checkIfShouldHaveBand(treeNode)) {
-                setDisabledBandSelect(false);
-                for (let node of nodes) {
-                    cleanBandSelect(node);
-                }
-            } else {
-                setDisabledBandSelect(true);
-            }
-        }
         //检测是否为field/param/text对象
         rpt_tpl_cfg_helper.checkAndSetSelectedNodeCfg(treeNode);
     },
@@ -404,9 +462,11 @@ let dataInfoMapTreeOprObj = {
             // alert("change band from: " + me.currentNode[JV.PROP_BAND_NAME] + " to : " + treeNode[JV.PROP_NAME]);
             me.currentNode[JV.PROP_BAND_NAME] = treeNode[JV.PROP_NAME];
             if (me.currentNode[JV.PROP_NAME].indexOf("子项") >= 0) {
-                me.currentNode[JV.PROP_NAME] = "子项(所在区域:" + treeNode[JV.PROP_NAME] + ")";
+                // me.currentNode[JV.PROP_NAME] = "子项(区域:" + treeNode[JV.PROP_NAME] + ")";
+                me.currentNode[JV.PROP_NAME] = "子项";
             } else {
-                me.currentNode.Title = "所在区域:" + treeNode[JV.PROP_NAME];
+                // me.currentNode.Title = "区域:" + treeNode[JV.PROP_NAME];
+                me.currentNode.Title = "";
             }
             me.treeObj.updateNode(me.currentNode);
         }
@@ -447,7 +507,8 @@ let dataInfoMapTreeOprObj = {
         let rst = false;
         if (targetNode.Name === JV.NODE_FLOW_CONTENT || targetNode.Name === JV.NODE_BILL_CONTENT || targetNode.Name === JV.NODE_CROSS_CONTENT
             || targetNode.Name === JV.NODE_CROSS_ROW || targetNode.Name === JV.NODE_CROSS_COL
-            || targetNode.Name === "离散字段集" || targetNode.Name === "统计指标集") {
+            || targetNode.Name === "离散字段集" || targetNode.Name === "统计指标集" || targetNode.Name === "分组判断指标集"
+            || targetNode.Name === "分组字段集") {
             rst = true;
         }
         return rst;
@@ -455,7 +516,10 @@ let dataInfoMapTreeOprObj = {
     onDrop: function(event, treeId, treeNodes, targetNode, moveType) {
         let me = dataInfoMapTreeOprObj;
         for (let node of treeNodes) {
-            me.private_setup_dummy_field_node(node);
+            me.private_setup_dummy_field_node(node, targetNode);
+            if (targetNode[JV.PROP_NAME] === "分组判断指标集") {
+                delete node[JV.PROP_AREA];
+            }
         }
     },
     onRemove: function (e, treeId, treeNode) {
@@ -473,20 +537,51 @@ let dataInfoMapTreeOprObj = {
         }
         return rst;
     },
+    checkIfCanAddBand: function (treeNode) {
+        let rst = false;
+        if (typeof(treeNode[JV.PROP_NAME]) === "string") {
+            if (treeNode[JV.PROP_NAME].indexOf(JV.NODE_FLOW_CONTENT) === 0 ||
+                treeNode[JV.PROP_NAME].indexOf(JV.NODE_FLOW_COLUMN) === 0 ||
+                treeNode[JV.PROP_NAME].indexOf(JV.NODE_FLOW_PAGE_SUM) === 0 ||
+                treeNode[JV.PROP_NAME].indexOf(JV.NODE_FLOW_SEG_SUM) === 0 ||
+                treeNode[JV.PROP_NAME].indexOf(JV.NODE_BILL_CONTENT) === 0 ||
+                treeNode[JV.PROP_NAME].indexOf("子项") === 0) {
+                rst = true;
+            }
+        }
+        return rst;
+    },
+    bandSelectChange: function(dom, treeNodeId) {
+        let me = dataInfoMapTreeOprObj, node = me.treeObj.getNodeByTId(treeNodeId);
+        if (dom.selectedIndex > 0) {
+            node[JV.PROP_BAND_NAME] = dom.value;
+        } else {
+            node[JV.PROP_BAND_NAME] = "";
+        }
+    },
+    addDiyDom: function (treeId, treeNode) {
+        let me = dataInfoMapTreeOprObj, aObj = $("#" + treeNode.tId + IDMark_A);
+        //加band selection
+        if (me.checkIfCanAddBand(treeNode)) {
+            //准备加selection
+            let addBandStr = "<select class='selDemo' id='diySelect_" +treeNode.tId+ "' onchange='dataInfoMapTreeOprObj.bandSelectChange(this, \"" + treeNode.tId + "\")'></select>";
+            aObj.after(addBandStr);
+        }
+    },
     addHoverDom: function(treeId, treeNode) {
-        let me = dataInfoMapTreeOprObj, sObj = $("#" + treeNode.tId + "_span");
-        if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length > 0) {
+        let me = dataInfoMapTreeOprObj, sObj = $("#" + treeNode.tId + IDMark_Span);
+        if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length > 0 || $("#selInput_"+treeNode.tId).length > 0) {
             return;
-        } else if (treeNode[JV.PROP_NAME] === JV.NODE_DISCRETE_INFO || me.checkIfCanAddTxt(treeNode)) {
+        } else if (treeNode[JV.PROP_NAME] === JV.NODE_DISCRETE_INFO || treeNode[JV.PROP_NAME] === "分组行" || me.checkIfCanAddTxt(treeNode)) {
             let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增' onfocus='this.blur();'></span>";
             sObj.after(addStr);
             let btn = $("#addBtn_"+treeNode.tId);
             if (treeNode[JV.PROP_NAME] === JV.NODE_DISCRETE_INFO) {
                 btn.bind("click", function(){
                     let node = {};
-                    node[JV.PROP_NAME] = "子项(所在区域:" + me.bandTreeObj.getNodes()[0][JV.PROP_NAME] + ")";
-                    node[JV.PROP_BAND_NAME] = me.bandTreeObj.getNodes()[0][JV.PROP_NAME];
-                    node.items = [];
+                    node[JV.PROP_NAME] = "子项";
+                    node[JV.PROP_BAND_NAME] = "";
+                        node.items = [];
                     let fields = {"Name": "离散字段集", "items": [], "isParent": true};
                     let texts = {"Name": "离散文本集", "items": [], "isParent": true};
                     node.items.push(fields);
@@ -494,11 +589,26 @@ let dataInfoMapTreeOprObj = {
                     let newNodes = [];
                     newNodes.push(node);
                     me.treeObj.addNodes(treeNode, -1, newNodes, true);
+                    me.refreshBandSelection();
+                });
+            } else if (treeNode[JV.PROP_NAME] === "分组行") {
+                btn.bind("click", function(){
+                    let node = {};
+                    node[JV.PROP_NAME] = "行";
+                    node.items = [];
+                    let fields = {"Name": "分组字段集", "items": [], "isParent": true};
+                    let texts = {"Name": "文本集", "items": [], "isParent": true};
+                    node.items.push(fields);
+                    node.items.push(texts);
+                    let newNodes = [];
+                    newNodes.push(node);
+                    me.treeObj.addNodes(treeNode, -1, newNodes, true);
+                    me.refreshBandSelection();
                 });
             } else {
                 //text
                 btn.bind("click", function(){
-                    let node = me.private_get_dummy_text_node();
+                    let node = me.private_get_dummy_text_node(treeNode);
                     let newNodes = [];
                     newNodes.push(node);
                     me.treeObj.addNodes(treeNode, -1, newNodes, true);
@@ -547,7 +657,8 @@ let dataInfoMapTreeOprObj = {
                     let newSegSum = me.private_extract_sum_info(node);
                     rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_PAGE_SUM] = newSegSum;
                 } else if (node[JV.PROP_NAME] === JV.NODE_FLOW_GROUP) {
-                    //
+                    let grpInfo = me.private_extract_grp_info(node);
+                    rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP] = grpInfo;
                 }
             }
         }
@@ -574,6 +685,48 @@ let dataInfoMapTreeOprObj = {
             }
         }
     },
+    private_extract_grp_info: function(grpNode) {
+        let me = dataInfoMapTreeOprObj, rst = {};
+        rst[JV.PROP_GROUP_FIELDS] = [];
+        rst[JV.PROP_SUM_FIELDS] = [];
+        rst[JV.PROP_GROUP_LINES] = [];
+        let sumFieldObj = {};
+        for (let subNode of grpNode.items) {
+            if (subNode[JV.PROP_NAME] === "分组判断指标集") {
+                for (let sumField of subNode.items) {
+                    let item = {FieldID: sumField[JV.PROP_FIELD_ID]};
+                    rst[JV.PROP_GROUP_FIELDS].push(item);
+                }
+            } else if (subNode[JV.PROP_NAME] === "分组行") {
+                for (let line of subNode.items) {
+                    let grpLine = {"SumKey_S": [], "text_s":[]};
+                    rst[JV.PROP_GROUP_LINES].push(grpLine);
+                    for (let dtl of line.items) {
+                        if (dtl[JV.PROP_NAME] === "分组字段集") {
+                            for (let gf of dtl.items) {
+                                if (!sumFieldObj[gf[JV.PROP_NAME]]) {
+                                    sumFieldObj[gf[JV.PROP_NAME]] = "Y";
+                                    rst[JV.PROP_SUM_FIELDS].push({"FieldID": gf[JV.PROP_FIELD_ID], "SumKey": gf[JV.PROP_NAME]});
+                                }
+                                let item = {};
+                                // rst[JV.PROP_SUM_FIELDS].push(item);
+                                me.private_copy_field_properties(gf, item);
+                                item[JV.PROP_SUM_KEY] = gf[JV.PROP_NAME];
+                                grpLine[JV.PROP_GROUP_SUM_KEYS].push(item);
+                            }
+                        } else if (dtl[JV.PROP_NAME] === "文本集") {
+                            for (let txt of dtl.items) {
+                                let item = {};
+                                grpLine[JV.PROP_TEXTS].push(item);
+                                me.private_copy_text_properties(txt, item);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    },
     private_extract_sum_info: function(sumNode) {
         let me = dataInfoMapTreeOprObj, rst = {};
         rst[JV.PROP_BAND_NAME] = sumNode[JV.PROP_BAND_NAME];

+ 21 - 21
web/maintain/report/js/rpt_tpl_field_map.js

@@ -68,26 +68,26 @@ let fieldMapTreeOprObj = {
         me.currentNode = treeNode;
         //then refresh the field map tab properties
         //数据类型
-        switch (me.dataTypeDef.indexOf(treeNode[JV.PROP_DATA_TYPE])) {
-            case 0:
-                $("#fieldDataTypeSelection").get(0).selectedIndex = 0;
-                break;
-            case 1:
-            case 2:
-            case 3:
-            case 4:
-                $("#fieldDataTypeSelection").get(0).selectedIndex = 1;
-                break;
-            case 5:
-                $("#fieldDataTypeSelection").get(0).selectedIndex = 2;
-                break;
-            case 6:
-                $("#fieldDataTypeSelection").get(0).selectedIndex = 3;
-                break;
-            default:
-                $("#fieldDataTypeSelection").get(0).selectedIndex = 0;
-                break;
-        }
+        // switch (me.dataTypeDef.indexOf(treeNode[JV.PROP_DATA_TYPE])) {
+        //     case 0:
+        //         $("#fieldDataTypeSelection").get(0).selectedIndex = 0;
+        //         break;
+        //     case 1:
+        //     case 2:
+        //     case 3:
+        //     case 4:
+        //         $("#fieldDataTypeSelection").get(0).selectedIndex = 1;
+        //         break;
+        //     case 5:
+        //         $("#fieldDataTypeSelection").get(0).selectedIndex = 2;
+        //         break;
+        //     case 6:
+        //         $("#fieldDataTypeSelection").get(0).selectedIndex = 3;
+        //         break;
+        //     default:
+        //         $("#fieldDataTypeSelection").get(0).selectedIndex = 0;
+        //         break;
+        // }
         //映射指标
     },
     onBeforeRemove: function(treeId, treeNode){
@@ -269,7 +269,7 @@ let discreteFieldParamTreeOprObj = {
                 let newNodes = [field];
                 me.treeObj.addNodes(treeNode, -1, newNodes, true);
             } else if (treeNode[JV.PROP_NAME] === JV.NODE_DISCRETE_PARAMS) {
-                let param = me.private_setup_dummy_discrete_param_node;
+                let param = me.private_setup_dummy_discrete_param_node();
                 let newNodes = [param];
                 me.treeObj.addNodes(treeNode, -1, newNodes, true);
             }

+ 339 - 193
web/maintain/report/js/rpt_tpl_main.js

@@ -1,5 +1,19 @@
 'use strict'
 
+const IDMark_Switch = "_switch",
+    IDMark_Icon = "_ico",
+    IDMark_Span = "_span",
+    IDMark_Input = "_input",
+    IDMark_Check = "_check",
+    IDMark_Edit = "_edit",
+    IDMark_Remove = "_remove",
+    IDMark_Ul = "_ul",
+    IDMark_A = "_a";
+
+const NODE_LEVEL_COMPILATION_OLD = 0,
+    NODE_LEVEL_COMPILATION_NEW = 1,
+    NODE_LEVEL_USER = 0;
+
 let rptTplObj = {
     iniPage: function() {
         zTreeOprObj.iniEngineerIdList();
@@ -11,7 +25,7 @@ let rptTplObj = {
         calculationTreeOprObj.buildExprTemplates();
         preHandleObj.buildTypeData();
     }
-}
+};
 
 let zTreeOprObj = {
     treeObj: null,
@@ -38,7 +52,8 @@ let zTreeOprObj = {
     refreshNodes: function() {
         let me = this;
         let private_setupIsParent = function(node){
-            if (node.nodeType === RT.NodeType.NODE || node.level === 0) {
+            // if (node.nodeType === RT.NodeType.NODE || node.level === 0) {
+            if (node.nodeType === RT.NodeType.NODE || node.level <= NODE_LEVEL_COMPILATION_NEW) {
                 node.isParent = true;
             } else {
                 node.isParent = false;
@@ -121,9 +136,6 @@ let zTreeOprObj = {
             let isReleased = false;
             if (subNode.nodeType === RT.NodeType.TEMPLATE) {
                 isReleased = subNode.checked;
-                // if (subNode.hasOwnProperty("released")) {
-                //     isReleased = subNode.released;
-                // }
             }
             rst = {
                 nodeType: subNode.nodeType,
@@ -146,9 +158,6 @@ let zTreeOprObj = {
                     let isReleased = false;
                     if (item.nodeType === RT.NodeType.TEMPLATE) {
                         isReleased = item.checked;
-                        // if (item.hasOwnProperty("released")) {
-                        //     isReleased = item.released;
-                        // }
                     }
                     let ir = {};
                     ir.nodeType = item.nodeType;
@@ -167,87 +176,117 @@ let zTreeOprObj = {
     addHoverDom: function(treeId, treeNode) {
         let me = zTreeOprObj, sObj = $("#" + treeNode.tId + "_span");
         if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length > 0 || treeNode.nodeType === RT.NodeType.TEMPLATE) return;
-        let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增子目录' onfocus='this.blur();'></span>";
-        sObj.after(addStr);
-        let btn = $("#addBtn_"+treeNode.tId);
-        if (btn) btn.bind("click", function(){
-            me.getNewNodeID(1, function (newNodeID) {
-                let rawNode = me.createIniNode();
-                rawNode.nodeType = RT.NodeType.NODE;
-                rawNode.name = "新增子节点";
-                rawNode.ID = newNodeID;
-                let newNodes = [], isSilent = false;
-                newNodes.push(rawNode);
-                if (me.treeObj) {
-                    let insertIdx = -1;
-                    if (treeNode.items && treeNode.items.length > 0) {
-                        for (let i = treeNode.items.length - 1; i >= 0; i--) {
-                            if (treeNode.items[i].nodeType === RT.NodeType.NODE) {
-                                insertIdx = i + 1;
-                                break;
+        if (treeNode.level === 0) {
+            let addStr = "<span class='button star' id='addBtn_" + treeNode.tId + "' title='新增项目类型' onfocus='this.blur();'></span>";
+            sObj.after(addStr);
+            let btn = $("#addBtn_"+treeNode.tId);
+            if (btn) btn.bind("click", function(){
+                let rawNode = me.createIniComilationNode();
+                if (!me.chkIfDupCompilationNode(rawNode, treeNode)) {
+                    rawNode.userId = treeNode.userId;
+                    me.addNewNodeEx(rawNode, function(rst){
+                        if (rst) {
+                            let newNodes = [], isSilent = false;
+                            rawNode.isParent = true;
+                            newNodes.push(rawNode);
+                            if (treeNode.items && treeNode.items.length > 0) {
+                                let insertIdx = -1;
+                                for (let i = 0; i < treeNode.items.length; i++) {
+                                    if (treeNode.items[i].compilationId === rawNode.compilationId) {
+                                        if (treeNode.items[i].engineerId > rawNode.engineerId) {
+                                            insertIdx = i;
+                                            break;
+                                        }
+                                    }
+                                }
+                                me.treeObj.addNodes(treeNode, insertIdx, newNodes, isSilent);
                             } else {
-                                insertIdx = i;
+                                me.treeObj.addNodes(treeNode, 0, newNodes, isSilent);
                             }
+                        } else {
+                            alert("后台创建失败,请确认是否有重复类型跟节点!")
                         }
-                    }
-                    me.treeObj.addNodes(treeNode, insertIdx, newNodes, isSilent);
-                    let tn = me.getTopNodeByCurrentNode(treeNode);
-                    let newTopNode = me.buildRootNodeDoc(tn);
-                    me.updateTreeRootNode(newTopNode, true, function(rst){
-                        if (!(rst)) {
-                            alert("新增节点失败!");
-                        }
-                        me.refreshNodes();
                     }, null);
+                } else {
+                    alert("有重复编办及工程类型!");
                 }
             });
-        });
+        } else {
+            let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增子目录' onfocus='this.blur();'></span>";
+            sObj.after(addStr);
+            let btn = $("#addBtn_"+treeNode.tId);
+            if (btn) btn.bind("click", function(){
+                me.getNewNodeID(1, function (newNodeID) {
+                    let rawNode = me.createIniNode();
+                    rawNode.nodeType = RT.NodeType.NODE;
+                    rawNode.name = "新增子节点";
+                    rawNode.ID = newNodeID;
+                    let newNodes = [], isSilent = false;
+                    newNodes.push(rawNode);
+                    if (me.treeObj) {
+                        let insertIdx = -1;
+                        if (treeNode.items && treeNode.items.length > 0) {
+                            for (let i = treeNode.items.length - 1; i >= 0; i--) {
+                                if (treeNode.items[i].nodeType === RT.NodeType.NODE) {
+                                    insertIdx = i + 1;
+                                    break;
+                                } else {
+                                    insertIdx = i;
+                                }
+                            }
+                        }
+                        me.treeObj.addNodes(treeNode, insertIdx, newNodes, isSilent);
+                        let tn = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
+                        let newTopNode = me.buildRootNodeDoc(tn);
+                        me.updateTreeRootNode(newTopNode, true, function(rst){
+                            if (!(rst)) {
+                                alert("新增节点失败!");
+                            }
+                            me.refreshNodes();
+                        }, null);
+                    }
+                });
+            });
+            addStr = "<span class='button blue_core' id='addBtn2_" + treeNode.tId + "' title='新增报表模板' onfocus='this.blur();'></span>";
+            sObj.after(addStr);
+            btn = $("#addBtn2_"+treeNode.tId + "");
+            if (btn) btn.bind("click", function(){
+                // let me = zTreeOprObj;
+                if (treeNode.nodeType === RT.NodeType.NODE || treeNode.level === NODE_LEVEL_COMPILATION_NEW) {
+                    me.getNewNodeID(1, function (newNodeID) {
+                        let rawNode = me.createIniNode();
+                        rawNode.nodeType = RT.NodeType.TEMPLATE;
+                        rawNode.name = "新增报表模板";
+                        rawNode.ID = newNodeID;
+                        rawNode.released = false;
+                        let newNodes = [], isSilent = false;
+                        newNodes.push(rawNode);
+                        me.treeObj.addNodes(treeNode, -1, newNodes, isSilent);
+                        let tn = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
+                        let topNode = me.buildRootNodeDoc(tn);
+                        me.updateTreeRootNode(topNode, true, function(rst){
+                            if (!(rst)) {
+                                alert("新增空白模板失败!");
+                            }
+                            me.refreshNodes();
+                        }, null);
+                    });
+                }
+            });
+        }
     },
     removeHoverDom: function(treeId, treeNode) {
         $("#addBtn_"+treeNode.tId).unbind().remove();
+        $("#addBtn2_"+treeNode.tId).unbind().remove();
     },
     addNewNodeEx: function(rawNode, callback, failCallback) {
         let params = {};
         params.doc = rawNode;
         CommonAjax.postEx("report_tpl_api/createTreeRootNode", params, 5000, true, callback, failCallback, null);
     },
-    moveUpNode: function() {
-        let me = this;
-        if (me.currentNode && me.currentNode.getPreNode() && me.currentNode.level > 0) {
-            let preNode = me.currentNode.getPreNode();
-            if (preNode.nodeType === me.currentNode.nodeType) {
-                me.treeObj.moveNode(preNode, me.currentNode, "prev", true);
-                //then update the db
-                let topPNode = me.getTopNodeByCurrentNode(preNode);
-                let newTopNode = me.buildRootNodeDoc(topPNode);
-                me.updateTreeRootNode(newTopNode, true, function(rst){
-                    if (!(rst)) {
-                        alert("移动请求失败!");
-                    }
-                });
-            }
-        }
-    },
-    moveDownNode: function() {
-        let me = this;
-        if (me.currentNode && me.currentNode.getNextNode() && me.currentNode.level > 0) {
-            let nextNode = me.currentNode.getNextNode();
-            if (nextNode.nodeType === me.currentNode.nodeType) {
-                me.treeObj.moveNode(nextNode, me.currentNode, "next", true);
-                //then update the db
-                let topPNode = me.getTopNodeByCurrentNode(nextNode);
-                let newTopNode = me.buildRootNodeDoc(topPNode);
-                me.updateTreeRootNode(newTopNode, true, function(rst){
-                    if (!(rst)) {
-                        alert("移动请求失败!");
-                    }
-                });
-            }
-        }
-    },
     oncheck: function (event, treeId, treeNode) {
         let me = zTreeOprObj;
-        let topPNode = me.getTopNodeByCurrentNode(treeNode);
+        let topPNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
         let newTopNode = me.buildRootNodeDoc(topPNode);
         me.updateTreeRootNode(newTopNode, true, function(rst){
             if (!(rst)) {
@@ -268,8 +307,8 @@ let zTreeOprObj = {
     onBeforeDrop: function (treeId, treeNodes, targetNode, moveType, isCopy) {
         let me = zTreeOprObj, rst = true;
         let srcNode = treeNodes[0];
-        let sourceTopNode = me.getTopNodeByCurrentNode(srcNode);
-        let targetTopNode = me.getTopNodeByCurrentNode(targetNode);
+        let sourceTopNode = me.getParentNodeByNodeLevel(srcNode, NODE_LEVEL_COMPILATION_NEW);
+        let targetTopNode = me.getParentNodeByNodeLevel(targetNode, NODE_LEVEL_COMPILATION_NEW);
         me.moveSrcTopNode = null;
         if (moveType === 'inner') {
             if (targetNode.nodeType === RT.NodeType.TEMPLATE) {
@@ -309,7 +348,7 @@ let zTreeOprObj = {
     },
     onDrop: function (event, treeId, treeNodes, targetNode, moveType, isCopy) {
         let me = zTreeOprObj;
-        let targetTopNode = me.getTopNodeByCurrentNode(targetNode);
+        let targetTopNode = me.getParentNodeByNodeLevel(targetNode, NODE_LEVEL_COMPILATION_NEW);
         let newTopNode = null;
         let canContinue = false;
         if (isCopy) {
@@ -321,19 +360,28 @@ let zTreeOprObj = {
                 me.copyReportTemplate(orgID, newNodeID, true, function(goodResult){
                     me.updateTreeRootNode(newTopNode, false, function(goodRst){
                         canContinue = true;
+                        if (treeNodes[0].rptTpl) {
+                            treeNodes[0].rptTpl.ID = newNodeID;
+                        }
+                        me.currentNode = treeNodes[0];
                     }, function(badRst){
                         displayMessage("更新模板节点失败!", "red", 2000);
+                        console.log(badRst.toString());
                     });
                 }, function(badResult){
                     displayMessage("Copy请求失败!", "red", 2000);
+                    console.log(badResult.toString());
                 });
             });
+            if (canContinue) me.chkAndRreshRefTpl();
         } else {
             newTopNode = me.buildRootNodeDoc(targetTopNode);
             me.updateTreeRootNode(newTopNode, false, function(rst){
                 canContinue = true;
+                me.currentNode = treeNodes[0];
             }, function(badResult){
                 displayMessage("移动请求失败!", "red", 2000);
+                console.log(badResult.toString());
                 canContinue = false;
             });
             if (canContinue && !isCopy && me.moveSrcTopNode) {
@@ -348,24 +396,96 @@ let zTreeOprObj = {
             me.moveSrcTopNode = null;
         }
     },
-    changeUser: function (dom) {
-        if (dom.id === "custRptOpt") {
-            //用户定制
-            $("#rpt_user_input")[0].disabled = false;
-            $("#rpt_user_find_btn")[0].disabled = false;
-        } else {
-            //公用
-            $("#rpt_user_input")[0].disabled = true;
-            $("#rpt_user_find_btn")[0].disabled = true;
+    addReportTemplate: function(newUsers) {
+        let me = zTreeOprObj, params = {};
+        params.compilationId = $("#compilations").get(0).value;
+        params.userId = [];
+        if (newUsers.length > 0) {
+            for (let user of newUsers) {
+                params.userId.push(user.userId);
+            }
+        }
+        let allEngIds = [];
+        for (let item of engineeringList) {
+            allEngIds.push(item.value);
         }
+        params.engineerId = allEngIds;
+        CommonAjax.postEx("report_tpl_api/getRptTplTree", params, 20000, true, function(result){
+            result.sort(function(item1, item2){
+                let rst = 0;
+                if (item1.userId === item2.userId) {
+                    rst = (item1.engineerId > item2.engineerId)?1:((item1.engineerId < item2.engineerId)?-1:0);
+                } else {
+                    if (item1.userId === "-100") {
+                        rst = 1
+                    } else if (item2.userId === "-100") {
+                        rst = -1
+                    } else {
+                        let idx1 = -1, idx2 = -1;
+                        for (let uidx = 0; uidx < newUsers.length; uidx++) {
+                            if (newUsers[uidx].userId === item1.userId) idx1 = uidx;
+                            if (newUsers[uidx].userId === item2.userId) idx2 = uidx;
+                            if (idx1 >= 0 && idx2 >= 0) {
+                                break;
+                            }
+                            rst = (idx1 > idx2)?1:((idx1 < idx2)?-1:0);
+                        }
+                    }
+                }
+                return rst;
+            });
+            let allTopUserIdNodes = [];
+            let allTopTplNodes = [];
+            for (let user of newUsers) {
+                allTopUserIdNodes.push(user.userId);
+                allTopTplNodes.push({userId: user.userId, name: user.real_name, items: [], isParent: true});
+            }
+            for (let item of result) {
+                let uidx = allTopUserIdNodes.indexOf(item.userId);
+                if (uidx >= 0) {
+                    item.isParent = true;
+                    allTopTplNodes[uidx].items.push(item);
+                }
+            }
+            // zTreeHelper.createTreeDirectly(allTopTplNodes, setting, "rptTplTree", me);
+            //add template nodes
+            let isSilent = false;
+            me.treeObj.addNodes(null, -1, allTopTplNodes, isSilent);
+            me.refreshNodes();
+            let private_setup_checked = function (itemNode) {
+                if (itemNode.nodeType === RT.NodeType.NODE) {
+                    me.treeObj.setChkDisabled(itemNode, true);
+                } else if (itemNode.nodeType === RT.NodeType.TEMPLATE) {
+                    me.treeObj.checkNode(itemNode, !!(itemNode.released));
+                }
+                if (itemNode.items && itemNode.items.length > 0) {
+                    for (let subItem of itemNode.items) {
+                        private_setup_checked(subItem);
+                    }
+                }
+            };
+            let topNodes = me.treeObj.getNodes();
+            // me.treeObj.expandAll(true);
+            for (let node of topNodes) {
+                me.treeObj.setChkDisabled(node, true);
+                if (node.items && node.items.length > 0) {
+                    for (let item of node.items) {
+                        me.treeObj.setChkDisabled(item, true);
+                        private_setup_checked(item);
+                    }
+                }
+            }
+        }, null, null);
     },
     getReportTemplateTree: function(compilationSelect) {
         let me = zTreeOprObj, params = {};
         params.compilationId = compilationSelect.value;
-        if ($("#custRptOpt")[0].checked) {
-            params.userId = (userAccount ===  'admin')?("-100"):userID;
-        } else {
-            params.userId = (userAccount ===  'admin')?("-100"):userID;
+        // params.userId = (userAccount ===  'admin')?("-100"):userID;
+        params.userId = ["-100"];
+        if (userListObj.foundedUserList.length > 0) {
+            for (let user of userListObj.foundedUserList) {
+                params.userId.push(user.userId);
+            }
         }
         let allEngIds = [];
         for (let item of engineeringList) {
@@ -375,23 +495,46 @@ let zTreeOprObj = {
         CommonAjax.postEx("report_tpl_api/getRptTplTree", params, 20000, true, function(result){
             result.sort(function(item1, item2){
                 let rst = 0;
-                if (item1.userId < item2.userId) {
-                    rst = 1
-                } else if (item1.userId > item2.userId) {
-                    rst = -1;
-                } else {
+                if (item1.userId === item2.userId) {
                     rst = (item1.engineerId > item2.engineerId)?1:((item1.engineerId < item2.engineerId)?-1:0);
+                } else {
+                    if (item1.userId === "-100") {
+                        rst = 1
+                    } else if (item2.userId === "-100") {
+                        rst = -1
+                    } else {
+                        let idx1 = -1, idx2 = -1;
+                        for (let uidx = 0; uidx < userListObj.foundedUserList.length; uidx++) {
+                            if (userListObj.foundedUserList[uidx].userId === item1.userId) idx1 = uidx;
+                            if (userListObj.foundedUserList[uidx].userId === item2.userId) idx2 = uidx;
+                            if (idx1 >= 0 && idx2 >= 0) {
+                                break;
+                            }
+                            rst = (idx1 > idx2)?1:((idx1 < idx2)?-1:0);
+                        }
+                    }
                 }
                 return rst;
             });
-            zTreeHelper.createTreeDirectly(result, setting, "rptTplTree", me);
+            let allTopUserIdNodes = ["-100"];
+            let allTopTplNodes = [{userId: "-100", name: "公共模板", items:[], isParent: true}];
+            for (let user of userListObj.foundedUserList) {
+                allTopUserIdNodes.push(user.userId);
+                allTopTplNodes.push({userId: user.userId, name: user.real_name, items: [], isParent: true});
+            }
+            for (let item of result) {
+                let uidx = allTopUserIdNodes.indexOf(item.userId);
+                item.isParent = true;
+                allTopTplNodes[uidx].items.push(item);
+            }
+            // zTreeHelper.createTreeDirectly(result, setting, "rptTplTree", me);
+            zTreeHelper.createTreeDirectly(allTopTplNodes, setting, "rptTplTree", me);
             me.refreshNodes();
             let private_setup_checked = function (itemNode) {
                 if (itemNode.nodeType === RT.NodeType.NODE) {
                     me.treeObj.setChkDisabled(itemNode, true);
                 } else if (itemNode.nodeType === RT.NodeType.TEMPLATE) {
-                    // me.treeObj.setChkDisabled(itemNode, !(itemNode.released));
-                    me.treeObj.checkNode(itemNode, (itemNode.released)?true:false);
+                    me.treeObj.checkNode(itemNode, !!(itemNode.released));
                 }
                 if (itemNode.items && itemNode.items.length > 0) {
                     for (let subItem of itemNode.items) {
@@ -405,75 +548,22 @@ let zTreeOprObj = {
                 me.treeObj.setChkDisabled(node, true);
                 if (node.items && node.items.length > 0) {
                     for (let item of node.items) {
+                        me.treeObj.setChkDisabled(item, true);
                         private_setup_checked(item);
                     }
                 }
             }
         }, null, null);
     },
-    addTplNode: function (){
-        let me = this;
-        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.NODE || me.currentNode.level === 0) {
-            me.getNewNodeID(1, function (newNodeID) {
-                let rawNode = me.createIniNode();
-                rawNode.nodeType = RT.NodeType.TEMPLATE;
-                rawNode.name = "新增报表模板";
-                rawNode.ID = newNodeID;
-                rawNode.released = false;
-                let newNodes = [], isSilent = false;
-                newNodes.push(rawNode);
-                me.treeObj.addNodes(me.currentNode, -1, newNodes, isSilent);
-                let topNode = me.buildRootNodeDoc(me.currentNode);
-                me.updateTreeRootNode(topNode, true, function(rst){
-                    if (!(rst)) {
-                        alert("新增空白模板失败!");
-                    }
-                    me.refreshNodes();
-                }, null);
-            });
-        }
-    },
     getNewNodeID: function (scope, callback) {
         let params = {};
         params.scope = scope;
         CommonAjax.postEx("report_tpl_api/getNewNodeID", params, 5000, true, callback, null, null);
     },
-    addRootNode: function() {
-        let me = this, rawNode = me.createIniRootNode();
-        if (!me.chkIfDupRootNode(rawNode)) {
-            me.addNewNodeEx(rawNode, function(rst){
-                if (rst) {
-                    let newNodes = [], isSilent = false;
-                    rawNode.isParent = true;
-                    newNodes.push(rawNode);
-                    if (me.treeObj) {
-                        let insertIdx = -1;
-                        let nodes = me.treeObj.getNodes();
-                        for (let i = 0; i < nodes.length; i++) {
-                            if (nodes[i].compilationId === rawNode.compilationId) {
-                                if (nodes[i].engineerId > rawNode.engineerId) {
-                                    insertIdx = i;
-                                    break;
-                                }
-                            }
-                        }
-                        me.treeObj.addNodes(null, insertIdx, newNodes, isSilent);
-                    } else {
-                        me.treeObj = $.fn.zTree.init($("#rptTplTree"), setting, newNodes);
-                    }
-                } else {
-                    alert("创建失败,请确认是否有重复类型跟节点!")
-                }
-            }, null);
-        } else {
-            alert("有重复编办及工程类型!");
-        }
-    },
-    chkIfDupRootNode: function (rawNode) {
-        let me = this, rst = false;
-        if (me.treeObj) {
-            let nodes = me.treeObj.getNodes();
-            for (let node of nodes) {
+    chkIfDupCompilationNode: function (rawNode, parentUserNode) {
+        let rst = false;
+        if (parentUserNode.items && parentUserNode.items.length > 0) {
+            for (let node of parentUserNode.items) {
                 if (node.compilationId === rawNode.compilationId && node.engineerId === rawNode.engineerId && node.userId === rawNode.userId) {
                     rst = true;
                     break;
@@ -482,7 +572,7 @@ let zTreeOprObj = {
         }
         return rst;
     },
-    createIniRootNode: function() {
+    createIniComilationNode: function() {
         let rst = {
             compilationId: $("#compilations").get(0).selectedOptions[0].value,
             engineerId: parseInt($("#engineerIds").get(0).selectedOptions[0].value),
@@ -497,30 +587,59 @@ let zTreeOprObj = {
     },
     onBeforeRemove: function(treeId, treeNode){
         let canRemove = false;
-        if (!(treeNode.items) || treeNode.items.length < 1) {
-            canRemove = confirm("请再确认您要删除!");
+        if (treeNode.level > NODE_LEVEL_USER) {
+            if (!(treeNode.items) || treeNode.items.length < 1) {
+                canRemove = confirm("请再确认您要删除!");
+            } else {
+                alert("含有子项,不能删除!");
+            }
         } else {
-            alert("含有子项,不能删除!");
+            alert("不能删除用户级别模板!");
         }
         return canRemove;
     },
     onRemove: function(e, treeId, treeNode){
-        let me = zTreeOprObj, topPNode = me.getTopNodeByCurrentNode(treeNode);
-        let rawNode = me.buildRootNodeDoc(topPNode, treeNode);
-        if (treeNode.level === 0) {
-            me.removeTreeRootNode(rawNode, true, function(rst){
-                if (!(rst)) {
-                    alert("删除请求失败!");
+        if (treeNode.level > NODE_LEVEL_USER) {
+            let me = zTreeOprObj,
+                topPNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
+            let rawNode = me.buildRootNodeDoc(topPNode, treeNode);
+            if (treeNode.level === NODE_LEVEL_COMPILATION_NEW) {
+                me.removeTreeRootNode(rawNode, true, function(rst){
+                    if (!(rst)) {
+                        alert("删除请求失败!");
+                    }
+                });
+            } else {
+                me.updateTreeRootNode(rawNode, true, function(rst){
+                    if (!(rst)) {
+                        alert("删除请求失败!");
+                    }
+                });
+            }
+            me.refreshNodes();
+        }
+    },
+    beforeEditName: function (treeId, treeNode) {
+        if (treeNode.level > NODE_LEVEL_COMPILATION_NEW) {
+            setTimeout(function(){
+                let ip = $("#" + treeNode.tId + IDMark_Input);
+                if (ip.length > 0) {
+                    ip[0].className = "individualRename";
+                } else {
+                    setTimeout(function(){
+                        let ip = $("#" + treeNode.tId + IDMark_Input);
+                        if (ip.length > 0) {
+                            ip[0].className = "individualRename";
+                        } else {
+                            console.log("sorry!");
+                        }
+                    }, 50);
                 }
-            });
+            }, 50);
+            return true;
         } else {
-            me.updateTreeRootNode(rawNode, true, function(rst){
-                if (!(rst)) {
-                    alert("删除请求失败!");
-                }
-            });
+            return false;
         }
-        me.refreshNodes();
     },
     beforeRename: function(treeId, treeNode, newName, isCancel) {
         if (newName.length === 0) {
@@ -538,7 +657,7 @@ let zTreeOprObj = {
                     }
                 }, null);
             } else {
-                let subTopNode = me.getSubTopNodeByCurrentNode(treeNode);
+                let subTopNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW + 1);
                 let topPNode = subTopNode.getParentNode();
                 let rawNode = me.buildSubRootNodeDoc(subTopNode);
                 me.updateSubNode(topPNode, rawNode, true, function(rst){
@@ -561,8 +680,8 @@ let zTreeOprObj = {
             params.rptName = me.currentNode.name;
             params.grpKey = me.getFolderText(me.currentNode, "_");
             me.currentNode.refId = me.currentNode.ID;
-            let subTopNode = me.getSubTopNodeByCurrentNode(me.currentNode);
-            let topPNode = me.getTopNodeByCurrentNode(subTopNode);
+            let subTopNode = me.getParentNodeByNodeLevel(me.currentNode, NODE_LEVEL_COMPILATION_NEW + 1);
+            let topPNode = me.getParentNodeByNodeLevel(subTopNode, NODE_LEVEL_COMPILATION_NEW);
             let rawNode = me.buildSubRootNodeDoc(subTopNode);
             params.compilationId = topPNode.compilationId;
             params.engineerId = topPNode.engineerId;
@@ -652,27 +771,54 @@ let zTreeOprObj = {
         if (rptTpl[JV.NODE_FLOW_INFO]) {
             rptTpl[JV.NODE_FLOW_INFO][JV.PROP_MULTI_COLUMN] = parseInt($("#rptTplMultiCols")[0].value);
         }
-        // rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_LEFT] = $("#rptTplMarginLeft")[0].value;
-        // rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_RIGHT] = $("#rptTplMarginRight")[0].value;
-        // rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_TOP] = $("#rptTplMarginTop")[0].value;
-        // rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_BOTTOM] = $("#rptTplMarginBottom")[0].value;
-    },
-    getTopNodeByCurrentNode: function (currentNode) {
-        let topPNode = currentNode, pNode = currentNode.getParentNode();
-        while (pNode !== null) {
-            topPNode = pNode;
-            pNode = pNode.getParentNode();
+        //考虑到页边距必然跟用户设置走,所以这里没必要特意去设置了,全部下架
+    },
+    getParentNodeByNodeLevel: function (currentNode, level) {
+        let rst = currentNode;
+        while (rst !== null) {
+            if (rst.level <= level) {
+                break;
+            } else {
+                rst = rst.getParentNode();
+            }
         }
-        return topPNode;
-    },
-    getSubTopNodeByCurrentNode: function (currentNode) {
-        let startNode = currentNode, resultPNode = null, pNode = startNode.getParentNode();
-        while (pNode !== null) {
-            resultPNode = startNode;
-            startNode = pNode;
-            pNode = startNode.getParentNode();
+        return rst;
+    }
+};
+
+let userListObj = {
+    foundedUserList: [],
+    UserIdList: [],
+    pushUser: function(user, newUsers) {
+        let me = userListObj;
+        if (me.UserIdList.indexOf(user._id) < 0) {
+            me.UserIdList.push(user._id);
+            let newUser = {userId: user._id, real_name: user.real_name, username: user.username, mobile: user.mobile};
+            me.foundedUserList.push(newUser);
+            newUsers.push(newUser);
         }
-        return resultPNode;
+    },
+    findUser: function () {
+        let key = $("#rpt_user_input1").get(0).value;
+        let newUsers = [];
+        $.ajax({
+            type:"GET",
+            url: "user/search?keyword=" + key,
+            cache: false,
+            timeout: 5000,
+            success: function(result){
+                if (result.data && result.data.length > 0) {
+                    for (let user of result.data) {
+                        userListObj.pushUser(user, newUsers);
+                    }
+                    if (newUsers.length > 0) {
+                        zTreeOprObj.addReportTemplate(newUsers);
+                    }
+                }
+            },
+            error: function(jqXHR, textStatus, errorThrown){
+            }
+        });
     }
 };
 

+ 344 - 144
web/maintain/report/js/rpt_tpl_pre_handle.js

@@ -4,88 +4,124 @@
 
 const sort_types = ["normal", "tree", "accord_to_parent", "self_define"];
 const condition_types = ["==", "===", ">", ">=", "<", "<=", "!=", "in", "not in"];
-const pre_handle_data_objects = ["bills", "ration", "ration_glj"];
-const pre_handle_data_objects_name = ["清单", "定额", "定额工料机"];
+const pre_handle_data_objects = ["bills", "ration", "ration_glj", "projectGLJ"];
+const pre_handle_data_objects_name = ["清单", "定额", "定额人材机", "项目人材机"];
+//供货方式
+const fixed_supply_types = [
+    {Name: "自行采购(0)", Title: "", Value: 0},
+    {Name: "部分甲供(1)", Title: "", Value: 1},
+    {Name: "完全甲供(2)", Title: "", Value: 2},
+    {Name: "甲定乙供(3)", Title: "", Value: 3}
+];
+//三材类别
+const fixed_material_types = [
+    {Name: "钢材(1)", Title: "", Value: 1},
+    {Name: "钢筋(2)", Title: "", Value: 2},
+    {Name: "木材(3)", Title: "", Value: 3},
+    {Name: "水泥(4)", Title: "", Value: 4},
+    {Name: "标准砖(5)", Title: "", Value: 5}
+];
+const fixed_glj_types = [
+    {Name: "人工(1)", Title: "", Value: 1},
+    {Name: "普通材料(201)", Title: "", Value: 201},
+    {Name: "混凝土(202)", Title: "", Value: 202},
+    {Name: "砂浆(203)", Title: "", Value: 203},
+    {Name: "配合比(204)", Title: "", Value: 204},
+    {Name: "商品混凝土(205)", Title: "", Value: 205},
+    {Name: "商品砂浆(206)", Title: "", Value: 206},
+    {Name: "普通机械(301)", Title: "", Value: 301},
+    {Name: "机械组成物(302)", Title: "", Value: 302},
+    {Name: "机上人工(303)", Value: 303},
+    {Name: "主材(4)", Title: "", Value: 4},
+    {Name: "设备(5)", Title: "", Value: 5}
+];
+const fixed_top_bills_nodes = [
+    {Name: "分部分项工程(1)", Title: "", Value: 1}
+    ,{Name: "措施项目(2)", Title: "", Value: 2}
+    ,{Name: "其他项目(7)", Title: "", Value: 7}
+    ,{Name: "规费(15)", Title: "", Value: 15}
+    ,{Name: "税金(18)", Title: "", Value: 18}
+    ,{Name: "工程造价(19)", Title: "", Value: 19}
+];
+const fixed_other_bills_types = [
+    {Name: "施工技术措施项目(3)", Title: "", Value: 3}
+    ,{Name: "安全文明施工按实计算费用(4)", Title: "", Value: 4}
+    ,{Name: "施工组织措施专项费用(5)", Title: "", Value: 5}
+    ,{Name: "安全文明施工专项费用(6)", Title: "", Value: 6}
+    ,{Name: "暂列金额(8)", Title: "", Value: 8}
+    ,{Name: "暂估价(9)", Title: "", Value: 9}
+    ,{Name: "材料(工程设备)暂估价(10)", Title: "", Value: 10}
+    ,{Name: "专业工程暂估价(11)", Title: "", Value: 11}
+    ,{Name: "计日工(12)", Title: "", Value: 12}
+    ,{Name: "总承包服务费(13)", Title: "", Value: 13}
+    ,{Name: "索赔与现场签证(14)", Title: "", Value: 14}
+    ,{Name: "社会保险费及住房公积金(16)", Title: "", Value: 16}
+    ,{Name: "工程排污费(17)", Title: "", Value: 17}
+];
+const fixed_bills_flags = [
+    {Name: "分部分项工程(1)", Title: "", Value: 1},
+    {Name: "措施项目(2)", Title: "", Value: 2},
+    {Name: "施工技术措施项目(3)", Title: "", Value: 3},
+    {Name: "安全文明施工按实计算费用(4)", Title: "", Value: 4},
+    {Name: "施工组织措施专项费用(5)", Title: "", Value: 5},
+    {Name: "安全文明施工专项费用(6)", Title: "", Value: 6},
+    {Name: "其他项目(7)", Title: "", Value: 7},
+    {Name: "暂列金额(8)", Title: "", Value: 8},
+    {Name: "暂估价(9)", Title: "", Value: 9},
+    {Name: "材料(工程设备)暂估价(10)", Title: "", Value: 10},
+    {Name: "专业工程暂估价(11)", Title: "", Value: 11},
+    {Name: "计日工(12)", Title: "", Value: 12},
+    {Name: "总承包服务费(13)", Title: "", Value: 13},
+    {Name: "索赔与现场签证(14)", Title: "", Value: 14},
+    {Name: "规费(15)", Title: "", Value: 15},
+    {Name: "社会保险费及住房公积金(16)", Title: "", Value: 16},
+    {Name: "工程排污费(17)", Title: "", Value: 17},
+    {Name: "税金(18)", Title: "", Value: 18},
+    {Name: "工程造价(19)", Title: "", Value: 19}
+];
+const fixed_bills_types = [
+    {Name: "大项费用(1)", Title: "", Value: 1},
+    {Name: "分部(2)", Title: "", Value: 2},
+    {Name: "分项(3)", Title: "", Value: 3},
+    {Name: "清单(4)", Title: "", Value: 4},
+    {Name: "补项(5)", Title: "", Value: 5},
+];
 const exposed_bills_properties = [
     {Name: "清单_所属项目ID", Title: "", Key: "projectID", Order: "ascend"}
     ,{Name: "清单_ID", Title: "", Key: "ID", Order: "ascend"}
+    ,{Name: "顶层父清单_标记", Title: "", Key: "topBillID", Order: "ascend", individualType: fixed_top_bills_nodes}
     ,{Name: "清单_层次", Title: "", Key: "treeLevel", Order: "ascend"}
-    ,{Name: "清单_标记", Title: "", Key: "flags.flag", Order: "ascend"}
-    // ,{Name: "清单_项目编码", Title: "", Key: "code", Order: "ascend"}
-    // ,{Name: "清单_项目名称", Title: "", Key: "name", Order: "ascend"}
-    // ,{Name: "清单_项目特征", Title: "", Key: "itemCharacterText", Order: "ascend"}
-    // ,{Name: "清单_计量单位", Title: "", Key: "unit", Order: "ascend"}
-    // ,{Name: "清单_工程量", Title: "", Key: "quantity", Order: "ascend"}
-    // ,{Name: "清单_综合单价", Title: "", Key: "unitFee", Order: "ascend"}
-    // ,{Name: "清单_综合合价", Title: "", Key: "totalFee", Order: "ascend"}
-    // ,{Name: "清单_暂估价", Title: "", Key: "tenderUnitFee", Order: "ascend"}
+    ,{Name: "清单_类别", Title: "", Key: "type", Order: "ascend", individualType: fixed_bills_types}
+    ,{Name: "清单_标记", Title: "", Key: "flags.flag", Order: "ascend", individualType: fixed_bills_flags}
 ];
 const exposed_ration_properties = [
     {Name: "定额_工程内部ID", Title: "", Key: "ID", Order: "ascend"}
     ,{Name: "定额_所属项目ID", Title: "", Key: "projectID", Order: "ascend"}
     ,{Name: "定额_所属清单ID", Title: "", Key: "billsItemID", Order: "ascend"}
     ,{Name: "定额_清单内顺序", Title: "", Key: "serialNo", Order: "ascend"}
-    // ,{Name: "定额_编号", Title: "", Key: "code", Order: "ascend"}
-    // ,{Name: "定额_项目名称", Title: "", Key: "caption", Order: "ascend"}
-    // ,{Name: "定额_单位", Title: "", Key: "unit", Order: "ascend"}
-    // ,{Name: "定额_数量", Title: "", Key: "quantity", Order: "ascend"}
-    // ,{Name: "定额_人工费", Title: "", Key: "labour", Order: "ascend"}
-    // ,{Name: "定额_材料费", Title: "", Key: "material", Order: "ascend"}
-    // ,{Name: "定额_机械费", Title: "", Key: "machine", Order: "ascend"}
-    // ,{Name: "定额_机上人工费", Title: "", Key: "machineLabour", Order: "ascend"}
-    // ,{Name: "定额_人工费调整", Title: "", Key: "adjustLabour", Order: "ascend"}
-    // ,{Name: "定额_材料费调整", Title: "", Key: "'adjustMaterial'", Order: "ascend"}
-    // ,{Name: "定额_机械费调整", Title: "", Key: "adjustMachine", Order: "ascend"}
-    // ,{Name: "定额_机上人工费调整", Title: "", Key: "adjustMachineLabour", Order: "ascend"}
-    // ,{Name: "定额_人工价差", Title: "", Key: "labourDiff", Order: "ascend"}
-    // ,{Name: "定额_材料价差", Title: "", Key: "materialDiff", Order: "ascend"}
-    // ,{Name: "定额_机械价差", Title: "", Key: "machineDiff", Order: "ascend"}
-    // ,{Name: "定额_风险费用", Title: "", Key: "risk", Order: "ascend"}
-    // ,{Name: "定额_管理费率", Title: "", Key: ""}
 ];
-const exposed_prj_glj_properties = [
-    {Name: "工料机_ID", Title: "", Key: "ID"},
-    {Name: "工料机_所属定额ID", Title: "", Key: "rationID", Order: "ascend"},
-    {Name: "工料机_所属清单ID", Title: "", Key: "billsItemID", Order: "ascend"},
-    {Name: "工料机_所属工程ID", Title: "", Key: "projectID", Order: "ascend"}
-    // {Name: "工料机_代码", Title: "", Key: "code", Order: "ascend"},
-    // {Name: "工料机_名称", Title: "", Key: "name", Order: "ascend"},
-    // {Name: "工料机_单位", Title: "", Key: "unit", Order: "ascend"},
-    // {Name: "工料机_数量", Title: "", Key: "quantity", Order: "ascend"}
-];
-const exposed_properties_arr = [exposed_bills_properties, exposed_ration_properties, exposed_prj_glj_properties];
-const fixed_top_bills_nodes = [
-    {Name: "分部分项工程", Title: "", Value: 1},
-    {Name: "措施项目", Title: "", Value: 2},
-    {Name: "其他项目", Title: "", Value: 7},
-    {Name: "规费", Title: "", Value: 15},
-    {Name: "税金", Title: "", Value: 18},
-    {Name: "工程造价", Title: "", Value: 19}
+const exposed_ration_glj_properties = [
+    {Name: "定额人材机_ID", Title: "", Key: "ID"}
+    ,{Name: "定额人材机_所属定额ID", Title: "", Key: "rationID", Order: "ascend"}
+    ,{Name: "定额人材机_所属清单ID", Title: "", Key: "billsItemID", Order: "ascend"}
+    ,{Name: "定额人材机_所属工程ID", Title: "", Key: "projectID", Order: "ascend"}
+    ,{Name: "定额人材机_代码", Title: "", Key: "code", Order: "ascend"}
+    ,{Name: "定额人材机_类型", Title: "", Key: "type", Order: "ascend", individualType: fixed_glj_types}
+    ,{Name: "定额人材机_是否暂估", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).is_evaluate", Order: "ascend", isBoolean: true, booleanOptions: [1,0]}
+    ,{Name: "定额人材机_供货方式", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).supply", Order: "ascend", individualType: fixed_supply_types}
+    ,{Name: "定额人材机_三材类别", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).materialType", Order: "ascend", individualType: fixed_material_types}
 ];
-const fixed_other_bills_types = [
-    {Name: "施工技术措施项目", Title: "", Value: 3},
-    {Name: "安全文明施工按实计算费用", Title: "", Value: 4},
-    {Name: "施工组织措施专项费用", Title: "", Value: 5},
-    {Name: "安全文明施工专项费用", Title: "", Value: 6},
-    {Name: "暂列金额", Title: "", Value: 8},
-    {Name: "暂估价", Title: "", Value: 9},
-    {Name: "材料(工程设备)暂估价", Title: "", Value: 10},
-    {Name: "专业工程暂估价", Title: "", Value: 11},
-    {Name: "计日工", Title: "", Value: 12},
-    {Name: "总承包服务费", Title: "", Value: 13},
-    {Name: "索赔与现场签证", Title: "", Value: 14},
-    {Name: "社会保险费及住房公积金", Title: "", Value: 16},
-    {Name: "工程排污费", Title: "", Value: 17}
+const exposed_prj_glj_properties = [
+    {Name: "项目人材机_ID", Title: "", Key: "ID"}
+    ,{Name: "项目人材机_所属工程ID", Title: "", Key: "projectID", Order: "ascend"}
+    ,{Name: "项目人材机_代码", Title: "", Key: "code", Order: "ascend"}
+    ,{Name: "项目人材机_类型", Title: "", Key: "type", Order: "ascend", individualType: fixed_glj_types}
+    ,{Name: "项目人材机_数量", Title: "", Key: "quantity", Order: "ascend"}
+    ,{Name: "项目人材机_是否暂估", Title: "", Key: "is_evaluate", Order: "ascend", isBoolean: true, booleanOptions: [1,0]}
+    ,{Name: "项目人材机_供货方式", Title: "", Key: "supply", Order: "ascend", individualType: fixed_supply_types}
+    ,{Name: "项目人材机_三材类别", Title: "", Key: "materialType", Order: "ascend", individualType: fixed_material_types}
 ];
-const IDMark_Switch = "_switch",
-    IDMark_Icon = "_ico",
-    IDMark_Span = "_span",
-    IDMark_Input = "_input",
-    IDMark_Check = "_check",
-    IDMark_Edit = "_edit",
-    IDMark_Remove = "_remove",
-    IDMark_Ul = "_ul",
-    IDMark_A = "_a";
+const exposed_properties_arr = [exposed_bills_properties, exposed_ration_properties, exposed_ration_glj_properties, exposed_prj_glj_properties];
 
 let preHandleObj = {
     treeObj: null,
@@ -141,34 +177,38 @@ let preHandleObj = {
             }
         }
     },
-    addNewNode: function(nodeType) {
-        let me = this, item = null, preHandleType = nodeType;
+    createNewNode: function (nodeType) {
+        let rst = null, preHandleType = nodeType;
         if (!nodeType) {
             preHandleType = JV.PROP_HANDLE_TYPE_SORT;
         }
         switch (nodeType) {
             case JV.PROP_HANDLE_TYPE_SORT:
-                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "排序方式": "normal", "排序键值集":[]};
+                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "排序方式": "normal", "排序键值集":[]};
                 break;
             case JV.PROP_HANDLE_TYPE_FILTER:
-                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "过滤键值集": []};
+                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "过滤键值集": []};
                 break;
             case JV.PROP_HANDLE_TYPE_BILLS_DATA_MOVE:
-                item = {Name: "预处理环节", Title: "", "映射数据对象": "ration", "预处理类型": preHandleType};
+                rst = {Name: "预处理环节", Title: "", "映射数据对象": "ration", "预处理类型": preHandleType};
                 break;
             case JV.PROP_HANDLE_TYPE_SUM:
-                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "分组键值集": [], "统计键值集":[]};
+                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "分组键值集": [], "统计键值集":[]};
                 break;
             case JV.PROP_HANDLE_TYPE_ADJUST:
-                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "数据调整集":[]};
+                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "数据调整集":[]};
                 break;
             case JV.PROP_HANDLE_TYPE_ADD_DUMMY:
-                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "Dummy数据集":[]};
+                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "Dummy数据集":[]};
                 break;
             default:
-                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": "排序", "排序方式": "normal", "排序键值集":[]};
+                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": "排序", "排序方式": "normal", "排序键值集":[]};
                 break;
         }
+        return rst;
+    },
+    addNewNode: function(nodeType) {
+        let me = this, item = me.createNewNode(nodeType);
         me.private_set_title(item);
         me.treeObj.addNodes(null, -1, [item], true);
     },
@@ -311,8 +351,22 @@ let preHandleObj = {
             preHandleObj.currentNode[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_DATA_KEY] = dom.value;
         }
     },
+    onBeforeDrag: function (treeId, treeNodes) {
+        let rst = true;
+        for (let node of treeNodes) {
+            if (node.level > 0) {
+                rst = false;
+                break;
+            }
+        }
+        return rst;
+    },
     onBeforeDrop: function(treeId, treeNodes, targetNode, moveType){
-        //
+        let rst = false;
+        if (targetNode.level === 0 && moveType !== "inner") {
+            rst = true;
+        }
+        return rst;
     },
     onBeforeRemove: function(treeId, treeNode){
         let rst = true;
@@ -323,6 +377,46 @@ let preHandleObj = {
         }
         return rst;
     },
+    addHoverDom: function(treeId, treeNode) {
+        let me = preHandleObj, sObj = $("#" + treeNode.tId + "_span");
+        if ((treeNode.level > 0 && treeNode[JV.PROP_HANDLE_TYPE] !== JV.PROP_HANDLE_TYPE_FILTER) || ($("#addBtn_"+treeNode.tId).length > 0) ) return;
+        if (treeNode[JV.PROP_HANDLE_TYPE] === JV.PROP_HANDLE_TYPE_SORT && treeNode[JV.PROP_SORT_TYPE] === "accord_to_parent") {
+            let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增子排序' onfocus='this.blur();'></span>";
+            sObj.after(addStr);
+            let btn = $("#addBtn_"+treeNode.tId);
+            if (btn) btn.bind("click", function(){
+                let newSubNodes = [];
+                let newNode = me.createNewNode(treeNode[JV.PROP_HANDLE_TYPE]);
+                newNode.Name = "子排序";
+                newNode[JV.PROP_DATA_KEY] = treeNode[JV.PROP_DATA_KEY];
+                me.private_set_title(newNode);
+                newSubNodes.push(newNode);
+                treeNode.isParent = true;
+                me.treeObj.addNodes(treeNode, -1, newSubNodes, true);
+                me.treeObj.expandNode(treeNode, true, false);
+            });
+        } else if (treeNode[JV.PROP_HANDLE_TYPE] === JV.PROP_HANDLE_TYPE_FILTER) {
+            let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增子过滤' onfocus='this.blur();'></span>";
+            sObj.after(addStr);
+            let btn = $("#addBtn_"+treeNode.tId);
+            if (btn) btn.bind("click", function(){
+                let newSubNodes = [];
+                let newNode = me.createNewNode(treeNode[JV.PROP_HANDLE_TYPE]);
+                newNode.Name = "子过滤";
+                newNode[JV.PROP_DATA_KEY] = treeNode[JV.PROP_DATA_KEY];
+                newNode.Title = "";
+                newNode[JV.PROP_HANDLE_TYPE] = JV.PROP_HANDLE_TYPE_FILTER;
+                // me.private_set_title(newNode);
+                newSubNodes.push(newNode);
+                treeNode.isParent = true;
+                me.treeObj.addNodes(treeNode, -1, newSubNodes, true);
+                me.treeObj.expandNode(treeNode, true, false);
+            });
+        }
+    },
+    removeHoverDom: function (treeId, treeNode) {
+        $("#addBtn_"+treeNode.tId).unbind().remove();
+    },
     extractTabFields: function (rptTpl) {
         let me = this, nodes = me.treeObj.getNodes();
         let rst = [];
@@ -360,6 +454,7 @@ let preHandleSortObj = {
     topBillsTreeObj: null,
     otherBillsTreeObj: null,
     copyNode: function (src, dest) {
+        let me = preHandleSortObj;
         dest[JV.PROP_SORT_TYPE] = src[JV.PROP_SORT_TYPE];
         switch (sort_types.indexOf(src[JV.PROP_SORT_TYPE])) {
             case -1:
@@ -390,7 +485,6 @@ let preHandleSortObj = {
             case 2 :
                 //according to parent
                 dest[JV.PROP_PARENT_CHILD_SORT_KEY] = {};
-                dest[JV.PROP_OTHER_SUB_SORT] = [];
                 dest[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_DATA_KEY] = src[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_DATA_KEY];
                 dest[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_SORT_KEYS] = [];
                 for (let item of src[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_SORT_KEYS]) {
@@ -400,19 +494,14 @@ let preHandleSortObj = {
                 for (let item of src[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_CHILD_SORT_KEYS]) {
                     dest[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_CHILD_SORT_KEYS].push(item);
                 }
+                dest[JV.PROP_OTHER_SUB_SORT] = [];
                 if (src[JV.PROP_OTHER_SUB_SORT] !== null && src[JV.PROP_OTHER_SUB_SORT] !== undefined) {
+                    dest.items = [];
                     for (let subSort of src[JV.PROP_OTHER_SUB_SORT]) {
-                        let st = {};
-                        st[JV.PROP_SORT_TYPE] = subSort[JV.PROP_SORT_TYPE];
-                        if (subSort[JV.PROP_SORT_TYPE] === "normal") {
-                            st[JV.PROP_SORT_KEYS] = [];
-                            for (let item of subSort[JV.PROP_SORT_KEYS]) {
-                                let di = {key: item.key, order: item.order};
-                                st[JV.PROP_SORT_KEYS].push(di);
-                            }
-                        } else {
-                            //其他暂时不实现,目前没那么复杂
-                        }
+                        let destSubSort = {Name: "子排序"};
+                        me.copyNode(subSort, destSubSort);
+                        destSubSort[JV.PROP_DATA_KEY] = src[JV.PROP_DATA_KEY];
+                        dest.items.push(destSubSort);
                     }
                 }
                 break;
@@ -639,6 +728,17 @@ let preHandleSortObj = {
             case 2 :
                 //according to parent
                 rst[JV.PROP_PARENT_CHILD_SORT_KEY] = handleObj[JV.PROP_PARENT_CHILD_SORT_KEY];
+                rst[JV.PROP_OTHER_SUB_SORT] = [];
+                if (handleObj.items && handleObj.items.length > 0) {
+                    for (let subSort of handleObj.items) {
+                        let dtlRst = {};
+                        me.copyNode(subSort, dtlRst);
+                        delete dtlRst.Name;
+                        delete dtlRst.PROP_DATA_KEY;
+                        rst[JV.PROP_OTHER_SUB_SORT].push(dtlRst);
+                        dtlRst = null;
+                    }
+                }
                 break;
             case 3 :
                 //self define
@@ -653,7 +753,7 @@ let preHandleSortObj = {
 let preHandleFilterObj = {
     treeObj: null,
     copyNode: function (src, dest) {
-        let keys = [];
+        let me = preHandleFilterObj, keys = [];
         for (let filterItem of src[JV.PROP_FILTER_KEYS]) {
             let item = {key: filterItem.key};
             item[JV.PROP_FILTER_CONDITION] = filterItem[JV.PROP_FILTER_CONDITION];
@@ -664,7 +764,21 @@ let preHandleFilterObj = {
             }
             keys.push(item);
         }
+        dest[JV.PROP_HANDLE_TYPE] = src[JV.PROP_HANDLE_TYPE];
+        dest[JV.PROP_DATA_KEY] = src[JV.PROP_DATA_KEY];
         dest[JV.PROP_FILTER_KEYS] = keys;
+
+        if (src[JV.PROP_OTHER_SUB_FILTER] && src[JV.PROP_OTHER_SUB_FILTER].length > 0) {
+            dest.items = [];
+            for (let subFilter of src[JV.PROP_OTHER_SUB_FILTER]) {
+                let dtlRst = {Name: "子过滤", Title: ""};
+                subFilter[JV.PROP_DATA_KEY] = src[JV.PROP_DATA_KEY];
+                me.copyNode(subFilter, dtlRst);
+                dtlRst[JV.PROP_HANDLE_TYPE] = src[JV.PROP_HANDLE_TYPE];
+                dtlRst[JV.PROP_DATA_KEY] = src[JV.PROP_DATA_KEY];
+                dest.items.push(dtlRst);
+            }
+        }
     },
     refresh_node: function () {
         let me = this;
@@ -680,26 +794,43 @@ let preHandleFilterObj = {
                         //and then others...
                         //过滤条件
                         keyNode[JV.PROP_FILTER_CONDITION] = filterItem[JV.PROP_FILTER_CONDITION];
-                        $("#diySelect_" + keyNode.tId)[0].selectedIndex = condition_types.indexOf(filterItem[JV.PROP_FILTER_CONDITION]);
-                        //条件值
-                        keyNode[JV.PROP_FILTER_COMPARE_VAL] = filterItem[JV.PROP_FILTER_COMPARE_VAL];
-                        $("#diyInput_" + keyNode.tId)[0].value = filterItem[JV.PROP_FILTER_COMPARE_VAL];
-                        //其他关联业务数据对象
-                        if (filterItem[JV.PROP_FILTER_COMPARE_OBJ]) {
-                            let cmpObjDom = $("#diyDataSelect_" + keyNode.tId)[0];
-                            keyNode[JV.PROP_FILTER_COMPARE_OBJ] = filterItem[JV.PROP_FILTER_COMPARE_OBJ];
-                            let idx = pre_handle_data_objects.indexOf(filterItem[JV.PROP_FILTER_COMPARE_OBJ]);
-                            cmpObjDom.selectedIndex = idx + 1;
-                            me.private_setup_compare_obj(cmpObjDom);
-                            let cmpObjIdDom = $("#diyDataDetailSelect_" + keyNode.tId)[0];
-                            for (let i = 0; i < cmpObjIdDom.children.length; i++) {
-                                let option = cmpObjIdDom.children[i];
-                                if (option.value === filterItem[JV.PROP_FILTER_COMPARE_OBJ_KEY]) {
-                                    keyNode[JV.PROP_FILTER_COMPARE_OBJ_KEY] = filterItem[JV.PROP_FILTER_COMPARE_OBJ_KEY]
-                                    cmpObjIdDom.selectedIndex = i;
+                        if (keyNode.isBoolean) {
+                            keyNode[JV.PROP_FILTER_COMPARE_VAL] = filterItem[JV.PROP_FILTER_COMPARE_VAL];
+                            $("#diyCheck_" + keyNode.tId)[0].checked = (keyNode["booleanOptions"].indexOf(filterItem["compareValue"]) === 0);
+                        } else if (keyNode.hasOwnProperty("individualType")) {
+                            $("#diySelect_" + keyNode.tId)[0].selectedIndex = condition_types.indexOf(filterItem[JV.PROP_FILTER_CONDITION]);
+                            //条件值
+                            keyNode[JV.PROP_FILTER_COMPARE_VAL] = filterItem[JV.PROP_FILTER_COMPARE_VAL];
+                            $("#diyInput_" + keyNode.tId)[0].value = filterItem[JV.PROP_FILTER_COMPARE_VAL];
+                            for (let idx = 0; idx < keyNode["individualType"].length; idx++) {
+                                let idType = keyNode["individualType"][idx];
+                                if (idType.Value.toString() === filterItem[JV.PROP_FILTER_COMPARE_VAL].toString()) {
+                                    $("#diyDataDetailSelect_" + keyNode.tId)[0].selectedIndex = idx;
                                     break;
                                 }
                             }
+                        } else {
+                            $("#diySelect_" + keyNode.tId)[0].selectedIndex = condition_types.indexOf(filterItem[JV.PROP_FILTER_CONDITION]);
+                            //条件值
+                            keyNode[JV.PROP_FILTER_COMPARE_VAL] = filterItem[JV.PROP_FILTER_COMPARE_VAL];
+                            $("#diyInput_" + keyNode.tId)[0].value = filterItem[JV.PROP_FILTER_COMPARE_VAL];
+                            //其他关联业务数据对象
+                            if (filterItem[JV.PROP_FILTER_COMPARE_OBJ]) {
+                                let cmpObjDom = $("#diyDataSelect_" + keyNode.tId)[0];
+                                keyNode[JV.PROP_FILTER_COMPARE_OBJ] = filterItem[JV.PROP_FILTER_COMPARE_OBJ];
+                                let idx = pre_handle_data_objects.indexOf(filterItem[JV.PROP_FILTER_COMPARE_OBJ]);
+                                cmpObjDom.selectedIndex = idx + 1;
+                                me.private_setup_compare_obj(cmpObjDom);
+                                let cmpObjIdDom = $("#diyDataDetailSelect_" + keyNode.tId)[0];
+                                for (let i = 0; i < cmpObjIdDom.children.length; i++) {
+                                    let option = cmpObjIdDom.children[i];
+                                    if (option.value === filterItem[JV.PROP_FILTER_COMPARE_OBJ_KEY]) {
+                                        keyNode[JV.PROP_FILTER_COMPARE_OBJ_KEY] = filterItem[JV.PROP_FILTER_COMPARE_OBJ_KEY]
+                                        cmpObjIdDom.selectedIndex = i;
+                                        break;
+                                    }
+                                }
+                            }
                         }
                         break;
                     }
@@ -746,32 +877,70 @@ let preHandleFilterObj = {
         rst.push("</select>");
         return rst.join("");
     },
+    build_individual_filter_selection_str: function (individualTypes,treeNode) {
+        let rst = [];
+        rst.push("<select class='selDemo' id='diyDataDetailSelect_" + treeNode.tId + "'>");
+        for (let i = 0; i < individualTypes.length; i++) {
+            rst.push("<option value='" + individualTypes[i].Value + "'>" + individualTypes[i].Name + "</option>");
+        }
+        rst.push("</select>");
+        return rst.join("");
+    },
     addDiyDom: function(treeId,treeNode) {
         let me = preHandleFilterObj;
         let aObj = $("#" + treeNode.tId + IDMark_A);
-        let dataDtlSelStr = me.build_filter_handle_data_detail_selection_str(treeId,treeNode);
-        aObj.after(dataDtlSelStr);
-        let dataSelStr = me.build_filter_handle_data_selection_str(treeId,treeNode);
-        aObj.after(dataSelStr);
-        let editStr = "<input type='text' id='diyInput_" + treeNode.tId + "' width='10'/>";
-        aObj.after(editStr);
-        let selStr = "<select class='selDemo' id='diySelect_" + treeNode.tId + "'><option value='=='>等于</option><option value='==='>全等于</option><option value='>'>大于</option><option value='>='>大于等于</option><option value='<'>小于</option><option value='<='>小于等于</option><option value='!='>不等于</option><option value='in'>在</option><option value='not in'>不在</option></select>";
-        aObj.after(selStr);
-        let sel = $("#diySelect_" + treeNode.tId);
-        if (sel) {
-            sel.bind("change", me.filterConditionChange);
-        }
-        sel = $("#diyInput_" + treeNode.tId);
-        if (sel) {
-            sel.bind("change", me.filterCompareValChange);
-        }
-        sel = $("#diyDataSelect_" + treeNode.tId);
-        if (sel) {
-            sel.bind("change", me.filterCompareObjChange);
-        }
-        sel = $("#diyDataDetailSelect_" + treeNode.tId);
-        if (sel) {
-            sel.bind("change", me.filterCompareObjKeyChange);
+        if (treeNode.hasOwnProperty("isBoolean")) {
+            let checkStr = "<input type='checkbox' id='diyCheck_" + treeNode.tId + "' />";
+            aObj.after(checkStr);
+            let sel = $("#diyCheck_" + treeNode.tId);
+            if (sel) {
+                sel.bind("change", me.filterConditionCheck);
+            }
+        } else if (treeNode.hasOwnProperty("individualType")) {
+            let dataDtlSelStr = me.build_individual_filter_selection_str(treeNode.individualType, treeNode);
+            aObj.after(dataDtlSelStr);
+            let editStr = "<input type='text' id='diyInput_" + treeNode.tId + "' width='10'/>";
+            aObj.after(editStr);
+            let selStr = "<select class='selDemo' id='diySelect_" + treeNode.tId + "'><option value='=='>等于</option><option value='==='>全等于</option><option value='>'>大于</option><option value='>='>大于等于</option><option value='<'>小于</option><option value='<='>小于等于</option><option value='!='>不等于</option><option value='in'>在</option><option value='not in'>不在</option></select>";
+            aObj.after(selStr);
+            let sel = $("#diySelect_" + treeNode.tId);
+            if (sel) {
+                sel.bind("change", me.filterConditionChange);
+            }
+            sel = $("#diyInput_" + treeNode.tId);
+            if (sel) {
+                sel.bind("change", me.filterCompareValChange);
+            }
+            sel = $("#diyDataDetailSelect_" + treeNode.tId);
+            if (sel) {
+                sel.bind("change", me.filterIndividualCompareObjKeyChange);
+            }
+        } else {
+            //注意:这是后面的DOM先生成
+            let dataDtlSelStr = me.build_filter_handle_data_detail_selection_str(treeId,treeNode);
+            aObj.after(dataDtlSelStr);
+            let dataSelStr = me.build_filter_handle_data_selection_str(treeId,treeNode);
+            aObj.after(dataSelStr);
+            let editStr = "<input type='text' id='diyInput_" + treeNode.tId + "' width='10'/>";
+            aObj.after(editStr);
+            let selStr = "<select class='selDemo' id='diySelect_" + treeNode.tId + "'><option value='=='>等于</option><option value='==='>全等于</option><option value='>'>大于</option><option value='>='>大于等于</option><option value='<'>小于</option><option value='<='>小于等于</option><option value='!='>不等于</option><option value='in'>在</option><option value='not in'>不在</option></select>";
+            aObj.after(selStr);
+            let sel = $("#diySelect_" + treeNode.tId);
+            if (sel) {
+                sel.bind("change", me.filterConditionChange);
+            }
+            sel = $("#diyInput_" + treeNode.tId);
+            if (sel) {
+                sel.bind("change", me.filterCompareValChange);
+            }
+            sel = $("#diyDataSelect_" + treeNode.tId);
+            if (sel) {
+                sel.bind("change", me.filterCompareObjChange);
+            }
+            sel = $("#diyDataDetailSelect_" + treeNode.tId);
+            if (sel) {
+                sel.bind("change", me.filterCompareObjKeyChange);
+            }
         }
     },
     filterCompareValChange(event) {
@@ -780,6 +949,18 @@ let preHandleFilterObj = {
         node[JV.PROP_FILTER_COMPARE_VAL] = sel.value;
         me.resetFilter();
     },
+    filterConditionCheck: function (event) {
+        let me = preHandleFilterObj, sel = event.currentTarget, tId = sel.id.slice(9);
+        let node = me.treeObj.getNodeByTId(tId);
+        node[JV.PROP_FILTER_CONDITION] = "===";
+        if (sel.checked === true) {
+            node[JV.PROP_FILTER_COMPARE_VAL] = node.booleanOptions[0];
+        } else {
+            node[JV.PROP_FILTER_COMPARE_VAL] = node.booleanOptions[1];
+        }
+        //注:这里虽然是boolean选项,但实际有可能是0,1的选择(非true,false),所以需要设置node节点的booleanOptions
+        me.resetFilter();
+    },
     filterConditionChange: function(event) {
         let me = preHandleFilterObj, sel = event.currentTarget, tId = sel.id.slice(10);
         let node = me.treeObj.getNodeByTId(tId);
@@ -809,6 +990,16 @@ let preHandleFilterObj = {
         me.private_setup_compare_obj(sel);
         me.resetFilter();
     },
+    filterIndividualCompareObjKeyChange: function(event) {
+        let me = preHandleFilterObj, sel = event.currentTarget, tId = sel.id.slice(20);
+        let inTxt = $("#diyInput_" + tId);
+        if (inTxt) {
+            inTxt[0].value = sel.value;
+        }
+        let node = me.treeObj.getNodeByTId(tId);
+        node[JV.PROP_FILTER_COMPARE_VAL] = sel.value;
+        me.resetFilter();
+    },
     filterCompareObjKeyChange: function(event) {
         let me = preHandleFilterObj, sel = event.currentTarget, tId = sel.id.slice(20);
         let node = me.treeObj.getNodeByTId(tId);
@@ -816,18 +1007,27 @@ let preHandleFilterObj = {
         me.resetFilter();
     },
     extractTabFields: function (handleObj) {
-        let me = this, rst = {};
-        rst[JV.PROP_HANDLE_TYPE] = handleObj[JV.PROP_HANDLE_TYPE];
-        rst[JV.PROP_DATA_KEY] = handleObj[JV.PROP_DATA_KEY];
-        rst[JV.PROP_FILTER_KEYS] = [];
-        for (let item of handleObj[JV.PROP_FILTER_KEYS]) {
-            let dtl = {};
-            dtl.key = item.key;
-            dtl[JV.PROP_FILTER_CONDITION] = item[JV.PROP_FILTER_CONDITION];
-            dtl[JV.PROP_FILTER_COMPARE_VAL] = item[JV.PROP_FILTER_COMPARE_VAL]?item[JV.PROP_FILTER_COMPARE_VAL]:null;
-            dtl[JV.PROP_FILTER_COMPARE_OBJ] = item[JV.PROP_FILTER_COMPARE_OBJ]?item[JV.PROP_FILTER_COMPARE_OBJ]:null;
-            dtl[JV.PROP_FILTER_COMPARE_OBJ_KEY] = item[JV.PROP_FILTER_COMPARE_OBJ_KEY]?item[JV.PROP_FILTER_COMPARE_OBJ_KEY]:null;
-            rst[JV.PROP_FILTER_KEYS].push(dtl);
+        let me = preHandleFilterObj, rst = {};
+        me.copyNode(handleObj, rst);
+        rst[JV.PROP_OTHER_SUB_FILTER] = [];
+        let private_extract_other_sub_filter = function (parentFilter, currentFilterNode) {
+            let dtlRst = {};
+            me.copyNode(currentFilterNode, dtlRst);
+            parentFilter[JV.PROP_OTHER_SUB_FILTER].push(dtlRst);
+            if (currentFilterNode.items && currentFilterNode.items.length > 0) {
+                dtlRst[JV.PROP_OTHER_SUB_FILTER] = [];
+                for (let subFilterNode of currentFilterNode.items) {
+                    private_extract_other_sub_filter(dtlRst, subFilterNode);
+                }
+            }
+            delete dtlRst.Name;
+            delete dtlRst[JV.PROP_DATA_KEY];
+            dtlRst = null;
+        };
+        if (handleObj.items && handleObj.items.length > 0) {
+            for (let subFilter of handleObj.items) {
+                private_extract_other_sub_filter(rst, subFilter);
+            }
         }
         return rst;
     }

+ 2 - 2
web/maintain/report/rpt_tpl_detail_calculation.html

@@ -8,7 +8,7 @@
         </div>
         <div class="p-3" id="exprDetail">
             <div class="row">
-                <div class="form-group col-md-3">
+                <div class="form-group col-md-5">
                     <label></label>
                     <select class="form-control" id="exprTemplatesSelect"></select>
                 </div>
@@ -28,7 +28,7 @@
                 </div>
             </div>
             <div class="form-group">
-                <textarea rows="16" cols="118" id="exprContent" onkeyup="calculationTreeOprObj.changeExpression(this)"></textarea>
+                <textarea rows="16" cols="108" id="exprContent" onkeyup="calculationTreeOprObj.changeExpression(this)"></textarea>
             </div>
         </div>
     </div>

+ 13 - 22
web/maintain/report/rpt_tpl_detail_field_location.html

@@ -2,14 +2,22 @@
     <div class="main-data">
         <div class="p-3">
             <div class="row">
-                <div class="form-group col-md-8">
-                    <div class="ztree-warp">
+                <div class="form-group col-md-8" style="max-height: 410px;">
+                    <div class="ztree-warp" style="height: 410px;">
                         <ul id="tpl_data_info_reversed" class="ztree"></ul>
                     </div>
                 </div>
-                <div class="form-group col-md-4" id="band_tree2_div">
-                    <div class="ztree-warp">
-                        <ul id="band_tree2_reversed" class="ztree"></ul>
+                <div class="form-group col-md-4" style="max-height: 410px;">
+                    <div class="tab-bar">
+                        <div class="form-group">
+                            <div class="ztree-warp" style="height: 130px;">
+                                <ul id="tpl_discrete_fields_params_reversed" class="ztree"></ul>
+                            </div>
+                            <br/>
+                            <div class="ztree-warp" style="height: 240px;">
+                                <ul id="tpl_data_selected_field_map_reversed" class="ztree"></ul>
+                            </div>
+                        </div>
                     </div>
                 </div>
             </div>
@@ -158,23 +166,6 @@
                     <input class="form-control" id="eleDftValue" value="" onkeyup="rpt_tpl_cfg_helper.changeDftValue(this)">
                 </div>
             </div>
-            <br/>
-            <div class="row">
-                <div class="form-group col-md-7">
-                    <div class="form-group">
-                        <label>已选映射指标</label>
-                        <div class="ztree-warp">
-                            <ul id="tpl_data_selected_field_map_reversed" class="ztree"></ul>
-                        </div>
-                    </div>
-                </div>
-                <div class="form-group col-md-5">
-                    <div class="ztree-warp">
-                        <label>离散独立指标/参数</label>
-                        <ul id="tpl_discrete_fields_params_reversed" class="ztree"></ul>
-                    </div>
-                </div>
-            </div>
         </div>
     </div>
 </div>

+ 2 - 2
web/maintain/report/rpt_tpl_detail_mapping_fields.html

@@ -4,13 +4,13 @@
             <div class="row">
                 <div class="form-group col-md-6">
                     <label>报表映射指标(勾选表示:主从关系的ID关联指标)</label>
-                    <div style="max-height: 750px; overflow: auto">
+                    <div style="max-height: 720px; overflow: auto">
                         <ul id="field_map_tree_reversed" class="ztree"></ul>
                     </div>
                 </div>
                 <div class="form-group col-md-6">
                     <label>可映射指标</label>
-                    <div style="max-height: 750px; overflow: auto">
+                    <div style="max-height: 720px; overflow: auto">
                         <ul id="selectable_field_tree_reversed" class="ztree"></ul>
                     </div>
                 </div>

+ 12 - 14
web/maintain/report/rpt_tpl_main.html

@@ -16,6 +16,10 @@
     <!--zTree-->
     <link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
     <style type="text/css">
+        .ztree li a input.individualRename {height:14px; width:260px; padding:0; margin:0;
+            font-size:12px; border:1px #7EC4CC solid; *border:0px}
+    </style>
+    <style type="text/css">
         .ztree li span.button.add{margin-right:2px;background-position:-144px 0;vertical-align:top;*vertical-align:middle}
     </style>
     <script>
@@ -48,34 +52,28 @@
                 </li>
             </ul>
             </div>
-            <div>
-                <label class="form-check-label">
-                    <input class="form-check-input" type="radio" name="rpt_templates_type_grp" id="commonRptOpt" checked="true" onchange="zTreeOprObj.changeUser(this)"> 公共类型
-                </label>
-                <label class="form-check-label"> </label>
-                <label class="form-check-label">
-                    <input class="form-check-input" type="radio" name="rpt_templates_type_grp" id="custRptOpt" onchange="zTreeOprObj.changeUser(this)"> 定制类型
-                </label>
-                <label class="form-check-label"> </label>
-            </div>
+            <!--
             <div class="btn-group">
                 <div class="input-group">
-                    <input type="text" class="form-control input-sm" id="rpt_user_input" placeholder="手机/邮箱/姓名/公司" disabled="true">
+                    <input type="text" class="form-control input-sm" id="rpt_user_input" placeholder="手机/邮箱/姓名/公司" list="users_list">
+                    <datalist id=users_list>
+                    </datalist>
                     <span class="input-group-btn">
-                        <button class="btn btn-primary" id="rpt_user_find_btn" onclick="" disabled="true">查询</button>
+                        <button class="btn btn-primary" id="rpt_user_find_btn" onclick="userListObj.findUser()">查询</button>
                     </span>
                 </div>
             </div>
+            -->
         </nav>
     </div>
     <div class="main">
         <div class="content">
             <div class="container-fluid">
                 <div class="row">
-                    <div class="main-side col-lg-2 p-0">
+                    <div class="main-side col-lg-3 p-0">
                         <%include ./rpt_tpl_tree.html %>
                     </div>
-                    <div class="main-content col-lg-10 p-0">
+                    <div class="main-content col-lg-9 p-0">
                         <div class="container-fluid">
                             <div class="row">
                                 <!-- 报表设置 -->

+ 10 - 7
web/maintain/report/rpt_tpl_tree.html

@@ -1,9 +1,12 @@
-<div class="tab-bar">
-    <a onclick="zTreeOprObj.addRootNode()" class="btn btn-secondary btn-sm fa fa-plus-square">项目类型</a>
-    <a onclick="zTreeOprObj.addTplNode()" class="btn btn-secondary btn-sm fa fa-plus-square">报表模板</a>
-    <a onclick="zTreeOprObj.moveDownNode()" class="btn btn-sm" id="downMove"><i class="fa fa-arrow-down" aria-hidden="true"></i>下移</a>
-    <a onclick="zTreeOprObj.moveUpNode()" class="btn btn-sm" id="upMove"><i class="fa fa-arrow-up" aria-hidden="true"></i>上移</a>
-</div>
-<div class="tab-content">
+<div class="sub-button p-1">
+    <div class="input-group">
+        <input type="text" class="form-control input-sm" id="rpt_user_input1" placeholder="姓名/手机/邮箱/公司" list="users_list1">
+        <datalist id=users_list1>
+        </datalist>
+        <span class="input-group-btn">
+            <button class="btn btn-primary" id="rpt_user_find_btn1" onclick="userListObj.findUser()">查询</button>
+        </span>
+    </div>
+    <label> </label>
     <ul id="rptTplTree" class="ztree"></ul>
 </div>

File diff suppressed because it is too large
+ 26 - 5
web/maintain/std_glj_lib/html/gongliao.html


+ 12 - 10
web/maintain/std_glj_lib/html/main.html

@@ -4,7 +4,7 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     <meta http-equiv="x-ua-compatible" content="ie=edge">
-    <title>工料机库编辑器</title>
+    <title>人材机库编辑器</title>
     <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
     <link rel="stylesheet" href="/web/maintain/std_glj_lib/css/main.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
@@ -21,7 +21,7 @@
         <nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0">
           <ul class="nav navbar-nav px-1">
               <li class="nav-item">
-                  <a class="nav-link" href="javacript:void(0);" aria-haspopup="true" aria-expanded="false" data-toggle="modal" data-target="#add">新建工料机库</a>
+                  <a class="nav-link" href="javacript:void(0);" aria-haspopup="true" aria-expanded="false" data-toggle="modal" data-target="#add">新建人材机库</a>
               </li>
           </ul>
         </nav>
@@ -33,7 +33,7 @@
                   <div class="col-md-8">
                     <div class="warp-p2 mt-3">
                       <table class="table table-hover table-bordered">
-                        <thead><tr><th>工料机库名称</th><th>编办</th><th>定额库</th><th width="160">添加时间</th><th width="90">操作</th></tr></thead>
+                        <thead><tr><th>人材机库名称</th><th>编办</th><th>定额库</th><th width="160">添加时间</th><th width="90">操作</th></tr></thead>
                         <tbody id="showArea">
                       <!--    <tr><td><a href="gongliao.html">XX工料机库</a></td><td>重庆2018</td><td>XXX定额库(重庆2018)</td><td>2017-01-01 </td><td><a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a> <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>
                           <tr><td><a href="gongliao.html">XX工料机库</a></td><td>重庆2018</td><td></td><td>2017-01-01 </td><td><a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a> <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>
@@ -51,7 +51,7 @@
         <div class="modal-dialog" role="document">
             <div class="modal-content">
                 <div class="modal-header">
-                  <h5 class="modal-title">添加工料机库</h5>
+                  <h5 class="modal-title">添加人材机库</h5>
                   <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                     <span aria-hidden="true">×</span>
                   </button>
@@ -59,8 +59,8 @@
                 <div class="modal-body">
                   <form>
                     <div class="form-group">
-                      <label>工料机名称</label>
-                      <input id="libNameTxt" class="form-control" placeholder="输入工料机库名称" type="text">
+                      <label>人材机名称</label>
+                      <input id="libNameTxt" class="form-control" placeholder="输入人材机库名称" type="text">
                     </div>
                     <div class="form-group">
                       <label>编办名称</label>
@@ -80,7 +80,7 @@
         <div class="modal-dialog" role="document">
             <div class="modal-content">
                 <div class="modal-header">
-                  <h5 class="modal-title">编辑工料机库</h5>
+                  <h5 class="modal-title">编辑人材机库</h5>
                   <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                     <span aria-hidden="true">×</span>
                   </button>
@@ -88,8 +88,8 @@
                 <div class="modal-body">
                   <form>
                     <div class="form-group">
-                      <label>工料机库名称</label>
-                      <input class="form-control" id="renameText" placeholder="输入工料机库名称" type="text" value="">
+                      <label>人材机库名称</label>
+                      <input class="form-control" id="renameText" placeholder="输入人材机库名称" type="text" value="">
                     </div>
                     <div class="form-group">
                       <label>编办名称</label>
@@ -119,8 +119,8 @@
                     <h5 class="text-danger">删除后无法恢复,确认是否删除?</h5>
                 </div>
                 <div class="modal-footer">
+                    <a id="deleteA" href="javascript: void(0);" class="btn btn-danger">确认</a>
                     <button id="delCancelBtn" type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                    <a id="deleteA" href="javascript: void(0);" class="btn btn-danger">删除</a>
                 </div>
             </div>
         </div>
@@ -130,6 +130,8 @@
     <script src="/lib/tether/tether.min.js"></script>
     <script src="/lib/bootstrap/bootstrap.min.js"></script>
     <script src="/web/maintain/std_glj_lib/js/global.js"></script>
+    <script src="/public/web/common_ajax.js"></script>
+    <script src="/public/web/PerfectLoad.js"></script>
     <!-- zTree -->
   	<script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
   	<script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>

+ 59 - 30
web/maintain/std_glj_lib/js/glj.js

@@ -52,7 +52,7 @@ let repositoryGljObj = {
             {headerName:"编码",headerWidth:80,dataCode:"code", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
             {headerName:"名称",headerWidth:160,dataCode:"name", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
             {headerName:"规格型号",headerWidth:120,dataCode:"specs", dataType: "String", formatter: "@", hAlign: "left", vAlign: "center"},
-            {headerName:"单位",headerWidth:45,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
+            {headerName:"单位",headerWidth:60,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
             {headerName:"定额价",headerWidth:80,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right", vAlign: "center"},
             {headerName:"类型",headerWidth:90,dataCode:"gljType", dataType: "String", hAlign: "center", vAlign: "center"},
             {headerName:"调整系数",headerWidth:60,dataCode:"adjCoe", dataType: "Number", hAlign: "center", vAlign: "center"},
@@ -67,6 +67,21 @@ let repositoryGljObj = {
             ]
         }
     },
+    setUnitCombo: function (sheet, headers) {
+        let me = this;
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        let combo = sheetCommonObj.getDynamicCombo();
+        combo.items(rationAndGljUnits).itemHeight(10).editable(true);
+        for(let i = 0; i < headers.length; i++){
+            if(headers[i].dataCode === 'unit'){
+                sheet.getRange(-1, i, -1, 1).cellType(combo);
+                break;
+            }
+        }
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
     getComboData: function (gljDistType) {
         let me = this;
         let distType;
@@ -127,7 +142,7 @@ let repositoryGljObj = {
                     if(result.data.length > 0){
                         me.rationLibs = result.data[0].rationLibs;
                         $(".navbar-text").append(
-                            "<a href='/stdGljRepository/main'>工料机库</a><i class='fa fa-angle-right fa-fw'></i>"+result.data[0].dispName
+                            "<a href='/stdGljRepository/main'>人材机库</a><i class='fa fa-angle-right fa-fw'></i>"+result.data[0].dispName
                         );
                         pageOprObj.gljLibName = result.data[0].dispName;
                     }
@@ -197,12 +212,14 @@ let repositoryGljObj = {
             sheetCommonObj.setDynamicCombo(me.workBook.getActiveSheet(), 0, 5, me.workBook.getActiveSheet().getRowCount(), me.distTypeTree.comboDatas, false, 'text');
             sheetCommonObj.setDynamicCombo(me.workBook.getActiveSheet(), 0, 7, me.workBook.getActiveSheet().getRowCount(), me.materialType.comboItems, false, 'text');
             cacheSection = null;
+            me.initSel(0);
         }
     },
     buildSheet: function(container) {
         let me = repositoryGljObj;
         me.workBook = sheetCommonObj.buildSheet(container, me.setting, 30, me);
         me.repositoryGljDelOpr();
+        me.setUnitCombo(me.workBook.getActiveSheet(), me.setting.header);
         me.workBook.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
         me.workBook.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.EditStarting, me.onCellEditStart);
@@ -304,44 +321,56 @@ let repositoryGljObj = {
             }
         }
     },
+    initSel: function (row) {
+        let me = repositoryGljObj, that = gljComponentOprObj;
+        sheetCommonObj.cleanSheet(that.workBook.getSheet(0), that.setting, -1);
+        me.workBook.focus(true);
+        me.currentComponent = [];
+        that.workBook.getSheet(0).setRowCount(10);
+        if(row < me.currentCache.length){
+            //标记当前工料机
+            me.currentGlj = me.currentCache[row];
+            if(me.allowComponent.indexOf(me.currentCache[row].gljType) !== -1){
+                //展示数据
+                if(me.currentGlj.component.length > 0){
+                    me.currentComponent = me.getCurrentComponent(me.currentGlj.component);
+                    if(me.currentComponent.length > 0){
+                        sheetsOprObj.showData(that.workBook.getSheet(0), that.setting, me.currentComponent);
+                    }
+                }
+            }
+        }
+        else{
+            me.currentGlj = null;
+        }
+    },
     onSelectionChanged: function (sender, info) {
         let me = repositoryGljObj, that = gljComponentOprObj;
         //混凝土202、砂浆203、配合比204、机械3
         if(info.oldSelections.length === 0 && info.newSelections.length > 0 || info.oldSelections[0].row !== info.newSelections[0].row){
             let row = info.newSelections[0].row;
-            sheetCommonObj.cleanSheet(that.workBook.getSheet(0), that.setting, -1);
-            me.workBook.focus(true);
-            me.currentComponent = [];
-            that.workBook.getSheet(0).setRowCount(10);
-            if(row < me.currentCache.length){
-                //标记当前工料机
-                me.currentGlj = me.currentCache[row];
-                if(me.allowComponent.indexOf(me.currentCache[row].gljType) !== -1){
-                    //展示数据
-                    if(me.currentGlj.component.length > 0){
-                        me.currentComponent = me.getCurrentComponent(me.currentGlj.component);
-                        if(me.currentComponent.length > 0){
-                            sheetsOprObj.showData(that.workBook.getSheet(0), that.setting, me.currentComponent);
-                        }
-                    }
-                }
-            }
-            else{
-                me.currentGlj = null;
-            }
+            me.initSel(row);
         }
     },
     onLeaveCell: function (sender, args) {
         let me = repositoryGljObj;
-        me.lastCol = args.col
+        me.lastCell = {row: args.row, col: args.col};
     },
     onEnterCell: function (sender, args) {
         let me = repositoryGljObj;
         let thisDataCode = me.setting.header[args.col].dataCode,
-            lastDataCode = me.setting.header[me.lastCol].dataCode;
-        if(thisDataCode === 'gljType' || lastDataCode === 'gljType'
+            lastDataCode = me.setting.header[me.lastCell.col].dataCode;
+        if(thisDataCode === 'unit'|| lastDataCode === 'unit' || thisDataCode === 'gljType' || lastDataCode === 'gljType'
             || thisDataCode === 'materialType' || lastDataCode === 'materialType'){
-            args.sheet.repaint();
+            let rects = [];
+            rects.push(args.sheet.getCellRect(args.row, args.col));
+            if(me.lastCell){
+                rects.push(args.sheet.getCellRect(me.lastCell.row, me.lastCell.col));
+            }
+            for(let rect of rects){
+                args.sheet.repaint(rect);
+            }
+            //args.sheet.repaint();
         }
         me.cellRowIdx = args.row;
         let isHasData = false;
@@ -359,15 +388,15 @@ let repositoryGljObj = {
                 let focusToCol;
                 function getFocusToCol (me){
                     if(!me.addGljObj[me.setting.header[0].dataCode]){
-                        $('#alertGljTxt').text('编号不能为空,继续增加工料机?');
+                        $('#alertGljTxt').text('编号不能为空,继续增加人材机?');
                         return 0;
                     }
                     else if(!me.addGljObj[me.setting.header[1].dataCode]){
-                        $('#alertGljTxt').text('名称不能为空,继续增加工料机?');
+                        $('#alertGljTxt').text('名称不能为空,继续增加人材机?');
                         return 1;
                     }
                     else if(!me.addGljObj[me.setting.header[5].dataCode]){
-                        $('#alertGljTxt').text('类型不能为空,继续增加工料机?');
+                        $('#alertGljTxt').text('类型不能为空,继续增加人材机?');
                         return 5;
                     }
                     else {
@@ -646,7 +675,7 @@ let repositoryGljObj = {
                 }
                 if(removeArr.length > 0 || updateArr.length > 0){
                     //删除警告
-                    let upAlertText = removeArr.length > 0 ? '可能已有定额引用了当前工料机,导致定额查找不到此工料机。确定要删除吗?' : '确认删除选中字段?';
+                    let upAlertText = removeArr.length > 0 ? '可能已有定额引用了当前人材机,导致定额查找不到此人材机。确定要删除吗?' : '确认删除选中字段?';
                     $('#alertGljTxt').text(upAlertText);
                     $('#gljAlertBtn').click();
                     //确认

+ 10 - 5
web/maintain/std_glj_lib/js/gljClassTree.js

@@ -48,6 +48,7 @@ let gljClassTreeObj = {
         },
         options: {
             tabStripVisible:  false,
+            allowContextMenu: false,
             allowCopyPasteExcelStyle : false,
             allowExtendPasteRange: false,
             allowUserDragDrop : false,
@@ -238,8 +239,12 @@ let gljClassTreeObj = {
         me.insertBtn.click(function () {
             me.insert();
         });
-        me.removeBtn.click(function () {
+        $('#delConfirm').click(function () {
             me.remove(me.tree.selected);
+            $('#delAlert').modal('hide');
+        });
+        me.removeBtn.click(function () {
+            $('#delAlert').modal('show');
         });
         me.upLevelBtn.click(function () {
             me.upLevel(me.tree.selected);
@@ -281,8 +286,8 @@ let gljClassTreeObj = {
                 me.controller.insert();
                 me.refreshBtn(me.tree.selected);
                 //fresh tools
-                me.initTools(me.tree.selected);
                 re.updateParentNodeIds(me.cache, re);
+                me.initSelection(me.tree.selected);
             });
         }
     },
@@ -320,8 +325,9 @@ let gljClassTreeObj = {
             me.gljClassTreeAjax(postData, function (rstData) {
                 me.controller.delete();
                 me.refreshBtn(me.tree.selected);
-                me.initTools(me.tree.selected);
                 re.updateParentNodeIds(me.cache, re);
+                me.initSelection(me.tree.selected);
+                me.workBook.getActiveSheet().setActiveCell(me.tree.selected ? me.tree.selected.serialNo() : 0, 0);
             });
         }
     },
@@ -478,11 +484,10 @@ let gljClassTreeObj = {
         let me = this,
             re = repositoryGljObj,
             that = gljComponentOprObj;
+        me.refreshBtn(node);
         if(!re.isDef(node)){
             return;
         }
-        me.refreshBtn(node);
-
         let gljTypeId = node.data.ID;
         re.gljCurTypeId = node.data.ID;
         re.addGljObj = null;

+ 3 - 2
web/maintain/std_glj_lib/js/gljComponent.js

@@ -4,6 +4,7 @@
 
 let gljComponentOprObj = {
     workBook: null,
+    processDecimal: -6,
     setting: {
         owner: "gljComponent",
         header:[
@@ -303,7 +304,7 @@ let gljComponentOprObj = {
                 }
             }
             if(!hasCode){
-                alert("不存在此工料机,请先添加!");
+                alert("不存在此人材机,请先添加!");
                 args.sheet.setValue(args.row, args.col, me.currentEditingComponent[me.setting.header[args.col].dataCode] ?
                     me.currentEditingComponent[me.setting.header[args.col].dataCode] : '');
                 //不存在
@@ -507,7 +508,7 @@ let gljComponentOprObj = {
             let roundBasePrc = scMathUtil.roundTo(parseFloat(component[i].basePrice), -2);
             let roundConsumeAmt = scMathUtil.roundTo(parseFloat(component[i].consumeAmt), -3);
             //gljBasePrc = scMathUtil.roundTo(scMathUtil.roundTo(roundBasePrc * parseFloat(component[i].consumeAmt), -2) + gljBasePrc, -2); 旧算法
-            gljBasePrc = roundBasePrc * roundConsumeAmt + gljBasePrc;
+            gljBasePrc = scMathUtil.roundTo(scMathUtil.roundTo(roundBasePrc * roundConsumeAmt, me.processDecimal) + gljBasePrc, me.processDecimal);
         }
         return scMathUtil.roundTo(gljBasePrc, -2);
     }

+ 28 - 9
web/maintain/std_glj_lib/js/main.js

@@ -5,6 +5,11 @@ $(function () {
     let dispNameArr;
     let compilationsArr;
     let usedCom;
+    let deleteCount = 0;
+    let preDeleteId = null;
+    $('#del').on('hidden.bs.modal', function () {
+        deleteCount = 0;
+    });
     getCompilationList(function (datas) {
         compilationsArr = datas;
         getAllGljLib(function (dispNames, compilationsUsedArr) {
@@ -24,7 +29,7 @@ $(function () {
                     $('#libNameTxt').val('')
                 }
                 else if(dispNames.indexOf(libName) !== -1){
-                    alert('此工料机库已存在!');
+                    alert('此人材机库已存在!');
                     $('#libNameTxt').val('')
                 }
                 else if(compilationName.trim().length === 0){
@@ -58,7 +63,7 @@ $(function () {
                     $("#renameText").val('');
                 }
                 else if(dispNameArr.indexOf(newName) !== -1){
-                    alert("该工料机库已存在!");
+                    alert("该人材机库已存在!");
                     $("#renameText").val('');
                 }
                 else{
@@ -72,16 +77,24 @@ $(function () {
             });
             $("#deleteA").click(function(){
                 let deleteId = $(this).attr("deleteId");
+                if(preDeleteId && preDeleteId !== deleteId){
+                    deleteCount = 0;
+                }
+                preDeleteId = deleteId;
+                deleteCount++;
                 let jqSel = "#" + deleteId + " td:first" + " a";
                 let libName = $(jqSel).text();
                 let compilationName = $("#" + deleteId + " td:eq(1)").text();
-                for(let i = 0, len = compilationsArr.length; i < len; i++){
-                    if(compilationsArr[i].name === compilationName.trim()){
-                        usedCom.splice(usedCom.indexOf(compilationsArr[i]._id), 1);
-                        break;
+                if(deleteCount === 3){
+                    for(let i = 0, len = compilationsArr.length; i < len; i++){
+                        if(compilationsArr[i].name === compilationName.trim()){
+                            usedCom.splice(usedCom.indexOf(compilationsArr[i]._id), 1);
+                            break;
+                        }
                     }
+                    removeGljLib({libId: deleteId, libName: libName}, dispNameArr);
+                    deleteCount = 0;
                 }
-                removeGljLib({libId: deleteId, libName: libName}, dispNameArr);
             });
 
 
@@ -197,6 +210,7 @@ function renameGljLib(renameObj, dispNames){
     })
 }
 function removeGljLib(delObj, dispNames){
+    $.bootstrapLoading.start();
     $.ajax({
         type: 'post',
         url: 'api/removeGljLib',
@@ -204,9 +218,9 @@ function removeGljLib(delObj, dispNames){
         dataType: 'json',
         success: function (result) {
             if(!result.error){
-                if(result.message === '此工料机库已被引用!'){
+                if(result.message === '此人材机库已被引用!'){
                     $('#delCancelBtn').click();
-                    alert("此工料机库已被引用,不可删除!");
+                    alert("此人材机库已被引用,不可删除!");
                 }
                 else if(result.message === '删除成功'){
                     var jqSel = "#"+ delObj.libId;
@@ -216,6 +230,11 @@ function removeGljLib(delObj, dispNames){
                     $('#delCancelBtn').click();
                 }
             }
+            $.bootstrapLoading.end();
+        },
+        error: function () {
+            alert('服务器出错!');
+            $.bootstrapLoading.end();
         }
     })
 }

+ 47 - 5
web/users/js/compilation.js

@@ -25,7 +25,7 @@ $(document).ready(function() {
     $("#add-compilation").click(function() {
         try {
             let data = getAndValidData(model);
-            let url = '/compilation/add';
+            let url = '/compilation/add'
             if (model === 'all') {
                 // 新增编办操作
                 $.ajax({
@@ -131,6 +131,10 @@ $(document).ready(function() {
                 $("#glj-area").show();
                 $("#add-compilation-title").text('添加定额库');
                 break;
+            case 'billsGuidance':
+                $("#billsGuidance-area").show();
+                $("#add-compilation-title").text('添加清单指引库');
+                break;
             case 'fee':
                 $("#fee-area").show();
                 $("#add-compilation-title").text('添加费率标准');
@@ -160,10 +164,26 @@ $(document).ready(function() {
     });
 
     // 移除操作
-    $(".bill-list, .ration-list, .glj-list, .fee-list, .artificial-list, .program-list").on("click", ".remove-lib", function() {
+    $(".bill-list, .ration-list, .glj-list, .fee-list, .artificial-list, .program-list, .billsGuidance-list").on("click", ".remove-lib", function() {
         $(this).parent().remove();
     });
 
+    //更改描述
+    $('#description').change(function () {
+        let description = $(this).val();
+        $.ajax({
+            url: '/compilation/setDescription',
+            type: 'post',
+            dataType: "json",
+            data: {id: id, description: description},
+            success: function(response) {
+                if (response.err !== 0) {
+                    alert('更改失败');
+                }
+            }
+        });
+    });
+
     // 计价规则启用/禁止
     $(".enable").click(function() {
         let goingChangeStatus = switchChange($(this));
@@ -196,7 +216,6 @@ $(document).ready(function() {
     //计价规则删除
     $('#delete-confirm').click(function () {
         let id = $('#del').attr('selectedId');
-        console.log(id);
         if (id === undefined || id === '') {
             return false;
         }
@@ -250,6 +269,7 @@ function initCompilation() {
     let feeLibData = feeRateList === undefined ? [] : JSON.parse(feeRateList);
     let artificialCoefficientData = artificialCoefficientList === undefined ? [] : JSON.parse(artificialCoefficientList);
     let programData = programList === undefined ? [] : JSON.parse(programList);
+    let billsGuidanceData = billsGuidanceList === undefined ? [] : JSON.parse(billsGuidanceList);
 
     mainTreeCol = mainTreeCol !== '' ? mainTreeCol.replace(/\n/g, '\\n') : mainTreeCol;
     billsTemplateData = billsTemplateData.replace(/\n/g, '\\n');
@@ -294,6 +314,14 @@ function initCompilation() {
     }
     $("select[name='glj_lib']").children("option").first().after(html);
 
+    // 清单指引库
+    html = '';
+    for(let tmp of billsGuidanceData) {
+        let tmpHtml = '<option value="' + tmp.ID + '">' + tmp.name + '</option>';
+        html += tmpHtml;
+    }
+    $("select[name='billsGuidance_lib']").children("option").first().after(html);
+
     // 费率标准库
     html = '';
     for(let tmp of feeLibData) {
@@ -334,6 +362,7 @@ function getAndValidData(model) {
     let feeLib = $("select[name='fee_lib']").children("option:selected").val();
     let artificialLib = $("select[name='artificial_lib']").children("option:selected").val();
     let programLib = $("select[name='program_lib']").children("option:selected").val();
+    let billsGuidanceLib = $("select[name='billsGuidance_lib']").children("option:selected").val();
 
     if (name === '' && model === 'all') {
         throw '编办名字不能为空';
@@ -348,7 +377,7 @@ function getAndValidData(model) {
     }
 
     if (model === 'glj' && (gljLib === '' || gljLib === undefined)) {
-        throw '请选择工料机库';
+        throw '请选择人材机库';
     }
 
     if (model === 'fee' && (feeLib === '' || feeLib === undefined)) {
@@ -363,12 +392,17 @@ function getAndValidData(model) {
         throw '请选择计算程序';
     }
 
+    if (model === 'billsGuidance' && (billsGuidanceLib === '' || billsGuidanceLib === undefined)) {
+        throw '请选择清单指引库';
+    }
+
     let standardBillString = $("select[name='standard_bill']").children("option:selected").text();
     let rationLibString = $("select[name='ration_lib']").children("option:selected").text();
     let gljLibString = $("select[name='glj_lib']").children("option:selected").text();
     let feeLibString = $("select[name='fee_lib']").children("option:selected").text();
     let artificialString = $("select[name='artificial_lib']").children("option:selected").text();
     let programString = $("select[name='program_lib']").children("option:selected").text();
+    let billsGuidanceString = $("select[name='billsGuidance_lib']").children("option:selected").text();
 
     let result = {
         name: name,
@@ -395,6 +429,10 @@ function getAndValidData(model) {
         program: {
             id: programLib,
             name: programString
+        },
+        billsGuidance: {
+            id: billsGuidanceLib,
+            name: billsGuidanceString
         }
     };
     return result;
@@ -427,7 +465,7 @@ function validLib() {
         }
 
         if ($("input:hidden[name='glj_lib']").length <= 0) {
-            throw '请添加工料机库';
+            throw '请添加人材机库';
         }
 
         if ($("input:hidden[name='fee_lib']").length <= 0) {
@@ -442,6 +480,10 @@ function validLib() {
             throw '请添加计算程序';
         }
 
+        if ($("input:hidden[name='billsGuidance_lib']").length <= 0) {
+            throw '请添加清单指引库';
+        }
+
         result = true;
     } catch (error) {
         alert(error);

+ 17 - 0
web/users/js/user.js

@@ -0,0 +1,17 @@
+/**
+ * 消息管理相关js
+ *
+ * @author CaiAoLin
+ * @date 2017/9/21
+ * @version
+ */
+$(document).ready(function() {
+    // 选择框
+    $(".selector > li > a").click(function() {
+        let value = $(this).data("value");
+        let string = $(this).text();
+        let selector = $(this).parent().parent();
+        selector.next("input:hidden").val(value);
+        selector.prev("button").html(string + ' <span class="caret"></span>');
+    });
+});

+ 0 - 0
web/users/views/compilation/add.html


Some files were not shown because too many files changed in this diff