Selaa lähdekoodia

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

Conflicts:
	web/users/js/main_tree_col.js
zhangweicheng 7 vuotta sitten
vanhempi
commit
153134bd48
32 muutettua tiedostoa jossa 2379 lisäystä ja 308 poistoa
  1. 42 0
      modules/ration_repository/controllers/installation_controller.js
  2. 33 12
      modules/ration_repository/models/glj_repository.js
  3. 76 0
      modules/ration_repository/models/installation.js
  4. 85 58
      modules/ration_repository/models/ration_item.js
  5. 16 6
      modules/ration_repository/models/schemas.js
  6. 8 0
      modules/ration_repository/routes/ration_rep_routes.js
  7. 1 0
      modules/reports/rpt_component/helper/jpc_helper_common.js
  8. 20 0
      modules/reports/rpt_component/helper/jpc_helper_field.js
  9. 53 97
      modules/reports/rpt_component/jpc_flow_tab.js
  10. 54 92
      modules/reports/util/rpt_excel_util.js
  11. 4 0
      modules/std_glj_lib/models/gljModel.js
  12. 2 1
      modules/users/models/bills_template_model.js
  13. 81 0
      public/web/PerfectLoad.js
  14. 1 0
      public/web/rpt_value_define.js
  15. 22 2
      public/web/scMathUtil.js
  16. 34 20
      test/demo/stringTest.js
  17. 171 0
      web/maintain/ration_repository/anzhuang.html
  18. 10 3
      web/maintain/ration_repository/dinge.html
  19. 1 0
      web/maintain/ration_repository/js/global.js
  20. 1232 0
      web/maintain/ration_repository/js/installation.js
  21. 13 2
      web/maintain/ration_repository/js/ration.js
  22. 301 0
      web/maintain/ration_repository/js/ration_installation.js
  23. 10 1
      web/maintain/ration_repository/js/section_tree.js
  24. 5 0
      web/maintain/std_glj_lib/html/gongliao.html
  25. 14 6
      web/maintain/std_glj_lib/js/glj.js
  26. 2 0
      web/maintain/std_glj_lib/js/gljComponent.js
  27. 1 0
      web/users/js/col_setting.js
  28. 10 0
      web/users/js/compilation.js
  29. 31 4
      web/users/js/main_tree_col.js
  30. 24 3
      web/users/js/template.js
  31. 2 1
      web/users/views/compilation/index.html
  32. 20 0
      web/users/views/compilation/modal.html

+ 42 - 0
modules/ration_repository/controllers/installation_controller.js

@@ -0,0 +1,42 @@
+/**
+ * Created by Zhong on 2018/1/24.
+ */
+import BaseController from '../../common/base/base_controller';
+import InstallationDao from '../models/installation';
+
+let installationDao = new InstallationDao();
+let callback = function(req,res,err,message, data){
+    res.json({error: err, message: message, data: data});
+};
+
+class InstallationController extends BaseController{
+    getInstallation(req, res){
+        let data = JSON.parse(req.body.data);
+        installationDao.getInstallation(data.rationRepId, function (err, data) {
+            callback(req, res, err, '', data);
+        });
+    }
+
+    updateSection(req, res){
+        let data = JSON.parse(req.body.data);
+        installationDao.updateSection(data.updateData, function (err, data) {
+            callback(req, res, err, '', data);
+        });
+    }
+
+    updateFeeItem(req, res){
+        let data = JSON.parse(req.body.data);
+        installationDao.updateFeeItem(data.updateData, function (err, data) {
+            callback(req, res, err, '', data);
+        });
+    }
+
+    batchUpdateInst(req, res){
+        let data = JSON.parse(req.body.data);
+        installationDao.batchUpdateInst(data.rationSection, data.inst, function (err, data) {
+            callback(req, res, err, '', data);
+        });
+    }
+}
+
+export default InstallationController;

+ 33 - 12
modules/ration_repository/models/glj_repository.js

@@ -74,23 +74,44 @@ gljItemDAO.prototype.getGljItems = function(gljIds, callback){
     })
 };
 
-gljItemDAO.prototype.getStdCompleGljItems = async function (rationGljList, callback) {
+/*gljItemDAO.prototype.getStdCompleGljItems = async function (rationGljList, callback) {
     try{
         let rst = [];
-        for(let i = 0, len = rationGljList.length; i < len; i++){
-            if(rationGljList[i].type !== undefined && rationGljList[i].type === 'complementary'){
-                let compleGlj = await compleGljModel.find({ID: rationGljList[i].gljId, deleteInfo: null});
-                if(compleGlj.length > 0){
-                    rst.push(compleGlj[0]);
-                }
+        let stdIds = [], compleIds = []
+        for(let glj of rationGljList){
+            if(glj.type !== undefined && glj.type === 'complementary'){
+                compleIds.push(glj.gljId);
             }
-            else {
-                let stdGlj = await gljModel.find({ID: rationGljList[i].gljId, $or: [{deleted: null}, {deleted: false}]});
-                if(stdGlj.length > 0){
-                    rst.push(stdGlj[0]);
-                }
+            else{
+                stdIds.push(glj.gljId);
             }
         }
+        if(compleIds.length > 0){
+            let compleGlj = await compleGljModel.find({ID: {$in: compleIds}, deleteInfo: null}, {ID: 1, gljType: 1, basePrice: 1});
+            rst = rst.concat(compleGlj);
+        }
+        if(stdIds.length > 0){
+            let stdGlj = await gljModel.find({ID: {$in: stdIds}, $or: [{deleted: null}, {deleted: false}]}, {ID: 1, gljType: 1, basePrice: 1});
+            rst = rst.concat(stdGlj);
+        }
+        callback(0, rst);
+    }
+    catch(err){
+        callback(err, null);
+    }
+};*/
+
+gljItemDAO.prototype.getStdCompleGljItems = async function (compleGljIds, stdGljIds, callback) {
+    try{
+        let rst = [];
+        if(compleGljIds.length > 0){
+            let compleGlj = await compleGljModel.find({ID: {$in: compleGljIds}, deleteInfo: null}, {ID: 1, gljType: 1, basePrice: 1});
+            rst = rst.concat(compleGlj);
+        }
+        if(stdGljIds.length > 0){
+            let stdGlj = await gljModel.find({ID: {$in: stdGljIds}, $or: [{deleted: null}, {deleted: false}]}, {ID: 1, gljType: 1, basePrice: 1});
+            rst = rst.concat(stdGlj);
+        }
         callback(0, rst);
     }
     catch(err){

+ 76 - 0
modules/ration_repository/models/installation.js

@@ -0,0 +1,76 @@
+/**
+ * Created by Zhong on 2018/1/24.
+ */
+
+import {rationItemModel, installFeeItemModel, installSectionModel} from '../models/schemas';
+
+class InstallationDao{
+    async getInstallation(rationRepId, callback){
+        try {
+            let feeItems = await installFeeItemModel.find({rationRepId: rationRepId, $or: [{deleted: false}, {deleted: null}]});
+            for(let feeItem of feeItems){
+                let sids = [];
+                for(let sec of feeItem.section){
+                    sids.push(sec.ID);
+                }
+                if(sids.length > 0){
+                    let sections = await installSectionModel.find({ID: {$in: sids}, $or: [{deleted: false}, {deleted: null}]});
+                    feeItem._doc.section = sections;
+                }
+            }
+            callback(0, feeItems);
+        }
+        catch(err){
+            callback(err, null);
+        }
+    }
+
+    async updateSection(updateData, callback){
+        try{
+            for(let data of updateData){
+                if(data.updateType === 'new'){
+                    await installSectionModel.create(data.updateData);
+                }
+                else if(data.updateType === 'update'){
+                    await installSectionModel.update({ID: data.updateData.ID}, data.updateData);
+                }
+            }
+            callback(0, null);
+        }
+        catch(err){
+            callback(err, null);
+        }
+    }
+
+    async updateFeeItem(updateData, callback){
+        try{
+            for(let data of updateData){
+                if(data.updateType === 'new'){
+                    await installFeeItemModel.create(data.updateData);
+                }
+                else if(data.updateType === 'update'){
+                    await installFeeItemModel.update({ID: data.updateData.ID}, data.updateData);
+                }
+            }
+            callback(0, null);
+        }
+        catch(err){
+            callback(err, null);
+        }
+    }
+
+    async batchUpdateInst(rationSection, inst, callback){
+        try{
+            for(let sectionId of rationSection){
+                await rationItemModel.update({sectionId: sectionId, $or: [{isDeleted: null}, {isDeleted: false}]},
+                    {$addToSet: {rationInstList: {feeItemId: inst.feeItemId, sectionId: inst.sectionId}}}, {multi: true});
+            }
+            callback(0, null);
+        }
+        catch(err){
+            callback(err, null);
+        }
+    }
+}
+
+export default InstallationDao;

+ 85 - 58
modules/ration_repository/models/ration_item.js

@@ -211,7 +211,6 @@ function round(v,e){
 
 
 rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
-
     async.each(basePrcArr, function (basePrcObj, finalCb) {
         let adjGljId = basePrcObj.gljId, adjBasePrice = basePrcObj.basePrice, adjGljType = basePrcObj.gljType;
         async.waterfall([
@@ -253,12 +252,12 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                     });
                 }
                 else{
-                    rationItemModel.find({'rationGljList.gljId': adjGljId}, function (err, result) {
+                    rationItemModel.find({'rationGljList.gljId': adjGljId}, {ID: 1, rationGljList: 1}, function (err, result) {
                         if(err){
                             cb(err);
                         }
                         else{
-                            compleRationModel.find({'rationGljList.gljId': adjGljId}, function (err, compleRst) {
+                            compleRationModel.find({'rationGljList.gljId': adjGljId}, {ID: 1, rationGljList: 1}, function (err, compleRst) {
                                 if(err){
                                     cb(err);
                                 }
@@ -274,34 +273,53 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                 }
             },
             function (result, cb) {
-                async.each(result, function (rationItem, ecb) {
-                    let rationGljList = rationItem.rationGljList,
-                        gljIds = [];
-                    gljDao.getStdCompleGljItems(rationGljList, function(err, gljItems){
-                        if(err){
-                            ecb(err);
+                let compleRTasks = [], stdRTasks = [];
+                //重算时需要用到的所有工料机,一次性取
+                let compleGljIds = [], stdGljIds = [];
+                for(let ration of result){
+                    for(let glj of ration.rationGljList){
+                        if(glj.type !== undefined && glj.type === 'complementary'){
+                            compleGljIds.push(glj.gljId);
                         }
-                        else{
+                        else {
+                            stdGljIds.push(glj.gljId);
+                        }
+                    }
+                }
+                gljDao.getStdCompleGljItems(compleGljIds, stdGljIds, function (err, allGljs) {
+                    if(err){
+                        cb(err);
+                    }
+                    else {
+                        let gljIndex = {};
+                        for(let glj of allGljs){
+                            gljIndex[glj.ID] = glj;
+                        }
+                        async.each(result, function (rationItem, ecb) {
+                            let rationGljList = rationItem.rationGljList;
                             let gljArr = [];
-                            for(let i=0; i<gljItems.length; i++){
-                                let gljParentType = -1;
-                                if(gljItems[i].ID === adjGljId){
-                                    gljItems[i].gljType = adjGljType;
-                                }
-                                if(gljItems[i].gljType <= 3){
-                                    gljParentType = gljItems[i].gljType;
-                                }
-                                if(gljItems[i].gljType > 200 && gljItems[i].gljType < 300){
-                                    gljParentType = 2;
-                                }
-                                if(gljItems[i].gljType > 300 && gljItems[i].gljType < 400){
-                                    gljParentType = 3;
-                                }
-                                if(gljItems[i].ID === adjGljId){
-                                    gljArr.push({gljId: gljItems[i].ID, basePrice: adjBasePrice, gljParentType: gljParentType});
-                                }
-                                else {
-                                    gljArr.push({gljId: gljItems[i].ID, basePrice: parseFloat(gljItems[i].basePrice), gljParentType: gljParentType});
+                            for(let i=0; i<rationGljList.length; i++){
+                                let theGlj = gljIndex[rationGljList[i].gljId];
+                                if(theGlj !== undefined && theGlj){
+                                    let gljParentType = -1;
+                                    if(theGlj.ID === adjGljId){
+                                        theGlj.gljType = adjGljType;
+                                    }
+                                    if(theGlj.gljType <= 3){
+                                        gljParentType = theGlj.gljType;
+                                    }
+                                    if(theGlj.gljType > 200 && theGlj.gljType < 300){
+                                        gljParentType = 2;
+                                    }
+                                    if(theGlj.gljType > 300 && theGlj.gljType < 400){
+                                        gljParentType = 3;
+                                    }
+                                    if(theGlj.ID === adjGljId){
+                                        gljArr.push({gljId: theGlj.ID, basePrice: adjBasePrice, gljParentType: gljParentType});
+                                    }
+                                    else {
+                                        gljArr.push({gljId: theGlj.ID, basePrice: parseFloat(theGlj.basePrice), gljParentType: gljParentType});
+                                    }
                                 }
                             }
                             gljArr.forEach(function (gljItem) {
@@ -349,39 +367,48 @@ rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, callback) {
                                 updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
                             }
                             updatePrc.basePrice = scMathUtil.roundTo(updatePrc.labourPrice + updatePrc.materialPrice + updatePrc.machinePrice, -2);
+                            let task = {
+                                updateOne: {
+                                    filter: {
+                                        ID: rationItem.ID
+                                    },
+                                    update: {
+                                        labourPrice: updatePrc.labourPrice.toString(),
+                                        materialPrice: updatePrc.materialPrice.toString(),
+                                        machinePrice: updatePrc.machinePrice.toString(),
+                                        basePrice: updatePrc.basePrice.toString()
+                                    }
+                                }
+                            };
                             //updateDataBase
                             if(rationItem._doc.type !== undefined && rationItem._doc.type === 'complementary'){
-                                compleRationModel.update({ID: rationItem.ID}, {$set: {labourPrice: updatePrc.labourPrice.toString(), materialPrice: updatePrc.materialPrice.toString(),
-                                        machinePrice: updatePrc.machinePrice.toString(), basePrice: updatePrc.basePrice.toString()}},
-                                    function (err, result) {
-                                        if(err){
-                                            ecb(err);
-                                        }
-                                        else {
-                                            ecb(null);
-                                        }
-                                    });
+                                compleRTasks.push(task);
+                                ecb(null);
                             }
                             else {
-                                rationItemModel.update({ID: rationItem.ID}, {$set: {labourPrice: updatePrc.labourPrice.toString(), materialPrice: updatePrc.materialPrice.toString(),
-                                        machinePrice: updatePrc.machinePrice.toString(), basePrice: updatePrc.basePrice.toString()}},
-                                    function (err, result) {
-                                        if(err){
-                                            ecb(err);
-                                        }
-                                        else {
-                                            ecb(null);
-                                        }
-                                    });
+                                stdRTasks.push(task);
+                                ecb(null);
                             }
-                        }
-                    });
-                }, function(err){
-                    if(err){
-                        cb(err);
-                    }
-                    else {
-                        cb(null);
+                        }, async function(err){
+                            if(err){
+                                cb(err);
+                            }
+                            else {
+                                //do sth
+                                try{
+                                    if(compleRTasks.length > 0){
+                                        await compleRationModel.bulkWrite(compleRTasks);
+                                    }
+                                    if(stdRTasks.length > 0){
+                                        await rationItemModel.bulkWrite(stdRTasks);
+                                    }
+                                }
+                                catch(e){
+                                    cb(err);
+                                }
+                                cb(null);
+                            }
+                        });
                     }
                 });
             },
@@ -603,7 +630,7 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
     }
     // 获取标准工料机库数据
     const stdBillsLibListsModel = new STDGLJListModel();
-    const stdGLJData = await stdBillsLibListsModel.getGljItemsByRep(rationRepository[0].gljLib);
+    const stdGLJData = await stdBillsLibListsModel.getGljItemsByRepId(rationRepository[0].gljLib);
     // 整理标准工料机库数据
     let stdGLJList = {};
     let stdGLJListByID = {};

+ 16 - 6
modules/ration_repository/models/schemas.js

@@ -69,6 +69,12 @@ let rationGljItemSchema = new Schema({
     proportion: Number //配合比,暂时无需使用,默认0
 }, { _id: false });
 
+//定额安装增加费用
+let rationInstSchema = new Schema({
+    feeItemId: String,
+    sectionId: String
+},{_id: false});
+
 //辅助定额调整
 let rationAssItemSchema = new Schema({
     name: String,
@@ -85,7 +91,6 @@ let rationAssItemSchema = new Schema({
 //安装增加费-费用规则
 let feeRuleSchema = new Schema({
     ID: String,
-    sectionId: String, //分册章节id
     code: String,
     rule: String,
     base: String,
@@ -97,20 +102,24 @@ let feeRuleSchema = new Schema({
 
 //安装增加费-分册章节
 let installSectionSchema = new Schema({
+    rationRepId: Number,
     ID: String,
     feeItemId: String,
     name: String,
-    feeRule: [feeRuleSchema]
-});
+    feeRule: [feeRuleSchema],
+    deleted: false
+}, {versionKey: false});
 
 //安装增加费-费用项
 let installFeeItemSchema = new Schema({
+    rationRepId: Number,
     ID: String,
     feeItem: String, //费用项
     feeType: String, //费用类型
     position: String, //记取位置
-    section: []
-});
+    section: [],
+    deleted: false
+}, {versionKey: false});
 
 //定额
 var rationItemSchema = new Schema({
@@ -131,6 +140,7 @@ var rationItemSchema = new Schema({
     rationGljList: [rationGljItemSchema],
     rationCoeList: Array,
     rationAssList: [rationAssItemSchema],
+    rationInstList: [rationInstSchema],
     isDeleted: Boolean
 });
 
@@ -162,7 +172,7 @@ let coeListModel = db.model("std_ration_lib_coe_list",coeListSchema, "std_ration
 let rationRepository = db.model("std_ration_lib_map", RepositoryMapSchema, "std_ration_lib_map");
 let rationChapterTreeModel = db.model("std_ration_lib_ration_chapter_trees", rationChapterTreeSchema, "std_ration_lib_ration_chapter_trees");
 let rationItemModel = db.model("std_ration_lib_ration_items",rationItemSchema, "std_ration_lib_ration_items");
-let installSectionModel = db.model("std_ration_lib_installationSection", installSectionSchema, "std_ration_lib_installationSection")
+let installSectionModel = db.model("std_ration_lib_installationSection", installSectionSchema, "std_ration_lib_installationSection");
 let installFeeItemModel = db.model("std_ration_lib_installation", installFeeItemSchema, "std_ration_lib_installation");
 //补充定额
 let compleRationModel = db.model('complementary_ration_items', compleRationSchema, 'complementary_ration_items');

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

@@ -12,11 +12,13 @@ import RepositoryGljController from "../controllers/repository_glj_controller";
 import CoeListController from "../controllers/coe_controller";
 import SearchController from "../controllers/search_controller";
 import GljController from "../../std_glj_lib/controllers/gljController";
+import InstallationController from '../controllers/installation_controller';
 let viewsController = new ViewsController();
 let rationRepositoryController = new RationRepositoryController();
 let rationChapterTreeController = new RationChapterTreeController();
 let rationController = new RationController();
 let coeListController = new CoeListController();
+let installationController = new InstallationController();
 let searchController = new SearchController();
 let repositoryGljController = new RepositoryGljController();
 let gljController = new GljController();
@@ -71,6 +73,12 @@ module.exports =  function (app) {
     apiRouter.post("/getCoeItemsByIDs",coeListController.auth, coeListController.init, coeListController.getCoeItemsByIDs);
     apiRouter.post("/getCoeItemsByNos",coeListController.auth, coeListController.init, coeListController.getCoeItemsByNos);
 
+    //安装增加费
+    apiRouter.post('/getInstallation', installationController.auth, installationController.init, installationController.getInstallation);
+    apiRouter.post('/updateFeeItem', installationController.auth, installationController.init, installationController.updateFeeItem);
+    apiRouter.post('/updateSection', installationController.auth, installationController.init, installationController.updateSection);
+    apiRouter.post('/batchUpdateInst', installationController.auth, installationController.init, installationController.batchUpdateInst);
+
     apiRouter.post('/getRationItem',searchController.auth, searchController.init, searchController.getRationItem);
     apiRouter.post('/findRation', searchController.auth, searchController.init, searchController.findRation);
 

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

@@ -70,6 +70,7 @@ let JpcCommonHelper = {
         let me = this, arrDPI = [];
         if (!me.commonConstant.resolution) {
             arrDPI = [96,96];
+            // arrDPI = [100,100];
             me.commonConstant.resolution = arrDPI;
         } else {
             arrDPI = me.commonConstant.resolution;

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

@@ -20,6 +20,7 @@ let JpcFieldHelper = {
         }
     },
     findAndPutDataFieldIdx: function (rptTpl, tab_fields, rstFields, rstFieldsIdx, isEx) {
+        //通过FieldID找到相关映射指标的位置IDX并记录下来,方便后续引用
         if (tab_fields) {
             let DTL_STR = isEx?JV.NODE_DETAIL_FIELDS_EX:JV.NODE_DETAIL_FIELDS;
             let detail_fields = rptTpl[JV.NODE_FIELD_MAP][DTL_STR];
@@ -39,6 +40,25 @@ let JpcFieldHelper = {
                 }
             }
         }
+    },
+    findAutoHeightFieldIdx: function(rptTpl, tab_fields, rstFieldsIdx, isEx) {
+        if (tab_fields) {
+            let DTL_STR = isEx?JV.NODE_DETAIL_FIELDS_EX:JV.NODE_DETAIL_FIELDS;
+            let detail_fields = rptTpl[JV.NODE_FIELD_MAP][DTL_STR];
+            for (let i = 0; i < tab_fields.length; i++) {
+                if (tab_fields[i][JV.PROP_IS_AUTO_HEIGHT]) {
+                    for (let j = 0; j < detail_fields.length; j++) {
+                        if (tab_fields[i]["FieldID"] === detail_fields[j]["ID"]) {
+                            let item = [];
+                            item[0] = j;
+                            item[1] = tab_fields[i];
+                            rstFieldsIdx.push(item);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
     }
 };
 

+ 53 - 97
modules/reports/rpt_component/jpc_flow_tab.js

@@ -9,6 +9,7 @@ let JpcDiscreteHelper = require('./helper/jpc_helper_discrete');
 let JpcTextHelper = require('./helper/jpc_helper_text');
 let JpcCommonOutputHelper = require('./helper/jpc_helper_common_output');
 let JpcAreaHelper = require('./helper/jpc_helper_area');
+let PDFKit = require('pdfkit');
 
 let JpcFlowTabSrv = function(){};
 //let grpPageInfo = {"segGrpRecStartIdx": 0, "insertedGrpRecAmt": 0, "preAddPageGrpInfo": null};
@@ -87,6 +88,8 @@ JpcFlowTabSrv.prototype.createNew = function(){
         me.page_sum_fields_idx = [];
         me.page_sum_tab_fields = [];
 
+        me.auto_height_fields_idx = [];//那些被标记为判断自动行高的指标集合
+        me.auto_height_info = [];
         me.group_fields = [];
         me.group_sum_fields = [];
         me.group_sum_values = null;
@@ -107,6 +110,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_PAGE_SUM][JV.PROP_SUM_FIELDS], me.page_sum_tab_fields, me.page_sum_fields_idx, me.isEx);
         JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_FIELDS], me.group_fields, null, me.isEx);
         JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_SUM_FIELDS], me.group_sum_fields, null, me.isEx);
+        JpcFieldHelper.findAutoHeightFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_CONTENT][JV.PROP_FLOW_FIELDS], me.auto_height_fields_idx, me.isEx);
         for (let si = 0; si < dataSeq.length; si++) {
             me.segments.push(dataSeq[si].slice(0));
         }
@@ -209,6 +213,49 @@ JpcFlowTabSrv.prototype.createNew = function(){
             }
         }
     };
+    JpcFlowTabResult.setupAutoHeightData = function(bands, segIdx, rptTpl, dataObj, $CURRENT_RPT) {
+        let me = this;
+        let CURRENT_FLOW_INFO = (me.isEx)?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
+        let band = bands[rptTpl[CURRENT_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.BAND_PROP_NAME]];
+        let data_details = me.isEx?dataObj[JV.DATA_DETAIL_DATA_EX]:dataObj[JV.DATA_DETAIL_DATA];
+        let reg1 = new RegExp('\n\r','g'), reg2 = new RegExp('\r\n','g'),
+            reg3 = new RegExp('\n','g'), reg4 = new RegExp('\r','g');
+        let doc = new PDFKit({autoFirstPage: false});
+        let private_get_max_lines_of_the_record = function(theRecIdx) {
+            let rst = 1;
+            for (let loop = 0; loop < me.auto_height_fields_idx.length; loop++) {
+                let data_field = null;
+                let tab_field = me.auto_height_fields_idx[loop][1];
+                if (me.auto_height_fields_idx[loop][0] !== JV.BLANK_FIELD_INDEX) {
+                    data_field = data_details[me.auto_height_fields_idx[loop][0]];
+                }
+                if (data_field) {
+                    let value = JpcFieldHelper.getValue(data_field, theRecIdx);
+                    let area = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, 1, 1, 0, 1, 0, 1, 0, false, false);
+                    if (value !== null && value !== undefined) {
+                        value = value.replace(reg1, '|').replace(reg2, '|').replace(reg3, '|').replace(reg4, '|');
+                    } else {
+                        value = '';
+                    }
+                    let values = value.split('|');
+                    if (values.length > rst) rst = values.length;
+                }
+            }
+            return rst;
+        };
+        if (me.auto_height_fields_idx.length > 0 && me.auto_height_info.length === segIdx) {
+            //自动行高功能,需要考虑以下情况:
+            //1. 每一Segment的需要增加行的数量
+            me.auto_height_info.push([]);
+            //rst[JV.PROP_AREA] = JpcAreaHelper.outputArea(textNode[JV.PROP_AREA], band, unitFactor, rows, rowIdx, cols, colIdx, multiCols, multiColIdx, false, false);
+            let segArr = me.segments[segIdx];
+            for (let i = 0; i < segArr.length; i++) {
+                //
+            }
+            //2.
+            //rptTpl[CURRENT_FLOW_INFO][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES].length;
+        }
+    };
 
     JpcFlowTabResult.preSetupPages = function (rptTpl, dataObj, defProperties, option, $CURRENT_RPT, followTabEx) {
         //换一种思路来整理流水式数据
@@ -302,13 +349,14 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 currentRecAmt = 0;
                 counterRowRec = 0;
                 counterRowRecEx = 0;
-                let ttlSegRecAmtNormal = me.segments[segIdx].length + grpRecAmt;
-                let ttlSegRecAmt = (followTabEx)?(me.segments[segIdx].length + grpRecAmt + followTabEx.segments[segIdx].length + grpRecAmtEx):(me.segments[segIdx].length + grpRecAmt);
+                let ttlSegRecAmtNormal = me.segments[segIdx].length + grpRecAmt; //正常的segment下的数据长度累计(含grouping data)
+                let ttlSegRecAmt = (followTabEx)?(me.segments[segIdx].length + grpRecAmt + followTabEx.segments[segIdx].length + grpRecAmtEx):(me.segments[segIdx].length + grpRecAmt); //所有的segment下的数据长度累计(包括ex部分)
                 while (true) {
                     if (currentRecAmt > 0) pageStatus[JV.STATUS_SEGMENT_START] = false;
                     if (pageIdx > 0) pageStatus[JV.STATUS_REPORT_START] = false;
                     //开始判断各种scenarios
                     if (ttlSegRecAmtNormal < ttlSegRecAmt) {
+                        //有流水拓展,并且是follow mode
                         if (currentRecAmt + maxRowRec > ttlSegRecAmtNormal) {
                             if (currentRecAmt >= ttlSegRecAmtNormal) {
                                 //纯 followTabEx 数据
@@ -355,6 +403,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                             private_addPage(segIdx, grpSeqInfo, false, false, -1);
                         }
                     } else {
+                        //普通流水数据情况
                         if (currentRecAmt + maxRowRec >= ttlSegRecAmt) {
                             pageStatus[JV.STATUS_SEGMENT_END] = true;
                             pageStatus[JV.STATUS_REPORT_END] = true;
@@ -379,9 +428,9 @@ JpcFlowTabSrv.prototype.createNew = function(){
                         //备注:这里必须得考虑多栏的情况,否则会造成pageStatus出界的问题
                         break;
                     }
-                    //控制阀值,超过阀值则强制退出,防止死循环
+                    //控制阈值,超过阈值则强制退出,防止死循环
                     threshold++;
-                    if (threshold > 500) {
+                    if (threshold > 1000) {
                         console.log("Hey! There may be a dead loop here!!!");
                         break;
                     }
@@ -394,99 +443,6 @@ JpcFlowTabSrv.prototype.createNew = function(){
         return rst;
     };
 
-    JpcFlowTabResult.preSetupPages_Org = function (rptTpl, dataObj, defProperties, option, $CURRENT_RPT, followTabEx) {
-        let me = this, rst = 1, counterRowRec = 0, maxRowRec = 1, pageIdx = 0;
-        me.setupGroupingData(rptTpl, dataObj, $CURRENT_RPT);
-        if (followTabEx) {
-            followTabEx.setupGroupingData(rptTpl, dataObj, $CURRENT_RPT);
-        }
-        //console.log(me.group_sum_values);
-        me.paging_option = option||JV.PAGING_OPTION_NORMAL;
-        let CURRENT_FLOW_INFO = (me.isEx)?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
-        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[CURRENT_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_FLOW_FIELDS], null, me.disp_fields_idx, me.isEx);
-        if (me.paging_option === JV.PAGING_OPTION_INFINITY) {
-            rst = me.segments.length;
-            let pageStatus = [true, true, false, true, true, true, false, false];
-            for (let segIdx = 0; segIdx < me.segments.length; segIdx++) {
-                if (segIdx === me.segments.length - 1) {
-                    pageStatus[JV.STATUS_REPORT_END] = true;
-                }
-                if (segIdx > 0) {
-                    pageStatus[JV.STATUS_REPORT_START] = false;
-                }
-                me.pageStatusLst.push(pageStatus.slice(0));
-                pageIdx++;
-                let grpSeqInfo = (me.group_node_info)?me.group_node_info[segIdx]:null;
-                private_addPageValue(me.dispValueIdxLst, me.segments[segIdx], grpSeqInfo, 0, me.segments[segIdx].length, me.page_seg_map, segIdx, pageIdx, null, false);
-                if (followTabEx) {
-                    //
-                }
-            }
-        } else {
-            let bands = JpcBand.createNew(rptTpl, defProperties);
-            let pageStatus = [true, true, false, true, false, false, false, false];
-            if (me.isEx) {
-                pageStatus[JV.STATUS_REPORT_START] = false;
-            }
-            if (rptTpl[CURRENT_FLOW_INFO][JV.PROP_MULTI_COLUMN]) {
-                me.multiCols = 1 * rptTpl[CURRENT_FLOW_INFO][JV.PROP_MULTI_COLUMN];
-            }
-            function private_resetBandArea() {
-                JpcBandHelper.setBandArea(bands, rptTpl, pageStatus, !me.isEx, me.isEx);
-                maxRowRec = JpcFlowTabHelper.getMaxRowsPerPage(bands, rptTpl, me.isEx);
-            }
-            let grpPageInfo = {};
-            for (let segIdx = 0; segIdx < me.segments.length; segIdx++) {
-                let grpSeqInfo = (me.group_node_info)?me.group_node_info[segIdx]:null;
-                grpPageInfo[JV.PROP_SEG_GRP_IDX] = 0;
-                grpPageInfo[JV.PROP_INSERTED_GRP_REC] = 0;
-                grpPageInfo[JV.PROP_PRE_ADD_GRP_REC_INFO] = [];
-                grpPageInfo[JV.PROP_GRP_LINES] = me.group_lines_amt;
-                private_resetBandArea();
-                let orgMaxRowRec = maxRowRec;
-                let grpRecAmt = (grpSeqInfo)?(grpSeqInfo.length*me.group_lines_amt):0;
-                let grpRecAmtEx = 0;
-                let rowSplitCnt = Math.ceil(1.0 * (me.segments[segIdx].length + grpRecAmt) / orgMaxRowRec);
-                let rowSplitCntEx = rowSplitCnt;
-                if (followTabEx) {
-                    rowSplitCntEx = Math.ceil(1.0 * (me.segments[segIdx].length + grpRecAmt + followTabEx.segments[segIdx].length + grpRecAmtEx) / orgMaxRowRec);
-                }
-                pageStatus[JV.STATUS_SEGMENT_END] = true;
-                private_resetBandArea();
-                let len = (followTabEx)?(me.segments[segIdx].length + grpRecAmt + followTabEx.segments[segIdx].length + grpRecAmtEx):(me.segments[segIdx].length + grpRecAmt);
-                //let hasAdHocRow = !JpcFlowTabHelper.chkSegEnd(bands, rptTpl, me.segments[segIdx].length, (rowSplitCntEx - 1) * orgMaxRowRec, maxRowRec, me.isEx);
-                let hasAdHocRow = !JpcFlowTabHelper.chkSegEnd(bands, rptTpl, len, (rowSplitCntEx - 1) * orgMaxRowRec, maxRowRec, me.isEx);
-                if (hasAdHocRow) rowSplitCntEx++;
-                if (rowSplitCntEx % me.multiCols > 0) {
-                    rowSplitCntEx++
-                }
-                counterRowRec = 0;
-                for (let segPageIdx = 0; segPageIdx < rowSplitCntEx; segPageIdx++) {
-                    pageStatus[JV.STATUS_SEGMENT_END] = (segPageIdx === (rowSplitCntEx - 1));
-                    if (pageIdx > 0) pageStatus[JV.STATUS_REPORT_START] = false;
-                    private_resetBandArea();
-                    me.pageStatusLst.push(pageStatus.slice(0));
-                    pageIdx++;
-                    if (followTabEx) {
-                        //
-                    } else {
-                        //
-                    }
-                    private_addPageValue(me.dispValueIdxLst, me.segments[segIdx], grpSeqInfo, counterRowRec, maxRowRec,me.page_seg_map, segIdx, pageIdx, grpPageInfo, false);
-                    //备注: 考虑到分组数据是临时融入的,所以需要知道这一页的数据融入了多少条group数据,并且得考虑边界条件情况(group数据可能跨页!)
-                    for (let dv of me.dispValueIdxLst[me.dispValueIdxLst.length - 1]) {
-                        if (dv[1] === JV.DISPLAY_VAL_TYPE_NORMAL) counterRowRec++;
-                    }
-                }
-                pageStatus[JV.STATUS_SEGMENT_END] = false;
-                pageStatus[JV.STATUS_REPORT_START] = false;
-            }
-            // console.log(me.dispValueIdxLst);
-            rst = Math.ceil(pageIdx / me.multiCols);
-        }
-        me.pagesAmt = rst;
-        return rst;
-    };
     JpcFlowTabResult.outputAsSimpleJSONPage = function (rptTpl, dataObj, page, bands, controls, adHocMergePos, $CURRENT_RPT) {
         let me = this, rst = [], tabRstLst = [];
         let FLOW_NODE_STR = me.isEx?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;

+ 54 - 92
modules/reports/util/rpt_excel_util.js

@@ -23,10 +23,10 @@ function writeContentTypes(sheets, isSinglePage) {
     rst.push('<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>');
     rst.push('<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>');
     if (isSinglePage) {
-        rst.push('<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>')
+        rst.push('<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>');
     } else {
         for (let i = 0; i < sheets.length; i++) {
-            rst.push('<Override PartName="/xl/worksheets/sheet' + (i + 1) + '.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>')
+            rst.push('<Override PartName="/xl/worksheets/sheet' + (i + 1) + '.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>');
         }
     }
     rst.push('<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>');
@@ -60,11 +60,11 @@ function writeApp(sheets, isSinglePage) {
     rst.push('<TitlesOfParts>');
     if (isSinglePage) {
         rst.push('<vt:vector size="1" baseType="lpstr">');
-        rst.push('<vt:lpstr>' + sheets[0].sheetName + '</vt:lpstr>')
+        rst.push('<vt:lpstr>' + sheets[0].sheetName + '</vt:lpstr>');
     } else {
         rst.push('<vt:vector size="' + sheets.length + '" baseType="lpstr">');
         for (let i = 0; i < sheets.length; i++) {
-            rst.push('<vt:lpstr>' + sheets[i].sheetName + '</vt:lpstr>')
+            rst.push('<vt:lpstr>' + sheets[i].sheetName + '</vt:lpstr>');
         }
     }
     rst.push('</vt:vector>');
@@ -74,7 +74,6 @@ function writeApp(sheets, isSinglePage) {
     rst.push('<SharedDoc>false</SharedDoc>');
     rst.push('<HyperlinksChanged>false</HyperlinksChanged>');
     rst.push('<AppVersion>12.0000</AppVersion>');
-    //rst.push('');
     rst.push('</Properties>');
     return rst;
 }
@@ -91,7 +90,9 @@ function writeCore() {
     rst.push('<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">');
     rst.push('<dc:creator>SmartCost</dc:creator>');
     rst.push('<cp:lastModifiedBy>SmartCost</cp:lastModifiedBy>');
-    let dt = new Date(), dtStr = dt.getFullYear() + '-' + p_fillZero(dt.getMonth()+1) + '-' + p_fillZero(dt.getDate()) + 'T' +
+    let dt = new Date();
+    dt.setDate(dt.getDate() - 8/24); //it's GMT time, so please add the server offset time ( -8 hours )
+    let dtStr = dt.getFullYear() + '-' + p_fillZero(dt.getMonth()+1) + '-' + p_fillZero(dt.getDate()) + 'T' +
         p_fillZero(dt.getHours()) + ':' + p_fillZero(dt.getMinutes()) + ':' + p_fillZero(dt.getSeconds()) + 'Z';
     rst.push('<dcterms:created xsi:type="dcterms:W3CDTF">' + dtStr + '</dcterms:created>');
     rst.push('<dcterms:modified xsi:type="dcterms:W3CDTF">' + dtStr + '</dcterms:modified>');
@@ -116,7 +117,6 @@ function writeXlWorkBook(sheets, isSinglePage){
     }
     rst.push('</sheets>');
     rst.push('<calcPr calcId="124519"/>');
-    //rst.push('');
     rst.push('</workbook>');
     return rst;
 }
@@ -125,11 +125,11 @@ function writeXlRels(sheets, isSinglePage){
     rst.push(dftHeadXml + '\r\n');
     rst.push('<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">');
     if (isSinglePage) {
-        rst.push('<Relationship Id="rId' + idx + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>')
+        rst.push('<Relationship Id="rId' + idx + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>');
         idx++;
     } else {
         for (let i = 0; i < sheets.length; i++) {
-            rst.push('<Relationship Id="rId' + idx + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet' + (i + 1) + '.xml"/>')
+            rst.push('<Relationship Id="rId' + idx + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet' + (i + 1) + '.xml"/>');
             idx++;
         }
     }
@@ -138,7 +138,6 @@ function writeXlRels(sheets, isSinglePage){
     rst.push('<Relationship Id="rId' + idx + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>');
     idx++;
     rst.push('<Relationship Id="rId' + idx + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>');
-    //rst.push('');
     rst.push('</Relationships>');
     return rst;
 }
@@ -151,7 +150,7 @@ function writeStyles(stylesObj){
     rst.push(dftHeadXml + '\r\n');
     rst.push('<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">');
     //1. push fonts
-    rst.push('<fonts count="' + stylesObj.fonts.length + '">')
+    rst.push('<fonts count="' + stylesObj.fonts.length + '">');
     for (let i = 0; i < stylesObj.fonts.length; i++) {
         let font = stylesObj.fonts[i];
         rst.push('<font>');
@@ -171,14 +170,14 @@ function writeStyles(stylesObj){
     //2. push default fills
     rst.push('<fills count="2"><fill><patternFill patternType="none" /></fill><fill><patternFill patternType="gray125" /></fill></fills>');
     //3. push borders
-    rst.push('<borders count="' + stylesObj.borders.length + '">')
+    rst.push('<borders count="' + stylesObj.borders.length + '">');
     let private_setBorder = function(border, borderDirection) {
-        if (border[borderDirection][JV.PROP_LINE_WEIGHT] == 0) {
+        if (parseInt(border[borderDirection][JV.PROP_LINE_WEIGHT]) === 0) {
             rst.push('<' + borderDirection.toLowerCase() + '/>');
         } else {
             let bW = 'thin';
-            if (border[borderDirection][JV.PROP_LINE_WEIGHT] == 2) bW = 'medium';
-            if (border[borderDirection][JV.PROP_LINE_WEIGHT] > 2) bW = 'thick';
+            if (parseInt(border[borderDirection][JV.PROP_LINE_WEIGHT]) === 2) bW = 'medium';
+            if (parseInt(border[borderDirection][JV.PROP_LINE_WEIGHT]) > 2) bW = 'thick';
             rst.push('<' + borderDirection.toLowerCase() + ' style="' + bW + '">' + '<color indexed="64"/>' + '</' + borderDirection.toLowerCase() + '>');
         }
     };
@@ -244,7 +243,7 @@ function writeStyles(stylesObj){
             newVertical = tmpV;
         }
         alignStr += ' horizontal="' + newHorizontal + '" vertical="' + newVertical + '"';
-        if (strUtil.convertStrToBoolean(excelStyle[JV.CONTROL_PROPS[1]])) {
+        if (strUtil.convertStrToBoolean(excelStyle[JV.CONTROL_PROPS[0]])) {
             alignStr += ' shrinkToFit="1"';
         }
         if (strUtil.convertStrToBoolean(excelStyle[JV.CONTROL_PROPS[4]])) {
@@ -340,26 +339,25 @@ function writeSheets(pageData, paperSize, sharedStrList, stylesObj, isSinglePage
 }
 function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
     let rst = [], xPos = [], yPos = [], yMultiPos = [], headerStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-    let cacheBorderCell = {};
     let currentPageMergePos = null; //在 JV.PAGING_OPTION_INFINITY 场合应用
     let private_pre_analyze_pos = function(){
         let cell, pos;
         let self_analyze_sheet_pos = function (theShtData, theXPos, theYPos) {
-            theShtData.cells.sort(function(cell1, cell2) {
-                let rst = 0;
-                if (cell1[JV.PROP_AREA][JV.PROP_TOP] > cell2[JV.PROP_AREA][JV.PROP_TOP]) {
-                    rst = 1;
-                } else if (cell1[JV.PROP_AREA][JV.PROP_TOP] < cell2[JV.PROP_AREA][JV.PROP_TOP]) {
-                    rst = -1;
-                } else {
-                    if (cell1[JV.PROP_AREA][JV.PROP_LEFT] > cell2[JV.PROP_AREA][JV.PROP_LEFT]) {
-                        rst = 1;
-                    } else if (cell1[JV.PROP_AREA][JV.PROP_LEFT] < cell2[JV.PROP_AREA][JV.PROP_LEFT]) {
-                        rst = -1;
-                    }
-                }
-                return rst;
-            });
+            // theShtData.cells.sort(function(cell1, cell2) {
+            //     let rst = 0;
+            //     if (cell1[JV.PROP_AREA][JV.PROP_TOP] > cell2[JV.PROP_AREA][JV.PROP_TOP]) {
+            //         rst = 1;
+            //     } else if (cell1[JV.PROP_AREA][JV.PROP_TOP] < cell2[JV.PROP_AREA][JV.PROP_TOP]) {
+            //         rst = -1;
+            //     } else {
+            //         if (cell1[JV.PROP_AREA][JV.PROP_LEFT] > cell2[JV.PROP_AREA][JV.PROP_LEFT]) {
+            //             rst = 1;
+            //         } else if (cell1[JV.PROP_AREA][JV.PROP_LEFT] < cell2[JV.PROP_AREA][JV.PROP_LEFT]) {
+            //             rst = -1;
+            //         }
+            //     }
+            //     return rst;
+            // });
             for (let i = 0; i < theShtData.cells.length; i++) {
                 cell = theShtData.cells[i];
                 pos = cell[JV.PROP_AREA][JV.PROP_LEFT];
@@ -381,11 +379,16 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
             yPos.sort(private_array_sort);
         } else {
             //total data in one sheet
+            let marginBottomPos = Math.round( (pageData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][1] - parseFloat(pageData[JV.NODE_PAGE_INFO][JV.NODE_MARGINS][JV.PROP_BOTTOM]) / 2.54 ) * DPI);
             for (let shtItemData of pageData.items) {
                 let tmpPos = [];
                 tmpPos.push(0);
                 self_analyze_sheet_pos(shtItemData, xPos, tmpPos);
                 tmpPos.sort(private_array_sort);
+                if (marginBottomPos - tmpPos[tmpPos.length - 1] > 10) {
+                    //此逻辑是为了防止打印跨页(假设有些报表模板高度设置离底部margin还好远,导出excel后预览时会发现跨页现象(即下一页的某几行数据会挪到前一页来预览))
+                    tmpPos.push(marginBottomPos - 10);
+                }
                 yMultiPos.push(tmpPos);
             }
             xPos.sort(private_array_sort);
@@ -493,7 +496,7 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
     };
     let private_chkAndGetMergeLine = function(cell, sheetBorder, borderStr, needFurtherChk) {
         let rst = 0,
-            mergeBorder = (sheetData[JV.PROP_PAGE_MERGE_BORDER])?sheetData[JV.PROP_PAGE_MERGE_BORDER]:pageData[JV.BAND_PROP_MERGE_BAND],
+            mergeBorder = (sheetData)?sheetData[JV.PROP_PAGE_MERGE_BORDER]:pageData[JV.BAND_PROP_MERGE_BAND],
             mergeBand = pageData[JV.BAND_PROP_MERGE_BAND]
         ;
         if (sheetBorder[borderStr] && sheetBorder[borderStr][JV.PROP_LINE_WEIGHT] !== undefined) {
@@ -625,7 +628,7 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
         return rst;
     };
     let private_setCols = function(){
-        //remark: 1 excel width = 2.117 mm
+        //remark: 1 excel unit width = 2.117 mm
         rst.push('<cols>');
         let w = 0;
         for (let i = 1; i < xPos.length - 1; i++) {
@@ -633,6 +636,7 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
             w = Math.round(w * 1000) / 1000;
             rst.push('<col min="' + i +'" max="' + i +'" width="' + w + '" customWidth="1"/>');
         }
+        rst.push('<col min="' + (xPos.length - 1) +'" max="' + (xPos.length - 1) +'" width="' + 10 + '" customWidth="1"/>');
         rst.push('</cols>');
     };
     let private_setMergedCells = function() {
@@ -666,58 +670,11 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
         rst[startIdx] = '<mergeCells count="' + cnt + '">';
         rst.push('</mergeCells>');
     };
-    let private_chkIfNeedCacheCell = function(cell){
-        let rst = false;
-        if (cell[JV.PROP_AREA][JV.PROP_LEFT] === pageData[JV.BAND_PROP_MERGE_BAND][JV.PROP_LEFT] ||
-            cell[JV.PROP_AREA][JV.PROP_RIGHT] === pageData[JV.BAND_PROP_MERGE_BAND][JV.PROP_RIGHT] ||
-            cell[JV.PROP_AREA][JV.PROP_TOP] === pageData[JV.BAND_PROP_MERGE_BAND][JV.PROP_TOP] ||
-            cell[JV.PROP_AREA][JV.PROP_BOTTOM] === pageData[JV.BAND_PROP_MERGE_BAND][JV.PROP_BOTTOM]){
-            if (cell[JV.PROP_AREA][JV.PROP_LEFT] >= pageData[JV.BAND_PROP_MERGE_BAND][JV.PROP_LEFT] &&
-                cell[JV.PROP_AREA][JV.PROP_RIGHT] <= pageData[JV.BAND_PROP_MERGE_BAND][JV.PROP_RIGHT] &&
-                cell[JV.PROP_AREA][JV.PROP_TOP] >= pageData[JV.BAND_PROP_MERGE_BAND][JV.PROP_TOP] &&
-                cell[JV.PROP_AREA][JV.PROP_BOTTOM] <= pageData[JV.BAND_PROP_MERGE_BAND][JV.PROP_BOTTOM]) {
-                rst = true;
-            }
-        }
-        return rst;
-    };
-    let private_cacheMergeBandBorderIdxs = function() {
-        let cell, idxR, idxL, idxT, idxB;
-        let self_cachMergeIdxs = function (theData, theYPos, offsetY) {
-            for (let i = 0; i < theData.cells.length; i++) {
-                cell = theData.cells[i];
-                idxR = xPos.indexOf(cell[JV.PROP_AREA][JV.PROP_RIGHT]);
-                idxL = xPos.indexOf(cell[JV.PROP_AREA][JV.PROP_LEFT]);
-                idxB = theYPos.indexOf(cell[JV.PROP_AREA][JV.PROP_BOTTOM]);
-                idxT = theYPos.indexOf(cell[JV.PROP_AREA][JV.PROP_TOP]);
-                if (idxR - idxL > 1 || idxB - idxT > 1) {
-                    if (private_chkIfNeedCacheCell(cell)) {
-                        for (let xi = idxL; xi < idxR; xi++) {
-                            for (let yj = idxT; yj < idxB; yj++) {
-                                cacheBorderCell[private_getCellIdxStr(xi - 1) + yj + offsetY] = cell;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        if (sheetData) {
-            self_cachMergeIdxs(sheetData, yPos, 0);
-        } else {
-            let osY = 0;
-            for (let i = 0; i < pageData.items.length; i++) {
-                let shtItemData = pageData.items[i];
-                let tmpPos = yMultiPos[i];
-                self_cachMergeIdxs(shtItemData, tmpPos, osY);
-                osY += tmpPos.length - 2;
-            }
-        }
-    };
     let private_setSheetData = function(){
-        //remark: 1 excel height = 0.3612 mm
+        //remark: 1 excel unit height = 0.3612 mm
         rst.push('<sheetData>');
         let spanX = xPos.length - 2, cellIdx = 0, h = 0
-            ;
+        ;
         let self_setDataEx = function (theShtData, theYPos, offsetY) {
             let rows = [];
             //1. build full set of blank rows/cells
@@ -783,7 +740,6 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
             //4. maybe need to dispose the memory
             //...
         };
-        private_cacheMergeBandBorderIdxs();
         if (sheetData) {
             //current sheet data
             currentPageMergePos = sheetData[JV.PAGE_SPECIAL_MERGE_POS];
@@ -817,7 +773,9 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
     private_setSheetData();
     private_setMergedCells();
     rst.push('<phoneticPr fontId="1" type="noConversion"/>');
-    rst.push('<pageMargins left="0.315" right="0.215" top="0.315" bottom="0.315" header="0" footer="0"/>');
+    // rst.push('<pageMargins left="0.315" right="0.215" top="0.315" bottom="0.315" header="0" footer="0"/>');
+    rst.push('<pageMargins left="' + (parseFloat(pageData[JV.NODE_PAGE_INFO][JV.NODE_MARGINS][JV.PROP_LEFT]) * 0.39375) +
+        '" right="0.215" top="0.315" bottom="0.315" header="0" footer="0"/>');
     let paperSizeIdx = JV.PAGES_SIZE_STR.indexOf(paperSize);
     let pStr = '';
     if (paperSizeIdx >= 0) {
@@ -928,12 +886,12 @@ module.exports = {
             zip.generateNodeStream({type:'nodebuffer',streamFiles:true})
                 .pipe(fs.createWriteStream(__dirname.slice(0, __dirname.length - 21) + '/tmp/' + newName + '.xlsx'))
                 .on('finish', function () {
-                    // JSZip generates a readable stream with a "end" event,
-                    // but is piped here in a writable stream which emits a "finish" event.
-                    console.log(newName + ".xlsx was written.");
-                    if (callback) callback(newName);
-                }
-            );
+                        // JSZip generates a readable stream with a "end" event,
+                        // but is piped here in a writable stream which emits a "finish" event.
+                        console.log(newName + ".xlsx was written.");
+                        if (callback) callback(newName);
+                    }
+                );
         } else {
             //return zip.generateNodeStream({type:'nodebuffer',streamFiles:true});
             return zip;
@@ -993,7 +951,11 @@ module.exports = {
                         pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_BOTTOM] += offsetY;
                         pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_TOP] += offsetY;
                     }
+                    let bottomGap = Math.round( (pageDataArray[i][JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][1] - parseFloat(pageDataArray[i][JV.NODE_PAGE_INFO][JV.NODE_MARGINS][JV.PROP_BOTTOM]) / 2.54 ) * DPI) - maxY;
                     offsetY += (maxY - minY);
+                    if (bottomGap > 10) {
+                        offsetY += (bottomGap - 10);
+                    }
                 }
             }
             //2. newPageData的items属性
@@ -1013,7 +975,7 @@ module.exports = {
             }
             //3. everything is ok, then call me
             me.exportExcel(newPageData, paperSize, fName, 'false', sheetNames, callback);
-            fsUtil.writeObjToFile(newPageData, 'D:/GitHome/ConstructionOperation/tmp/combinedHeader.js');
+            // fsUtil.writeObjToFile(newPageData, 'D:/GitHome/ConstructionOperation/tmp/combinedHeader.js');
         } catch (e) {
             console.log(e);
         }

+ 4 - 0
modules/std_glj_lib/models/gljModel.js

@@ -500,6 +500,10 @@ class GljDao  extends OprDao{
             else callback(false, 'sc', result);
         });
     }
+
+    async getGljItemsByRepId(repositoryId){
+         return gljModel.find({"repositoryId": repositoryId});
+    }
 }
 
 export default GljDao;

+ 2 - 1
modules/users/models/bills_template_model.js

@@ -50,7 +50,7 @@ class BillsTemplateModel extends BaseModel {
             for (let data of datas) {
                 data.data.valuationId = valuationId;
                 data.data.engineering = engineering;
-                let condition = {valuationId: valuationId, ID: data.data.ID}, result;
+                let condition = {valuationId: valuationId, engineering: engineering, ID: data.data.ID}, result;
                 if (data.type === 'update') {
                     result = await this.db.update(condition, data.data);
                     if (result === undefined || result.ok ===undefined || !result.ok) {
@@ -63,6 +63,7 @@ class BillsTemplateModel extends BaseModel {
                     }
                 } else if (data.type === 'delete') {
                     result = await this.db.delete(condition);
+                    result = result.result;
                     if (result === undefined || result.ok ===undefined || !result.ok) {
                         throw '删除数据错误';
                     }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 81 - 0
public/web/PerfectLoad.js


+ 1 - 0
public/web/rpt_value_define.js

@@ -107,6 +107,7 @@ const JV = {
     PROP_POSITION: "Position",
     PROP_HIDDEN: "Hidden",
     PROP_IS_SERIAL: "isSerial",
+    PROP_IS_AUTO_HEIGHT: "isAutoHeight",
     PROP_FONT: "font",
     PROP_CONTROL: "control",
     PROP_STYLE: "style",

+ 22 - 2
public/web/scMathUtil.js

@@ -2,6 +2,9 @@
  * Created by jimiz on 2017/3/28.
  * 经验证:10000次四舍五入,用num.toFixed为15毫秒,用roundTo为47毫秒,速度低一些,但可以接受
  * 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
+ *
+ * zhangyin 2018-02-28
+ * 采用重复一次四舍五入解决浮点精度误差后,10000次roundTo的时间为94毫秒。
  */
 
 let scMathUtil = {
@@ -152,13 +155,30 @@ let scMathUtil = {
         };
         return result;
     },
-    roundTo: function(num, digit){
+    reRoundTo: function(num, digit){
         let me = this;
         return me.innerRoundTo(me.binToFloat(me.incMantissa(me.floatToBin(num))), digit);
     },
+    // zhangyin 2018-02-28
+    // 经过运算后的浮点数,误差可能更大,加尾数也不能消除。目前采用笨办法,将有效位数加一位再四舍五入一次,以消除浮点误差。
+    // 此办法效率较低,没有别的更好办法时暂时用着
+    roundTo: function(num, digit){
+        let me = this;
+        return me.reRoundTo(me.reRoundTo(num, digit - 1), digit);
+    },
     isNumber : function (obj) {
         return obj === +obj;
     },
+    roundForObj:function(obj,decimal){
+        let me = this;
+        let value;
+        if(me.isNumber(obj)){
+            value = me.roundTo(obj,-decimal)
+        }else {
+            value = me.roundTo(Number(obj),-decimal);
+        }
+        return value
+    },
     roundToString:function(obj,decimal){
         let me = this;
         let value;
@@ -173,7 +193,7 @@ let scMathUtil = {
 
 Number.prototype.toDecimal = function (ADigit) {
     //return parseFloat(this.toFixed(ADigit));
-    digit = (ADigit && typeof(ADigit) === 'number' && Number.isInteger(ADigit) && ADigit >= 0) ? -ADigit : -2;
+    digit = ((ADigit!=null||ADigit!=undefined) && typeof(ADigit) === 'number' && Number.isInteger(ADigit) && ADigit >= 0) ? -ADigit : -2;
     // var s = scMathUtil.roundTo(this, digit);
     // console.log('Number: ' + this + '   Digit: ' + digit + '    Result: ' + s);
     // return parseFloat(s);

+ 34 - 20
test/demo/stringTest.js

@@ -65,27 +65,41 @@ let strUtil = require('../../public/stringUtil');
 //     t.end();
 // })
 
-test('test number to Chinese', function(t){
-    t.equal(strUtil.convertToCaptionNum(0, false, false), '零');
-    t.equal(strUtil.convertToCaptionNum(0, true, false), '零元整');
-    t.equal(strUtil.convertToCaptionNum(0.68, true, false), '零元六角八分');
-    t.equal(strUtil.convertToCaptionNum(0.68, true, true), '零元陆角捌分');
-    t.equal(strUtil.convertToCaptionNum(10, false, false), '一十');
-    t.equal(strUtil.convertToCaptionNum(10, false, true), '壹拾');
-    t.equal(strUtil.convertToCaptionNum(11, false, false), '一十一');
-    t.equal(strUtil.convertToCaptionNum(11, false, true), '壹拾壹');
-    t.equal(strUtil.convertToCaptionNum(12, false, false), '一十二');
-    t.equal(strUtil.convertToCaptionNum(12, false, true), '壹拾贰');
-    t.equal(strUtil.convertToCaptionNum(21, false, false), '二十一');
-    t.equal(strUtil.convertToCaptionNum(21, false, true), '贰拾壹');
-
-    t.equal(strUtil.convertToCaptionNum(0.123456789, false, false), '零点一二三四五六七八九');
-    t.equal(strUtil.convertToCaptionNum(10.123456789, false, false), '一十点一二三四五六七八九');
+// test('test number to Chinese', function(t){
+//     t.equal(strUtil.convertToCaptionNum(0, false, false), '零');
+//     t.equal(strUtil.convertToCaptionNum(0, true, false), '零元整');
+//     t.equal(strUtil.convertToCaptionNum(0.68, true, false), '零元六角八分');
+//     t.equal(strUtil.convertToCaptionNum(0.68, true, true), '零元陆角捌分');
+//     t.equal(strUtil.convertToCaptionNum(10, false, false), '一十');
+//     t.equal(strUtil.convertToCaptionNum(10, false, true), '壹拾');
+//     t.equal(strUtil.convertToCaptionNum(11, false, false), '一十一');
+//     t.equal(strUtil.convertToCaptionNum(11, false, true), '壹拾壹');
+//     t.equal(strUtil.convertToCaptionNum(12, false, false), '一十二');
+//     t.equal(strUtil.convertToCaptionNum(12, false, true), '壹拾贰');
+//     t.equal(strUtil.convertToCaptionNum(21, false, false), '二十一');
+//     t.equal(strUtil.convertToCaptionNum(21, false, true), '贰拾壹');
+//
+//     t.equal(strUtil.convertToCaptionNum(0.123456789, false, false), '零点一二三四五六七八九');
+//     t.equal(strUtil.convertToCaptionNum(10.123456789, false, false), '一十点一二三四五六七八九');
+//
+//     t.equal(strUtil.convertToCaptionNum(123456789.15, false, false), '一亿二千三百四十五万六千七百八十九点一五');
+//     t.equal(strUtil.convertToCaptionNum(123456789.15, false, true), '壹億贰仟叁佰肆拾伍萬陆仟柒佰捌拾玖点壹伍');
+//     t.equal(strUtil.convertToCaptionNum(123456789.15, true, false), '一亿二千三百四十五万六千七百八十九元一角五分');
+//     t.equal(strUtil.convertToCaptionNum(123456789.15, true, true), '壹億贰仟叁佰肆拾伍萬陆仟柒佰捌拾玖元壹角伍分');
+//
+//     t.end();
+// });
 
-    t.equal(strUtil.convertToCaptionNum(123456789.15, false, false), '一亿二千三百四十五万六千七百八十九点一五');
-    t.equal(strUtil.convertToCaptionNum(123456789.15, false, true), '壹億贰仟叁佰肆拾伍萬陆仟柒佰捌拾玖点壹伍');
-    t.equal(strUtil.convertToCaptionNum(123456789.15, true, false), '一亿二千三百四十五万六千七百八十九元一角五分');
-    t.equal(strUtil.convertToCaptionNum(123456789.15, true, true), '壹億贰仟叁佰肆拾伍萬陆仟柒佰捌拾玖元壹角伍分');
+// test('test string combine', function(t){
+//     t.pass('ABC:' + 1 + 0);
+//
+//     t.end();
+// });
 
+test('test string replacement of return/new line', function(t){
+    new RegExp('\n\r','g');
+    let str = 'ABC-\n\r-123\r\n-zyx\n-987\r';
+    str = str.replace(new RegExp('\n\r','g'), '|').replace(new RegExp('\r\n','g'), '|').replace(new RegExp('\n','g'), '|').replace(new RegExp('\r','g'), '|');
+    t.pass('test result: ' + str);
     t.end();
 });

+ 171 - 0
web/maintain/ration_repository/anzhuang.html

@@ -0,0 +1,171 @@
+<!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="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css" type="text/css">
+    <link rel="stylesheet" href="/web/maintain/ration_repository/css/main.css">
+    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" href="/lib/jquery-contextmenu/jquery.contextMenu.css">
+</head>
+
+<body>
+    <div class="header">
+        <nav class="navbar navbar-toggleable-lg navbar-light bg-faded p-0 ">
+            <span class="header-logo px-2">Smartcost</span>
+            <div class="navbar-text" id="rationname"><a href="main">定额库</a><i class="fa fa-angle-right fa-fw"></i>XXX定额库</div>
+        </nav>
+        <nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0">
+              <ul class="nav nav-tabs" role="tablist">
+                  <li class="nav-item">
+                      <a class="nav-link px-3" id="dinge" href="dinge.html">定额</a>
+                  </li>
+                  <li class="nav-item">
+                      <a class="nav-link px-3" id="gongliao" href="gongliao.html">工料机</a>
+                  </li>
+                  <li class="nav-item">
+                      <a class="nav-link px-3" id="fuzhu" href="fuzhu.html">附注条件</a>
+                  </li>
+                  <li class="nav-item">
+                      <a class="nav-link active px-3" >安装增加费</a>
+                  </li>
+              </ul>
+        </nav>
+    </div>
+    <div class="main">
+        <div class="content">
+            <div class="container-fluid">
+              <div class="row">
+                <div class="main-content col-lg-12 p-0">
+                    <div class="container-fluid">
+                      <div class="row">
+                          <div class="main-data-top-fluid" id="feeItemSpread" style="width: 50%">
+                          <!--  <table class="table table-sm table-bordered mt-1">
+                              <thead><tr><th></th><th>费用项</th><th>费用类型</th><th>记取位置</th></tr></thead>
+                              <tbody>
+                                <tr><td>1</td><td>高层增加费</td><td>子目费用</td><td></td></tr>
+                              </tbody>
+                            </table>-->
+                          </div>
+                          <div class="main-data-top-fluid" id="instSectionSpread" style="width: 50%" >
+                            <!--<table class="table table-sm table-bordered mt-1">
+                              <thead><tr><th></th><th>分册章节</th></tr></thead>
+                              <tbody>
+                                <tr><td>1</td><td>第一册 机械设备安装工程1~6、8~16章节</td></tr>
+                              </tbody>
+                            </table>-->
+                          </div>
+                      </div>
+                    </div>
+                    <div class="bottom-content" id="instFeeRuleSpread">
+                        <!--<table class="table table-sm table-bordered">
+                          <thead><tr><th></th><th>编码</th><th>费用规则</th><th>基数</th><th>费率(%)</th><th>其中人工(%)</th><th>其中材料(%)</th><th>其中机械(%)</th></tr></thead>
+                          <tbody>
+                            <tr><td>1</td><td>AZFY1</td><td>超高费(标高15m以内)(第一册 机械设备安装工程1~6章节)</td><td>分贝按人材机乘系数</td><td></td><td>25</td><td></td><td>25</td></tr>
+                          </tbody>
+                        </table>-->
+                    </div>
+                  </div>
+              </div>
+            </div>
+        </div>
+    </div>
+    <button id="rcjAlertBtn" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#rcjAlert" style="display: none"></button>
+    <button id="codeAlertBtn" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#codeAlert" style="display: none"></button>
+    <div class="modal fade" id="rcjAlert" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <input type="hidden" id="gdid" value="123">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">取消确认</h5>
+                    <button type="button" id="gljAleClose" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <h5 class="text-danger" id="alertGljTxt">人工、材料、机械之和必须为100,是否取消输入?</h5>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" id="aleCanceBtn" data-dismiss="modal">取消</button>
+                    <a href="javascript: void(0);" id="aleConfBtn" class="btn btn-danger" data-dismiss="modal">确认</a>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="modal" id="codeAlert" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <input type="hidden" id="codedid" value="123">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">警告</h5>
+                    <button type="button" id="codAleClose" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <h5 class="text-danger" id="alertText">输入的编号已存在,请重新输入!</h5>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" id="codAlertQX" data-dismiss="modal">取消</button>
+                    <button type="button" class="btn btn-danger" id="codAlertQR" data-dismiss="modal">确认</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!--批量关联分册至定额-->
+    <div class="modal fade" id="sectionTreeModal" data-backdrop="static">
+        <div class="modal-dialog modal-feeRate" role="document" id="fee_rate_dialog">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">请选择定额章节</h5>
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">&times;</span>
+                    </button>
+                </div>
+                <div class="modal-body" >
+                    <input type="hidden" id="edit_from">
+                    <div class="row" style="height: 500px">
+                        <div class="modal-auto-height col-12" style="overflow: hidden" id="batchSectionSpread"></div>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" id="scTreeCancel" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                        <a href="javascript:void(0);" id="bsTree_conf" class="btn btn-primary">确定</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- JS. -->
+    <!-- JS. -->
+    <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
+    <script>GC.Spread.Sheets.LicenseKey = "559432293813965#A0y3iTOzEDOzkjMyMDN9UTNiojIklkI1pjIEJCLi4TPB9mM5AFNTd4cvZ7SaJUVy3CWKtWYXx4VVhjMpp7dYNGdx2ia9sEVlZGOTh7NRlTUwkWR9wEV4gmbjBDZ4ElR8N7cGdHVvEWVBtCOwIGW0ZmeYVWVr3mI0IyUiwCMzETN8kzNzYTM0IicfJye&Qf35VfiEzRwEkI0IyQiwiIwEjL6ByUKBCZhVmcwNlI0IiTis7W0ICZyBlIsIyNyMzM5ADI5ADNwcTMwIjI0ICdyNkIsIibj9SbvNmL4N7bjRnch56ciojIz5GRiwiI8+Y9sWY9QmZ0Jyp96uL9v6L0wap9biY9qiq95q197Wr9g+89iojIh94Wiqi";</script>
+    <script src="/lib/jquery/jquery.min.js"></script>
+    <script src="/lib/jquery-contextmenu/jquery.contextMenu.min.js"></script>
+    <script src="/lib/jquery-contextmenu/jquery.ui.position.js"></script>
+    <script src="/lib/tether/tether.min.js"></script>
+    <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script type="text/javascript" src="/public/web/QueryParam.js"></script>
+    <script src="/public/web/uuid.js"></script>
+    <script src="/public/web/scMathUtil.js"></script>
+    <script src="/public/common_util.js"></script>
+    <script src="/public/web/storageUtil.js"></script>
+    <script  src="/public/web/id_tree.js"></script>
+    <script src="/public/web/tree_sheet/tree_sheet_controller.js"></script>
+    <script src="/public/web/tree_sheet/tree_sheet_helper.js"></script>
+    <script src="/public/web/sheet/sheet_common.js"></script>
+    <script src="/public/web/common_ajax.js"></script>
+    <script src="/web/maintain/ration_repository/js/global.js"></script>
+    <script src="/web/maintain/ration_repository/js/installation.js"></script>
+
+</body>
+<script type="text/javascript">
+    autoFlashHeight();
+</script>
+
+</html>

+ 10 - 3
web/maintain/ration_repository/dinge.html

@@ -97,8 +97,7 @@
                                           <a class="nav-link" id="linkFZTJ" data-toggle="tab" href="#rDetail" role="tab">附注条件调整</a>
                                       </li>
                                       <li class="nav-item">
-                                          <!--<a class="nav-link" id="linkAZZJ" data-toggle="tab" href="#" role="tab">安装增加费</a>-->
-                                          <a class="nav-link" href="#">安装增加费</a>
+                                          <a class="nav-link" id="linkAZZJ" data-toggle="tab" href="#" role="tab">安装增加费</a>
                                       </li>
                                   </ul>
                                   <!-- 内容 -->
@@ -461,6 +460,7 @@
         <script type="text/javascript" src="/web/maintain/ration_repository/js/rationUnits.js"></script>
         <script type="text/javascript" src="/web/maintain/ration_repository/js/ration.js"></script>
         <script type="text/javascript" src="/web/maintain/ration_repository/js/ration_glj.js"></script>
+        <script type="text/javascript" src="/web/maintain/ration_repository/js/ration_installation.js"></script>
         <script type="text/javascript" src="/public/web/sheet/sheet_creater.js"></script>
         <script type="text/javascript" src="/web/maintain/ration_repository/js/ration_coe.js"></script>
         <script type="text/javascript" src="/web/maintain/ration_repository/js/ration_assist.js"></script>
@@ -523,7 +523,7 @@
                // sheetCommonObj.shieldAllCells(rationOprObj.workBook.getSheet(0), rationOprObj.setting);
 
                // tabPanel 下有多个Spread时,相互之间不能正确显示。改成一个Spread下多个Sheet。
-                var rdSpread = sheetCommonObj.createSpread($("#rdSpread")[0], 3);
+                var rdSpread = sheetCommonObj.createSpread($("#rdSpread")[0], 4);
                 rationGLJOprObj.buildSheet(rdSpread.getSheet(0));
                // sheetCommonObj.shieldAllCells(rdSpread.getSheet(0), rationGLJOprObj.setting);
 
@@ -532,6 +532,9 @@
 
                 rationCoeOprObj.buildSheet(rdSpread.getSheet(2));
               //  sheetCommonObj.shieldAllCells(rdSpread.getSheet(2), rationCoeOprObj.setting);
+                rationInstObj.getInstallation(parseInt(getQueryString("repository")), function () {
+                    rationInstObj.buildSheet(rdSpread.getSheet(3));
+                });
 
                 $("#linkGLJ").click(function(){
                     rationGLJOprObj.bindRationGljDelOpr();
@@ -547,6 +550,10 @@
                     rationCoeOprObj.bindRationCoeDel();
                     rdSpread.setActiveSheetIndex(2);
                 });
+                $("#linkAZZJ").click(function(){
+                    rationInstObj.bindRationInstDel();
+                    rdSpread.setActiveSheetIndex(3);
+                });
             });
         </script>
     </div>

+ 1 - 0
web/maintain/ration_repository/js/global.js

@@ -10,6 +10,7 @@ function autoFlashHeight(){
     $(".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-top-fluid").height($(window).height()-headerHeight-bottomContentHeight-2);
     $(".main-data").height($(window).height()-headerHeight);
     $(".main-side .tab-content").height($(window).height()-headerHeight-38);
 };

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1232 - 0
web/maintain/ration_repository/js/installation.js


+ 13 - 2
web/maintain/ration_repository/js/ration.js

@@ -82,10 +82,12 @@ let rationOprObj = {
             let me = rationOprObj,
                 sheetGLJ = rationGLJOprObj.sheet, settingGLJ = rationGLJOprObj.setting,
                 sheetCoe = rationCoeOprObj.sheet, settingCoe = rationCoeOprObj.setting,
-                sheetAss = rationAssistOprObj.sheet, settingAss = rationAssistOprObj.setting;
+                sheetAss = rationAssistOprObj.sheet, settingAss = rationAssistOprObj.setting,
+                sheetInst = rationInstObj.sheet, settingInst = rationInstObj.setting;
             sheetCommonObj.cleanSheet(sheetGLJ, settingGLJ, -1);
             sheetCommonObj.cleanSheet(sheetCoe, settingCoe, -1);
             sheetCommonObj.cleanSheet(sheetAss, settingAss, -1);
+            sheetCommonObj.cleanSheet(sheetInst, settingInst, -1);
             let cacheSection = me.getCache();
             if (cacheSection && row < cacheSection.length) {
                 rationGLJOprObj.getGljItems(cacheSection[row], function () {
@@ -95,6 +97,9 @@ let rationOprObj = {
                     me.workBook.focus(true);
                 });
                 rationAssistOprObj.getAssItems(cacheSection[row]);
+                rationInstObj.getInstItems(cacheSection[row], function () {
+                    me.workBook.focus(true);
+                });
             }
             else {
                 rationGLJOprObj.currentRationItem = null;
@@ -135,6 +140,7 @@ let rationOprObj = {
                         cacheSection[j]["rationGljList"] = result.data.ops[i]["rationGljList"];
                         cacheSection[j]["rationCoeList"] = result.data.ops[i]["rationCoeList"];
                         cacheSection[j]["rationAssList"] = result.data.ops[i]["rationAssList"];
+                        cacheSection[j]["rationInstList"] = result.data.ops[i]["rationInstList"];
                     }
                 }
             }
@@ -564,7 +570,8 @@ let rationOprObj = {
         let me = rationOprObj,
             sheetGLJ = rationGLJOprObj.sheet, settingGLJ = rationGLJOprObj.setting,
             sheetCoe = rationCoeOprObj.sheet, settingCoe = rationCoeOprObj.setting,
-            sheetAss = rationAssistOprObj.sheet, settingAss = rationAssistOprObj.setting;
+            sheetAss = rationAssistOprObj.sheet, settingAss = rationAssistOprObj.setting,
+            sheetInst = rationInstObj.sheet, settingInst = rationInstObj.setting;
         if (me.workBook) {
             if (me.currentRations && me.currentRations["_SEC_ID_" + sectionID] && me.currentRations["_SEC_ID_" + sectionID].length > 0) {
                 let cacheSection = me.currentRations["_SEC_ID_" + sectionID];
@@ -579,15 +586,18 @@ let rationOprObj = {
                         sheetCommonObj.cleanData(sheetGLJ, settingGLJ, -1);
                         sheetCommonObj.cleanData(sheetCoe, settingCoe, -1);
                         sheetCommonObj.cleanData(sheetAss, settingAss, -1);
+                        sheetCommonObj.cleanData(sheetInst, settingInst, -1);
                         rationGLJOprObj.getGljItems(cacheSection[row]);
                         rationCoeOprObj.getCoeItems(cacheSection[row]);
                         rationAssistOprObj.getAssItems(cacheSection[row]);
+                        rationInstObj.getInstItems(cacheSection[row]);
                     }
                     else {
                         rationGLJOprObj.currentRationItem = null;
                         sheetCommonObj.cleanData(sheetGLJ, settingGLJ, -1);
                         sheetCommonObj.cleanData(sheetCoe, settingCoe, -1);
                         sheetCommonObj.cleanData(sheetAss, settingAss, -1);
+                        sheetCommonObj.cleanData(sheetInst, settingInst, -1);
                         sheetCommonObj.setDynamicCombo(sheetAss, 0, 5, sheetAss.getRowCount(), rationAssistOprObj.setting.comboItems, false, false);
                     }
                 }
@@ -601,6 +611,7 @@ let rationOprObj = {
                 sheetCommonObj.cleanSheet(sheetGLJ, settingGLJ, -1);
                 sheetCommonObj.cleanSheet(sheetCoe, settingCoe, -1);
                 sheetCommonObj.cleanSheet(sheetAss, settingAss, -1);
+                sheetCommonObj.cleanSheet(sheetInst, settingInst, -1);
             }
            //--- me.workBook.focus(true);
         }

+ 301 - 0
web/maintain/ration_repository/js/ration_installation.js

@@ -0,0 +1,301 @@
+/**
+ * Created by Zhong on 2018/1/25.
+ */
+let rationInstObj = {
+    IDMapping: null, //ID - name
+    feeItem: null, //name - ID
+    sheet: null,
+    rationRepId: null,
+    curRation: null,
+    cache: [],
+    setting: {
+        header:[
+            {headerName:"费用项",headerWidth:200,dataCode:"feeItem", dataType: "String", hAlign: 'left'},
+            {headerName:"分册章节",headerWidth:400,dataCode:"section", dataType: "String", hAlign: 'left'}
+        ],
+        view:{
+            comboBox:[],
+            lockColumns:[]
+        },
+    },
+    buildSheet: function(sheet) {
+        let me = this;
+        me.sheet = sheet;
+        me.sheet.options.clipBoardOptions = GC.Spread.Sheets.ClipboardPasteOptions.values;
+        me.rationRepId = parseInt(pageOprObj.rationLibId); // 不可靠,有时取不到
+        if (me.rationRepId == undefined){me.rationRepId = parseInt(getQueryString('repository'))};
+        sheetCommonObj.initSheet(me.sheet, me.setting, 30);
+        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.EnterCell, me.onEnterCell);
+        me.sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStarting);
+        me.sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
+        //右键
+      //  me.onContextmenuOpr();
+    },
+    renderFunc: function (sheet, func) {
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        if(func){
+            func();
+        }
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
+    isDef: function (v) {
+        return v !== undefined && v !== null;
+    },
+    getInstallation: function (rationRepId, callback) {
+        let me = this;
+        CommonAjax.post('/rationRepository/api/getInstallation', {rationRepId: rationRepId}, function (rstData) {
+            //建立name - ID 映射, ID - name 映射
+            me.feeItem = {};
+            me.IDMapping = {feeItem: {}, section: {}};
+            for(let feeItem of rstData){
+                me.feeItem[feeItem.feeItem] = {ID: feeItem.ID, section: {}};
+                me.IDMapping['feeItem'][feeItem.ID] = feeItem.feeItem;
+                for(let section of feeItem.section){
+                    me.feeItem[feeItem.feeItem]['section'][section.name] = section.ID;
+                    me.IDMapping['section'][section.ID] = section.name;
+                }
+            }
+            if(callback){
+                callback(rstData);
+            }
+        });
+    },
+    getFeeItemCombo: function () {
+        let feeItemArr = [];
+        for(let name in this.feeItem){
+            feeItemArr.push(name);
+        }
+        let combo = sheetCommonObj.getDynamicCombo();
+        combo.items(feeItemArr).itemHeight(10).editable(false);
+        return combo;
+    },
+    getSectionCombo: function (feeItem) {
+        let sectionObjs = this.feeItem[feeItem]['section'];
+        let sectionArr = [];
+        for(let name in sectionObjs){
+            sectionArr.push(name);
+        }
+        let combo = sheetCommonObj.getDynamicCombo();
+        combo.items(sectionArr).itemHeight(10).editable(false);
+        return combo;
+    },
+    getInstItems: function (ration, callback) {
+        let me = this, rst = [];
+        me.curRation = ration;
+        me.cache = ration.rationInstList;
+        for(let inst of me.cache){
+            let data = Object.create(null);
+            let feeItem = me.IDMapping['feeItem'][inst.feeItemId];
+            let section = me.IDMapping['section'][inst.sectionId];
+            data.feeItem = me.isDef(feeItem) ? feeItem : '';
+            data.section = me.isDef(section) ? section : '';
+            rst.push(data);
+        }
+        me.showInstItems(rst);
+        if(callback){
+            callback();
+        }
+    },
+    showInstItems: function (data) {
+        let me = this;
+        sheetCommonObj.showData(this.sheet, this.setting, data);
+        //init combo
+        this.renderFunc(this.sheet, function () {
+            let feeIemCombo = me.getFeeItemCombo();
+            let rowCount = me.sheet.getRowCount();
+            for(let i = 0, len = rowCount.length; i < len; i++){
+                me.getRange(i, -1, 1, -1).cellType(null);
+            }
+            me.sheet.getRange(-1, 0, -1, 1).cellType(feeIemCombo);
+            for(let i = 0, len = data.length; i < len; i++){
+                let sectionCombo = me.getSectionCombo(data[i].feeItem);
+                me.sheet.getCell(i, 1).cellType(sectionCombo);
+            }
+        });
+    },
+    onEnterCell: function (sender, args) {
+        args.sheet.repaint();
+    },
+    onEditStarting: function (sender, args) {
+        let me = rationInstObj;
+        if(!me.isDef(me.curRation)){
+            args.cancel = true;
+            return;
+        }
+        if(!me.isDef(me.cache[args.row]) && args.col === 1){
+            args.cancel = true;
+            return;
+        }
+    },
+    onEditEnded: function (sender, args) {
+        let me = rationInstObj;
+        let v = me.isDef(args.editingText) ? args.editingText.toString().trim() : '';
+        let field = me.setting.header[args.col]['dataCode'];
+        let inst = me.cache[args.row];
+        let toUpdate = false;
+        //update
+        if(me.isDef(inst)){
+            if(field === 'feeItem'){
+                let feeItemId = me.isDef(me.feeItem[v]) ? me.feeItem[v]['ID'] : null;
+                if(feeItemId){
+                    inst.feeItemId = feeItemId;
+                    toUpdate = true;
+                }
+                else {
+                    me.sheet.setValue(args.row, args.col, me.IDMapping['feeItem'][inst.feeItemId]);
+                    return;
+                }
+            }
+            else{
+                let sectionId = me.isDef(me.feeItem[me.IDMapping['feeItem'][inst.feeItemId]]) ? me.feeItem[me.IDMapping['feeItem'][inst.feeItemId]]['section'][v] : null;
+                inst.sectionId = sectionId;
+                toUpdate = true;
+            }
+        }
+        //insert
+        else{
+            let feeItemId = me.isDef(me.feeItem[v]) ? me.feeItem[v]['ID'] : null;
+            if(feeItemId){
+                let obj = {feeItemId: feeItemId, sectionId: null};
+                me.cache.push(obj);
+                toUpdate = true;
+            }
+        }
+        if(toUpdate){
+            me.updateRation(me.curRation, function () {
+                me.getInstItems(me.curRation);
+            });
+        }
+    },
+    validUpdatePaste: function (rowData, data) {
+        if(this.isDef(data.feeItem) && this.isDef(data.section) && data.feeItem !== '' && data.section !== ''){
+            if(!this.isDef(this.feeItem[data.feeItem])){
+                return false;
+            }
+            if(!this.isDef(this.feeItem[data.feeItem]['section'][data.section])){
+                return false;
+            }
+        }
+        else if(this.isDef(data.feeItem) && data.feeItem !== ''){
+            if(!this.isDef(this.feeItem[data.feeItem])){
+                return false;
+            }
+        }
+        else if(this.isDef(data.section) && data.section !== ''){
+            if(!this.isDef(this.feeItem[this.IDMapping['feeItem'][rowData.feeItemId]]['section'][data.section])){
+                return false;
+            }
+        }
+        return true;
+    },
+    validInsertPaste: function (data) {
+        if(!this.isDef(data.feeItem) || data.feeItem == ''){
+            return false;
+        }
+        if(!this.isDef(this.feeItem[data.feeItem])){
+            return false;
+        }
+        if(this.isDef(data.section) && data.section !== '' && !this.isDef(this.feeItem[data.feeItem]['section'][data.section])){
+            return false;
+        }
+        return true;
+    },
+    toSaveData: function (data, rowData = null) {
+        let obj = {feeItemId: null, sectionId: null};
+        if(this.isDef(data.feeItem) && data.feeItem !== ''){
+            obj.feeItemId = this.isDef(this.feeItem[data.feeItem]) ? this.feeItem[data.feeItem]['ID'] : null;
+        }
+        else if(this.isDef(rowData)){
+            obj.feeItemId = rowData.feeItemId;
+        }
+        if(this.isDef(data.section) && data.section !== ''){
+            obj.sectionId = this.isDef(this.feeItem[this.IDMapping['feeItem'][obj.feeItemId]]['section'][data.section]) ?
+                this.feeItem[this.IDMapping['feeItem'][obj.feeItemId]]['section'][data.section]: null;
+        }
+        return obj;
+    },
+    bindRationInstDel: function () {
+        let me = this;
+        let workBook = me.sheet.getParent();
+        workBook.commandManager().register('rationInstDel', function () {
+            let toUpdate = false;
+            let sels = me.sheet.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 inst = me.cache[row];
+                        //有数据,删除数据
+                        if(me.isDef(inst)){
+                            if(!toUpdate){
+                                toUpdate = true;
+                            }
+                        }
+                    }
+                    //front delete
+                    me.cache.splice(sel.row, sel.rowCount);
+                }
+            }
+            if(toUpdate && me.curRation){
+                me.updateRation(me.curRation, function () {
+                    me.getInstItems(me.curRation);
+                });
+            }
+        });
+        workBook.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
+        workBook.commandManager().setShortcutKey('rationInstDel', GC.Spread.Commands.Key.del, false, false, false, false);
+    },
+    onClipboardPasting: function (sender, info) {
+        let me = rationInstObj;
+        if(!me.isDef(me.curRation)){
+            info.cancel = true;
+        }
+    },
+    onClipboardPasted: function (sender, info) {
+        let me = rationInstObj;
+        let items = sheetCommonObj.analyzePasteData(me.setting, info);
+        let toUpdate = false;
+        for(let i = 0, len = items.length; i < len; i++){
+            let row = info.cellRange.row + i;
+            //update
+            let inst = me.cache[row];
+            if(me.isDef(inst)){
+                if(me.validUpdatePaste(inst, items[i])){
+                    let updateObj = me.toSaveData(items[i], inst);
+                    for(let attr in updateObj){
+                        inst[attr] = updateObj[attr];
+                    }
+                    toUpdate = true;
+                }
+            }
+            //insert
+            else{
+                if(me.validInsertPaste(items[i])){
+                    me.cache.push(me.toSaveData(items[i]));
+                    toUpdate = true;
+                }
+            }
+        }
+        if(toUpdate){
+            me.updateRation(me.curRation, function () {
+                me.getInstItems(me.curRation);
+            });
+        }
+        else {
+            me.getInstItems(me.curRation);
+        }
+    },
+    updateRation: function (ration,callback) {
+        rationOprObj.mixUpdateRequest([ration], [], [], function () {
+            if(callback){
+                callback();
+            }
+        });
+    }
+};

+ 10 - 1
web/maintain/ration_repository/js/section_tree.js

@@ -312,6 +312,7 @@ let sectionTreeObj = {
                     me.refreshBtn(me.tree.selected);
                     //fresh tools
                     me.initTools(me.tree.selected);
+                    me.workBook.focus();
                 });
             }
         });
@@ -350,6 +351,7 @@ let sectionTreeObj = {
                 me.controller.delete();
                 me.refreshBtn(me.tree.selected);
                 me.initTools(me.tree.selected);
+                me.workBook.focus();
             });
         }
     },
@@ -387,6 +389,7 @@ let sectionTreeObj = {
             me.sectionTreeAjax(postData, function (rstData) {
                 me.controller.upLevel();
                 me.refreshBtn(me.tree.selected);
+                me.workBook.focus();
             });
         }
 
@@ -414,6 +417,7 @@ let sectionTreeObj = {
             me.sectionTreeAjax(postData, function (rstData) {
                 me.controller.downLevel();
                 me.refreshBtn(me.tree.selected);
+                me.workBook.focus();
             });
         }
     },
@@ -440,6 +444,7 @@ let sectionTreeObj = {
             me.sectionTreeAjax(postData, function (rstData) {
                 me.controller.upMove();
                 me.refreshBtn(me.tree.selected);
+                me.workBook.focus();
             });
         }
     },
@@ -466,6 +471,7 @@ let sectionTreeObj = {
             me.sectionTreeAjax(postData, function (rstData) {
                 me.controller.downMove();
                 me.refreshBtn(me.tree.selected);
+                me.workBook.focus();
             });
         }
     },
@@ -535,9 +541,12 @@ let sectionTreeObj = {
             annotationOprObj.setRadiosDisabled(true, annotationOprObj.radios);
             annotationOprObj.hideTable($('#fzTableAll'), $('#fzTablePartial'));
             sheetCommonObj.cleanSheet(rationOprObj.workBook.getSheet(0), rationOprObj.setting, -1);
+            rationGLJOprObj.sheet.getParent().focus(false);
         }
         sheetCommonObj.cleanSheet(rationGLJOprObj.sheet, rationGLJOprObj.setting, -1);
-        rationGLJOprObj.sheet.getParent().focus(false);
+        sheetCommonObj.cleanSheet(rationAssistOprObj.sheet, rationAssistOprObj.setting, -1);
+        sheetCommonObj.cleanSheet(rationCoeOprObj.sheet, rationCoeOprObj.setting, -1);
+        sheetCommonObj.cleanSheet(rationInstObj.sheet, rationInstObj.setting, -1);
         me.workBook.focus(true);
     }
 };

+ 5 - 0
web/maintain/std_glj_lib/html/gongliao.html

@@ -146,6 +146,7 @@
     <script src="/lib/jquery-contextmenu/jquery.ui.position.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/std_glj_lib/js/global.js"></script>
     <!-- zTree -->
     <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
@@ -246,6 +247,10 @@
             }
         };
         $(document).ready(function(){
+            //test
+            console.log(scMathUtil.roundTo(parseFloat(25*1.277), -2));
+            console.log(25*1.277);
+            //test
             //解决spreadjs sheet初始化没高度宽度
             $('#modalCon').width($(window).width()*0.5);
             $('#componentTreeDiv').height($(window).height() - 300);

+ 14 - 6
web/maintain/std_glj_lib/js/glj.js

@@ -393,6 +393,10 @@ let repositoryGljObj = {
     onCellEditStart: function(sender, args) {
         let me = repositoryGljObj;
         let rObj = sheetsOprObj.combineRowData(me.workBook.getSheet(0), me.setting, args.row);
+        if(me.prevent){
+            args.cancel = true;
+            return;
+        }
         me.currentEditingGlj = rObj;
         me.orgCode = me.workBook.getSheet(0).getValue(args.row, 0);
         if(args.row < me.currentCache.length){
@@ -535,7 +539,6 @@ let repositoryGljObj = {
                         rObj.basePrice = 0;
                     }
                     rObj.basePrice = !isNaN(parseFloat(rObj.basePrice)) && (rObj.basePrice && typeof rObj.basePrice !== 'undefined') ? scMathUtil.roundTo(parseFloat(rObj.basePrice), -2) : 0;
-                    console.log(rObj.basePrice);
                     addArr.push(rObj);
                 }
             }
@@ -818,7 +821,7 @@ let repositoryGljObj = {
                 for(let i = 0, len = info.cellRange.rowCount; i < len; i++){
                     let row = i + info.cellRange.row;
                     if(row < me.currentCache.length){
-                        if(me.allowComponent.indexOf(me.currentCache[row].gljType) !== -1){
+                        if(me.allowComponent.indexOf(me.currentCache[row].gljType) !== -1 && me.currentCache[row].component.length > 0){
                             rst = false;
                         }
                     }
@@ -852,9 +855,9 @@ let repositoryGljObj = {
                 if(updateObj && typeof updateObj.updateGlj !== 'undefined' && updateObj.updateGlj.length > 0){
                     //updateArr = updateObj.updateGlj;
                     updateArr = updateArr.concat(updateObj.updateGlj);
-                    if(typeof updateObj.updateBasePrc !== 'undefined'){
+                    if(typeof updateObj.updateBasePrcArr !== 'undefined'){
                         //updateBasePrcArr = updateObj.updateBasePrc;
-                        updateBasePrcArr = updateBasePrcArr.concat(updateObj.updateBasePrc);
+                        updateBasePrcArr = updateBasePrcArr.concat(updateObj.updateBasePrcArr);
                     }
                 }
                 else{
@@ -868,8 +871,8 @@ let repositoryGljObj = {
                 let updateObj = me.validUpdateObj(items[i], info.cellRange.row + i);
                 if(updateObj && typeof updateObj.updateGlj !== 'undefined'){
                     updateArr = updateArr.concat(updateObj.updateGlj);
-                    if(typeof updateObj.updateBasePrc !== 'undefined'){
-                        updateBasePrcArr = updateBasePrcArr.concat(updateObj.updateBasePrc);
+                    if(typeof updateObj.updateBasePrcArr !== 'undefined'){
+                        updateBasePrcArr = updateBasePrcArr.concat(updateObj.updateBasePrcArr);
                     }
                 }
                 else{
@@ -951,6 +954,9 @@ let repositoryGljObj = {
         }
     },
     updateRationBasePrcRq: function (basePrcArr) {
+        let me = this;
+        me.prevent = true;
+        $.bootstrapLoading.start();
         $.ajax({
             type: 'post',
             url: 'api/updateRationBasePrc',
@@ -960,6 +966,8 @@ let repositoryGljObj = {
                 if(result.error){
                     alert("计算定额基价失败");
                 }
+                $.bootstrapLoading.end();
+                me.prevent = false;
             }
         });
     },

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

@@ -507,6 +507,8 @@ let gljComponentOprObj = {
         let me = gljComponentOprObj, gljBasePrc = 0;
         for(let i = 0; i < component.length; i++){
             let roundBasePrc = scMathUtil.roundTo(parseFloat(component[i].basePrice), -2);
+            console.log(roundBasePrc);
+            console.log();
             gljBasePrc = scMathUtil.roundTo(scMathUtil.roundTo(roundBasePrc * parseFloat(component[i].consumeAmt), -2) + gljBasePrc, -2);
         }
         return gljBasePrc;

+ 1 - 0
web/users/js/col_setting.js

@@ -215,6 +215,7 @@ let ColSettingObj = {
         }
     },
     getActualCellRange: function (cellRange, rowCount, columnCount) {
+        let spreadNS = GC.Spread.Sheets;
         if (cellRange.row == -1 && cellRange.col == -1) {
             return new spreadNS.Range(0, 0, rowCount, columnCount);
         }

+ 10 - 0
web/users/js/compilation.js

@@ -193,6 +193,16 @@ $(document).ready(function() {
         });
     });
 
+    //计价规则删除
+    $('#delete-confirm').click(function () {
+        let id = $('#del').attr('selectedId');
+        console.log(id);
+        if (id === undefined || id === '') {
+            return false;
+        }
+        window.location.href = `/compilation/valuation/bill/delete/${id}`;
+    });
+
     // 发布编办
     $("#release").click(function() {
         let id = $(this).data("id");

+ 31 - 4
web/users/js/main_tree_col.js

@@ -4,6 +4,9 @@
 
 let MainTreeCol = {
     getText: {
+        subType: function (node) {
+
+        },
         type: function (node) {
             if (node.sourceType === projectObj.project.Bills.getSourceType()) {
                 return '';
@@ -25,11 +28,13 @@ let MainTreeCol = {
         code: function (node) {
 
         },
-        marketPrice:function (node) {
-            if((node.sourceType === projectObj.project.Ration.getSourceType()&&node.data.type==rationType.gljRation)||node.sourceType==projectObj.project.ration_glj.getSourceType()){
-                return assistCalcer.uiGLJPrice(node.data.marketUnitFee);
-            }
+        //取费专业
+        calcProgramName: function (node) {
+
+        },
+        marketPrice: function (node) {
         }
+
     },
     readOnly: {
         bills: function (node) {
@@ -90,6 +95,17 @@ let MainTreeCol = {
             }else {
                 return treeNodeTools.isRation(node);
             }
+        },
+        forContentCharacter: function (node) {
+            return !MainTreeCol.readOnly.bills(node) || (node.data.type !== billType.BILL && node.data.type !== billType.FX);
+        },
+        forRuleText: function (node) {
+            if(MainTreeCol.readOnly.bills(node)){
+                if(node.data.type === billType.FX || (node.data.type === billType.BILL && node.source.children.length === 0)){
+                    return false;
+                }
+            }
+            return true;
         }
     },
     cellType: {
@@ -104,6 +120,17 @@ let MainTreeCol = {
         },
         calcBase: function () {
             return calcBaseView.getCalcBaseCellType();
+        },
+        calcProgramName: function (node) {
+
+        },
+        //类别
+        subType: function (node) {
+
+        },
+        //是否分包
+        isSubcontract: function (node) {
+
         }
      },
     getEvent: function (eventName) {

+ 24 - 3
web/users/js/template.js

@@ -33,13 +33,14 @@ let TEMPLATE_BILLS_SETTING = {
             "spanRows":[1],
             "vAlign":[1],
             "hAlign":[1],
-            "font":["Arial"]
+            "font":["Arial"],
         },
         "data":{
             "field":"code",
             "vAlign":0,
             "hAlign":3,
-            "font":"Arail"
+            "font":"Arail",
+            "formatter": '@'
         }
     }, {
         "width":300,
@@ -229,7 +230,8 @@ $(document).ready(function () {
     let tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
     let billsSpread = TREE_SHEET_HELPER.createNewSpread($('#billsSpread')[0]);
     let controller = TREE_SHEET_CONTROLLER.createNew(tree, billsSpread.getActiveSheet(), TEMPLATE_BILLS_SETTING);
-
+    //format code
+    //billsSpread.getSheet(0).setFormatter(-1, 1, '@');
     controller.bind('refreshBaseActn', RefreshBaseActn);
 
     billsSpread.bind(GC.Spread.Sheets.Events.EditEnded, function (sender, info) {
@@ -287,6 +289,8 @@ $(document).ready(function () {
     RefreshBaseActn(tree);
 
     $('#insert').click(function () {
+        let me = this;
+        $(me).addClass('disabled');
         var selected = controller.tree.selected, updateData;
         if (selected) {
             updateData = controller.tree.getInsertData(selected.getParentID(), selected.getNextSiblingID());
@@ -297,58 +301,75 @@ $(document).ready(function () {
             CommonAjax.post(updateUrl, updateData, function (data) {
                 controller.insert();
                 controller.showTreeData();
+                $(me).removeClass('disabled');
             });
         } else {
             alert('新增节点失败, 请重试.');
+            $(me).removeClass('disabled');
         }
     });
     $('#delete').click(function () {
+        let me = this;
+        $(me).addClass('disabled');
         var selected = controller.tree.selected, updateData;
         if (selected) {
             updateData = controller.tree.getDeleteData(selected);
             CommonAjax.post(updateUrl, updateData, function (data) {
                 controller.delete();
                 controller.showTreeData();
+                $(me).removeClass('disabled');
             });
         }
     });
     $('#upLevel').click(function () {
+        let me = this;
+        $(me).addClass('disabled');
         var selected = controller.tree.selected, updateData;
         if (selected) {
             updateData = selected.getUpLevelData();
             CommonAjax.post(updateUrl, updateData, function (data) {
                 controller.upLevel();
                 controller.showTreeData();
+                $(me).removeClass('disabled');
             });
         }
     });
     $('#downLevel').click(function () {
+        let me = this;
+        $(me).addClass('disabled');
         var selected = controller.tree.selected, updateData;
         if (selected) {
             updateData = selected.getDownLevelData();
             CommonAjax.post(updateUrl, updateData, function (data) {
                 controller.downLevel();
                 controller.showTreeData();
+                $(me).removeClass('disabled');
             });
         }
     });
     $('#upMove').click(function () {
+        let me = this;
+        $(me).addClass('disabled');
         var selected = controller.tree.selected, updateData;
         if (selected) {
             updateData = selected.getUpMoveData();
             CommonAjax.post(updateUrl, updateData, function (data) {
                 controller.upMove();
                 controller.showTreeData();
+                $(me).removeClass('disabled');
             });
         }
     });
     $('#downMove').click(function () {
+        let me = this;
+        $(me).addClass('disabled');
         var selected = controller.tree.selected, updateData;
         if (selected) {
             updateData = selected.getDownMoveData();
             CommonAjax.post(updateUrl, updateData, function (data) {
                 controller.downMove();
                 controller.showTreeData();
+                $(me).removeClass('disabled');
             });
         }
     });

+ 2 - 1
web/users/views/compilation/index.html

@@ -50,7 +50,8 @@
                         </td>
                         <td>
                             <a href="/compilation/valuation/bill/<%= bill.id %>" class="btn btn-sm">编辑</a>
-                            <a href="/compilation/valuation/bill/delete/<%= bill.id %>" class="btn btn-sm text-danger">删除</a>
+                            <a onclick="$('#del').attr('selectedId', '<%= bill.id %>')" href="#" data-id="<%= bill.id %>" data-toggle="modal" data-target="#del" class="btn btn-sm text-danger">删除</a>
+                            <!--<a href="/compilation/valuation/bill/delete/<%= bill.id %>" class="btn btn-sm text-danger">删除</a>-->
                         </td>
                     </tr>
                     <% }) %>

+ 20 - 0
web/users/views/compilation/modal.html

@@ -183,4 +183,24 @@
         </div>
     </div>
 </div>
+<!--弹出删除-->
+<div class="modal fade" id="del" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">删除确认</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <h5 class="text-danger" id="tenderHint">删除计价规则 ?</h5>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a href="javascript:void(0);" class="btn btn-danger" id="delete-confirm">删除</a>
+            </div>
+        </div>
+    </div>
+</div>
 <script type="text/javascript" src="/web/users/js/col_setting.js"></script>