jpc_ex.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. let JV = require('./jpc_value_define');
  2. let JpcBand = require('./jpc_band');
  3. let JpcFlowTab = require('./jpc_flow_tab');
  4. let JpcBillTab = require('./jpc_bill_tab');
  5. let JpcCrossTab = require('./jpc_cross_tab');
  6. let JpcField = require('./jpc_field');
  7. let JpcParam = require('./jpc_param');
  8. let JpcFunc = require('./jpc_function');
  9. let JpcData = require('./jpc_data');
  10. let JpcCommonHelper = require('./helper/jpc_helper_common');
  11. let $JE = require('./jpc_rte'); //Important: for self-define function execution purpose
  12. let JpcExSrv = function(){};
  13. JpcExSrv.prototype.createNew = function(){
  14. function private_buildDftItems(rptTpl, dftCollection, propArray, nodeName) {
  15. let rst = {};
  16. if (dftCollection) {
  17. for (let i = 0; i < dftCollection.length; i++) {
  18. let item = {};
  19. for (let j = 0; j < propArray.length; j++) {
  20. item[propArray[j]] = dftCollection[i][propArray[j]];
  21. }
  22. rst[dftCollection[i][JV.PROP_ID]] = item;
  23. }
  24. if (rptTpl && rptTpl[nodeName] && rptTpl[nodeName].length > 0) {
  25. for (let i = 0; i < rptTpl[nodeName].length; i++) {
  26. let rptDftItem = rptTpl[nodeName][i];
  27. if (rst[rptDftItem[JV.PROP_ID]] === undefined) {
  28. let item = {};
  29. for (let j = 0; j < propArray.length; j++) {
  30. item[propArray[j]] = rptDftItem[propArray[j]];
  31. }
  32. rst[rptDftItem[JV.PROP_ID]] = item;
  33. }
  34. }
  35. }
  36. }
  37. return rst;
  38. }
  39. function private_buildDftControls(rptTpl, dftControlCollection) {
  40. return private_buildDftItems(rptTpl,dftControlCollection, JV.CONTROL_PROPS, JV.NODE_CONTROL_COLLECTION);
  41. }
  42. function private_buildDftFonts(rptTpl, dftFontCollection) {
  43. return private_buildDftItems(rptTpl,dftFontCollection, JV.FONT_PROPS, JV.NODE_FONT_COLLECTION);
  44. }
  45. function private_buildDftStyles(rptTpl, dftStyleCollection) {
  46. let rst = {};
  47. function private_CopyBorder(destItem, srcItem) {
  48. destItem[JV.PROP_LINE_WEIGHT] = srcItem[JV.PROP_LINE_WEIGHT];
  49. destItem[JV.PROP_DASH_STYLE] = srcItem[JV.PROP_DASH_STYLE];
  50. destItem[JV.PROP_COLOR] = srcItem[JV.PROP_COLOR];
  51. }
  52. if (dftStyleCollection) {
  53. for (let i = 0; i < dftStyleCollection.length; i++) {
  54. let item = {};
  55. if (dftStyleCollection[i][JV.PROP_BORDER_STYLE] && dftStyleCollection[i][JV.PROP_BORDER_STYLE].length > 0) {
  56. for (let j = 0; j < dftStyleCollection[i][JV.PROP_BORDER_STYLE].length; j++) {
  57. let borderItem = {};
  58. private_CopyBorder(borderItem, dftStyleCollection[i][JV.PROP_BORDER_STYLE][j]);
  59. item[dftStyleCollection[i][JV.PROP_BORDER_STYLE][j][JV.PROP_POSITION]] = borderItem;
  60. }
  61. }
  62. rst[dftStyleCollection[i][JV.PROP_ID]] = item;
  63. }
  64. if (rptTpl && rptTpl[JV.NODE_STYLE_COLLECTION] && rptTpl[JV.NODE_STYLE_COLLECTION].length > 0) {
  65. for (let i = 0; i < rptTpl[JV.NODE_STYLE_COLLECTION].length; i++) {
  66. let rptDftItem = rptTpl[JV.NODE_STYLE_COLLECTION][i];
  67. if (rst[rptDftItem[JV.PROP_ID]] === undefined) {
  68. if (rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Top') > 0) {
  69. let key = rptDftItem[JV.PROP_ID].substr(0, rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Top'));
  70. if (rst[key]) {
  71. let item = {};
  72. if (rst[key][JV.PROP_LEFT]) {
  73. item[JV.PROP_LEFT] = {};
  74. private_CopyBorder(item[JV.PROP_LEFT], rst[key][JV.PROP_LEFT]);
  75. }
  76. if (rst[key][JV.PROP_RIGHT]) {
  77. item[JV.PROP_RIGHT] = {};
  78. private_CopyBorder(item[JV.PROP_RIGHT], rst[key][JV.PROP_RIGHT]);
  79. }
  80. if (rst[key][JV.PROP_TOP]) {
  81. item[JV.PROP_TOP] = {};
  82. private_CopyBorder(item[JV.PROP_TOP], rst[key][JV.PROP_TOP]);
  83. }
  84. rst[rptDftItem[JV.PROP_ID]] = item;
  85. }
  86. } else if (rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Middle') > 0) {
  87. let key = rptDftItem[JV.PROP_ID].substr(0, rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Middle'));
  88. if (rst[key]) {
  89. let item = {};
  90. if (rst[key][JV.PROP_LEFT]) {
  91. item[JV.PROP_LEFT] = {};
  92. private_CopyBorder(item[JV.PROP_LEFT], rst[key][JV.PROP_LEFT]);
  93. }
  94. if (rst[key][JV.PROP_RIGHT]) {
  95. item[JV.PROP_RIGHT] = {};
  96. private_CopyBorder(item[JV.PROP_RIGHT], rst[key][JV.PROP_RIGHT]);
  97. }
  98. rst[rptDftItem[JV.PROP_ID]] = item;
  99. }
  100. } else if (rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Bottom') > 0) {
  101. let key = rptDftItem[JV.PROP_ID].substr(0, rptDftItem[JV.PROP_ID].indexOf('_AutoHeightMerge_Bottom'));
  102. if (rst[key]) {
  103. let item = {};
  104. if (rst[key][JV.PROP_LEFT]) {
  105. item[JV.PROP_LEFT] = {};
  106. private_CopyBorder(item[JV.PROP_LEFT], rst[key][JV.PROP_LEFT]);
  107. }
  108. if (rst[key][JV.PROP_RIGHT]) {
  109. item[JV.PROP_RIGHT] = {};
  110. private_CopyBorder(item[JV.PROP_RIGHT], rst[key][JV.PROP_RIGHT]);
  111. }
  112. if (rst[key][JV.PROP_BOTTOM]) {
  113. item[JV.PROP_BOTTOM] = {};
  114. private_CopyBorder(item[JV.PROP_BOTTOM], rst[key][JV.PROP_BOTTOM]);
  115. }
  116. rst[rptDftItem[JV.PROP_ID]] = item;
  117. }
  118. } else {
  119. let item = {};
  120. for (let j = 0; j < rptDftItem[JV.PROP_BORDER_STYLE].length; j++) {
  121. let borderItem = {};
  122. private_CopyBorder(borderItem, rptDftItem[JV.PROP_BORDER_STYLE][j]);
  123. item[rptDftItem[JV.PROP_BORDER_STYLE][j][JV.PROP_POSITION]] = borderItem;
  124. }
  125. rst[rptDftItem[JV.PROP_ID]] = item;
  126. }
  127. }
  128. }
  129. }
  130. }
  131. return rst;
  132. }
  133. let JpcResult = {};
  134. //JpcResult.report_title
  135. JpcResult.initialize = function(rptTpl) {
  136. let me = this;
  137. if (rptTpl[JV.NODE_FLOW_INFO]) {
  138. me.flowTab = JpcFlowTab.createNew();
  139. me.flowTab.initialize(false);
  140. me.isFollowMode = false;
  141. }
  142. if (rptTpl[JV.NODE_FLOW_INFO_EX]) {
  143. me.flowTabEx = JpcFlowTab.createNew();
  144. me.flowTabEx.initialize(true);
  145. if (rptTpl[JV.NODE_FLOW_INFO_EX][JV.PROP_FLOW_EX_DISPLAY_MODE] === JV.DISPLAY_MODE_FOLLOW) {
  146. me.isFollowMode = true;
  147. }
  148. }
  149. if (rptTpl[JV.NODE_BILL_INFO]) {
  150. me.billTab = JpcBillTab.createNew();
  151. me.billTab.initialize();
  152. }
  153. //let dt1 = new Date();
  154. if (rptTpl[JV.NODE_CROSS_INFO]) {
  155. me.crossTab = JpcCrossTab.createNew();
  156. me.crossTab.initialize();
  157. }
  158. me.totalPages = 0;
  159. me.exTotalPages = 0;
  160. me.runTimePageData = {};
  161. me.fields = JpcField.createNew(rptTpl);
  162. me.params = JpcParam.createNew(rptTpl);
  163. me.formulas = JpcFunc.createNew(rptTpl);
  164. };
  165. JpcResult.analyzeData = function(rptTpl, dataObj, defProperties, option, outputType) {
  166. let me = this, dftPagingOption = option||JV.PAGING_OPTION_NORMAL;
  167. //1. data object
  168. let dataHelper = JpcData.createNew();
  169. me.executeFormulas(JV.RUN_TYPE_BEFORE_ANALYZING, rptTpl, dataObj, me); //在分析前运行,主要是增加灵活性,比如:重新编排数据的主从关系
  170. if (me.crossTab) {
  171. me.executeFormulas(JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me);
  172. dataHelper.analyzeData(rptTpl, dataObj);
  173. me.crossTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
  174. } else {
  175. dataHelper.analyzeData(rptTpl, dataObj);
  176. //2. tab object
  177. //pre-condition: the data should be sorted in SQL/NoSQL level!
  178. //let dt1 = new Date();
  179. if (me.flowTab) {
  180. me.flowTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
  181. if (me.flowTabEx) {
  182. me.flowTabEx.sorting(rptTpl, dataObj, dataHelper.exDataSeq.slice(0), me);
  183. }
  184. }
  185. if (me.billTab) {
  186. me.billTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
  187. }
  188. //let dt2 = new Date();
  189. //alert(dt2 - dt1);
  190. //3. formulas
  191. me.executeFormulas(JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me);
  192. }
  193. //4. paging
  194. me.paging(rptTpl, dataObj, defProperties, dftPagingOption, outputType);
  195. //alert('analyzeData was completed!');
  196. //for garbage collection:
  197. dataHelper = null;
  198. };
  199. JpcResult.paging = function(rptTpl, dataObj, defProperties, option, outputType) {
  200. let me = this, dftPagingOption = option||JV.PAGING_OPTION_NORMAL;
  201. if (me.flowTab) {
  202. if (me.isFollowMode) {
  203. me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, me.flowTabEx, outputType);
  204. } else {
  205. me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null, outputType);
  206. if (me.flowTabEx) {
  207. me.exTotalPages = me.flowTabEx.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null, outputType);
  208. //console.log('ad-hoc flow pages: ' + me.exTotalPages);
  209. }
  210. me.totalPages += me.exTotalPages;
  211. }
  212. } else if (me.crossTab) {
  213. //me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, dftPagingOption);
  214. me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, JV.PAGING_OPTION_NORMAL); //infinity对交叉表来说无意义
  215. } else if (me.billTab) {
  216. me.totalPages = me.billTab.paging(rptTpl, dataObj);
  217. }
  218. };
  219. JpcResult.executeFormulas = function(runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT) {
  220. let execFmlMe = this;
  221. for (let execFmlIdx = 0; execFmlIdx < execFmlMe.formulas.length; execFmlIdx++) {
  222. //remark: 搞这么复杂的变量名是为了防止与表达式起冲突(如循环变量i,j,k,容易造成变量冲突且不容易看出问题)
  223. if (execFmlMe.formulas[execFmlIdx][JV.PROP_RUN_TYPE] === runType) {
  224. let expression = execFmlMe.formulas[execFmlIdx][JV.PROP_EXPRESSION];
  225. if (expression) {
  226. let $ME = execFmlMe.formulas[execFmlIdx];
  227. // console.log("current expression idx: " + execFmlIdx);
  228. // console.log(expression);
  229. try {
  230. eval(expression);
  231. } catch (ex) {
  232. console.log(ex);
  233. }
  234. }
  235. }
  236. }
  237. };
  238. JpcResult.outputAsPreviewPage= function(rptTpl, defProperties) {
  239. let me = this, rst = {};
  240. rst[JV.NODE_CONTROL_COLLECTION] = private_buildDftControls(rptTpl, (defProperties === null)?null:defProperties.ctrls);
  241. rst[JV.NODE_STYLE_COLLECTION] = private_buildDftStyles(rptTpl, (defProperties === null)?null:defProperties.styles);
  242. rst[JV.NODE_FONT_COLLECTION] = private_buildDftFonts(rptTpl, (defProperties === null)?null:defProperties.fonts);
  243. rst[JV.NODE_PAGE_INFO] = {};
  244. rst[JV.NODE_PAGE_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME];
  245. rst[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE] = JpcCommonHelper.getPageSize(rptTpl);
  246. rst[JV.NODE_PAGE_INFO][JV.NODE_MARGINS] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS];
  247. rst.items = [];
  248. let bands = JpcBand.createNew(rptTpl, defProperties);
  249. try {
  250. function getPageMergeBorder() {
  251. let mergeRst = null;
  252. if (bands[JV.BAND_PROP_MERGE_BAND]) {
  253. let mergedBand = bands[JV.BAND_PROP_MERGE_BAND];
  254. mergeRst = {};
  255. mergeRst[JV.PROP_LEFT] = parseInt(mergedBand[JV.PROP_LEFT].toFixed(0));
  256. mergeRst[JV.PROP_RIGHT] = parseInt(mergedBand[JV.PROP_RIGHT].toFixed(0));
  257. mergeRst[JV.PROP_TOP] = parseInt(mergedBand[JV.PROP_TOP].toFixed(0));
  258. mergeRst[JV.PROP_BOTTOM] = parseInt(mergedBand[JV.PROP_BOTTOM].toFixed(0));
  259. }
  260. return mergeRst;
  261. }
  262. //1.
  263. let rstPage = {};
  264. rstPage[JV.PROP_PAGE_SEQ] = 1;
  265. if (me.flowTab) {
  266. rstPage[JV.PROP_CELLS] = me.flowTab.outputAsPreviewPage(rptTpl, bands, rst[JV.NODE_CONTROL_COLLECTION], me);
  267. } else if (me.crossTab) {
  268. rstPage[JV.PROP_CELLS] = me.crossTab.outputAsPreviewPage(rptTpl, bands, rst[JV.NODE_CONTROL_COLLECTION], me);
  269. } else if (me.billTab) {
  270. rstPage[JV.PROP_CELLS] = me.billTab.outputAsPreviewPage(rptTpl, bands, rst[JV.NODE_CONTROL_COLLECTION], me);
  271. }
  272. let pageMergeBorder = getPageMergeBorder();
  273. if (pageMergeBorder) {
  274. rstPage[JV.PROP_PAGE_MERGE_BORDER] = pageMergeBorder;
  275. }
  276. rst.items.push(rstPage);
  277. //2.
  278. if (bands[JV.BAND_PROP_MERGE_BAND]) {
  279. let mergedBand = {}, band = bands[JV.BAND_PROP_MERGE_BAND];
  280. mergedBand[JV.PROP_LEFT] = parseInt(band[JV.PROP_LEFT].toFixed(0));
  281. mergedBand[JV.PROP_RIGHT] = parseInt(band[JV.PROP_RIGHT].toFixed(0));
  282. mergedBand[JV.PROP_TOP] = parseInt(band[JV.PROP_TOP].toFixed(0));
  283. mergedBand[JV.PROP_BOTTOM] = parseInt(band[JV.PROP_BOTTOM].toFixed(0));
  284. mergedBand[JV.BAND_PROP_STYLE] = band[JV.BAND_PROP_STYLE];
  285. rst[JV.BAND_PROP_MERGE_BAND] = mergedBand;
  286. }
  287. } catch(exception) {
  288. console.log(exception);
  289. } finally {
  290. bands = null;
  291. }
  292. return rst;
  293. };
  294. JpcResult.outputAsSimpleJSONPageArray = function(rptTpl, dataObj, startPage, endPage, defProperties, customizeCfg) {
  295. let me = this, rst = {};
  296. if ((startPage > 0) && (startPage <= endPage) && (endPage <= me.totalPages)) {
  297. rst[JV.NODE_CONTROL_COLLECTION] = private_buildDftControls(rptTpl, (defProperties === null)?null:defProperties.ctrls);
  298. rst[JV.NODE_STYLE_COLLECTION] = private_buildDftStyles(rptTpl, (defProperties === null)?null:defProperties.styles);
  299. rst[JV.NODE_FONT_COLLECTION] = private_buildDftFonts(rptTpl, (defProperties === null)?null:defProperties.fonts);
  300. rst[JV.NODE_PAGE_INFO] = {};
  301. rst[JV.NODE_PAGE_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME];
  302. rst[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE] = JpcCommonHelper.getPageSize(rptTpl);
  303. rst[JV.NODE_PAGE_INFO][JV.NODE_MARGINS] = rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS];
  304. rst.items = [];
  305. let bands = JpcBand.createNew(rptTpl, defProperties);
  306. try {
  307. for (let page = startPage; page <= endPage; page++) {
  308. me.runTimePageData.currentPage = page;
  309. me.executeFormulas(JV.RUN_TYPE_BEFORE_OUTPUT, rptTpl, dataObj, me);
  310. rst.items.push(me.outputAsSimpleJSONPage(rptTpl, dataObj, bands, page, rst[JV.NODE_CONTROL_COLLECTION], customizeCfg));
  311. }
  312. if (bands[JV.BAND_PROP_MERGE_BAND]) {
  313. let mergedBand = {}, band = bands[JV.BAND_PROP_MERGE_BAND];
  314. mergedBand[JV.PROP_LEFT] = parseInt(band[JV.PROP_LEFT].toFixed(0));
  315. mergedBand[JV.PROP_RIGHT] = parseInt(band[JV.PROP_RIGHT].toFixed(0));
  316. mergedBand[JV.PROP_TOP] = parseInt(band[JV.PROP_TOP].toFixed(0));
  317. mergedBand[JV.PROP_BOTTOM] = parseInt(band[JV.PROP_BOTTOM].toFixed(0));
  318. mergedBand[JV.BAND_PROP_STYLE] = band[JV.BAND_PROP_STYLE];
  319. rst[JV.BAND_PROP_MERGE_BAND] = mergedBand;
  320. }
  321. } catch(exception) {
  322. console.log(exception);
  323. } finally {
  324. bands = null;
  325. }
  326. }
  327. return rst;
  328. };
  329. JpcResult.outputAsSimpleJSONPage = function(rptTpl, dataObj, bands, page, controls, customizeCfg) {
  330. let me = this, rst = null;
  331. function getPageMergeBorder() {
  332. let mergeRst = null;
  333. if (bands[JV.BAND_PROP_MERGE_BAND]) {
  334. let mergedBand = bands[JV.BAND_PROP_MERGE_BAND];
  335. mergeRst = {};
  336. mergeRst[JV.PROP_LEFT] = parseInt(mergedBand[JV.PROP_LEFT].toFixed(0));
  337. mergeRst[JV.PROP_RIGHT] = parseInt(mergedBand[JV.PROP_RIGHT].toFixed(0));
  338. mergeRst[JV.PROP_TOP] = parseInt(mergedBand[JV.PROP_TOP].toFixed(0));
  339. mergeRst[JV.PROP_BOTTOM] = parseInt(mergedBand[JV.PROP_BOTTOM].toFixed(0));
  340. }
  341. return mergeRst;
  342. }
  343. if (me.totalPages >= page) {
  344. rst = {};
  345. rst[JV.PROP_PAGE_SEQ] = page;
  346. //rst.cells = [];
  347. let adHocMergePos = null;
  348. if (me.flowTab) {
  349. if (me.totalPages - me.exTotalPages >= page) {
  350. if (me.flowTab.paging_option === JV.PAGING_OPTION_INFINITY) {
  351. adHocMergePos = {};
  352. }
  353. rst[JV.PROP_CELLS] = me.flowTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, adHocMergePos, me, customizeCfg);
  354. if (adHocMergePos) {
  355. adHocMergePos[JV.NODE_PAGE_SIZE] = JpcCommonHelper.getPageSize(rptTpl);
  356. rst[JV.PAGE_SPECIAL_MERGE_POS] = adHocMergePos;
  357. }
  358. } else {
  359. if (!me.isFollowMode) {
  360. rst[JV.PROP_CELLS] = me.flowTabEx.outputAsSimpleJSONPage(rptTpl, dataObj, page - (me.totalPages - me.exTotalPages), bands, controls, adHocMergePos, me, customizeCfg);
  361. }
  362. }
  363. } else if (me.crossTab) {
  364. rst[JV.PROP_CELLS] = me.crossTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me, customizeCfg);
  365. } else if (me.billTab) {
  366. rst[JV.PROP_CELLS] = me.billTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me, customizeCfg);
  367. }
  368. if (!(me.flowTab && me.flowTab.paging_option === JV.PAGING_OPTION_INFINITY)) {
  369. let pageMergeBorder = getPageMergeBorder();
  370. if (pageMergeBorder) {
  371. rst[JV.PROP_PAGE_MERGE_BORDER] = pageMergeBorder;
  372. }
  373. }
  374. }
  375. return rst;
  376. };
  377. //JpcEx.rte.currentRptObj = JpcResult;
  378. return JpcResult;
  379. };
  380. export default new JpcExSrv();