浏览代码

导出Excel复杂场景

TonyKang 5 年之前
父节点
当前提交
a57faf9350

+ 64 - 6
app/controller/report_controller.js

@@ -27,7 +27,7 @@ module.exports = app => {
                 const tender = ctx.tender;
                 const stage = ctx.stage;
                 // console.log(tender.data);
-                // console.log(stage);
+                // console.log(tender.info);
                 let stage_id = -1;
                 let stage_order = -1;
                 let stage_times = -1;
@@ -55,6 +55,7 @@ module.exports = app => {
                     cust_cfg: JSON.stringify(custCfg),
                     project_id: tender.data.project_id,
                     tender_id: tender.id,
+                    tender_name: tender.data.name,
                     stg_id: stage_id,
                     stg_order: stage_order,
                     stg_times: stage_times,
@@ -154,9 +155,6 @@ module.exports = app => {
             const params = JSON.parse(ctx.request.body.params);
             const baseDir = this.app.baseDir;
             function getExcelByPageData(pageRst, rpt_name, innerRoleRel) {
-                // console.log('in getExcelByPageData!');
-                // console.log(innerRoleRel);
-                // console.log('rpt_name: ' + rpt_name);
                 return new Promise(function(resolve, reject) {
                     rpt_xl_util.exportExcel(pageRst, params.pageSize, rpt_name, params.isOneSheet, null, null, baseDir, innerRoleRel,
                         (err, uuidName) => {
@@ -179,7 +177,7 @@ module.exports = app => {
                     }
                 }
                 // console.log('roleRel.rel_content: ' + roleRel.rel_content);
-                fsUtil.writeObjToFile(pageRstArr, 'D:/GitHome/temp/testBuiltPageResult.jsp');
+                // fsUtil.writeObjToFile(pageRstArr, 'D:/GitHome/temp/testBuiltPageResult.jsp');
                 runnableRst.push(getExcelByPageData(pageRstArr[idx], params.rpt_names[idx], roleRel));
             }
             const uuidRst = await Promise.all(runnableRst);
@@ -187,6 +185,66 @@ module.exports = app => {
             ctx.status = 201;
         }
 
+        async createExcelFilesInOneBookEx(ctx) {
+            const params = JSON.parse(ctx.request.body.params);
+            const baseDir = this.app.baseDir;
+            function getExcelByPageData(pageRstArr, rpt_name, innerRoleRel) {
+                return new Promise(function(resolve, reject) {
+                    rpt_xl_util.exportExcelInOneBook(pageRstArr, params.pageSize, rpt_name, baseDir, innerRoleRel,
+                        (err, uuidName) => {
+                            if (err) return reject(err);
+                            const fileRst = { uuid: uuidName, reportName: rpt_name };
+                            resolve(fileRst);
+                        }
+                    );
+                });
+            }
+            const roleRelArr = await ctx.service.roleRptRel.getRoleRptRelByDetailIds(params.tender_id, params.rpt_ids);
+            const pageRstArr = await getMultiRptsCommon(ctx, params, JV.OUTPUT_TYPE_NORMAL);
+            const runnableRst = [];
+            let rptRoleRelArr = [];
+            const reAssignSignatureName = function(pageData, roleRel, rpt_name_key) {
+                const keyMap = {};
+                for (const pageItem of pageData.items) {
+                    for (const signCell of pageItem[JV.PROP_SIGNATURE_CELLS]) {
+                        if (!keyMap.hasOwnProperty(signCell.signature_name)) {
+                            keyMap[signCell.signature_name] = rpt_name_key + '_' + signCell.signature_name;
+                        }
+                    }
+                }
+                for (const pageItem of pageData.items) {
+                    for (const signCell of pageItem[JV.PROP_SIGNATURE_CELLS]) {
+                        if (keyMap.hasOwnProperty(signCell.signature_name)) {
+                            signCell.signature_name = keyMap[signCell.signature_name];
+                        }
+                    }
+                }
+                for (const roleSign of roleRel) {
+                    if (keyMap.hasOwnProperty(roleSign.signature_name)) {
+                        roleSign.signature_name = keyMap[roleSign.signature_name];
+                    }
+                }
+                // console.log('keyMap of : ' + rpt_name_key);
+                // console.log(keyMap);
+            };
+            for (let idx = 0; idx < pageRstArr.length; idx++) {
+                let roleRel = null;
+                for (const roleR of roleRelArr) {
+                    if (roleR.rpt_id === params.rpt_ids[idx]) {
+                        roleRel = JSON.parse(roleR.rel_content);
+                        // 这里要做些电子签名的signature_name转换,以防重名
+                        reAssignSignatureName(pageRstArr[idx], roleRel, params.rpt_names[idx]);
+                        rptRoleRelArr = rptRoleRelArr.concat(roleRel);
+                        break;
+                    }
+                }
+            }
+            runnableRst.push(getExcelByPageData(pageRstArr, params.rptName, rptRoleRelArr));
+            const uuidRst = await Promise.all(runnableRst);
+            ctx.body = { data: uuidRst };
+            ctx.status = 201;
+        }
+
         async getFileByUUID(ctx) {
             // console.log('downloading : ' + ctx.params.uuid);
             const uuid = ctx.params.uuid;
@@ -318,7 +376,7 @@ async function getMultiRptsCommon(ctx, params, outputType) {
     for (let idx = 0; idx < params.rpt_ids.length; idx++) {
         params.rpt_ids[idx] = parseInt(params.rpt_ids[idx]); // 转换一下,以防万一
     }
-    const rptTpls = await ctx.service.rptTpl.getTplById(params.rpt_ids);
+    const rptTpls = await ctx.service.rptTpl.getAllTplByIds(params.rpt_ids);
     // console.log(rptTpls);
     for (let rtIdx = 0; rtIdx < rptTpls.length; rtIdx++) {
         rptTpls[rtIdx] = JSON.parse(rptTpls[rtIdx].rpt_content);

+ 16 - 39
app/public/report/js/rpt_main.js

@@ -458,45 +458,22 @@ let rptControlObj = {
     getAllInOneBook: function () {
         if (zTreeOprObj.checkedRptTplNodes && zTreeOprObj.checkedRptTplNodes.length > 0) {
             let me = rptControlObj;
-            let orgRptName = projectObj.project.projectInfo.name;
-            let refRptTplIds = [], refBillSumPrjsIds = [], refGljSumPrjsIds = [];
-            rptControlObj.getTplIdsCommon(refRptTplIds, refBillSumPrjsIds, refGljSumPrjsIds);
-            if (zTreeOprObj.selectedPrjIDs.length > 0 && (refBillSumPrjsIds.length > 0 || refGljSumPrjsIds.length > 0)) {
-                let params = rptControlObj.creatCommonExportParam(refRptTplIds, refBillSumPrjsIds, refGljSumPrjsIds);
-                params.rptName = orgRptName;
-
-                CommonAjax.postEx("report_api/createExcelFilesInOneBook", params, WAIT_TIME_EXPORT, true, function(result){
-                        if (result) {
-                            let uuIdUrls = [];
-                            let uuIdUrl =  "/report_api/getFileByUUID/" + result.uuid + "/" + stringUtil.replaceAll(result.reportName, "#", "_") + "/xlsx";
-                            uuIdUrls.push(uuIdUrl);
-                            downloadReport(uuIdUrls);
-                        } else {
-                            //
-                        }
-                    }, null, null
-                );
-            } else {
-                let params = {};
-                params.prj_id = PROJECT_ID;
-                params.rpt_ids = refRptTplIds;
-                params.rptName = orgRptName;
-                params.pageSize = me.getCurrentPageSize();
-                params.orientation = ((zTreeOprObj.checkedRptTplNodes.length > 1)?null:me.getCurrentOrientation());
-                params.custCfg = CUST_CFG;
-                params.option = "normal";
-                CommonAjax.postEx("report_api/createExcelFilesInOneBook", params, WAIT_TIME_EXPORT, true, function(result){
-                        if (result) {
-                            let uuIdUrls = [];
-                            let uuIdUrl =  "/report_api/getFileByUUID/" + result.uuid + "/" + stringUtil.replaceAll(result.reportName, "#", "_") + "/xlsx";
-                            uuIdUrls.push(uuIdUrl);
-                            downloadReport(uuIdUrls);
-                        } else {
-                            //
-                        }
-                    }, null, null
-                );
-            }
+            let refRptTplIds = [], rpt_sheet_names = [];
+            rptControlObj.getTplIdsCommon(refRptTplIds, rpt_sheet_names);
+            let params = rptControlObj.creatCommonExportParam(refRptTplIds);
+            params.rpt_names = rpt_sheet_names;
+            params.rptName = TENDER_NAME;
+            CommonAjax.postXsrfEx("/tender/report_api/createExcelFilesInOneBook", params, 60000, true, getCookie('csrfToken'), function(result){
+                    if (result) {
+                        let uuIdUrls = [];
+                        let uuIdUrl =  "/getFileByUUID/" + result.data[0].uuid + "/" + stringUtil.replaceAll(result.data[0].reportName, "#", "_") + "/xlsx";
+                        uuIdUrls.push(uuIdUrl);
+                        downloadReport(uuIdUrls);
+                    } else {
+                        //
+                    }
+                }, null, null
+            );
         }
     },
     getAllIndividualExcelBook: function () {

+ 0 - 3
app/reports/rpt_component/helper/jpc_helper_discrete.js

@@ -11,9 +11,6 @@ const JpcDiscreteHelper = {
     outputDiscreteInfo: function(discreteArray, bands, dataObj, unitFactor, pageStatus, segIdx, multiCols, multiColIdx, $CURRENT_RPT, customizeCfg, signatureRst, signatureDateRst) {
         const rst = [];
         if (discreteArray && dataObj) {
-            if (Array.isArray(signatureRst)) {
-                signatureRst.splice(0, signatureRst.length);
-            }
             for (let i = 0; i < discreteArray.length; i++) {
                 const band = bands[discreteArray[i][JV.PROP_BAND_NAME]];
                 if (band && pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]] === true) {

+ 3 - 2
app/reports/rpt_component/jpc_flow_tab.js

@@ -771,6 +771,9 @@ JpcFlowTabSrv.prototype.createNew = function() {
         const tabRstLst = [];
         const FLOW_NODE_STR = me.isEx ? JV.NODE_FLOW_INFO_EX : JV.NODE_FLOW_INFO;
         const unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+        // 电子签名内容需要先清空
+        me.signatureRst = [];
+        me.signatureDateRst = [];
         if (me.paging_option === JV.PAGING_OPTION_INFINITY) {
             const segIdx = page - 1;
             // 1 calculate the band position
@@ -827,8 +830,6 @@ JpcFlowTabSrv.prototype.createNew = function() {
                 // 2.6 Discrete
                 if (pi === 0) {
                     tabRstLst.push(JpcDiscreteHelper.outputDiscreteInfo(rptTpl[FLOW_NODE_STR][JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[actualPage - 1], segIdx, 1, pi, $CURRENT_RPT, customizeCfg, me.signatureRst, me.signatureDateRst));
-                    // console.log('current page: ' + page);
-                    // console.log(me.signatureRst);
                 }
             }
         }

+ 150 - 71
app/reports/util/rpt_excel_util.js

@@ -11,6 +11,7 @@ const DPI = jpcCmnHelper.getScreenDPI()[0];
 const fsUtil = require('../public/fsUtil');
 const dftHeadXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
 const uuidV1 = require('uuid/v1');
+const atob = require('atob');
 
 function writeContentTypes(sheets, isSinglePage, hasSignature) {
     const rst = [];
@@ -330,7 +331,7 @@ function writeSharedString(sharedStrList) {
     }
     return rst;
 }
-function writeSheets(pageData, paperSize, sharedStrList, stylesObj, isSinglePage, custSheetMergeBands, hasSignature) {
+function writeSheets(pageData, paperSize, sharedStrList, stylesObj, isSinglePage, custSheetMergeBands, hasSignature, signSheetIdxArr) {
     const rst = [];
     const private_pushDftFont = function() {
         const font = {};
@@ -373,14 +374,14 @@ function writeSheets(pageData, paperSize, sharedStrList, stylesObj, isSinglePage
     private_buildFirstDftStyle();
     let sheetIdx = 0;
     if (isSinglePage) {
-        rst.push(writeSheet(pageData, null, paperSize, sharedStrList, stylesObj, null, hasSignature, sheetIdx));
+        rst.push(writeSheet(pageData, null, paperSize, sharedStrList, stylesObj, null, hasSignature, sheetIdx, signSheetIdxArr));
     } else {
         for (let i = 0; i < pageData.items.length; i++) {
             let appointedMergeBand = null;
             if (custSheetMergeBands && custSheetMergeBands.length > i) {
                 appointedMergeBand = custSheetMergeBands[i];
             }
-            rst.push(writeSheet(pageData, pageData.items[i], paperSize, sharedStrList, stylesObj, appointedMergeBand, hasSignature, sheetIdx));
+            rst.push(writeSheet(pageData, pageData.items[i], paperSize, sharedStrList, stylesObj, appointedMergeBand, hasSignature, sheetIdx, signSheetIdxArr));
             sheetIdx++;
         }
     }
@@ -476,7 +477,7 @@ function preAnalyzePos(pageData, sheetData, xPos, yPos, yMultiPos) {
     xPos.push(0);
     if (sheetData) {
         // current sheet data
-        console.log('preAnalyzePos not single');
+        // console.log('preAnalyzePos not single');
         yPos.push(0);
         self_analyze_sheet_pos(sheetData, xPos, yPos);
         xPos.sort(private_array_sort);
@@ -504,7 +505,7 @@ function preAnalyzePos(pageData, sheetData, xPos, yPos, yMultiPos) {
         }
     }
 }
-function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj, appointedMergeBand, hasSignature, sheetIdx) {
+function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj, appointedMergeBand, hasSignature, sheetIdx, signSheetIdxArr) {
     const rst = [];
     const xPos = [];
     const yPos = [];
@@ -706,7 +707,7 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj, ap
     const private_checkControl = function(cellControl, sheetControl) {
         let rst = true;
         for (let i = 0; i < JV.CONTROL_PROPS.length; i++) {
-            if (cellControl[JV.CONTROL_PROPS[i]] != sheetControl[JV.CONTROL_PROPS[i]]) {
+            if (cellControl[JV.CONTROL_PROPS[i]] !== sheetControl[JV.CONTROL_PROPS[i]]) {
                 rst = false;
                 break;
             }
@@ -783,7 +784,7 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj, ap
                     cnt++;
                 }
             }
-        }
+        };
         if (sheetData) {
             self_setMergedCells(sheetData, yPos, 0);
         } else {
@@ -924,17 +925,24 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj, ap
     }
     rst.push('<pageSetup ' + pStr + ' fitToWidth="0" fitToHeight="0" orientation="' + orientationStr + '" />');
     rst.push('<headerFooter alignWithMargins="0"/>');
-    if (hasSignature) {
-        rst.push('<drawing r:id="rId' + (sheetIdx + 1) + '"/>');
+    if (hasSignature && signSheetIdxArr[sheetIdx]) {
+        // let rIdx = 1;
+        // for (let ssIdx = 0; ssIdx < signSheetIdxArr.length; ssIdx++) {
+        //     if (signSheetIdxArr[ssIdx]) {
+        //         if (ssIdx < sheetIdx) rIdx++
+        //         else break;
+        //     }
+        // }
+        rst.push('<drawing r:id="rId1"/>');
     }
     rst.push('</worksheet>');
     return rst;
 }
-function writeWorkSheetRels(sheetIdx) {
+function writeWorkSheetRels(signSheetIdx) {
     const rst = [];
     rst.push('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
     rst.push('<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">');
-    rst.push('<Relationship Id="rId' + (sheetIdx + 1) + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing" Target="../drawings/drawing' + (sheetIdx + 1) + '.xml"/>');
+    rst.push('<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing" Target="../drawings/drawing' + signSheetIdx + '.xml"/>');
     rst.push('</Relationships>');
     return rst;
 }
@@ -942,26 +950,29 @@ function writeImage(path, pic, baseDir) {
     let rst = null;
     if (pic) {
         // 这里pic的数据就是base64的,不能是其他
-        rst = base64ToStream(pic);
+        rst = base64ToBuffer(pic);
+        // fs.createReadStream
     } else if (path) {
         const filePath = baseDir + '/app' + path;
         rst = fs.readFileSync(filePath);
     }
     return rst;
 }
-function writeDrawings(pageData, signKeyArr, signPathArr, isSinglePage) {
+function writeDrawings(pageData, signKeyArr, signPathArr, isSinglePage, signSheetIdxArr) {
     const rst = [];
     console.log('isSinglePage: ' + isSinglePage);
     if (isSinglePage) {
-        rst.push(writeDrawing(pageData, null, signKeyArr, signPathArr, 0));
+        rst.push(writeDrawing(pageData, null, signKeyArr[0]));
     } else {
         for (let i = 0; i < pageData.items.length; i++) {
-            rst.push(writeDrawing(pageData, pageData.items[i], signKeyArr, signPathArr, i));
+            if (signSheetIdxArr[i]) {
+                rst.push(writeDrawing(pageData, pageData.items[i], signKeyArr[i]));
+            }
         }
     }
     return rst;
 }
-function writeDrawing(pageData, sheetData, signKeyArr, signPathArr, sheetIdx) {
+function writeDrawing(pageData, sheetData, subSignKeyArr) {
     const rst = [];
     const xPos = [];
     const yPos = [];
@@ -1013,7 +1024,7 @@ function writeDrawing(pageData, sheetData, signKeyArr, signPathArr, sheetIdx) {
         // 3.2
         rst.push('<xdr:blipFill>');
         // 重点!!!
-        const picIdx = signKeyArr.indexOf(signCell.signature_name) + 1;
+        const picIdx = subSignKeyArr.indexOf(signCell.signature_name) + 1;
         // 3.2.1
         rst.push('<a:blip xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:embed="rId' + picIdx + '" cstate="print">');
         rst.push('<a:extLst>');
@@ -1036,7 +1047,7 @@ function writeDrawing(pageData, sheetData, signKeyArr, signPathArr, sheetIdx) {
         rst.push('<a:ext cx="0" cy="0"/>');
         rst.push('</a:xfrm>');
         // 3.3.2
-        rst.push('<a:prstGeom prst="rect"><a:avLst/></a:prstGeom>')
+        rst.push('<a:prstGeom prst="rect"><a:avLst/></a:prstGeom>');
         // 3.3.3
         rst.push('<a:noFill/>');
         // 3.3.4
@@ -1053,14 +1064,14 @@ function writeDrawing(pageData, sheetData, signKeyArr, signPathArr, sheetIdx) {
         // 4. client Data
         rst.push('<xdr:clientData/>');
         rst.push('</xdr:twoCellAnchor>');
-    }
+    };
     preAnalyzePos(pageData, sheetData, xPos, yPos, yMultiPos);
     rst.push('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
     rst.push('<xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">');
     if (sheetData) {
         let startPicIdx = 2;
         for (const sCell of sheetData[JV.PROP_SIGNATURE_CELLS]) {
-            if (signKeyArr.indexOf(sCell.signature_name) >= 0) {
+            if (subSignKeyArr.indexOf(sCell.signature_name) >= 0) {
                 private_setSheetDrawingCellData(sCell, yPos, startPicIdx, 0);
                 startPicIdx++;
             }
@@ -1073,7 +1084,7 @@ function writeDrawing(pageData, sheetData, signKeyArr, signPathArr, sheetIdx) {
             const tmpPos = yMultiPos[i];
             let startPicIdx = 2;
             for (const sCell of shtItemData[JV.PROP_SIGNATURE_CELLS]) {
-                if (signKeyArr.indexOf(sCell.signature_name) >= 0) {
+                if (subSignKeyArr.indexOf(sCell.signature_name) >= 0) {
                     private_setSheetDrawingCellData(sCell, tmpPos, startPicIdx, rowOffset);
                     startPicIdx++;
                 }
@@ -1084,12 +1095,12 @@ function writeDrawing(pageData, sheetData, signKeyArr, signPathArr, sheetIdx) {
     rst.push('</xdr:wsDr>');
     return rst;
 }
-function writeDrawingsRels(amt) {
+function writeDrawingsRels(amt, startIdx) {
     const rst = [];
     rst.push('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
     rst.push('<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">');
     for (let idx = 0; idx < amt; idx++) {
-        rst.push('<Relationship Id="rId' + (idx + 1) + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image' + (idx + 1) + '.png"/>');
+        rst.push('<Relationship Id="rId' + (idx + 1) + '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image' + (startIdx + idx + 1) + '.png"/>');
     }
     rst.push('</Relationships>');
     return rst;
@@ -1110,7 +1121,7 @@ function mergeProperties(orgObj, newObj) {
         }
     }
 }
-function checkAndSetSignatureCache(pageData, signKeyArr, signPathArr, roleRel) {
+function checkAndSetSignatureCache(pageData, signKeyArr, signPathArr, roleRel, signSheetIdxArr) {
     // 备注:电子签名是以图形的方式处理,一页可以有多个签名,多页的签名基本是引用同样的图片,在这里先处理一下,后期统一引用。
     //      另:以后的图片(在电子签名(signature_cells)以外的图片)会单独处理(如计算图等)
     let rst = false;
@@ -1121,33 +1132,43 @@ function checkAndSetSignatureCache(pageData, signKeyArr, signPathArr, roleRel) {
         chkRoles.push(roleRel);
     }
     // console.log(chkRoles);
-    for (const page of pageData.items) {
+    // console.log(signKeyArr);
+    // for (const page of pageData.items) {
+    for (let pageIdx = 0; pageIdx < pageData.items.length; pageIdx++) {
+        const page = pageData.items[pageIdx];
+        signKeyArr.push([]);
+        signPathArr.push([]);
+        signSheetIdxArr[pageIdx] = false;
         if (page[JV.PROP_SIGNATURE_CELLS] && page[JV.PROP_SIGNATURE_CELLS].length > 0) {
-            // console.log('has SignatureCells!');
+            // console.log('page index: ' + pageIdx);
+            // console.log(page[JV.PROP_SIGNATURE_CELLS]);
             for (const signature of page[JV.PROP_SIGNATURE_CELLS]) {
-                if (signKeyArr.indexOf(signature.signature_name) < 0) {
+                if (signKeyArr[pageIdx].indexOf(signature.signature_name) < 0) {
                     if (signature.pic) {
                         const signPath = { path: null, pic: null };
-                        signPathArr.push(signPath);
+                        signPathArr[pageIdx].push(signPath);
                         signPath.pic = signature.pic; // 历史报表
-                        signKeyArr.push(signature.signature_name);
+                        signKeyArr[pageIdx].push(signature.signature_name);
                         rst = true;
+                        signSheetIdxArr[pageIdx] = true;
                     } else {
                         for (const role of chkRoles) {
                             if (signature.signature_name === role.signature_name) {
                                 // console.log('signature.signature_name: ' + signature.signature_name);
                                 if (role.sign_pic) {
                                     const signPath = { path: null, pic: null };
-                                    signPathArr.push(signPath);
+                                    signPathArr[pageIdx].push(signPath);
                                     signPath.pic = role.sign_pic;
-                                    signKeyArr.push(signature.signature_name);
+                                    signKeyArr[pageIdx].push(signature.signature_name);
                                     rst = true;
+                                    signSheetIdxArr[pageIdx] = true;
                                 } else if (role.sign_path) {
                                     const signPath = { path: null, pic: null };
-                                    signPathArr.push(signPath);
+                                    signPathArr[pageIdx].push(signPath);
                                     signPath.path = role.sign_path;
-                                    signKeyArr.push(signature.signature_name);
+                                    signKeyArr[pageIdx].push(signature.signature_name);
                                     rst = true;
+                                    signSheetIdxArr[pageIdx] = true;
                                 }
                                 break;
                             }
@@ -1159,19 +1180,14 @@ function checkAndSetSignatureCache(pageData, signKeyArr, signPathArr, roleRel) {
     }
     return rst;
 }
-function base64ToStream(dataurl) {
-    // 将base64转换为
+function base64ToBuffer(dataurl) {
+    // 将base64转换为buffer
     const arr = dataurl.split(',');
-    const bstr = atob(arr[1]);
-    let n = bstr.length;
-    const u8arr = new Uint8Array(n);
-    while (n--) {
-        u8arr[n] = bstr.charCodeAt(n);
-    }
-    return u8arr;
+    // console.log(arr[1]);
+    const rst = new Buffer(arr[1], 'base64');
+    return rst;
 }
 
-
 module.exports = {
     exportExcel: function(pageData, paperSize, fName, options, custSheetNames, custSheetMergeBands, baseDir, roleRel, callback) {
         const rptOptions = ({ singlePage: false, fileName: 'report' });
@@ -1182,11 +1198,14 @@ module.exports = {
         const sheets = [];
         const signKeyArr = [];
         const signPathArr = [];
+        const signSheetIdxArr = []; // 确定哪些sheet有签名(在多表导出的时候,有些表可能没有签名,但其他的表有签名)
         // console.log('in exportExcel!');
         // console.log(roleRel);
-        const hasSignature = (roleRel !== null) ? checkAndSetSignatureCache(pageData, signKeyArr, signPathArr, roleRel) : false;
+        const hasSignature = (roleRel !== null) ? checkAndSetSignatureCache(pageData, signKeyArr, signPathArr, roleRel, signSheetIdxArr) : false;
+        // console.log('signSheetIdxArr');
+        // console.log(signSheetIdxArr);
         // const hasSignature = false;
-        console.log('hasSignature: ' + hasSignature);
+        // console.log('hasSignature: ' + hasSignature);
         if (isSinglePage) {
             sheets.push({ sheetName: '全部页' });
         } else {
@@ -1233,16 +1252,24 @@ module.exports = {
         data = writeTheme();
         zip_theme.file(file, data, { compression: 'DEFLATE' });
         if (hasSignature) {
-            // 5.1
+            // 5.1 写所有的image
             const zip_media = zip_xl.folder('media');
+            let picIdx = 0;
+            // console.log(signKeyArr);
+            // console.log(signPathArr);
             for (let signIdx = 0; signIdx < signPathArr.length; signIdx++) {
-                data = writeImage(signPathArr[signIdx].path, signPathArr[signIdx].pic, baseDir);
-                file = 'image' + (signIdx + 1) + '.png';
-                zip_media.file(file, data, { compression: 'DEFLATE' });
+                if (signKeyArr[signIdx].length > 0) {
+                    for (let pathIdx = 0; pathIdx < signPathArr[signIdx].length; pathIdx++) {
+                        picIdx++;
+                        data = writeImage(signPathArr[signIdx][pathIdx].path, signPathArr[signIdx][pathIdx].pic, baseDir);
+                        file = 'image' + picIdx + '.png';
+                        zip_media.file(file, data, { compression: 'DEFLATE' });
+                    }
+                }
             }
             // 5.2
             const zip_drawings = zip_xl.folder('drawings');
-            data = writeDrawings(pageData, signKeyArr, signPathArr, isSinglePage);
+            data = writeDrawings(pageData, signKeyArr, signPathArr, isSinglePage, signSheetIdxArr);
             // console.log('isSinglePage: ' + isSinglePage);
             // console.log(data);
             for (let psIdx = 0; psIdx < data.length; psIdx++) {
@@ -1253,17 +1280,25 @@ module.exports = {
             }
             // 5.3
             const zip_drawings_rels = zip_drawings.folder('_rels');
-            data = writeDrawingsRels(signPathArr.length); // 这个一个文件搞定算了,无需多个文件
-            // console.log('drawing1.xml.rels data');
-            // console.log(data);
-            file = 'drawing1.xml.rels';
-            zip_drawings_rels.file(file, data.join(''), { compression: 'DEFLATE' });
+            let relsIdx = 0;
+            let relsImgAmt = 0;
+            for (let ssIdx = 0; ssIdx < signKeyArr.length; ssIdx++) {
+                if (signKeyArr[ssIdx].length > 0) {
+                    data = writeDrawingsRels(signKeyArr[ssIdx].length, relsImgAmt); // 一个drawingX.xml.rels文件与一个drawingX.xml对应
+                    relsIdx++;
+                    relsImgAmt += signKeyArr[ssIdx].length;
+                    // console.log('drawing1.xml.rels data');
+                    // console.log(data);
+                    file = 'drawing' + relsIdx + '.xml.rels';
+                    zip_drawings_rels.file(file, data.join(''), { compression: 'DEFLATE' });
+                }
+            }
         }
         // 6.
         const zip_xl_worksheets = zip_xl.folder('worksheets');
         const sharedStrList = [];
         const stylesObj = {};
-        data = writeSheets(pageData, paperSize, sharedStrList, stylesObj, isSinglePage, custSheetMergeBands, hasSignature);
+        data = writeSheets(pageData, paperSize, sharedStrList, stylesObj, isSinglePage, custSheetMergeBands, hasSignature, signSheetIdxArr);
         if (isSinglePage) {
             for (let i = 0; i < 1; i++) {
                 file = 'sheet' + (i + 1) + '.xml';
@@ -1279,14 +1314,18 @@ module.exports = {
         if (hasSignature) {
             const zip_xl_worksheets_rels = zip_xl_worksheets.folder('_rels');
             if (isSinglePage) {
-                data = writeWorkSheetRels(0);
+                data = writeWorkSheetRels(1);
                 file = 'sheet1.xml.rels';
                 zip_xl_worksheets_rels.file(file, data.join(''), { compression: 'DEFLATE' });
             } else {
+                let ssIdx = 0;
                 for (let i = 0; i < data.length; i++) {
-                    data = writeWorkSheetRels(i);
-                    file = 'sheet' + (i + 1) + '.xml.rels';
-                    zip_xl_worksheets_rels.file(file, data.join(''), { compression: 'DEFLATE' });
+                    if (signSheetIdxArr[i]) {
+                        ssIdx++;
+                        const ssData = writeWorkSheetRels(ssIdx);
+                        file = 'sheet' + (i + 1) + '.xml.rels';
+                        zip_xl_worksheets_rels.file(file, ssData.join(''), { compression: 'DEFLATE' });
+                    }
                 }
             }
         }
@@ -1372,17 +1411,45 @@ module.exports = {
                         mergeBand[JV.PROP_TOP].push(pageDataArray[i][JV.BAND_PROP_MERGE_BAND][JV.PROP_TOP] + offsetY);
                         mergeBand[JV.PROP_BOTTOM].push(pageDataArray[i][JV.BAND_PROP_MERGE_BAND][JV.PROP_BOTTOM] + offsetY);
                     }
-                    for (let k = 0; k < pageDataArray[i].items[j].cells.length; k++) {
-                        if (maxY < pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_BOTTOM]) {
-                            maxY = pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_BOTTOM];
+                    // 1.2.1 重新设置普通cells的Top Bottom坐标
+                    for (const cell of pageDataArray[i].items[j].cells) {
+                    // for (let k = 0; k < pageDataArray[i].items[j].cells.length; k++) {
+                        if (maxY < cell[JV.PROP_AREA][JV.PROP_BOTTOM]) {
+                            maxY = cell[JV.PROP_AREA][JV.PROP_BOTTOM];
+                        }
+                        if (minY > cell[JV.PROP_AREA][JV.PROP_TOP]) {
+                            minY = cell[JV.PROP_AREA][JV.PROP_TOP];
+                        }
+                        cell[JV.PROP_AREA][JV.PROP_BOTTOM] += offsetY;
+                        cell[JV.PROP_AREA][JV.PROP_TOP] += offsetY;
+                    }
+                    // 1.2.2 重新设置电子签名cells的Top Bottom坐标
+                    for (const cell of pageDataArray[i].items[j].signature_cells) {
+                        if (maxY < cell[JV.PROP_AREA][JV.PROP_BOTTOM]) {
+                            maxY = cell[JV.PROP_AREA][JV.PROP_BOTTOM];
+                        }
+                        if (minY > cell[JV.PROP_AREA][JV.PROP_TOP]) {
+                            minY = cell[JV.PROP_AREA][JV.PROP_TOP];
+                        }
+                        // console.log('before');
+                        // console.log(cell);
+                        cell[JV.PROP_AREA][JV.PROP_BOTTOM] += offsetY;
+                        cell[JV.PROP_AREA][JV.PROP_TOP] += offsetY;
+                        // console.log('after');
+                        // console.log(cell);
+                    }
+                    // 1.2.3 重新设置电子签名日期cells的Top Bottom坐标
+                    for (const cell of pageDataArray[i].items[j].signature_date_cells) {
+                        if (maxY < cell[JV.PROP_AREA][JV.PROP_BOTTOM]) {
+                            maxY = cell[JV.PROP_AREA][JV.PROP_BOTTOM];
                         }
-                        if (minY > pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_TOP]) {
-                            minY = pageDataArray[i].items[j].cells[k][JV.PROP_AREA][JV.PROP_TOP];
+                        if (minY > cell[JV.PROP_AREA][JV.PROP_TOP]) {
+                            minY = cell[JV.PROP_AREA][JV.PROP_TOP];
                         }
-                        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;
+                        cell[JV.PROP_AREA][JV.PROP_BOTTOM] += offsetY;
+                        cell[JV.PROP_AREA][JV.PROP_TOP] += offsetY;
                     }
-                    const 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;
+                    const 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);
@@ -1396,8 +1463,20 @@ module.exports = {
                 pageItem[JV.PROP_PAGE_SEQ] = i + 1;
                 pageItem[JV.PROP_CELLS] = [];
                 for (let j = 0; j < pageDataArray[i].items.length; j++) {
-                    for (let k = 0; k < pageDataArray[i].items[j].cells.length; k++) {
-                        pageItem[JV.PROP_CELLS].push(pageDataArray[i].items[j].cells[k]);
+                    for (let k = 0; k < pageDataArray[i].items[j][JV.PROP_CELLS].length; k++) {
+                        pageItem[JV.PROP_CELLS].push(pageDataArray[i].items[j][JV.PROP_CELLS][k]);
+                    }
+                }
+                pageItem[JV.PROP_SIGNATURE_CELLS] = [];
+                for (let j = 0; j < pageDataArray[i].items.length; j++) {
+                    for (let k = 0; k < pageDataArray[i].items[j][JV.PROP_SIGNATURE_CELLS].length; k++) {
+                        pageItem[JV.PROP_SIGNATURE_CELLS].push(pageDataArray[i].items[j][JV.PROP_SIGNATURE_CELLS][k]);
+                    }
+                }
+                pageItem[JV.PROP_SIGNATURE_DATE_CELLS] = [];
+                for (let j = 0; j < pageDataArray[i].items.length; j++) {
+                    for (let k = 0; k < pageDataArray[i].items[j][JV.PROP_SIGNATURE_DATE_CELLS].length; k++) {
+                        pageItem[JV.PROP_SIGNATURE_DATE_CELLS].push(pageDataArray[i].items[j][JV.PROP_SIGNATURE_DATE_CELLS][k]);
                     }
                 }
                 newPagePos[i][JV.NODE_PAGE_SIZE] = pageDataArray[i][JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE];
@@ -1407,7 +1486,7 @@ module.exports = {
             // 3. everything is ok, then call me
             // let roleRel = null; // 未来调用的时候,这个属性要从外面给!!!
             // roleRelArr
-            me.exportExcel(newPageData, paperSize, fName, 'false', sheetNames, custMergeBands, baseDir, null, callback);
+            me.exportExcel(newPageData, paperSize, fName, 'false', sheetNames, custMergeBands, baseDir, roleRelArr, callback);
             // fsUtil.writeObjToFile(newPageData, 'D:/GitHome/ConstructionOperation/tmp/combinedHeader.js');
         } catch (e) {
             console.log(e);

+ 1 - 0
app/router.js

@@ -188,6 +188,7 @@ module.exports = app => {
     app.post('/tender/report_api/getReport', sessionAuth, 'reportController.getReport');
     app.post('/tender/report_api/getMultiReports', sessionAuth, 'reportController.getMultiReportsEx');
     app.post('/tender/report_api/createExcelFiles', sessionAuth, 'reportController.createExcelFilesEx');
+    app.post('/tender/report_api/createExcelFilesInOneBook', sessionAuth, 'reportController.createExcelFilesInOneBookEx');
     app.get('/getFileByUUID/:uuid/:rptName/:suffix', sessionAuth, 'reportController.getFileByUUID');
     // rptRouter.get('/getFileByUUID/:uuid/:rptName/:suffix', reportController.getFileByUUID);
     app.post('/tender/report_api/createSignatureRole', sessionAuth, 'signatureController.createSignatureRole');

+ 1 - 0
app/view/report/index.ejs

@@ -188,6 +188,7 @@
     CUST_CFG = JSON.parse(CUST_CFG[0].cfg_content);
     const PROJECT_ID = <%- project_id %>;
     const TENDER_ID = <%- tender_id %>;
+    const TENDER_NAME = '<%- tender_name %>';
     const STAGE_ID = <%- stg_id %>;
     const STAGE_ORDER = <%- stg_order %>;
     const STAGE_TIMES = <%- stg_times %>;

文件差异内容过多而无法显示
+ 2837 - 2864
package-lock.json


+ 1 - 0
package.json

@@ -5,6 +5,7 @@
   "private": true,
   "dependencies": {
     "ali-rds": "^3.3.0",
+    "atob": "^2.1.2",
     "bignumber.js": "^8.1.1",
     "decimal.js": "^10.2.0",
     "egg": "^1.13.0",