浏览代码

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

zhangweicheng 7 年之前
父节点
当前提交
e8125c0178

+ 11 - 1
modules/pm/controllers/pm_controller.js

@@ -543,5 +543,15 @@ module.exports = {
         catch (err){
             callback(req, res, 1, err, null);
         }
-    }
+    },
+    getSummaryInfo: async function(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let summaryInfo = await pm_facade.getSummaryInfo(data.projectIDs);
+            callback(req, res, 0, 'success', summaryInfo);
+        }
+        catch (err){
+            callback(req, res, 1, err, null);
+        }
+    },
 };

+ 134 - 1
modules/pm/facade/pm_facade.js

@@ -23,13 +23,22 @@ let rationGLJModel = mongoose.model('ration_glj');
 let rationCoeModel = mongoose.model('ration_coe');
 let rationInstallationModel = mongoose.model('ration_installation');
 let quantityDetailModel = mongoose.model('quantity_detail');
+let scMathUtil = require('../../../public/scMathUtil').getUtil();
 import CounterModel from "../../glj/models/counter_model";
 import moment from 'moment';
+import billsFlags from '../../common/const/bills_fixed';
+const projectType = {
+    folder: 'Folder',
+    tender: 'Tender',
+    project: 'Project',
+    engineering: 'Engineering',
+};
 
 
 module.exports={
     moveProject:moveProject,
-    copyProject:copyProject
+    copyProject:copyProject,
+    getSummaryInfo: getSummaryInfo
 };
 
 async function copyProject(userID, compilationID,data) {
@@ -447,4 +456,128 @@ function setProperty(Obj,updateData) {
     }
 
 
+}
+
+function isDef(v){
+    return typeof v !== 'undefined' && v !== null;
+}
+
+function getCommonTotalFee(bills) {
+    if(!isDef(bills)){
+        return 0;
+    }
+    if(!isDef(bills.fees) || bills.fees.length <= 0){
+        return 0;
+    }
+    for(let fee of bills.fees){
+        if(isDef(fee.fieldName) && fee.fieldName === 'common'){
+            return isDef(fee.totalFee) ? fee.totalFee : 0;
+        }
+    }
+    return 0;
+}
+
+function summarizeToParent(parent, child) {
+    const decimal = -2;
+    parent.engineeringCost = scMathUtil.roundTo(parseFloat(parent.engineeringCost) + parseFloat(child.engineeringCost), decimal);
+    parent.subEngineering = scMathUtil.roundTo(parseFloat(parent.subEngineering) + parseFloat(child.subEngineering), decimal);
+    parent.measure = scMathUtil.roundTo(parseFloat(parent.measure) + parseFloat(child.measure), decimal);
+    parent.safetyConstruction = scMathUtil.roundTo(parseFloat(parent.safetyConstruction) + parseFloat(child.safetyConstruction), decimal);
+    parent.other = scMathUtil.roundTo(parseFloat(parent.other) + parseFloat(child.other), decimal);
+    parent.charge = scMathUtil.roundTo(parseFloat(parent.charge) + parseFloat(child.charge), decimal);
+    parent.tax = scMathUtil.roundTo(parseFloat(parent.tax) + parseFloat(child.tax), decimal);
+}
+
+function getBuildingArea(projFeature){
+    if(!projFeature || projFeature.length === 0){
+        return null;
+    }
+    for(let f of projFeature){
+        if(f.key === 'buildingArea'){
+            return f.value;
+        }
+    }
+    return null;
+}
+
+async function getSummaryInfo(projectIDs){
+    //ID与汇总信息映射
+    let IDMapping = {};
+    //固定清单类别与汇总金额字段映射
+    let flagFieldMapping = {};
+    flagFieldMapping[billsFlags.ENGINEERINGCOST] = 'engineeringCost';
+    flagFieldMapping[billsFlags.SUB_ENGINERRING] = 'subEngineering';
+    flagFieldMapping[billsFlags.MEASURE] = 'measure';
+    flagFieldMapping[billsFlags.SAFETY_CONSTRUCTION] = 'safetyConstruction';
+    flagFieldMapping[billsFlags.OTHER] = 'other';
+    flagFieldMapping[billsFlags.CHARGE] = 'charge';
+    flagFieldMapping[billsFlags.TAX] = 'tax';
+    for(let projectID of projectIDs){
+        IDMapping[projectID] = {engineeringCost: 0, subEngineering: 0, measure: 0, safetyConstruction: 0, other: 0, charge: 0, tax: 0, rate: 0, buildingArea: '', perCost: ''};
+    }
+    //let projects = await projectModel.find({ID: {$in : projectIDs}, projType: projectType.project, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]});
+    //单项工程
+    let engineerings = await projectModel.find({ParentID: {$in : projectIDs}, projType: projectType.engineering, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]});
+    //单位工程
+    let tenders = [];
+    let engIDs = [];
+    for(let eng of engineerings){
+        engIDs.push(eng.ID);
+        IDMapping[eng.ID] = {engineeringCost: 0, subEngineering: 0, measure: 0, safetyConstruction: 0, other: 0, charge: 0, tax: 0, rate: 0, buildingArea: '', perCost: ''};
+    }
+    if(engIDs.length > 0){
+        tenders = await projectModel.find({ParentID: {$in : engIDs}, projType: projectType.tender, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]});
+    }
+    let tenderIDs = [];
+    if(tenders.length > 0){
+        for(let tender of tenders){
+            tenderIDs.push(tender.ID);
+            IDMapping[tender.ID] = {engineeringCost: 0, subEngineering: 0, measure: 0, safetyConstruction: 0, other: 0, charge: 0, tax: 0, rate: 0, buildingArea: '', perCost: ''};
+            let buildingArea = getBuildingArea(tender.property.projectFeature);
+            if(buildingArea){
+                IDMapping[tender.ID]['buildingArea'] = buildingArea;
+            }
+        }
+        //需要获取的清单固定类别综合合价:工程造价、分部分项、措施项目、安全文明施工专项、规费、其他项目、税金
+        let needFlags = [billsFlags.ENGINEERINGCOST, billsFlags.SUB_ENGINERRING, billsFlags.MEASURE,
+            billsFlags.SAFETY_CONSTRUCTION, billsFlags.CHARGE, billsFlags.OTHER, billsFlags.TAX];
+        //获取单位工程汇总金额需要用到的所有清单
+        let allBills = await billsModel.find({projectID: {$in: tenderIDs}, 'flags.flag': {$in: needFlags}, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]},
+                                            '-_id projectID fees flags');
+        //进行单位工程级别的汇总
+        for(let bills of allBills){
+            let billsFlag = bills.flags[0]['flag'];
+            let costField = flagFieldMapping[billsFlag];
+            IDMapping[bills.projectID][costField] = getCommonTotalFee(bills);
+        }
+        //进行单项工程级别的汇总
+        for(let tender of tenders){
+            summarizeToParent(IDMapping[tender.ParentID], IDMapping[tender.ID]);
+        }
+        //进行建设项目级别的汇总
+        for(let eng of engineerings){
+            summarizeToParent(IDMapping[eng.ParentID], IDMapping[eng.ID]);
+        }
+        //占造价比例、单方造价
+        const rateDecimal = -2;
+        const perCostDecimal = -2;
+        for(let tender of tenders){
+            let tenderInfo = IDMapping[tender.ID];
+            let engInfo = IDMapping[tender.ParentID];
+            tenderInfo.rate = engInfo.engineeringCost == 0 ? 0 : scMathUtil.roundTo(tenderInfo.engineeringCost * 100 / engInfo.engineeringCost, rateDecimal);
+            //单方造价
+            tenderInfo.perCost = tenderInfo.buildingArea.toString().trim() === '' || tenderInfo.buildingArea == 0 ?
+                                 tenderInfo.buildingArea.toString().trim() : scMathUtil.roundTo(tenderInfo.engineeringCost / tenderInfo.buildingArea, perCostDecimal);
+        }
+        for(let eng of engineerings){
+            let engInfo = IDMapping[eng.ID];
+            let projInfo = IDMapping[eng.ParentID];
+            engInfo.rate = !isDef(projInfo) || projInfo.engineeringCost == 0 ? 0 : scMathUtil.roundTo(engInfo.engineeringCost * 100 / projInfo.engineeringCost, rateDecimal);
+        }
+        for(let projectID of projectIDs){
+            IDMapping[projectID].rate = 100;
+        }
+    }
+    console.log(IDMapping);
+    return IDMapping;
 }

+ 24 - 8
modules/pm/models/project_model.js

@@ -24,6 +24,7 @@ let feeRateFacade = require('../../fee_rates/facade/fee_rates_facade');
 let labourCoeFacade = require('../../main/facade/labour_coe_facade');
 let calcProgramFacade = require('../../main/facade/calc_program_facade');
 let installationFacade = require('../../main/facade/installation_facade');
+let pmFacade = require('../facade/pm_facade');
 let logger = require("../../../logs/log_helper").logger;
 let BillsModel = require("../../main/models/bills").model;
 let _ = require('lodash');
@@ -46,7 +47,7 @@ let ProjectsDAO = function () {
 let G_FILE_VER = '1.0.1';
 
 ProjectsDAO.prototype.getUserProjects = async function (userId, compilation, callback) {
-    try {
+    try {//
         let projects = await Projects.find({
             '$or': [{
                 'userID': userId,
@@ -55,14 +56,29 @@ ProjectsDAO.prototype.getUserProjects = async function (userId, compilation, cal
             }, {'userID': userId, 'compilation': compilation, 'deleteInfo.deleted': {'$in': [null, false]}}]
         }, '-_id');
         let projIDs= [];
-        let projIndex = {};
-        for(let proj of projects){
-            projIDs.push(proj.ID);
-            projIndex[proj.ID] = proj;
+        for(let project of projects){
+            if(project.projType === projectType.project){
+                projIDs.push(project.ID);
+            }
         }
-        let bills = await BillsModel.find({projectID: {$in : projIDs}, 'flags.flag': fixedFlag.ENGINEERINGCOST, 'fees.totalFee': {$exists: true}}, 'projectID fees');
-        for(let bill of bills){
-            projIndex[bill.projectID]._doc.engineeringCost = bill.fees[0].totalFee;
+        //test
+        let summaryInfo = await pmFacade.getSummaryInfo(projIDs);
+        //test
+        //设置汇总字段
+        for(let proj of projects){
+            let summaryProj = summaryInfo[proj.ID];
+            if(summaryProj){
+                proj._doc.engineeringCost = summaryProj.engineeringCost;
+                proj._doc.subEngineering = summaryProj.subEngineering;
+                proj._doc.measure = summaryProj.measure;
+                proj._doc.safetyConstruction = summaryProj.safetyConstruction;
+                proj._doc.other = summaryProj.other;
+                proj._doc.charge = summaryProj.charge;
+                proj._doc.tax = summaryProj.tax;
+                proj._doc.rate = summaryProj.rate;
+                proj._doc.buildingArea = summaryProj.buildingArea;
+                proj._doc.perCost = summaryProj.perCost;
+            }
         }
         callback(0, '', projects);
     }

+ 1 - 0
modules/pm/routes/pm_route.js

@@ -25,6 +25,7 @@ module.exports = function (app) {
      req.body = {data: '{user_id}'}
      */
     pmRouter.post('/getProjects', pmController.getProjects);
+    pmRouter.post('/getSummaryInfo', pmController.getSummaryInfo);
 
     /*
      req.body = {data: '{user_id: user_id, updateData: [{updateType, updateData}]}'}

+ 155 - 51
modules/reports/controllers/rpt_controller.js

@@ -269,15 +269,17 @@ module.exports = {
         let params = JSON.parse(req.body.params),
             prj_id = params.prj_id,
             rpt_ids = params.rpt_ids.split(','),
+            pageSize = params.pageSize,
+            orientation = params.orientation,
             customizeCfg = params.custCfg,
             option = params.option;
         let user_id = req.session.sessionUser.id;
-        let parallelFucs = [];
+        let parallelFunctions = [];
         let dftOption = option||JV.PAGING_OPTION_NORMAL;
         for (let id of rpt_ids) {
-            parallelFucs.push((function (rpt_id) {
+            parallelFunctions.push((function (rpt_id) {
                 return function (cb) {
-                    getAllPagesCommon(user_id, prj_id, rpt_id, null, null, customizeCfg, dftOption, function (err, pageRst) {
+                    getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, orientation, customizeCfg, dftOption, function (err, pageRst) {
                         if(err){
                             cb(err);
                         }
@@ -288,7 +290,7 @@ module.exports = {
                 }
             })(parseInt(id)));
         }
-        async.parallel(parallelFucs, function (err, pageRstArray) {
+        async.parallel(parallelFunctions, function (err, pageRstArray) {
             if (err) {
                 callback(req, res, '数据有误', null);
             } else {
@@ -312,14 +314,106 @@ module.exports = {
         });
     },
 
-    getTestReportAllPages: function(req, res){
-        let rpt_id = req.body.ID;
-        let pageSize = req.body.pageSize;
-        getAllPagesCommonOrg(rpt_id, pageSize, JV.PAGING_OPTION_NORMAL, function(err, pageRst){
-            //fs.writeFileSync('D:/GitHome/ConstructionOperation/tmp/testRpt.js', JSON.stringify(pageRst));
-            callback(req, res, err, pageRst);
+    createExcelFilesInOneBook: function (req, res) {
+        let params = JSON.parse(req.body.params),
+            prj_id = params.prj_id,
+            rpt_ids = params.rpt_ids,
+            rptName = params.rptName,
+            pageSize = params.pageSize,
+            orientation = params.orientation,
+            customizeCfg = params.custCfg,
+            option = params.option;
+        let user_id = req.session.sessionUser.id;
+        let parallelFunctions = [];
+        let dftOption = option||JV.PAGING_OPTION_NORMAL;
+        for (let idx = 0; idx < rpt_ids.length; idx++) {
+            let r_id = rpt_ids[idx];
+            parallelFunctions.push((function (rpt_id) {
+                return function (cb) {
+                    getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, orientation, customizeCfg, dftOption, function (err, pageRst) {
+                        if(err){
+                            cb(err);
+                        }
+                        else{
+                            cb(err, pageRst);
+                        }
+                    })
+                }
+            })(parseInt(r_id)));
+        }
+        async.parallel(parallelFunctions, function (err, pageRstArray) {
+            if (err) {
+                callback(req, res, '数据有误', null);
+            } else {
+                rpt_xl_util.exportExcelInOneBook(pageRstArray, pageSize, rptName, function(uuidName){
+                    let fileRst = {uuid: uuidName, reportName: rptName};
+                    callback(req, res, err, fileRst);
+                });
+            }
         })
     },
+
+    createExcelFiles: function (req, res) {
+        let params = JSON.parse(req.body.params),
+            prj_id = params.prj_id,
+            rpt_ids = params.rpt_ids,
+            rpt_names = params.rpt_names,
+            pageSize = params.pageSize,
+            orientation = params.orientation,
+            isOneSheet = params.isOneSheet,
+            customizeCfg = params.custCfg,
+            option = params.option;
+        let user_id = req.session.sessionUser.id;
+        let parallelFunctions = [];
+        let dftOption = option||JV.PAGING_OPTION_NORMAL;
+        for (let idx = 0; idx < rpt_ids.length; idx++) {
+            let r_id = rpt_ids[idx];
+            let r_name = rpt_names[idx];
+            parallelFunctions.push((function (rpt_id, rpt_name) {
+                return function (cb) {
+                    getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, orientation, customizeCfg, dftOption, function (err, pageRst) {
+                        if(err){
+                            cb(err);
+                        }
+                        else{
+                            rpt_xl_util.exportExcel(pageRst, pageSize, rpt_name, isOneSheet, null, null, function(uuidName){
+                                let fileRst = {uuid: uuidName, reportName: rpt_name};
+                                cb(err, fileRst);
+                            })
+                        }
+                    })
+                }
+            })(parseInt(r_id), r_name));
+        }
+        async.parallel(parallelFunctions, function (err, fileRstArray) {
+            if (err) {
+                callback(req, res, '数据有误', null);
+            } else {
+                // console.log(err);
+                callback(req, res, err, fileRstArray);
+            }
+        })
+    },
+    getExcelByUUID: function (req, res) {
+        let uuid = req.params.uuid,
+            rptName = req.params.rptName
+        ;
+        // let user_id = req.session.sessionUser.id; //未来要校验user id
+        try {
+            res.setHeader('Content-Type', 'application/vnd.openxmlformats');
+            let rptNameURI = encodeURI(rptName);
+            res.setHeader("Content-Disposition", "attachment; filename=\"" + rptNameURI + ".xlsx\"; filename*=utf-8''" + rptNameURI + '.xlsx' );
+            let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + uuid + '.xlsx');
+            filestream.on('data', function(chunk) {
+                res.write(chunk);
+            });
+            filestream.on('end', function() {
+                res.end();
+            });
+        } catch (e) {
+            console.log(e);
+        }
+    },
     getExcel: function(req, res) {
         let prj_id = req.params.prj_id,
             rpt_id = req.params.rpt_id,
@@ -327,16 +421,18 @@ module.exports = {
             orientation = req.params.orientation,
             rptName = req.params.rptName,
             isOneSheet = req.params.isOneSheet,
-            option = req.params.option;
+            option = req.params.option
+        ;
+        let customizeCfg = null;
         let user_id = req.session.sessionUser.id;
         let dftOption = option||JV.PAGING_OPTION_NORMAL;
-        getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, orientation, null, dftOption, function(err, pageRst){
+        getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, orientation, customizeCfg, dftOption, function(err, pageRst){
             try {
-                rpt_xl_util.exportExcel(pageRst, pageSize, rptName, isOneSheet, null, null, function(newName){
+                rpt_xl_util.exportExcel(pageRst, pageSize, rptName, isOneSheet, null, null, function(uuidName){
                     res.setHeader('Content-Type', 'application/vnd.openxmlformats');
                     let rptNameURI = encodeURI(rptName);
                     res.setHeader("Content-Disposition", "attachment; filename=\"" + rptNameURI + ".xlsx\"; filename*=utf-8''" + rptNameURI + '.xlsx' );
-                    let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + newName + '.xlsx');
+                    let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + uuidName + '.xlsx');
                     filestream.on('data', function(chunk) {
                         res.write(chunk);
                     });
@@ -356,10 +452,10 @@ module.exports = {
             rptName = req.params.rptName,
             option = req.params.option;
         let user_id = req.session.sessionUser.id;
-        let parallelFucs = [];
+        let parallelFunctions = [];
         let dftOption = option||JV.PAGING_OPTION_NORMAL;
         for (let id of rpt_ids) {
-            parallelFucs.push((function (rpt_id) {
+            parallelFunctions.push((function (rpt_id) {
                 return function (cb) {
                     getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, null, null, dftOption, function (err, pageRst) {
                         if(err){
@@ -372,7 +468,7 @@ module.exports = {
                 }
             })(parseInt(id)));
         }
-        async.parallel(parallelFucs, function (err, pageRstArray) {
+        async.parallel(parallelFunctions, function (err, pageRstArray) {
             if (err) {
                 callback(req, res, '数据有误', null);
             } else {
@@ -391,6 +487,41 @@ module.exports = {
             }
         })
     },
+    getPDF:function (req, res) {
+        let prj_id = req.params.prj_id,
+            rpt_id = req.params.rpt_id,
+            pageSize = req.params.size,
+            orientation = req.params.orientation,
+            rptName = req.params.rptName
+        ;
+        let user_id = req.session.sessionUser.id;
+        getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, orientation, null, JV.PAGING_OPTION_NORMAL, function(err, pageRst){
+            rpt_pdf_util.export_pdf_file(pageRst, pageSize, rptName,function (uuidName) {
+                res.setHeader('Content-Type', 'application/vnd.openxmlformats');
+                // res.setHeader("Content-Disposition", "attachment; filename=" + strUtil.getPinYinCamelChars(rptName) + ".pdf");
+                let rptNameURI = encodeURI(rptName);
+                res.setHeader("Content-Disposition", "attachment; filename=\"" + rptNameURI + ".pdf\"; filename*=utf-8''" + rptNameURI + ".pdf" );
+
+                let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + uuidName + '.pdf');
+                filestream.on('data', function(chunk) {
+                    res.write(chunk);
+                });
+                filestream.on('end', function() {
+                    res.end();
+                });
+            })
+
+        })
+
+    },
+    getTestReportAllPages: function(req, res){
+        let rpt_id = req.body.ID;
+        let pageSize = req.body.pageSize;
+        getAllPagesCommonOrg(rpt_id, pageSize, JV.PAGING_OPTION_NORMAL, function(err, pageRst){
+            //fs.writeFileSync('D:/GitHome/ConstructionOperation/tmp/testRpt.js', JSON.stringify(pageRst));
+            callback(req, res, err, pageRst);
+        })
+    },
     getTestExcel: function(req, res) {
         let rpt_id = req.params.id,
             pageSize = req.params.size,
@@ -401,10 +532,10 @@ module.exports = {
         getAllPagesCommonOrg(rpt_id, pageSize, dftOption, function(err, pageRst){
             fs.writeFileSync('D:/GitHome/ConstructionOperation/tmp/testRpt.js', JSON.stringify(pageRst));
             try {
-                rpt_xl_util.exportExcel(pageRst, pageSize, rptName, isOneSheet, null, null, function(newName){
+                rpt_xl_util.exportExcel(pageRst, pageSize, rptName, isOneSheet, null, null, function(uuidName){
                     res.setHeader('Content-Type', 'application/vnd.openxmlformats');
                     res.setHeader("Content-Disposition", "attachment; filename=" + strUtil.getPinYinCamelChars(rptName) + ".xlsx");
-                    let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + newName + '.xlsx');
+                    let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + uuidName + '.xlsx');
                     filestream.on('data', function(chunk) {
                         res.write(chunk);
                     });
@@ -422,10 +553,10 @@ module.exports = {
             pageSize = req.params.size,
             rptName = req.params.rptName,
             option = req.params.option;
-        let parallelFucs = [];
+        let parallelFunctions = [];
         let dftOption = option||JV.PAGING_OPTION_NORMAL;
         for (let id of rpt_ids) {
-            parallelFucs.push((function (rpt_id) {
+            parallelFunctions.push((function (rpt_id) {
                 return function (cb) {
                     getAllPagesCommonOrg(rpt_id, pageSize, dftOption, function (err, pageRst) {
                         if(err){
@@ -438,7 +569,7 @@ module.exports = {
                 }
             })(parseInt(id)));
         }
-        async.parallel(parallelFucs, function (err, pageRstArray) {
+        async.parallel(parallelFunctions, function (err, pageRstArray) {
             if (err) {
                 callback(req, res, '数据有误', null);
             } else {
@@ -457,46 +588,19 @@ module.exports = {
             }
         })
     },
-    getPDF:function (req, res) {
-        let prj_id = req.params.prj_id,
-            rpt_id = req.params.rpt_id,
-            pageSize = req.params.size,
-            orientation = req.params.orientation,
-            rptName = req.params.rptName
-        ;
-        let user_id = req.session.sessionUser.id;
-        getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, orientation, null, JV.PAGING_OPTION_NORMAL, function(err, pageRst){
-            rpt_pdf_util.export_pdf_file(pageRst, pageSize, rptName,function (newName) {
-                res.setHeader('Content-Type', 'application/vnd.openxmlformats');
-                // res.setHeader("Content-Disposition", "attachment; filename=" + strUtil.getPinYinCamelChars(rptName) + ".pdf");
-                let rptNameURI = encodeURI(rptName);
-                res.setHeader("Content-Disposition", "attachment; filename=\"" + rptNameURI + ".pdf\"; filename*=utf-8''" + rptNameURI + ".pdf" );
-
-                let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + newName + '.pdf');
-                filestream.on('data', function(chunk) {
-                    res.write(chunk);
-                });
-                filestream.on('end', function() {
-                    res.end();
-                });
-            })
-
-        })
-
-    },
     getTestPDF:function (req, res) {
         let rpt_id = req.params.id,
             pageSize = req.params.size,
             rptName = req.params.rptName;
 
         getAllPagesCommonOrg(rpt_id, pageSize, JV.PAGING_OPTION_NORMAL, function(err, pageRst){
-            rpt_pdf_util.export_pdf_file(pageRst, pageSize, rptName,function (newName) {
+            rpt_pdf_util.export_pdf_file(pageRst, pageSize, rptName,function (uuidName) {
                 res.setHeader('Content-Type', 'application/vnd.openxmlformats');
                 // res.setHeader("Content-Disposition", "attachment; filename=" + strUtil.getPinYinCamelChars(rptName) + ".pdf");
                 let rptNameURI = encodeURI(rptName);
                 res.setHeader("Content-Disposition", "attachment; filename=\"" + rptNameURI + ".pdf\"; filename*=utf-8''" + rptNameURI + ".pdf"  );
 
-                let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + newName + '.pdf');
+                let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + uuidName + '.pdf');
                 filestream.on('data', function(chunk) {
                     res.write(chunk);
                 });

+ 3 - 0
modules/reports/routes/report_router.js

@@ -27,8 +27,11 @@ module.exports =function (app) {
     rptRouter.post('/getReport', reportController.getReportAllPages);
     rptRouter.post('/getReportSvg', reportController.getReportAllPagesSvg);
     rptRouter.post('/getMultiReports', reportController.getMultiReports);
+    rptRouter.post('/createExcelFiles', reportController.createExcelFiles);
+    rptRouter.post('/createExcelFilesInOneBook', reportController.createExcelFilesInOneBook);
     rptRouter.get('/getExcelInOneBook/:prj_id/:rpt_ids/:size/:rptName/:option', reportController.getExcelInOneBook);
     rptRouter.get('/getExcel/:prj_id/:rpt_id/:size/:orientation/:rptName/:isOneSheet/:option', reportController.getExcel);
+    rptRouter.get('/getExcelByUUID/:uuid/:rptName', reportController.getExcelByUUID);
     rptRouter.get('/getPDF/:prj_id/:rpt_id/:size/:orientation/:rptName', reportController.getPDF);
     // rptRouter.get('/getExcelInOneBook/:ids/:size/:rptName/:option', reportController.getExcelInOneBook);
 

+ 11 - 3
modules/reports/util/rpt_excel_util.js

@@ -9,6 +9,7 @@ let jpcCmnHelper = require('../rpt_component/helper/jpc_helper_common');
 let DPI = jpcCmnHelper.getScreenDPI()[0];
 let fsUtil = require('../../../public/fsUtil');
 const dftHeadXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
+const uuidV1 = require('uuid/v1');
 
 function writeContentTypes(sheets, isSinglePage) {
     let rst = [];
@@ -157,6 +158,9 @@ function writeStyles(stylesObj){
         if (strUtil.convertStrToBoolean(font[JV.FONT_PROPS[3]])) {
             rst.push('<b/>');
         }
+        if (strUtil.convertStrToBoolean(font[JV.FONT_PROPS[4]])) {
+            rst.push('<i/>');
+        }
         if (strUtil.convertStrToBoolean(font[JV.FONT_PROPS[5]])) {
             rst.push('<u/>');
         }
@@ -443,7 +447,8 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj, ap
             if (sheetFont) {
                 // if (font[JV.FONT_PROPS[0]] === sheetFont[JV.FONT_PROPS[0]] && font.size === Math.round(sheetFont[JV.FONT_PROPS[1]] * 3 / 4)
                 if (font[JV.FONT_PROPS[0]] === sheetFont[JV.FONT_PROPS[0]] && font.size === Math.floor(sheetFont[JV.FONT_PROPS[1]] * 3 / 4)
-                    && font[JV.FONT_PROPS[3]] === sheetFont[JV.FONT_PROPS[3]] && font[JV.FONT_PROPS[5]] === sheetFont[JV.FONT_PROPS[5]]) {
+                    && font[JV.FONT_PROPS[3]] === sheetFont[JV.FONT_PROPS[3]] && font[JV.FONT_PROPS[4]] === sheetFont[JV.FONT_PROPS[4]]
+                    && font[JV.FONT_PROPS[5]] === sheetFont[JV.FONT_PROPS[5]] ) {
                     hasFont = true;
                     rst = i;
                     break;
@@ -460,6 +465,7 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj, ap
             font.charset = 134;
             font.colorIdx = "8";
             font[JV.FONT_PROPS[3]] = sheetFont[JV.FONT_PROPS[3]]; //font bold
+            font[JV.FONT_PROPS[4]] = sheetFont[JV.FONT_PROPS[4]]; //font italic
             font[JV.FONT_PROPS[5]] = sheetFont[JV.FONT_PROPS[5]]; //font underline
             stylesObj.fonts.push(font);
             rst = stylesObj.fonts.length - 1;
@@ -818,7 +824,7 @@ function mergeProperties(orgObj, newObj) {
 module.exports = {
     exportExcel: function (pageData, paperSize, fName, options, custSheetNames, custSheetMergeBands, callback) {
         let rptOptions = ({singlePage: false, fileName: 'report'});
-        if (options === 'true') {
+        if (options === 'true' || options === true) {
             rptOptions.singlePage = true;
         }
         let isSinglePage = rptOptions.singlePage;
@@ -891,7 +897,9 @@ module.exports = {
         zip_xl.file(file, data.join(''), {compression: 'DEFLATE'});
 
         if (fName) {
-            let newName = '' + (new Date()).valueOf();
+            // let newName = '' + (new Date()).valueOf();
+            let newName = uuidV1();
+
             zip.generateNodeStream({type:'nodebuffer',streamFiles:true})
                 .pipe(fs.createWriteStream(__dirname.slice(0, __dirname.length - 21) + '/tmp/' + newName + '.xlsx'))
                 .on('finish', function () {

+ 5 - 4
modules/reports/util/rpt_pdf_util.js

@@ -10,22 +10,23 @@ let fs = require('fs');
 let jpcCmnHelper = require('../rpt_component/helper/jpc_helper_common');
 let DPI = jpcCmnHelper.getScreenDPI()[0];
 let JV = require('../rpt_component/jpc_value_define');
+const uuidV1 = require('uuid/v1');
 
 // hwxsb.ttf: 华文中宋
 // Smart.ttf: 宋体(常规)
 // Smart-italic.ttf: 宋体(斜体)
-//目前不支持下划线
+// 目前不支持下划线
 
-module.exports ={
+module.exports = {
     export_pdf_file:export_pdf_file
 }
 
-
 function export_pdf_file (pageData, paperSize, fName, callback) {
     let offsetX= 10;
     let offsetY=10;
     let doc = new pdf({autoFirstPage: false});
-    let newName = '' + (new Date()).valueOf();
+    // let newName = '' + (new Date()).valueOf();
+    let newName = uuidV1();
     let stream = doc.pipe(fs.createWriteStream(__dirname.slice(0, __dirname.length - 21) + '/tmp/'+newName+'.pdf'));
     let pageObj = pageData;
     // doc.rect(5,5,1190,890).lineWidth(1).strokeColor('black').stroke();//边框

+ 6 - 0
public/web/common_util.js

@@ -50,4 +50,10 @@ function seqString(num,length){
         numstr = "0" + numstr;
     }
     return numstr;
+};
+
+function customRowHeader(sheet, dataLength) {
+    for (let i = 0; i < dataLength; i++) {
+        sheet.setValue(i, 0, `F${i + 1}`, GC.Spread.Sheets.SheetArea.rowHeader);
+    }
 }

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

@@ -65,6 +65,7 @@ var sheetCommonObj = {
         var me = this, ch = GC.Spread.Sheets.SheetArea.colHeader;
         for (var i = 0; i < setting.header.length; i++) {
             sheet.setValue(0, i, setting.header[i].headerName, ch);
+            sheet.getCell(0, i, ch).wordWrap(true);
             sheet.setColumnWidth(i, setting.header[i].headerWidth?setting.header[i].headerWidth:100);
             sheet.setColumnVisible(i,setting.header[i].visible === false ? false:true);
         }
@@ -128,9 +129,6 @@ var sheetCommonObj = {
             vAlign = setting.header[col].vAlign?setting.header[col].vAlign:vAlign;
             me.setAreaAlign(sheet.getRange(-1, col, -1, 1), hAlign, vAlign);
             if (setting.header[col].formatter) {
-                //var style = new GC.Spread.Sheets.Style();
-                //style.formatter = setting.header[col].formatter;
-                //sheet.setStyle(row,col,style,GC.Spread.Sheets.SheetArea.viewport);
                 sheet.setFormatter(-1, col, setting.header[col].formatter, GC.Spread.Sheets.SheetArea.viewport);
             }
             if(setting.header[col].cellType === "checkBox"||setting.header[col].cellType === "button"){//clear and reset
@@ -143,7 +141,7 @@ var sheetCommonObj = {
             if(setting.header[col].visible === false){
                 sheet.setColumnVisible(col,false);
             }
-
+            sheet.getCell(0, col, GC.Spread.Sheets.SheetArea.colHeader).wordWrap(true);
         }
         for (var row = 0; row < data.length; row++) {
             //var cell = sheet.getCell(row, col, GC.Spread.Sheets.SheetArea.viewport);

+ 34 - 16
web/building_saas/main/html/main.html

@@ -587,13 +587,17 @@
                                             <div class="row m-0">
                                                 <div class="col-sm-3">
                                                     <div class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">单价</div>
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">单价</span>
+                                                        </div>
                                                         <input type="number" name="bills-unitPrice" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>
                                                 <div class="col-sm-3">
                                                     <div class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">合价</div>
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">合价</span>
+                                                        </div>
                                                         <input type="number" name="bills-totalPrice" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>
@@ -602,40 +606,52 @@
                                             <div class="row m-0">
                                                 <div class="col-sm-3">
                                                     <div class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">工程量</div>
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">工程量</span>
+                                                        </div>
                                                         <input type="number" name="ration-quantity" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>
                                                 <div class="col-sm-3">
                                                     <div class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">单价</div>
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">单价</span>
+                                                        </div>
                                                         <input type="number" name="ration-unitPrice" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>
                                                 <div class="col-sm-3">
                                                     <div class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">合价</div>
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">合价</span>
+                                                        </div>
                                                         <input type="number" name="ration-totalPrice" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>
                                             </div>
-                                            <h5 class="mt-3">人材机</h5>
+                                            <h5 class="mt-3">工料机</h5>
                                             <div class="row m-0">
-                                                <div style="width: 23.3%;">
-                                                    <div style="width:120px;" class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">消耗量</div>
+                                                <div class="col-sm-3">
+                                                    <div class="input-group input-group-sm mb-2">
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">消耗量</span>
+                                                        </div>
                                                         <input type="number" name="glj-quantity" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>
-                                                <div  style="width: 38.3%;">
-                                                    <div style="width:190px;" class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">单价(有组成物)</div>
+                                                <div class="col-sm-4">
+                                                    <div class="input-group input-group-sm mb-2">
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">单价<small class="text-muted">(有组成物)</small></span>
+                                                        </div>
                                                         <input type="number" name="glj-unitPriceHasMix" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>
-                                                <div style="width: 38.3%;">
-                                                    <div  style="width:190px;" class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">单价(无组成物)</div>
+                                                <div class="col-sm-4">
+                                                    <div class="input-group input-group-sm mb-2">
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">单价<small class="text-muted">(无组成物)</small></span>
+                                                        </div>
                                                         <input type="number" name="glj-unitPrice" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>
@@ -644,7 +660,9 @@
                                             <div class="row m-0">
                                                 <div class="col-sm-3">
                                                     <div class="input-group input-group-sm mb-2">
-                                                        <div class="input-group-addon">费率</div>
+                                                        <div class="input-group-prepend">
+                                                            <span class="input-group-text">费率</span>
+                                                        </div>
                                                         <input type="number" name="feeRate" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
                                                 </div>

+ 7 - 4
web/building_saas/main/js/views/calc_program_manage.js

@@ -70,7 +70,7 @@ let calcProgramManage = {
         feeRateObject.setFeeRateCellCol(dSheet,_.findIndex(me.detailSetting.header,{'dataCode':'feeRate'}));
         dSheet.getRange(-1, _.findIndex(me.detailSetting.header, {'dataCode': 'dispExprUser'}), -1, 1).cellType(calcBaseView.getCalcBaseCellType('ration'));
         sheetCommonObj.showData(dSheet, me.detailSetting, me.datas[0].calcItems);
-
+        customRowHeader(dSheet, me.datas[0].calcItems.length);
         if(!projectReadOnly){
             me.loadMainContextMenu();
             me.loadDetailContextMenu();
@@ -111,6 +111,7 @@ let calcProgramManage = {
         var dData = me.datas[row].calcItems;
         dSheet.setRowCount(dData.length, GC.Spread.Sheets.SheetArea.viewport);
         sheetCommonObj.showData(dSheet, me.detailSetting, dData);
+        customRowHeader(dSheet, dData.length);
         me.detailSpread.resumePaint();
     },
     onRangeChanged:function (sender,args) {
@@ -502,17 +503,19 @@ let calcProgramManage = {
             let detailSheet = me.detailSpread.getActiveSheet();
             detailSheet.setRowCount(calcItems.length);
             sheetCommonObj.showData(detailSheet, me.detailSetting, calcItems);
+            customRowHeader(detailSheet, calcItems.length);
         }
     }
-
 };
 
 $(document).ready(function(){
     $('#tab_calc_program_manage').on('shown.bs.tab', function (e) {
         sessionStorage.setItem('mainTab', '#tab_calc_program_manage');
         $(e.relatedTarget.hash).removeClass('active');
-        calcProgramManage.buildSheet();
-        // calcProgramManage.getStdCalcProgramFiles();
+        if (!calcProgramManage.mainSpread)
+            calcProgramManage.buildSheet()
+        else
+            calcProgramManage.mainSpread.refresh();
     });
 
     $("#calcProgramFileSelect").change(function() {

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

@@ -62,12 +62,14 @@ let calcProgramObj = {
         me.datas = treeNode.data.calcTemplate ? treeNode.data.calcTemplate.calcItems : [];
         sheetCommonObj.initSheet(me.sheet, me.setting, me.datas.length);
         sheetCommonObj.showData(me.sheet, me.setting, me.datas);
+        customRowHeader(me.sheet, me.datas.length);
     },
 
     clearData: function (){
         var me = this;
         me.treeNode = null;
         sheetCommonObj.cleanSheet(me.sheet, me.setting, -1);
+        customRowHeader(me.sheet, me.datas.length);
     }
 };
 

+ 0 - 5
web/building_saas/main/js/views/project_glj_view.js

@@ -67,12 +67,7 @@ projectGljObject={
         this.projectGljSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onProjectGljSelectionChange);
         this.projectGljSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onProjectGljEditStarting);
         this.projectGljSheet.name('projectGljSheet');
-
         this.projectGljSheet.setRowHeight(0, 45, 1);
-        let cell = this.projectGljSheet.getCell(0, 9, GC.Spread.Sheets.SheetArea.colHeader);
-        // console.log(cell.value());
-        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center).vAlign(GC.Spread.Sheets.VerticalAlign.center).wordWrap(true);
-        // cell.wordWrap(true);
     },
     initMixRatio:function () {
         let me = projectGljObject;

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

@@ -1675,6 +1675,9 @@ $('#downLevel').click(function () {
         projectObj.converseCalculateBills(selected.parent);
     }
 });
+$('#insertRation').click(function () {
+    projectObj.project.Ration.addNewRation(null,rationType.ration);
+});
 $('#upMove').click(function () {
     var controller = projectObj.mainController, project = projectObj.project;
     var selected = controller.tree.selected, pre = selected.preSibling, preSerialNo;

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

@@ -140,6 +140,40 @@ $("#linkTZJNR").click(function () {
     gljOprObj.activeTab='#linkTZJNR';
 });
 
+//应用到选中清单、应用到所有,添加位置列如果隐藏了,则重新显示
+function colSettingAddPosition(addPosition){
+    let settingMapping = {1: 'itemCharacterText', 2: 'name', 3: 'jobContentText', 4: 'both'};
+    let settingInfo = settingMapping[addPosition];
+    if(!settingInfo){
+        return;
+    }
+    let fields = [];
+    if(settingInfo === 'both'){
+        fields = [settingMapping['1'], settingMapping['3']];
+    }
+    else{
+        fields = [settingInfo];
+    }
+    let needToUpdate = false;
+    let showItemCharacter = false;
+    for(let field of fields){
+        let colVisible = colSettingObj.getVisible(field);
+        if(field === settingMapping['1'] && !colVisible){
+            showItemCharacter = true;
+        }
+        if(!colVisible){
+            colSettingObj.setVisible(field, true);
+            needToUpdate = true;
+        }
+    }
+    if(showItemCharacter){
+        switchTznrHtml(false);
+    }
+    if(needToUpdate){
+       colSettingObj.updateColSetting(true);
+    }
+}
+
 // 应用到选中清单
 let isSaving = false;
 $("#use-to-current").click(function() {
@@ -150,6 +184,7 @@ $("#use-to-current").click(function() {
         return false;
     }
     const setting = getAddRuleSetting();
+    colSettingAddPosition(setting.position);
     isSaving = true;
     const self = $(this);
     self.attr('disabled', 'disabled');
@@ -177,6 +212,7 @@ $("#use-to-all").click(function() {
     }
     let treeNode = projectObj.mainController.tree;
     const setting = getAddRuleSetting();
+    colSettingAddPosition(setting.position);
     if (treeNode.items === undefined || treeNode.items.length <= 0) {
         return false;
     }

+ 2 - 2
web/building_saas/main/js/views/tender_price_view.js

@@ -417,11 +417,11 @@ $(function () {
         $(e.relatedTarget.hash).removeClass('active');
         if(!tender_obj.tenderSpread){
             tender_obj.initTenderSpread();
+            tender_obj.showTenderData();
+            tender_obj.initPageContent();
         }
         autoFlashHeight();
         tender_obj.tenderSpread.refresh();
-        tender_obj.showTenderData();
-        tender_obj.initPageContent();
     });
 
     $('#tenderGLJQuantity').bind('click',function () {

+ 110 - 17
web/building_saas/pm/js/pm_newMain.js

@@ -29,6 +29,10 @@ let taxTypeMap = {
     2:"简易计税"
 };
 
+function isDef(v) {
+    return typeof v !== 'undefined' && v !== null;
+}
+
 const projTreeObj = {
     tree: null,
     workBook: null,
@@ -43,12 +47,22 @@ const projTreeObj = {
             rootId: -1,
             autoUpdate: false
         },
+        //0.48 0.13 0.15 0.15 0.09
         header: [
-            {name: '工程列表', dataCode: 'name', width: 0.48, vAlign: 'center', hAlign: 'left'},
-            {name: '工程造价', dataCode: 'engineeringCost', width: 0.13, vAlign: 'center', hAlign: 'right'},
-            {name: '单价文件', dataCode: 'unitPriceFile', width: 0.15, vAlign: 'center', hAlign: 'left'},
-            {name: '费率文件', dataCode: 'feeRateFile', width: 0.15, vAlign: 'center', hAlign: 'left'},
-            {name: '创建日期', dataCode: 'createDateTime', width: 0.09, vAlign: 'center', hAlign: 'center'}
+            {name: '工程列表', dataCode: 'name', width: 300, vAlign: 'center', hAlign: 'left'},
+            {name: '工程造价', dataCode: 'engineeringCost', width: 120, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '分部分项合计', dataCode: 'subEngineering', width: 120, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '措施项目合计', dataCode: 'measure', width: 120, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '其他项目合计', dataCode: 'other', width: 120, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '安全文明施工费', dataCode: 'safetyConstruction', width: 120, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '规费', dataCode: 'charge', width: 120, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '税金', dataCode: 'tax', width: 120, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '占造价比例(%)', dataCode: 'rate', width: 100, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '建筑面积', dataCode: 'buildingArea', width: 100, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '单方造价', dataCode: 'perCost', width: 100, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
+            {name: '单价文件', dataCode: 'unitPriceFile', width: 140, vAlign: 'center', hAlign: 'left'},
+            {name: '费率文件', dataCode: 'feeRateFile', width: 140, vAlign: 'center', hAlign: 'left'},
+            {name: '创建日期', dataCode: 'createDateTime', width: 100, vAlign: 'center', hAlign: 'center'}
         ],
         //选中行颜色
         style: {
@@ -118,8 +132,11 @@ const projTreeObj = {
             let workBookWidth = getWorkBookWidth();
             for(let i = 0, len = headers.length; i < len; i++){
                 sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
-                let width = workBookWidth * headers[i].width;
+                let width = headers[i].width;
                 sheet.setColumnWidth(i, width, GC.Spread.Sheets.SheetArea.colHeader);
+                if (headers[i].formatter) {
+                    sheet.setFormatter(-1, i, headers[i].formatter, GC.Spread.Sheets.SheetArea.viewport);
+                }
             }
         };
         me.renderSheetFuc(sheet, fuc);
@@ -307,6 +324,30 @@ const projTreeObj = {
                             });
                         }, 500);
                     }
+                },
+                "refreshSummary": {
+                    name: "刷新当前项目造价",
+                    icon: 'fa-refresh',
+                    disabled: function () {
+                        let selectedItem = projTreeObj.tree.selected;
+                        return !(selectedItem && selectedItem.data.projType !== projectType.folder);
+                    },
+                    callback: function (key, opt) {
+                        //获取当前节点的建设项目ID
+                        let project = projTreeObj.tree.selected;
+                        while (project.data.projType !== projectType.project && project.parent){
+                            project = project.parent;
+                        }
+                        if(project && project.data.ID){
+                            $.bootstrapLoading.start();
+                            CommonAjax.post('/pm/api/getSummaryInfo', {user_id: userID, projectIDs: [project.data.ID]}, function (summaryInfo) {
+                                refreshProjSummary(project, summaryInfo);
+                                $.bootstrapLoading.end();
+                            }, function () {
+                                $.bootstrapLoading.start();
+                            });
+                        }
+                    }
                 }
             }
         });
@@ -819,13 +860,7 @@ const projTreeObj = {
         const {row, col} = cell;
         let dataCode = this.setting.header[col]['dataCode'];
         let value = '';
-        if(dataCode === 'engineeringCost'){
-            if(node.data.projType !== projectType.folder){//显示除了文件夹节点的工程造价结果 -- vincent
-                value =  node.data.engineeringCost ? node.data.engineeringCost : '0.00';
-                value = scMathUtil.roundToString(value,2);
-            }
-        }
-        else if(dataCode === 'unitPriceFile'){
+        if(dataCode === 'unitPriceFile'){
             if(node.data.projType === projectType.tender){
                 value = node.data.property && node.data.property.unitPriceFile && node.data.property.unitPriceFile.name ? node.data.property.unitPriceFile.name : '';
             }
@@ -839,7 +874,7 @@ const projTreeObj = {
             value = node.data.createDateTime ? new Date(node.data.createDateTime).Format('yyyy-MM-dd') : '';
         }
         else {
-            value = node.data[dataCode] ? node.data[dataCode] : '';
+            value = isDef(node.data[dataCode]) ? node.data[dataCode] : '';
         }
         sheet.setValue(row, col, value);
     },
@@ -1028,7 +1063,7 @@ const projTreeObj = {
 $(document).ready(function() {
     //列宽随着屏幕改变
     $(window).resize(function () {
-        autoPmWdith(projTreeObj.workBook, projTreeObj.setting.header);
+        //autoPmWdith(projTreeObj.workBook, projTreeObj.setting.header);
         autoPmWdith(gcTreeObj.workBook, gcTreeObj.setting.header);
         autoPmWdith(pmShare.spreadObj.workBook, pmShare.headers)
 
@@ -1672,12 +1707,30 @@ function getChangedFunc(input, nameInfo){
             nameInfo.show();
         }
         else {
-            nameInfo.text('');N
+            nameInfo.text('');
             nameInfo.hide();
         }
     }
 }
 
+//新增节点,初始化汇总数值
+function setInitSummaryData(data) {
+    if(data.projType === projectType.folder){
+        return;
+    }
+    //just for View
+    data.engineeringCost = 0;
+    data.subEngineering = 0;
+    data.measure = 0;
+    data.safetyConstruction = 0;
+    data.other = 0;
+    data.charge = 0;
+    data.tax = 0;
+    data.rate = data.projType === projectType.project ? 100 : 0;
+    data.buildingArea = '';
+    data.perCost = '';
+}
+
 function AddTenderItems(selected, projName, engName, tenderName, property, callback){
     const addPath = {p_e_t: 'p_e_t', e_t: 'e_t', t: 't'};
     let path, updateDatas = [];
@@ -1727,6 +1780,7 @@ function AddTenderItems(selected, projName, engName, tenderName, property, callb
                 let projData, engData, tenderData;
                 datas.forEach(function (data) {
                     if (data.updateType === 'new') {
+                        setInitSummaryData(data.updateData);
                         if(data.updateData.projType === projectType.project){
                             projData = data.updateData;
                         }
@@ -1767,6 +1821,7 @@ function AddTenderItems(selected, projName, engName, tenderName, property, callb
                 let engData, tenderData;
                 datas.forEach(function (data) {
                     if (data.updateType === 'new') {
+                        setInitSummaryData(data.updateData);
                         if(data.updateData.projType === projectType.engineering){
                             engData = data.updateData;
                         }
@@ -1794,6 +1849,7 @@ function AddTenderItems(selected, projName, engName, tenderName, property, callb
             UpdateProjectData(updateDatas, function (datas) {
                 datas.forEach(function (data) {
                     if(data.updateType === 'new') {
+                        setInitSummaryData(data.updateData);
                         projTreeObj.insert(data.updateData, tempEng, null);
                     }
                 });
@@ -1832,6 +1888,7 @@ function AddChildrenItem(selected, name, property, type, existCallback, sucCallb
             UpdateProjectData(updateData, function(datas){
                 datas.forEach(function (data) {
                     if (data.updateType === 'new') {
+                        setInitSummaryData(data.updateData);
                         projTreeObj.insert(data.updateData, parent, null);
                     }
                 });
@@ -1870,6 +1927,7 @@ function AddSiblingsItem(selected, name, property, type, existCallback, sucCallb
             UpdateProjectData(updateData, function(datas){
                 datas.forEach(function (data) {
                     if (data.updateType === 'new') {
+                        setInitSummaryData(data.updateData);
                         projTreeObj.insert(data.updateData, parent, next);
                     }
                 });
@@ -2291,7 +2349,11 @@ function getAddTenderFile(tenderName, selected, options){
     //选择的是新建单价/费率文件
     if(selValue === ''){
         //若新建的单位工程名称与建设项目下文件重名,则引用该文件
-        for(let option of options){
+        for(let i = 0; i < options.length; i++){
+            if(i === 0){
+                continue;
+            }
+            let option = options[i];
             if($(option).text() === tenderName){
                 rst.id = $(option).val();
                 break;
@@ -3097,3 +3159,34 @@ $('#allowCopy').change(function () {
         $('#allowCopyHint').hide();
     }
 });
+
+//刷新建设项目汇总金额信息
+function refreshProjSummary(project, summaryInfo) {
+    let refreshNodes = [];
+    refreshNodes.push(project);
+    getNodes(project);
+    function getNodes(node) {
+        if(node.children.length > 0){
+            refreshNodes = refreshNodes.concat(node.children);
+            for(let cNode of node.children){
+                getNodes(cNode);
+            }
+        }
+    }
+    for(let node of refreshNodes){
+        let nodeInfo = summaryInfo[node.data.ID];
+        if(nodeInfo){
+            node.data.engineeringCost = nodeInfo.engineeringCost;
+            node.data.subEngineering = nodeInfo.subEngineering;
+            node.data.measure = nodeInfo.measure;
+            node.data.safetyConstruction = nodeInfo.safetyConstruction;
+            node.data.other = nodeInfo.other;
+            node.data.charge = nodeInfo.charge;
+            node.data.tax = nodeInfo.tax;
+            node.data.rate = nodeInfo.rate;
+            node.data.buildingArea = nodeInfo.buildingArea;
+            node.data.perCost = nodeInfo.perCost;
+        }
+    }
+    projTreeObj.refreshNodeData(refreshNodes);
+}

+ 48 - 12
web/building_saas/report/js/rpt_main.js

@@ -350,28 +350,63 @@ let rptControlObj = {
     },
     getAllInOneBook: function () {
         if (zTreeOprObj.checkedRptTplNodes && zTreeOprObj.checkedRptTplNodes.length > 0) {
+            let me = rptControlObj;
             let orgRptName = projectInfoObj.projectInfo.name;
             let refRptTplIds = [];
             for (let node of zTreeOprObj.checkedRptTplNodes) {
                 refRptTplIds.push(node.refId);
             }
-            window.location = "/report_api/getExcelInOneBook/" + projectInfoObj.projectInfo.ID + "/" + refRptTplIds.join(",") + "/" +
-                rptControlObj.getCurrentPageSize() + "/" + orgRptName + "/" + 'normal';
+            let params = {};
+            params.prj_id = projectInfoObj.projectInfo.ID;
+            params.rpt_ids = refRptTplIds;
+            params.rptName = orgRptName;
+            params.pageSize = me.getCurrentPageSize();
+            params.orientation = ((zTreeOprObj.checkedRptTplNodes.length > 1)?null:me.getCurrentOrientation());
+            params.custCfg = zTreeOprObj.reportPageCfg;
+            params.option = "normal";
+            CommonAjax.postEx("report_api/createExcelFilesInOneBook", params, 20000, true, function(result){
+                    if (result) {
+                        let uuIdUrls = [];
+                        let uuIdUrl =  "/report_api/getExcelByUUID/" + result.uuid + "/" + result.reportName;
+                        uuIdUrls.push(uuIdUrl);
+                        downloadReport(uuIdUrls);
+                    } else {
+                        //
+                    }
+                }, null, null
+            );
         }
     },
     getAllIndividualExcelBook: function () {
         let me = rptControlObj;
         if (zTreeOprObj.checkedRptTplNodes && zTreeOprObj.checkedRptTplNodes.length > 0) {
-            let urls = [];
-            let orientation = ((zTreeOprObj.checkedRptTplNodes.length > 1)?null:me.getCurrentOrientation());
-            if (zTreeOprObj.checkedRptTplNodes.length > 1) orientation = null;
+            let rpt_ids = [], rpt_names = [];
             for (let tplNode of zTreeOprObj.checkedRptTplNodes) {
-                let orgRptName = tplNode.name;
-                let url =  "/report_api/getExcel/" + projectInfoObj.projectInfo.ID + "/" + tplNode.refId + "/" +
-                    me.getCurrentPageSize() + "/" + orientation + "/" + orgRptName + "/" + true + "/" + 'normal';
-                urls.push(url);
+                rpt_ids.push(tplNode.refId);
+                rpt_names.push(tplNode.name)
             }
-            downloadReport(urls);
+            let params = {};
+            params.prj_id = projectInfoObj.projectInfo.ID;
+            params.rpt_ids = rpt_ids;
+            params.rpt_names = rpt_names;
+            params.pageSize = me.getCurrentPageSize();
+            params.orientation = ((zTreeOprObj.checkedRptTplNodes.length > 1)?null:me.getCurrentOrientation());
+            params.isOneSheet = true;
+            params.custCfg = zTreeOprObj.reportPageCfg;
+            params.option = "normal";
+            CommonAjax.postEx("report_api/createExcelFiles", params, 20000, true, function(result){
+                    if (result) {
+                        let uuIdUrls = [];
+                        for (let uuIdObj of result) {
+                            let uuIdUrl =  "/report_api/getExcelByUUID/" + uuIdObj.uuid + "/" + uuIdObj.reportName;
+                            uuIdUrls.push(uuIdUrl);
+                        }
+                        downloadReport(uuIdUrls);
+                    } else {
+                        //
+                    }
+                }, null, null
+            );
         }
     },
     checkAndGetExcel: function () {
@@ -400,7 +435,8 @@ let rptControlObj = {
             for (let tplNode of zTreeOprObj.checkedRptTplNodes) {
                 let orgRptName = tplNode.name;
                 let url =  "/report_api/getPDF/" + projectInfoObj.projectInfo.ID + "/" + tplNode.refId + "/" +
-                    me.getCurrentPageSize() + "/" + orientation + "/" + orgRptName;
+                    me.getCurrentPageSize() + "/" + orientation + "/" + orgRptName
+                    // + "/" + encodeURI(JSON.stringify(zTreeOprObj.reportPageCfg));
                 urls.push(url);
             }
             downloadReport(urls);
@@ -527,4 +563,4 @@ function downloadReport(urls) {
         }
     }
     private_download();
-}
+}

+ 2 - 0
web/building_saas/report/js/rpt_print.js

@@ -7,6 +7,8 @@ let rptPrintHelper = {
         if (zTreeOprObj.checkedRptTplNodes && zTreeOprObj.checkedRptTplNodes.length > 0) {
             let rptIds = [];
             let params = {};
+            params.pageSize = rptControlObj.getCurrentPageSize();
+            params.orientation = ((zTreeOprObj.checkedRptTplNodes.length > 1)?null:rptControlObj.getCurrentOrientation());
             params.custCfg = zTreeOprObj.reportPageCfg;
             params.prj_id = projectInfoObj.projectInfo.ID;
             for (let tplNode of zTreeOprObj.checkedRptTplNodes) {