'use strict'; const JV = require('./jpc_value_define'); const JpcBand = require('./jpc_band'); const JpcFlowTab = require('./jpc_flow_tab'); const JpcBillTab = require('./jpc_bill_tab'); const JpcCrossTab = require('./jpc_cross_tab'); const JpcField = require('./jpc_field'); const JpcParam = require('./jpc_param'); const JpcFunc = require('./jpc_function'); const JpcEvent = require('./jpc_event'); const JpcData = require('./jpc_data'); const JpcCommonHelper = require('./helper/jpc_helper_common'); const $JE = require('./jpc_rte'); // Important: for self-define function execution purpose const JpcExSrv = function() {}; JpcExSrv.prototype.createNew = function() { function private_buildDftItems(rptTpl, dftCollection, propArray, nodeName) { const rst = {}; if (dftCollection) { for (let i = 0; i < dftCollection.length; i++) { const item = {}; for (let j = 0; j < propArray.length; j++) { item[propArray[j]] = dftCollection[i][propArray[j]]; } rst[dftCollection[i][JV.PROP_ID]] = item; } if (rptTpl && rptTpl[nodeName] && rptTpl[nodeName].length > 0) { for (let i = 0; i < rptTpl[nodeName].length; i++) { const rptDftItem = rptTpl[nodeName][i]; if (rst[rptDftItem[JV.PROP_ID]] === undefined) { const item = {}; for (let j = 0; j < propArray.length; j++) { item[propArray[j]] = rptDftItem[propArray[j]]; } rst[rptDftItem[JV.PROP_ID]] = item; } } } } return rst; } function private_buildDftControls(rptTpl, dftControlCollection) { return private_buildDftItems(rptTpl, dftControlCollection, JV.CONTROL_PROPS, JV.NODE_CONTROL_COLLECTION); } function private_buildDftFonts(rptTpl, dftFontCollection) { return private_buildDftItems(rptTpl, dftFontCollection, JV.FONT_PROPS, JV.NODE_FONT_COLLECTION); } function private_buildDftStyles(rptTpl, dftStyleCollection) { const rst = {}; function private_CopyBorder(destItem, srcItem) { destItem[JV.PROP_LINE_WEIGHT] = srcItem[JV.PROP_LINE_WEIGHT]; destItem[JV.PROP_DASH_STYLE] = srcItem[JV.PROP_DASH_STYLE]; destItem[JV.PROP_COLOR] = srcItem[JV.PROP_COLOR]; } if (dftStyleCollection) { for (let i = 0; i < dftStyleCollection.length; i++) { const item = {}; if (dftStyleCollection[i][JV.PROP_BORDER_STYLE] && dftStyleCollection[i][JV.PROP_BORDER_STYLE].length > 0) { for (let j = 0; j < dftStyleCollection[i][JV.PROP_BORDER_STYLE].length; j++) { const borderItem = {}; private_CopyBorder(borderItem, dftStyleCollection[i][JV.PROP_BORDER_STYLE][j]); item[dftStyleCollection[i][JV.PROP_BORDER_STYLE][j][JV.PROP_POSITION]] = borderItem; } } rst[dftStyleCollection[i][JV.PROP_ID]] = item; } if (rptTpl && rptTpl[JV.NODE_STYLE_COLLECTION] && rptTpl[JV.NODE_STYLE_COLLECTION].length > 0) { for (let i = 0; i < rptTpl[JV.NODE_STYLE_COLLECTION].length; i++) { const rptDftItem = rptTpl[JV.NODE_STYLE_COLLECTION][i]; if (rst[rptDftItem[JV.PROP_ID]] === undefined) { if (rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Top') > 0) { const key = rptDftItem[JV.PROP_ID].substr(0, rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Top')); if (rst[key]) { const item = {}; if (rst[key][JV.PROP_LEFT]) { item[JV.PROP_LEFT] = {}; private_CopyBorder(item[JV.PROP_LEFT], rst[key][JV.PROP_LEFT]); } if (rst[key][JV.PROP_RIGHT]) { item[JV.PROP_RIGHT] = {}; private_CopyBorder(item[JV.PROP_RIGHT], rst[key][JV.PROP_RIGHT]); } if (rst[key][JV.PROP_TOP]) { item[JV.PROP_TOP] = {}; private_CopyBorder(item[JV.PROP_TOP], rst[key][JV.PROP_TOP]); } rst[rptDftItem[JV.PROP_ID]] = item; } } else if (rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Middle') > 0) { const key = rptDftItem[JV.PROP_ID].substr(0, rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Middle')); if (rst[key]) { const item = {}; if (rst[key][JV.PROP_LEFT]) { item[JV.PROP_LEFT] = {}; private_CopyBorder(item[JV.PROP_LEFT], rst[key][JV.PROP_LEFT]); } if (rst[key][JV.PROP_RIGHT]) { item[JV.PROP_RIGHT] = {}; private_CopyBorder(item[JV.PROP_RIGHT], rst[key][JV.PROP_RIGHT]); } rst[rptDftItem[JV.PROP_ID]] = item; } } else if (rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Bottom') > 0) { const key = rptDftItem[JV.PROP_ID].substr(0, rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Bottom')); if (rst[key]) { const item = {}; if (rst[key][JV.PROP_LEFT]) { item[JV.PROP_LEFT] = {}; private_CopyBorder(item[JV.PROP_LEFT], rst[key][JV.PROP_LEFT]); } if (rst[key][JV.PROP_RIGHT]) { item[JV.PROP_RIGHT] = {}; private_CopyBorder(item[JV.PROP_RIGHT], rst[key][JV.PROP_RIGHT]); } if (rst[key][JV.PROP_BOTTOM]) { item[JV.PROP_BOTTOM] = {}; private_CopyBorder(item[JV.PROP_BOTTOM], rst[key][JV.PROP_BOTTOM]); } rst[rptDftItem[JV.PROP_ID]] = item; } } else { const item = {}; for (let j = 0; j < rptDftItem[JV.PROP_BORDER_STYLE].length; j++) { const borderItem = {}; private_CopyBorder(borderItem, rptDftItem[JV.PROP_BORDER_STYLE][j]); item[rptDftItem[JV.PROP_BORDER_STYLE][j][JV.PROP_POSITION]] = borderItem; } rst[rptDftItem[JV.PROP_ID]] = item; } } } } } return rst; } const JpcResult = {}; JpcResult.initialize = function(rptTpl) { const me = this; if (rptTpl[JV.NODE_FLOW_INFO]) { me.flowTab = JpcFlowTab.createNew(); me.flowTab.initialize(false); me.isFollowMode = false; } if (rptTpl[JV.NODE_FLOW_INFO_EX]) { me.flowTabEx = JpcFlowTab.createNew(); me.flowTabEx.initialize(true); if (rptTpl[JV.NODE_FLOW_INFO_EX][JV.PROP_FLOW_EX_DISPLAY_MODE] === JV.DISPLAY_MODE_FOLLOW) { me.isFollowMode = true; } } if (rptTpl[JV.NODE_BILL_INFO]) { me.billTab = JpcBillTab.createNew(); me.billTab.initialize(); } if (rptTpl[JV.NODE_CROSS_INFO]) { me.crossTab = JpcCrossTab.createNew(); me.crossTab.initialize(); } me.totalPages = 0; me.exTotalPages = 0; me.runTimePageData = {}; me.fields = JpcField.createNew(rptTpl); me.params = JpcParam.createNew(rptTpl); // console.log('params:'); // console.log(me.params); me.formulas = JpcFunc.createNew(rptTpl); me.events = JpcEvent.createNew(rptTpl); }; JpcResult.analyzeData = function($CTX_HELPER, rptTpl, dataObj, defProperties, option, outputType, $CUSTOM_DEFINE) { const me = this; const dftPagingOption = option || JV.PAGING_OPTION_NORMAL; // 1. data object let dataHelper = JpcData.createNew(); // console.log(JSON.stringify(rptTpl)); me.executeFormulas($CTX_HELPER, JV.RUN_TYPE_BEFORE_ANALYZING, rptTpl, dataObj, me, $CUSTOM_DEFINE); // 在分析前运行,主要是增加灵活性,比如:重新编排数据的主从关系 // console.log(JSON.stringify(rptTpl)); if (me.crossTab) { me.executeFormulas($CTX_HELPER, JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me, $CUSTOM_DEFINE); dataHelper.analyzeData(rptTpl, dataObj); me.crossTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me); } else { dataHelper.analyzeData(rptTpl, dataObj); // 2. tab object // pre-condition: the data should be sorted in SQL/NoSQL level! // let dt1 = new Date(); if (me.flowTab) { me.flowTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me); if (me.flowTabEx) { me.flowTabEx.sorting(rptTpl, dataObj, dataHelper.exDataSeq.slice(0), me); } } if (me.billTab) { me.billTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me); } // let dt2 = new Date(); // alert(dt2 - dt1); // 3. formulas me.executeFormulas($CTX_HELPER, JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me, $CUSTOM_DEFINE); } // 4. paging me.paging(rptTpl, dataObj, defProperties, dftPagingOption, outputType); // alert('analyzeData was completed!'); // for garbage collection: dataHelper = null; }; JpcResult.paging = function(rptTpl, dataObj, defProperties, option, outputType) { const me = this; const dftPagingOption = option || JV.PAGING_OPTION_NORMAL; if (me.flowTab) { if (me.isFollowMode) { me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, me.flowTabEx, outputType); } else { me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null, outputType); if (me.flowTabEx) { me.exTotalPages = me.flowTabEx.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null, outputType); // console.log('ad-hoc flow pages: ' + me.exTotalPages); } me.totalPages += me.exTotalPages; } } else if (me.crossTab) { // me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, dftPagingOption); me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, JV.PAGING_OPTION_NORMAL); // infinity对交叉表来说无意义 } else if (me.billTab) { me.totalPages = me.billTab.paging(rptTpl, dataObj); } }; JpcResult.executeFormulas = function($CTX_HELPER, runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT, $CUSTOM_DEFINE) { const execFmlMe = this; for (let execFmlIdx = 0; execFmlIdx < execFmlMe.formulas.length; execFmlIdx++) { // remark: 搞这么复杂的变量名是为了防止与表达式起冲突(如循环变量i,j,k,容易造成变量冲突且不容易看出问题) // console.log('execFmlMe.formulas[execFmlIdx][JV.PROP_RUN_TYPE]: ' + execFmlMe.formulas[execFmlIdx][JV.PROP_RUN_TYPE]); // console.log('runType: ' + runType); if (execFmlMe.formulas[execFmlIdx][JV.PROP_RUN_TYPE] === runType) { const expression = execFmlMe.formulas[execFmlIdx][JV.PROP_EXPRESSION]; if (expression) { const $ME = execFmlMe.formulas[execFmlIdx]; // console.log("current expression idx: " + execFmlIdx); // console.log(expression); try { eval(expression); } catch (ex) { console.log(ex); } } } } }; JpcResult.outputAsPreviewPage = function(rptTpl, defProperties) { const me = this; const rst = {}; rst[JV.NODE_CONTROL_COLLECTION] = private_buildDftControls(rptTpl, (defProperties === null) ? null : defProperties.ctrls); rst[JV.NODE_STYLE_COLLECTION] = private_buildDftStyles(rptTpl, (defProperties === null) ? null : defProperties.styles); rst[JV.NODE_FONT_COLLECTION] = private_buildDftFonts(rptTpl, (defProperties === null) ? null : defProperties.fonts); rst[JV.NODE_PAGE_INFO] = {}; rst[JV.NODE_PAGE_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME]; rst[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE] = JpcCommonHelper.getPageSize(rptTpl); rst[JV.NODE_PAGE_INFO][JV.NODE_MARGINS] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS]; rst.items = []; let bands = JpcBand.createNew(rptTpl, defProperties); function getPageMergeBorder() { let mergeRst = null; if (bands[JV.BAND_PROP_MERGE_BAND]) { const mergedBand = bands[JV.BAND_PROP_MERGE_BAND]; mergeRst = {}; mergeRst[JV.PROP_LEFT] = parseInt(mergedBand[JV.PROP_LEFT].toFixed(0)); mergeRst[JV.PROP_RIGHT] = parseInt(mergedBand[JV.PROP_RIGHT].toFixed(0)); mergeRst[JV.PROP_TOP] = parseInt(mergedBand[JV.PROP_TOP].toFixed(0)); mergeRst[JV.PROP_BOTTOM] = parseInt(mergedBand[JV.PROP_BOTTOM].toFixed(0)); } return mergeRst; } try { // 1. const rstPage = {}; rstPage[JV.PROP_PAGE_SEQ] = 1; if (me.flowTab) { rstPage[JV.PROP_CELLS] = me.flowTab.outputAsPreviewPage(rptTpl, bands, rst[JV.NODE_CONTROL_COLLECTION], me); } else if (me.crossTab) { rstPage[JV.PROP_CELLS] = me.crossTab.outputAsPreviewPage(rptTpl, bands, rst[JV.NODE_CONTROL_COLLECTION], me); } else if (me.billTab) { rstPage[JV.PROP_CELLS] = me.billTab.outputAsPreviewPage(rptTpl, bands, rst[JV.NODE_CONTROL_COLLECTION], me); } const pageMergeBorder = getPageMergeBorder(); if (pageMergeBorder) { rstPage[JV.PROP_PAGE_MERGE_BORDER] = pageMergeBorder; } rstPage[JV.PROP_SIGNATURE_CELLS] = []; rstPage[JV.PROP_SIGNATURE_DATE_CELLS] = []; rstPage[JV.PROP_SIGNATURE_AUDIT_CELLS] = []; rst.items.push(rstPage); // 2. if (bands[JV.BAND_PROP_MERGE_BAND]) { const mergedBand = {}; const band = bands[JV.BAND_PROP_MERGE_BAND]; mergedBand[JV.PROP_LEFT] = parseInt(band[JV.PROP_LEFT].toFixed(0)); mergedBand[JV.PROP_RIGHT] = parseInt(band[JV.PROP_RIGHT].toFixed(0)); mergedBand[JV.PROP_TOP] = parseInt(band[JV.PROP_TOP].toFixed(0)); mergedBand[JV.PROP_BOTTOM] = parseInt(band[JV.PROP_BOTTOM].toFixed(0)); mergedBand[JV.BAND_PROP_STYLE] = band[JV.BAND_PROP_STYLE]; rst[JV.BAND_PROP_MERGE_BAND] = mergedBand; } } catch (exception) { console.log(exception); } finally { bands = null; } return rst; }; JpcResult.outputAsSimpleJSONPageArray = function($CTX_HELPER, rptTpl, dataObj, startPage, endPage, defProperties, customizeCfg, $CUSTOM_DEFINE) { const me = this; const rst = {}; if ((startPage > 0) && (startPage <= endPage) && (endPage <= me.totalPages)) { rst[JV.NODE_CONTROL_COLLECTION] = private_buildDftControls(rptTpl, (defProperties === null) ? null : defProperties.ctrls); // console.log('controls: '); // console.log(rst[JV.NODE_CONTROL_COLLECTION]); rst[JV.NODE_STYLE_COLLECTION] = private_buildDftStyles(rptTpl, (defProperties === null) ? null : defProperties.styles); rst[JV.NODE_FONT_COLLECTION] = private_buildDftFonts(rptTpl, (defProperties === null) ? null : defProperties.fonts); rst[JV.NODE_PAGE_INFO] = {}; rst[JV.NODE_PAGE_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME]; rst[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE] = JpcCommonHelper.getPageSize(rptTpl); rst[JV.NODE_PAGE_INFO][JV.NODE_MARGINS] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS]; rst.items = []; let bands = JpcBand.createNew(rptTpl, defProperties); try { for (let page = startPage; page <= endPage; page++) { me.runTimePageData.currentPage = page; me.executeFormulas($CTX_HELPER, JV.RUN_TYPE_BEFORE_OUTPUT, rptTpl, dataObj, me, $CUSTOM_DEFINE); rst.items.push(me.outputAsSimpleJSONPage(rptTpl, dataObj, bands, page, rst[JV.NODE_CONTROL_COLLECTION], customizeCfg)); } if (bands[JV.BAND_PROP_MERGE_BAND]) { const mergedBand = {}; const band = bands[JV.BAND_PROP_MERGE_BAND]; mergedBand[JV.PROP_LEFT] = parseInt(band[JV.PROP_LEFT].toFixed(0)); mergedBand[JV.PROP_RIGHT] = parseInt(band[JV.PROP_RIGHT].toFixed(0)); mergedBand[JV.PROP_TOP] = parseInt(band[JV.PROP_TOP].toFixed(0)); mergedBand[JV.PROP_BOTTOM] = parseInt(band[JV.PROP_BOTTOM].toFixed(0)); mergedBand[JV.BAND_PROP_STYLE] = band[JV.BAND_PROP_STYLE]; rst[JV.BAND_PROP_MERGE_BAND] = mergedBand; } } catch (exception) { console.log(exception); } finally { bands = null; } } return rst; }; JpcResult.outputAsSimpleJSONPage = function(rptTpl, dataObj, bands, page, controls, customizeCfg) { const me = this; let rst = null; function getPageMergeBorder() { let mergeRst = null; if (bands[JV.BAND_PROP_MERGE_BAND]) { const mergedBand = bands[JV.BAND_PROP_MERGE_BAND]; mergeRst = {}; mergeRst[JV.PROP_LEFT] = parseInt(mergedBand[JV.PROP_LEFT].toFixed(0)); mergeRst[JV.PROP_RIGHT] = parseInt(mergedBand[JV.PROP_RIGHT].toFixed(0)); mergeRst[JV.PROP_TOP] = parseInt(mergedBand[JV.PROP_TOP].toFixed(0)); mergeRst[JV.PROP_BOTTOM] = parseInt(mergedBand[JV.PROP_BOTTOM].toFixed(0)); } return mergeRst; } if (me.totalPages >= page) { rst = {}; rst[JV.PROP_PAGE_SEQ] = page; // rst.cells = []; let adHocMergePos = null; if (me.flowTab) { // console.log('page_seg_map:'); // console.log(me.flowTab.page_seg_map); if (me.totalPages - me.exTotalPages >= page) { if (me.flowTab.paging_option === JV.PAGING_OPTION_INFINITY) { adHocMergePos = {}; } rst[JV.PROP_CELLS] = me.flowTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, adHocMergePos, me, customizeCfg); rst[JV.PROP_SIGNATURE_CELLS] = me.flowTab.signatureRst; rst[JV.PROP_SIGNATURE_DATE_CELLS] = me.flowTab.signatureDateRst; rst[JV.PROP_SIGNATURE_AUDIT_CELLS] = me.flowTab.signatureAuditRst; if (adHocMergePos) { adHocMergePos[JV.NODE_PAGE_SIZE] = JpcCommonHelper.getPageSize(rptTpl); rst[JV.PAGE_SPECIAL_MERGE_POS] = adHocMergePos; } } else { if (!me.isFollowMode) { rst[JV.PROP_CELLS] = me.flowTabEx.outputAsSimpleJSONPage(rptTpl, dataObj, page - (me.totalPages - me.exTotalPages), bands, controls, adHocMergePos, me, customizeCfg); rst[JV.PROP_SIGNATURE_CELLS] = me.flowTabEx.signatureRst; rst[JV.PROP_SIGNATURE_DATE_CELLS] = me.flowTabEx.signatureDateRst; rst[JV.PROP_SIGNATURE_AUDIT_CELLS] = me.flowTabEx.signatureAuditRst; } } } else if (me.crossTab) { rst[JV.PROP_CELLS] = me.crossTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me, customizeCfg); rst[JV.PROP_SIGNATURE_CELLS] = me.crossTab.signatureRst; rst[JV.PROP_SIGNATURE_DATE_CELLS] = me.crossTab.signatureDateRst; rst[JV.PROP_SIGNATURE_AUDIT_CELLS] = me.crossTab.signatureAuditRst; } else if (me.billTab) { rst[JV.PROP_CELLS] = me.billTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me, customizeCfg); rst[JV.PROP_SIGNATURE_CELLS] = me.billTab.signatureRst; rst[JV.PROP_SIGNATURE_DATE_CELLS] = me.billTab.signatureDateRst; rst[JV.PROP_SIGNATURE_AUDIT_CELLS] = me.billTab.signatureAuditRst; } if (!(me.flowTab && me.flowTab.paging_option === JV.PAGING_OPTION_INFINITY)) { const pageMergeBorder = getPageMergeBorder(); if (pageMergeBorder) { rst[JV.PROP_PAGE_MERGE_BORDER] = pageMergeBorder; } } } else { console.log('no page result was found!'); } return rst; }; // JpcEx.rte.currentRptObj = JpcResult; return JpcResult; }; module.exports = new JpcExSrv();