jpc_ex.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. import JE from './jpc_rte'; //Important: for self-define function execution purpose
  2. import $JV from './jpc_value_define';
  3. import JpcBand from './jpc_band';
  4. import JpcFlowTab from './jpc_flow_tab';
  5. import JpcBillTab from './jpc_bill_tab';
  6. import JpcCrossTab from './jpc_cross_tab';
  7. import JpcField from './jpc_field';
  8. import JpcParam from './jpc_param';
  9. import JpcFunc from './jpc_function';
  10. import JpcEvent from './jpc_event';
  11. import JpcData from './jpc_data';
  12. import JpcCommonHelper from './helper/jpc_helper_common';
  13. import useReportDate from '../public/ReportDate'
  14. import { IDefProperties, IFormula, IParams, ICurrent_RPT, ICurrent_DATA, ICustomizeCfg, ITargetFields, IRptTpl, IDataObj, IBands, IControlCollection, IStyles, BorderStyle, IFontSubCollection, IControlSubCollection, IPreviewPage, IRstPage, IMergeBand } from '../interface/basic'
  15. import { IFlowTabClass, IBillTabClass, ICostTabClass } from '../interface/classType';
  16. import { IControlProps, IFontProps, IPagingOption, IPositionProps } from '../interface/enum';
  17. import { Key } from 'readline';
  18. const JV=$JV;
  19. class JpcExClass {
  20. flowTab!: IFlowTabClass;
  21. flowTabEx!: IFlowTabClass;
  22. billTab!: IBillTabClass;
  23. crossTab!: ICostTabClass;
  24. isFollowMode: boolean = false;
  25. totalPages: number = 0;
  26. exTotalPages: number = 0;
  27. runTimePageData: { currentPage?: number };
  28. fields: ITargetFields;
  29. params: IParams;
  30. formulas: IFormula[];
  31. events: any;
  32. constructor(rptTpl: IRptTpl) {
  33. if (rptTpl.流水式表_信息) {
  34. this.flowTab = new JpcFlowTab(false);
  35. this.isFollowMode = false;
  36. }
  37. if (rptTpl.流水式表_拓展信息) {
  38. this.flowTabEx = new JpcFlowTab(true);
  39. if (rptTpl.流水式表_拓展信息.流水拓展显示模式 === '紧随模式') {
  40. this.isFollowMode = true;
  41. }
  42. }
  43. if (rptTpl.账单式表_信息) {
  44. this.billTab = new JpcBillTab();
  45. }
  46. //let dt1 = new Date();
  47. if (rptTpl.交叉表_信息) {
  48. this.crossTab = new JpcCrossTab();
  49. }
  50. this.runTimePageData = {};
  51. this.fields = JpcField.createNew(rptTpl);
  52. this.params = JpcParam.createNew(rptTpl);
  53. this.formulas = JpcFunc.createNew(rptTpl);
  54. this.events = JpcEvent.createNew(rptTpl);
  55. };
  56. analyzeData(rptTpl: IRptTpl, dataObj: IDataObj, defProperties: IDefProperties, option: string, outputType: string) {
  57. let me = this, dftPagingOption = option || IPagingOption.normal;
  58. //1. data object
  59. let dataHelper: any = JpcData.createNew();
  60. // 主要是通过计算rptTpl参数里面的 指标_数据_映射 属性中的公式,赋值于dataObj中的相对应(根据)的属性
  61. me.executeFormulas('before_analyzing', rptTpl, dataObj, me); //在分析前运行,主要是增加灵活性,比如:重新编排数据的主从关系
  62. if (me.crossTab) {
  63. me.executeFormulas('before_paging', rptTpl, dataObj, me);
  64. dataHelper.analyzeData(rptTpl, dataObj);
  65. me.crossTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
  66. } else {
  67. dataHelper.analyzeData(rptTpl, dataObj);
  68. //2. tab object
  69. //pre-condition: the data should be sorted in SQL/NoSQL level!
  70. //let dt1 = new Date();
  71. if (me.flowTab) {
  72. me.flowTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
  73. if (me.flowTabEx) {
  74. me.flowTabEx.sorting(rptTpl, dataObj, dataHelper.exDataSeq.slice(0), me);
  75. }
  76. }
  77. if (me.billTab) {
  78. // 先记录下账单式表_信息.账单式表_数据中的数据相对应于从 数据指标_集合 中的相对应的数组序号,后面便于计算
  79. // me.billTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
  80. //edit by lish,方法中需要的参数只有一个,但是这里存入了4个
  81. me.billTab.sorting(rptTpl);
  82. }
  83. //3. formulas
  84. // 主要是通过计算rptTpl参数里面的 指标_数据_映射 属性中的公式,赋值于dataObj中的相对应(根据)的属性
  85. me.executeFormulas('before_paging', rptTpl, dataObj, me);
  86. }
  87. //4. paging
  88. //获取总页数
  89. me.paging(rptTpl, dataObj, defProperties, dftPagingOption);
  90. //alert('analyzeData was completed!');
  91. //for garbage collection:
  92. dataHelper = null;
  93. };
  94. //获取总页数
  95. paging(rptTpl: IRptTpl, dataObj: IDataObj, defProperties: IDefProperties, option: string) {
  96. let me = this, dftPagingOption = option || IPagingOption.normal;
  97. if (me.flowTab) {
  98. if (me.isFollowMode) {
  99. me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, me.flowTabEx);
  100. } else {
  101. me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null);
  102. if (me.flowTabEx) {
  103. me.exTotalPages = me.flowTabEx.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null);
  104. //console.log('ad-hoc flow pages: ' + me.exTotalPages);
  105. }
  106. me.totalPages += me.exTotalPages;
  107. }
  108. } else if (me.crossTab) {
  109. //me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, dftPagingOption);
  110. me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, IPagingOption.normal); //infinity对交叉表来说无意义
  111. } else if (me.billTab) {
  112. me.totalPages = me.billTab.paging(rptTpl, dataObj);
  113. }
  114. };
  115. //根据步骤,对formulas中的计算式进行处理,并赋值到相应属性中
  116. executeFormulas(runType: string, $CURRENT_TEMPLATE: IRptTpl, $CURRENT_DATA: IDataObj, $CURRENT_RPT: ICurrent_RPT) {
  117. let execFmlMe = this;
  118. for (let execFmlIdx = 0; execFmlIdx < execFmlMe.formulas.length; execFmlIdx++) {
  119. //remark: 搞这么复杂的变量名是为了防止与表达式起冲突(如循环变量i,j,k,容易造成变量冲突且不容易看出问题)
  120. if (execFmlMe.formulas[execFmlIdx].run_type === runType) {
  121. let expression = execFmlMe.formulas[execFmlIdx].expression;
  122. if (expression) {
  123. // 计算式集合,目前是放置打印信息的,用于配置属性的计算
  124. let $ME = execFmlMe.formulas[execFmlIdx];
  125. // console.log("current expression idx: " + execFmlIdx);
  126. // console.log(expression);
  127. try {
  128. const $JE = JE;
  129. const ReportDate = useReportDate;
  130. console.log(expression);
  131. //临时处理
  132. if (expression.indexOf('Date()') > -1) {
  133. eval(expression.replace('Date()', 'ReportDate()'));
  134. } else {
  135. eval(expression);
  136. }
  137. } catch (ex) {
  138. console.log(ex);
  139. }
  140. }
  141. }
  142. }
  143. };
  144. outputAsPreviewPage(rptTpl: IRptTpl, defProperties: IDefProperties) {
  145. let me = this, rst: any = {};
  146. rst.control_collection = private_buildDftControls(rptTpl, (defProperties === null) ? null : defProperties.ctrls);
  147. rst.style_collection = private_buildDftStyles(rptTpl, (defProperties === null) ? null : defProperties.styles);
  148. rst.font_collection = private_buildDftFonts(rptTpl, (defProperties === null) ? null : defProperties.fonts);
  149. rst.打印页面_信息 = {};
  150. rst.打印页面_信息.报表名称 = rptTpl.主信息.报表名称;
  151. rst.打印页面_信息.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
  152. rst.打印页面_信息.页边距 = rptTpl.主信息.页边距;
  153. rst.items = [];
  154. let bands = JpcBand.createNew(rptTpl, defProperties);
  155. try {
  156. function getPageMergeBorder() {
  157. let mergeRst = {} as IMergeBand;
  158. if (bands.MergeBand) {
  159. let mergedBand = bands.MergeBand;
  160. mergeRst.Left = parseInt(mergedBand.Left.toFixed(0));
  161. mergeRst.Right = parseInt(mergedBand.Right.toFixed(0));
  162. mergeRst.Top = parseInt(mergedBand.Top.toFixed(0));
  163. mergeRst.Bottom = parseInt(mergedBand.Bottom.toFixed(0));
  164. }
  165. return null;
  166. }
  167. //1.
  168. let rstPage: IRstPage = {};
  169. rstPage.page_seq = 1;
  170. if (me.flowTab) {
  171. rstPage.cells = me.flowTab.outputAsPreviewPage(rptTpl, bands, rst.control_collection, me);
  172. } else if (me.crossTab) {
  173. rstPage.cells = me.crossTab.outputAsPreviewPage(rptTpl, bands, rst.control_collection, me, null as unknown as ICustomizeCfg);//方法中定义了5个参数,这里只传进去了4个参数,故加一个参数,by lish
  174. } else if (me.billTab) {
  175. rstPage.cells = me.billTab.outputAsPreviewPage(rptTpl, bands, rst.control_collection, me);
  176. }
  177. let pageMergeBorder = getPageMergeBorder();
  178. if (pageMergeBorder) {
  179. rstPage.page_merge_border = pageMergeBorder;
  180. }
  181. rst.items.push(rstPage);
  182. //2.
  183. if (bands.MergeBand) {
  184. let band = bands.MergeBand;
  185. let mergedBand :IMergeBand= {
  186. Left : parseInt(band.Left.toFixed(0)),
  187. Right: parseInt(band.Right.toFixed(0)),
  188. Top : parseInt(band.Top.toFixed(0)),
  189. Bottom :parseInt(band.Bottom.toFixed(0)),
  190. style: band.style,
  191. } ;
  192. rst.MergeBand = mergedBand;
  193. }
  194. } catch (exception) {
  195. console.log(exception);
  196. } finally {
  197. bands = null;
  198. }
  199. return rst;
  200. };
  201. outputAsSimpleJSONPageArray(rptTpl: IRptTpl, dataObj: IDataObj, startPage: number, endPage: number, defProperties: IDefProperties, customizeCfg: ICustomizeCfg) {
  202. let me = this, rst: any = {};
  203. if ((startPage > 0) && (startPage <= endPage) && (endPage <= me.totalPages)) {
  204. rst.control_collection = private_buildDftControls(rptTpl, (defProperties === null) ? null : defProperties.ctrls);
  205. rst.style_collection = private_buildDftStyles(rptTpl, (defProperties === null) ? null : defProperties.styles);
  206. rst.font_collection = private_buildDftFonts(rptTpl, (defProperties === null) ? null : defProperties.fonts);
  207. rst.打印页面_信息 = {};
  208. rst.打印页面_信息.报表名称 = rptTpl.主信息.报表名称;
  209. rst.打印页面_信息.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
  210. rst.打印页面_信息.页边距 = rptTpl.主信息.页边距;
  211. rst.items = [];
  212. //初始化band(每个大板块的属性)
  213. let bands = JpcBand.createNew(rptTpl, defProperties);
  214. try {
  215. for (let page = startPage; page <= endPage; page++) {
  216. me.runTimePageData.currentPage = page;
  217. me.executeFormulas('before_output', rptTpl, dataObj, me);
  218. console.log('=======================');
  219. rst.items.push(me.outputAsSimpleJSONPage(rptTpl, dataObj, bands, page, rst.control_collection, customizeCfg));
  220. }
  221. if (bands.MergeBand) {
  222. let band = bands.MergeBand;
  223. let mergedBand: IMergeBand = {
  224. Left : parseInt(band.Left.toFixed(0)),
  225. Right: parseInt(band.Right.toFixed(0)),
  226. Top : parseInt(band.Top.toFixed(0)),
  227. Bottom : parseInt(band.Bottom.toFixed(0)),
  228. style : band.style,
  229. };
  230. rst.MergeBand = mergedBand;
  231. }
  232. } catch (exception) {
  233. console.log(exception);
  234. } finally {
  235. bands = null;
  236. }
  237. }
  238. return rst;
  239. };
  240. outputAsSimpleJSONPage(rptTpl: IRptTpl, dataObj: IDataObj, bands: IBands, page: number, controls: IControlCollection, customizeCfg: ICustomizeCfg) {
  241. let me = this, rst: any = null;
  242. function getPageMergeBorder() {
  243. // let mergeRst = null;
  244. let mergeRst = {} as IMergeBand;
  245. if (bands.MergeBand) {
  246. let mergedBand = bands.MergeBand;
  247. mergeRst.Left = parseInt(mergedBand.Left.toFixed(0));
  248. mergeRst.Right = parseInt(mergedBand.Right.toFixed(0));
  249. mergeRst.Top = parseInt(mergedBand.Top.toFixed(0));
  250. mergeRst.Bottom = parseInt(mergedBand.Bottom.toFixed(0));
  251. }
  252. return mergeRst;
  253. // return false;
  254. }
  255. if (me.totalPages >= page) {
  256. rst = {};
  257. rst.page_seq = page;
  258. //rst.cells = [];
  259. let adHocMergePos: any = null;
  260. if (me.flowTab) {
  261. if (me.totalPages - me.exTotalPages >= page) {
  262. if (me.flowTab.paging_option === JV.PAGING_OPTION_INFINITY) {
  263. adHocMergePos = {};
  264. }
  265. rst.cells = me.flowTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, adHocMergePos, me, customizeCfg);
  266. if (adHocMergePos) {
  267. adHocMergePos.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
  268. rst.page_merge_pos = adHocMergePos;
  269. }
  270. } else {
  271. if (!me.isFollowMode) {
  272. rst.cells = me.flowTabEx.outputAsSimpleJSONPage(rptTpl, dataObj, page - (me.totalPages - me.exTotalPages), bands, controls, adHocMergePos, me, customizeCfg);
  273. }
  274. }
  275. } else if (me.crossTab) {
  276. rst.cells = me.crossTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me, customizeCfg);
  277. } else if (me.billTab) {
  278. rst.cells = me.billTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me, customizeCfg);
  279. }
  280. if (!(me.flowTab && me.flowTab.paging_option === IPagingOption.infinity)) {
  281. let pageMergeBorder = getPageMergeBorder();
  282. if (pageMergeBorder) {
  283. rst.page_merge_border = pageMergeBorder;
  284. }
  285. }
  286. }
  287. return rst;
  288. };
  289. }
  290. //暂定
  291. const private_buildDftItems = (
  292. rptTpl: any,
  293. dftCollection: IControlSubCollection[] | IFontSubCollection[] | null,
  294. nodeName: string
  295. ) => {
  296. const rst: any = {};
  297. if (dftCollection) {
  298. for (let i = 0; i < dftCollection.length; i++) {
  299. const { ID, ...dftCollectionProps } = dftCollection[i];
  300. rst[dftCollection[i].ID] = { ...dftCollectionProps };
  301. }
  302. const propArray = (nodeName === 'control_collection') ? JV.CONTROL_PROPS : JV.FONT_PROPS;
  303. if (rptTpl && rptTpl[nodeName] && rptTpl[nodeName].length) {
  304. for (let i = 0; i < rptTpl[nodeName].length; i++) {
  305. const rptDftItem = rptTpl[nodeName][i];
  306. if (rst[rptDftItem.ID] === undefined) {
  307. const item: any = {};
  308. for (let j = 0; j < propArray.length; j++) {
  309. item[propArray[j]] = rptDftItem[propArray[j]];
  310. }
  311. rst[rptDftItem.ID] = item;
  312. }
  313. }
  314. }
  315. }
  316. return rst;
  317. }
  318. function private_buildDftControls(rptTpl: IRptTpl, dftControlCollection: IControlSubCollection[] | null) {
  319. return private_buildDftItems(rptTpl, dftControlCollection, 'control_collection');
  320. }
  321. function private_buildDftFonts(rptTpl: IRptTpl, dftFontCollection: IFontSubCollection[] | null) {
  322. return private_buildDftItems(rptTpl, dftFontCollection, 'font_collection');
  323. }
  324. function private_buildDftStyles(rptTpl: IRptTpl, dftStyleCollection: IStyles[] | null) {
  325. const rst: any = {};
  326. function private_CopyBorder(destItem: BorderStyle, srcItem: BorderStyle) {
  327. destItem.LineWeight = srcItem.LineWeight;
  328. destItem.DashStyle = srcItem.DashStyle;
  329. destItem.Color = srcItem.Color;
  330. }
  331. if (dftStyleCollection) {
  332. for (let i = 0; i < dftStyleCollection.length; i++) {
  333. const item: any = {};
  334. if (dftStyleCollection[i].border_style && dftStyleCollection[i].border_style.length > 0) {
  335. for (let j = 0; j < dftStyleCollection[i].border_style.length; j++) {
  336. const borderItem = {} as BorderStyle;
  337. private_CopyBorder(borderItem, dftStyleCollection[i].border_style[j]);
  338. item[dftStyleCollection[i].border_style[j].Position] = borderItem;
  339. }
  340. }
  341. rst[dftStyleCollection[i].ID] = item;
  342. }
  343. if (rptTpl && rptTpl.style_collection && rptTpl.style_collection.length > 0) {
  344. for (let i = 0; i < rptTpl.style_collection.length; i++) {
  345. const rptDftItem = rptTpl.style_collection[i];
  346. if (rst[rptDftItem.ID] === undefined) {
  347. if (rptDftItem.ID.indexOf('_AutoHeightMerge_Top') > 0) {
  348. const key = rptDftItem.ID.substr(0, rptDftItem.ID.indexOf('_AutoHeightMerge_Top'));
  349. if (rst[key]) {
  350. const item: any = {};
  351. if (rst[key].Left) {
  352. item.Left = {};
  353. private_CopyBorder(item.Left, rst[key].Left);
  354. }
  355. if (rst[key].Right) {
  356. item.Right = {};
  357. private_CopyBorder(item.Right, rst[key].Right);
  358. }
  359. if (rst[key].Top) {
  360. item.Top = {};
  361. private_CopyBorder(item.Top, rst[key].Top);
  362. }
  363. rst[rptDftItem.ID] = item;
  364. }
  365. } else if (rptDftItem.ID.indexOf('_AutoHeightMerge_Middle') > 0) {
  366. const key = rptDftItem.ID.substr(0, rptDftItem.ID.indexOf('_AutoHeightMerge_Middle'));
  367. if (rst[key]) {
  368. const item: any = {};
  369. if (rst[key].Left) {
  370. item.Left = {};
  371. private_CopyBorder(item.Left, rst[key].Left);
  372. }
  373. if (rst[key].Right) {
  374. item.Right = {};
  375. private_CopyBorder(item.Right, rst[key].Right);
  376. }
  377. rst[rptDftItem.ID] = item;
  378. }
  379. } else if (rptDftItem.ID.indexOf('_AutoHeightMerge_Bottom') > 0) {
  380. const key = rptDftItem.ID.substr(0, rptDftItem.ID.indexOf('_AutoHeightMerge_Bottom'));
  381. if (rst[key]) {
  382. const item: any = {};
  383. if (rst[key].Left) {
  384. item.Left = {};
  385. private_CopyBorder(item.Left, rst[key].Left);
  386. }
  387. if (rst[key].Right) {
  388. item.Right = {};
  389. private_CopyBorder(item.Right, rst[key].Right);
  390. }
  391. if (rst[key].Bottom) {
  392. item.Bottom = {};
  393. private_CopyBorder(item.Bottom, rst[key].Bottom);
  394. }
  395. rst[rptDftItem.ID] = item;
  396. }
  397. } else {
  398. const item: any = {};
  399. for (let j = 0; j < rptDftItem.border_style.length; j++) {
  400. const borderItem = {} as BorderStyle;
  401. private_CopyBorder(borderItem, rptDftItem.border_style[j]);
  402. item[rptDftItem.border_style[j].Position] = borderItem;
  403. }
  404. rst[rptDftItem.ID] = item;
  405. }
  406. }
  407. }
  408. }
  409. }
  410. return rst;
  411. }
  412. export default JpcExClass;