y-admin-ui 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,997 @@
1
+ /** 打印插件 */
2
+
3
+ export interface PrintThisOptions {
4
+ hide?: Array<string> | string;
5
+ horizontal?: boolean | string | null | undefined;
6
+ iePreview?: boolean;
7
+ blank?: boolean;
8
+ close?: boolean;
9
+ margin?: string | number | null | undefined;
10
+ title?: string;
11
+ isHideNone?: boolean;
12
+ }
13
+
14
+ export interface PrintHtmlOptions {
15
+ html?: string;
16
+ print?: boolean;
17
+ loading?: boolean;
18
+ header?: string;
19
+ footer?: string;
20
+ before?: Function;
21
+ done?: Function;
22
+ style?: string;
23
+ }
24
+
25
+ export interface PrintHtmlOptionsExtends extends PrintThisOptions {
26
+ html?: string;
27
+ print?: boolean;
28
+ loading?: boolean;
29
+ header?: string;
30
+ footer?: string;
31
+ before?: Function;
32
+ done?: Function;
33
+ style?: string;
34
+ }
35
+
36
+ export interface PrintPageOptionsExtends extends PrintHtmlOptionsExtends {
37
+ htmls?: Array<string>;
38
+ pages?: Array<string>;
39
+ style?: string;
40
+ padding?: string;
41
+ isDebug?: boolean;
42
+ width?: string;
43
+ height?: string;
44
+ }
45
+
46
+ export interface makeTableCols {
47
+ field?: string;
48
+ title?: string;
49
+ width?: number | string;
50
+ align?: string;
51
+ thAlign?: string;
52
+ colspan?: number;
53
+ rowspan?: number;
54
+ style?: string;
55
+ thStyle?: string;
56
+ templet?: Function;
57
+ [key : string]: any;
58
+ }
59
+
60
+
61
+ /**
62
+ * ie 打印预览控件
63
+ */
64
+ const ieWebBrowser =
65
+ '<object id="WebBrowser" classid="clsid:8856F961-340A-11D0-A96B-00C04FD705A2" width="0" height="0"></object>';
66
+
67
+ /**
68
+ * iframe 打印窗口的 id
69
+ */
70
+ const printFrameId = 'y-printer-frame';
71
+
72
+ /**
73
+ * 打印全局样式的 style 的 id
74
+ */
75
+ const printStyleId = 'y-printer-style';
76
+
77
+ /**
78
+ * 打印方向设置的 style 的 id
79
+ */
80
+ const printOptionId = 'y-printer-set';
81
+
82
+ /**
83
+ * 加载层 id
84
+ */
85
+ const loadingElId = 'y-printer-loading';
86
+
87
+ /**
88
+ * 正在打印标识的 class
89
+ */
90
+ const printingClass = 'y-printer-printing';
91
+
92
+ /**
93
+ * 打印时隐藏的 class
94
+ */
95
+ const hideClass = 'y-printer-hide';
96
+
97
+ /**
98
+ * 打印时隐藏不占位置的 class
99
+ */
100
+ const hideNoneClass = 'y-printer-hide-none';
101
+
102
+ /**
103
+ * 生成随机 id
104
+ * @param length 长度
105
+ */
106
+ function uuid(length = 8) {
107
+ const num = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
108
+ let str = 'p_';
109
+ for (let i = 0; i < length; i++) {
110
+ str += num.charAt(Math.floor(Math.random() * num.length));
111
+ }
112
+ return str;
113
+ }
114
+
115
+ /**
116
+ * 是否是 ie
117
+ */
118
+ function isIE() {
119
+ return !!window['ActiveXObject'] || 'ActiveXObject' in window;
120
+ }
121
+
122
+ /**
123
+ * 获取的打印 iframe
124
+ */
125
+ function getPrintFrame() {
126
+ const pFrame = document.getElementById(printFrameId);
127
+ if (pFrame && pFrame.parentNode) {
128
+ pFrame.parentNode.removeChild(pFrame);
129
+ }
130
+ const elem = document.createElement('iframe');
131
+ elem.id = printFrameId;
132
+ elem.style.width = '0px';
133
+ elem.style.height = '0px';
134
+ elem.style.position = 'fixed';
135
+ elem.style.visibility = 'hidden';
136
+ document.body.appendChild(elem);
137
+ elem.focus();
138
+ return elem;
139
+ }
140
+
141
+ /**
142
+ * 获取打印全局样式
143
+ * @param isPrinting 是否已开始打印
144
+ */
145
+ function getCommonCss(isPrinting = false) {
146
+ return `
147
+ @media print {
148
+ html, body {
149
+ padding: 0;
150
+ margin: 0;
151
+ }
152
+
153
+ ::-webkit-scrollbar {
154
+ width: 0 !important;
155
+ height: 0!important;
156
+ }
157
+
158
+ .el-scrollbar__wrap {
159
+ margin: 0 !important;
160
+ }
161
+ }
162
+
163
+ /* 打印时不显示的元素 */
164
+ .${hideClass}.${printingClass} {
165
+ visibility: hidden !important;
166
+ }
167
+ .${hideClass} {
168
+ ${isPrinting ? 'visibility: hidden !important;' : ''}
169
+ }
170
+ .${hideClass}.${printingClass}.${hideNoneClass},
171
+ .${hideClass}.${hideNoneClass}${isPrinting ? '' : '-no'} {
172
+ display: none !important;
173
+ }
174
+
175
+ /* 表格样式 */
176
+ .y-printer-table {
177
+ width: 100%;
178
+ border-collapse: collapse;
179
+ border: none;
180
+ }
181
+ .y-printer-table td, .y-printer-table th {
182
+ color: #333;
183
+ padding: 9px 15px;
184
+ border: 1px solid #333;
185
+ word-break: break-all;
186
+ }
187
+
188
+ /* loading样式 */
189
+ #${loadingElId} {
190
+ position: fixed;
191
+ top: 0;
192
+ left: 0;
193
+ right: 0;
194
+ bottom: 0;
195
+ background-color: hsla(0, 0%, 100%, .9);
196
+ z-index: 19000000;
197
+ }
198
+ #${loadingElId}:after {
199
+ content: "";
200
+ width: 40px;
201
+ height: 40px;
202
+ position: absolute;
203
+ top: 50%;
204
+ left: 50%;
205
+ margin: -20px auto auto -20px;
206
+ border: 2px solid #3296FA;
207
+ border-right-color: transparent;
208
+ border-bottom-color: transparent;
209
+ border-radius: 50%;
210
+ animation: ele-printer-loading-anim .8s linear infinite;
211
+ }
212
+ @keyframes ele-printer-loading-anim {
213
+ from {
214
+ transform: rotate(0deg);
215
+ }
216
+ to {
217
+ transform: rotate(360deg);
218
+ }
219
+ }
220
+
221
+ /* 带页眉页脚页面样式 */
222
+ .y-printer-table-page {
223
+ width: 100%;
224
+ border-collapse: collapse;
225
+ border: none;
226
+ }
227
+ .y-printer-table-page td {
228
+ padding: 0;
229
+ border: none;
230
+ }
231
+ `;
232
+ }
233
+
234
+ /**
235
+ * 获取分页打印的样式
236
+ * @param padding 每一页边距
237
+ * @param width 每一页宽度
238
+ * @param height 每一页高度
239
+ */
240
+ function getPageStyleHtml(padding: any, width: any, height: any) {
241
+ return `
242
+ <style>
243
+ body {
244
+ margin: 0 !important;
245
+ }
246
+
247
+ /* 自定义边距及宽高样式 */
248
+ .ele-printer-page .ele-printer-page-item {
249
+ width: ${width ?? 'auto'};
250
+ height: ${height ?? 'auto'};
251
+ padding: ${padding ?? '0'};
252
+ page-break-after: always !important;
253
+ box-sizing: border-box !important;
254
+ border: none !important;
255
+ position: relative;
256
+ }
257
+
258
+ /* 调试模式样式 */
259
+ .ele-printer-page.ele-printer-debug .ele-printer-page-item {
260
+ border: 1px solid red !important;
261
+ }
262
+
263
+ /* 全局样式 */
264
+ ${getCommonCss(true)}
265
+ </style>
266
+ `;
267
+ }
268
+
269
+ /**
270
+ * 生成控制打印的 html
271
+ * @param option PrintHtmlOption
272
+ */
273
+ function getOptionHtml(option: PrintPageOptionsExtends) {
274
+ const { beforeJs, doneJs } = addCallback(option.before, option.done);
275
+ const blank = option.blank || (option.iePreview !== false && isIE());
276
+ const closeJs = blank && option.close !== false ? 'window.close();' : '';
277
+ const hideLoadJs =
278
+ 'parent.hideElePrinterLoading&&parent.hideElePrinterLoading();';
279
+ const optHtml = [];
280
+
281
+ // 增加打印设置的 css
282
+ optHtml.push(`<style type="text/css" media="print" id="${printOptionId}">`);
283
+ optHtml.push('@page {');
284
+ // 打印方向
285
+ if (typeof option.horizontal !== 'undefined') {
286
+ optHtml.push(`size: ${option.horizontal ? 'landscape' : 'portrait'};`);
287
+ }
288
+ // 页间距
289
+ if (option.margin != null) {
290
+ optHtml.push(`margin: ${option.margin};`);
291
+ }
292
+ optHtml.push(`}`);
293
+ optHtml.push(`</style>`);
294
+
295
+ // 增加打印和回调的 js
296
+ if (option.iePreview !== false && isIE()) {
297
+ // 兼容 ie 打印预览
298
+ optHtml.push(ieWebBrowser);
299
+ if (option.print !== false) {
300
+ optHtml.push(`
301
+ <script>
302
+ window.onload = function() {
303
+ ${beforeJs}
304
+ try {
305
+ window.WebBrowser.ExecWB(7, 1);
306
+ } catch(e) {
307
+ console.error(e);
308
+ window.print();
309
+ }
310
+ ${hideLoadJs}
311
+ ${doneJs}
312
+ ${closeJs}
313
+ }
314
+ </script>
315
+ `);
316
+ }
317
+ } else if (option.print !== false) {
318
+ optHtml.push(`
319
+ <script>
320
+ window.onload = function() {
321
+ ${beforeJs}
322
+ window.print();
323
+ ${hideLoadJs}
324
+ ${doneJs}
325
+ ${closeJs}
326
+ }
327
+ </script>
328
+ `);
329
+ }
330
+ return optHtml.join('');
331
+ }
332
+
333
+ /**
334
+ * 加入核心样式
335
+ */
336
+ function addCommonCss() {
337
+ if (!document.getElementById(printStyleId)) {
338
+ const elem = document.createElement('style');
339
+ elem.id = printStyleId;
340
+ elem.setAttribute('type', 'text/css');
341
+ elem.innerHTML = getCommonCss();
342
+ document.body.appendChild(elem);
343
+ }
344
+ }
345
+
346
+ /**
347
+ * 增加页眉页脚
348
+ * @param html 页面内容
349
+ * @param header 页眉
350
+ * @param footer 页脚
351
+ */
352
+ function addHeaderFooter(html: string, header: string | undefined, footer: string | undefined) {
353
+ if (!header && !footer) {
354
+ return html ?? '';
355
+ }
356
+ let result = '<table class="y-printer-table-page">';
357
+ if (header) {
358
+ result += `<thead><tr><td>${header}</td></tr></thead>`;
359
+ }
360
+ result += `<tbody><tr><td>${html ?? ''}</td></tr></tbody>`;
361
+ if (footer) {
362
+ result += `<tfoot><tr><td>${footer}</td></tr></tfoot>`;
363
+ }
364
+ return result + '</table>';
365
+ }
366
+
367
+ /**
368
+ * 添加回调监听
369
+ * @param before 打印前回调
370
+ * @param done 打印后回调
371
+ */
372
+ function addCallback(before: any, done: any) {
373
+ const taskId = 'p' + uuid();
374
+ if (!window['yPrinterBefore']) {
375
+ window['yPrinterBefore'] = {};
376
+ }
377
+ if (!window['yPrinterDone']) {
378
+ window['yPrinterDone'] = {};
379
+ }
380
+ if (before) {
381
+ window['yPrinterBefore'][taskId] = before;
382
+ }
383
+ if (done) {
384
+ window['yPrinterDone'][taskId] = done;
385
+ }
386
+ const beforeJs = `;parent.elePrinterBefore&&parent.elePrinterBefore.${taskId}&&parent.elePrinterBefore.${taskId}();`;
387
+ const doneJs = `;parent.elePrinterDone&&parent.elePrinterDone.${taskId}&&parent.elePrinterDone.${taskId}();`;
388
+ return { taskId, beforeJs, doneJs };
389
+ }
390
+
391
+ /**
392
+ * 隐藏元素
393
+ * @param elems 需要隐藏的元素
394
+ * @param isNone 是否是隐藏不占位置
395
+ */
396
+ function hideElem(elems: Array<string> | string, isNone: boolean) {
397
+ Array.prototype.forEach.call(
398
+ document.getElementsByClassName(hideClass),
399
+ (elem) => {
400
+ if (elem?.classList) {
401
+ elem.classList.add(printingClass);
402
+ }
403
+ }
404
+ );
405
+ if (!elems) {
406
+ return;
407
+ }
408
+ const isArray =
409
+ Array?.isArray(elems) ||
410
+ // eslint-disable-next-line no-prototype-builtins
411
+ NodeList?.prototype?.isPrototypeOf(elems) ||
412
+ // eslint-disable-next-line no-prototype-builtins
413
+ HTMLCollection?.prototype?.isPrototypeOf(elems);
414
+ Array.prototype.forEach.call(isArray ? elems : [elems], (elem) => {
415
+ if (typeof elem === 'string') {
416
+ Array.prototype.forEach.call(document.querySelectorAll(elem), (el) => {
417
+ if (el?.classList) {
418
+ el.classList.add(hideClass);
419
+ el.classList.add(printingClass);
420
+ if (isNone) {
421
+ el.classList.add(hideNoneClass);
422
+ }
423
+ }
424
+ });
425
+ } else if (elem?.classList) {
426
+ elem.classList.add(hideClass);
427
+ elem.classList.add(printingClass);
428
+ if (isNone) {
429
+ elem.classList.add(hideNoneClass);
430
+ }
431
+ }
432
+ });
433
+ }
434
+
435
+ /**
436
+ * 取消隐藏元素
437
+ * @param elems 需要取消隐藏的元素
438
+ */
439
+ function showElem(elems: string | Object) {
440
+ Array.prototype.forEach.call(
441
+ document.getElementsByClassName(hideClass),
442
+ (elem) => {
443
+ if (elem?.classList) {
444
+ elem.classList.remove(printingClass);
445
+ }
446
+ }
447
+ );
448
+ if (!elems) {
449
+ return;
450
+ }
451
+ const isArray =
452
+ Array?.isArray(elems) ||
453
+ // eslint-disable-next-line no-prototype-builtins
454
+ NodeList?.prototype?.isPrototypeOf(elems) ||
455
+ // eslint-disable-next-line no-prototype-builtins
456
+ HTMLCollection?.prototype?.isPrototypeOf(elems);
457
+ Array.prototype.forEach.call(isArray ? elems : [elems], (elem) => {
458
+ if (typeof elem === 'string') {
459
+ Array.prototype.forEach.call(document.querySelectorAll(elem), (el) => {
460
+ if (el?.classList) {
461
+ el.classList.remove(hideClass);
462
+ el.classList.remove(printingClass);
463
+ el.classList.remove(hideNoneClass);
464
+ }
465
+ });
466
+ } else if (elem?.classList) {
467
+ elem.classList.remove(hideClass);
468
+ elem.classList.remove(printingClass);
469
+ elem.classList.remove(hideNoneClass);
470
+ }
471
+ });
472
+ }
473
+
474
+ /**
475
+ * 显示加载层
476
+ */
477
+ export function showPrintLoading() {
478
+ addCommonCss();
479
+ let elem = document.getElementById(loadingElId);
480
+ if (!elem) {
481
+ elem = document.createElement('div');
482
+ elem.id = loadingElId;
483
+ document.body.appendChild(elem);
484
+ }
485
+ elem.style.display = 'block';
486
+ window['hideElePrinterLoading'] = () => {
487
+ hidePrintLoading();
488
+ };
489
+ return elem;
490
+ }
491
+
492
+ /**
493
+ * 关闭加载层
494
+ */
495
+ export function hidePrintLoading() {
496
+ const elem = document.getElementById(loadingElId);
497
+ if (elem) {
498
+ elem.style.display = 'none';
499
+ }
500
+ }
501
+
502
+ /**
503
+ * 打印当前页面
504
+ * @param hide 需要隐藏的元素
505
+ * @param horizontal 是否横向打印
506
+ * @param iePreview 是否支持ie打印预览
507
+ * @param blank 是否在新窗口打印
508
+ * @param close 如果在新窗口打印,打印完是否关闭新窗口
509
+ * @param margin 页间距
510
+ * @param title 页面标题
511
+ *
512
+ */
513
+ export function printThis(
514
+ {
515
+ hide = '',
516
+ horizontal = false,
517
+ iePreview = true,
518
+ blank = false,
519
+ close = true,
520
+ margin = 0,
521
+ title,
522
+ isHideNone
523
+ }: PrintThisOptions
524
+ ) {
525
+ // 让当前窗口获取焦点
526
+ window.focus();
527
+
528
+ // 加入打印全局样式
529
+ addCommonCss();
530
+
531
+ // 增加打印设置的 css
532
+ const optElem = document.getElementById(printOptionId);
533
+ if (optElem && optElem.parentNode) {
534
+ optElem.parentNode.removeChild(optElem);
535
+ }
536
+ const optStr = [];
537
+ // 打印方向设置
538
+ if (typeof horizontal === 'boolean') {
539
+ optStr.push(`size: ${horizontal ? 'landscape' : 'portrait'};`);
540
+ }
541
+ // 页间距设置
542
+ if (margin != null) {
543
+ optStr.push(`margin: ${margin};`);
544
+ }
545
+ if (optStr) {
546
+ const elem = document.createElement('style');
547
+ elem.id = printOptionId;
548
+ elem.setAttribute('type', 'text/css');
549
+ elem.setAttribute('media', 'print');
550
+ elem.innerHTML = `@page { ${optStr.join('')} }`;
551
+ document.body.appendChild(elem);
552
+ }
553
+
554
+ // 隐藏打印时需要隐藏的内容
555
+ hideElem(hide, isHideNone);
556
+
557
+ // 设置窗口标题
558
+ const oldTitle = document.title;
559
+ if (title) {
560
+ document.title = title;
561
+ }
562
+
563
+ let pWin;
564
+ if (!blank) {
565
+ // 当前窗口打印
566
+ pWin = window;
567
+ if (iePreview !== false && isIE()) {
568
+ if (!document.getElementById('WebBrowser')) {
569
+ const elem = document.createElement('object');
570
+ elem.id = 'WebBrowser';
571
+ elem.setAttribute(
572
+ 'classid',
573
+ 'clsid:8856F961-340A-11D0-A96B-00C04FD705A2'
574
+ );
575
+ elem.style.display = 'none';
576
+ document.body.appendChild(elem);
577
+ }
578
+ try {
579
+ window['WebBrowser'].ExecWB(7, 1);
580
+ } catch (e) {
581
+ pWin.print();
582
+ }
583
+ } else {
584
+ pWin.print();
585
+ }
586
+ } else {
587
+ // 新窗口打印
588
+ pWin = window.open('', '_blank');
589
+ if (pWin) {
590
+ pWin.focus();
591
+ // 写入内容到打印窗口
592
+ const pDoc = pWin.document;
593
+ if (pDoc) {
594
+ pDoc.open();
595
+ let html =
596
+ '<!DOCTYPE html>' +
597
+ document.getElementsByTagName('html')[0]?.outerHTML;
598
+ // 去除js
599
+ html = html
600
+ .replace(/<script/g, '<div style="display:none;" ')
601
+ .replace(/<\/script>/g, '</div>');
602
+
603
+ const addHtml = function (str: string) {
604
+ html = html.replace(/<\/html>/, `${str}</html>`);
605
+ };
606
+
607
+ if (iePreview !== false && isIE()) {
608
+ if (!document.getElementById('WebBrowser')) {
609
+ addHtml(ieWebBrowser);
610
+ }
611
+ addHtml(`
612
+ <script>
613
+ window.onload = function() {
614
+ try {
615
+ window.WebBrowser.ExecWB(7,1);
616
+ } catch(e) {
617
+ console.error(e);
618
+ window.print();
619
+ }
620
+ ${close !== false ? 'window.close();' : ''}
621
+ }
622
+ </script>
623
+ `);
624
+ } else {
625
+ addHtml(`
626
+ <script>
627
+ window.onload = function() {
628
+ window.print();
629
+ ${close !== false ? 'window.close();' : ''}
630
+ }
631
+ </script>
632
+ `);
633
+ }
634
+
635
+ pDoc.write(html);
636
+ pDoc.close();
637
+ }
638
+ }
639
+ }
640
+
641
+ // 恢复窗口标题
642
+ if (title) {
643
+ document.title = oldTitle;
644
+ }
645
+
646
+ // 恢复隐藏的内容
647
+ showElem(hide);
648
+
649
+ return pWin;
650
+ }
651
+
652
+ /**
653
+ * 打印任意内容
654
+ * @param option PrintHtmlOption
655
+ * @param 参数说明,都是可选参数,此外还支持 printThis 的所有参数
656
+ * @param html 要打印内容 String
657
+ * @param print 是否立即打印 Boolean
658
+ * @param loading 是否显示加载层 Boolean
659
+ * @param header 页眉 String
660
+ * @param footer 页脚 String
661
+ * @param before Function 打印开始的回调
662
+ * @param done Function 打印完成的回调
663
+ * @param style String 打印的自定义样式
664
+ */
665
+ export function printHtml(option: PrintHtmlOptionsExtends) {
666
+ if (option.loading !== false && option.blank !== true) {
667
+ showPrintLoading();
668
+ }
669
+
670
+ // 创建打印窗口
671
+ let pWin, pDoc;
672
+ if (option.blank || (option.iePreview !== false && isIE())) {
673
+ // 新窗口打印
674
+ pWin = window.open('', '_blank');
675
+ pDoc = pWin?.document;
676
+ } else {
677
+ // 当前窗口打印
678
+ const pFrame = getPrintFrame();
679
+ pWin = pFrame.contentWindow;
680
+ pDoc = pFrame.contentDocument || pWin?.document;
681
+ }
682
+
683
+ if (pWin) {
684
+ // 让打印窗口获取焦点
685
+ pWin.focus();
686
+ // 写入内容到打印窗口
687
+ if (pDoc && option.html) {
688
+ pDoc.open();
689
+ pDoc.write(`
690
+ <!DOCTYPE html>
691
+ <head>
692
+ <meta charset="UTF-8"/>
693
+ <title>${option.title ?? ''}</title>
694
+ <style>
695
+ ${getCommonCss(true)}
696
+ </style>
697
+ ${option.style ?? ''}
698
+ </head>
699
+ <html>
700
+ <body>
701
+ ${addHeaderFooter(option.html, option.header, option.footer)}
702
+ ${getOptionHtml(option)}
703
+ </body>
704
+ </html>
705
+ `);
706
+ pDoc.close();
707
+ }
708
+ }
709
+ return pWin;
710
+ }
711
+
712
+ /**
713
+ * 分页打印
714
+ * @param option PrintPageOption
715
+ */
716
+ export function printPage(option: PrintPageOptionsExtends) {
717
+ if (option.loading !== false && option.blank !== true) {
718
+ showPrintLoading();
719
+ }
720
+
721
+ // 创建打印窗口
722
+ let pWin, pDoc;
723
+ if (option.blank || (option.iePreview !== false && isIE())) {
724
+ // 新窗口打印
725
+ pWin = window.open('', '_blank');
726
+ pDoc = pWin?.document;
727
+ } else {
728
+ // 当前窗口打印
729
+ const pFrame = getPrintFrame();
730
+ pWin = pFrame.contentWindow;
731
+ pDoc = pFrame.contentDocument || pWin?.document;
732
+ }
733
+
734
+ if (pWin && pDoc) {
735
+ // 让打印窗口获取焦点
736
+ pWin.focus();
737
+ // 写入内容到打印窗口
738
+ const content =
739
+ (option.pages ?? option.htmls)
740
+ ?.map((h) => `<div class="ele-printer-page-item">${h}</div>`)
741
+ .join('') ?? '';
742
+ const pageClass =
743
+ 'ele-printer-page' + (option.isDebug ? ' ele-printer-debug' : '');
744
+ const contentHtml = `<div class="${pageClass}">${content}</div>`;
745
+ pDoc.open();
746
+ pDoc.write(`
747
+ <!DOCTYPE html>
748
+ <html>
749
+ <head>
750
+ <meta charset="UTF-8"/>
751
+ <title>${option.title ?? ''}</title>
752
+ ${getPageStyleHtml(option.padding, option.width, option.height)}
753
+ ${option.style ?? ''}
754
+ </head>
755
+ <body>
756
+ ${addHeaderFooter(contentHtml, option.header, option.footer)}
757
+ ${getOptionHtml(option)}
758
+ </body>
759
+ </html>
760
+ `);
761
+ pDoc.close();
762
+ }
763
+ return pWin;
764
+ }
765
+
766
+ /**
767
+ * 打印 pdf
768
+ * @param option PrintPdfOption
769
+ */
770
+ export function printPdf(option: any) {
771
+ if (option.loading !== false) {
772
+ showPrintLoading();
773
+ }
774
+ const pFrame = getPrintFrame();
775
+ const pWin = pFrame.contentWindow;
776
+ pFrame.onload = () => {
777
+ if (!pFrame.getAttribute('src')) {
778
+ return;
779
+ }
780
+ pFrame.focus();
781
+ option.before && option.before();
782
+ pWin?.print();
783
+ hidePrintLoading();
784
+ option.done && option.done();
785
+ };
786
+
787
+ // 开始打印
788
+ function doPrint(arraybuffer: BlobPart) {
789
+ const localPdf = new window.Blob([arraybuffer], {
790
+ type: 'application/pdf'
791
+ });
792
+ // 兼容 IE
793
+ if (window.navigator && window.navigator['msSaveOrOpenBlob']) {
794
+ window.navigator['msSaveOrOpenBlob'](localPdf, 'print.pdf');
795
+ hidePrintLoading();
796
+ } else {
797
+ pFrame.setAttribute('src', window.URL.createObjectURL(localPdf));
798
+ }
799
+ }
800
+
801
+ // 请求 pdf 数据
802
+ if (option.arraybuffer) {
803
+ doPrint(option.arraybuffer);
804
+ } else if (option.url) {
805
+ const req = new window.XMLHttpRequest();
806
+ req.open('GET', option.url, true);
807
+ req.responseType = 'arraybuffer';
808
+ req.onload = () => {
809
+ if ([200, 201].indexOf(req.status) === -1) {
810
+ return option.error && option.error(req.status, req.statusText);
811
+ }
812
+ doPrint(req.response);
813
+ };
814
+ req.send();
815
+ }
816
+ return pWin;
817
+ }
818
+
819
+ /**
820
+ * 生成表格 html
821
+ * @param data 数据
822
+ * @param cols 列配置
823
+ * @param thead 是否需要表头
824
+ */
825
+ export function makeTable(data: Array<any>, cols: makeTableCols, thead = true) {
826
+ // 恢复 cols 参数初始状态
827
+ cols.forEach((col: any[]) => {
828
+ col.forEach((c) => {
829
+ c.INIT_OK = void 0;
830
+ c.key = void 0;
831
+ c.colGroup = void 0;
832
+ c.HAS_PARENT = void 0;
833
+ c.parentKey = void 0;
834
+ c.PARENT_COL_INDEX = void 0;
835
+ });
836
+ });
837
+
838
+ // cols 转为嵌套结构
839
+ const colArrays: any[] = [];
840
+ let colIndex = 0;
841
+ for (let i1 = 0; i1 < cols.length; i1++) {
842
+ const item1 = cols[i1];
843
+ for (let i2 = 0; i2 < item1.length; i2++) {
844
+ const item2 = item1[i2];
845
+ if (!item2) {
846
+ item1.splice(i2, 1);
847
+ continue;
848
+ }
849
+ // 合并单元格处理
850
+ item2.key = i1 + '-' + i2;
851
+ let CHILD_COLS = null;
852
+ if (item2.colGroup || (item2.colspan && item2.colspan > 1)) {
853
+ item2.colGroup = true;
854
+ CHILD_COLS = [];
855
+ colIndex++;
856
+ let childIndex = 0;
857
+ for (let i22 = 0; i22 < cols[i1 + 1].length; i22++) {
858
+ const item22 = { ...cols[i1 + 1][i22] };
859
+ if (
860
+ item22.HAS_PARENT ||
861
+ (childIndex > 1 && childIndex == item2.colspan)
862
+ ) {
863
+ cols[i1 + 1][i22] = item22;
864
+ continue;
865
+ }
866
+ item22.HAS_PARENT = true;
867
+ item22.parentKey = i1 + '-' + i2;
868
+ item22.key = i1 + 1 + '-' + i22;
869
+ item22.PARENT_COL_INDEX = colIndex;
870
+ CHILD_COLS.push(item22);
871
+ childIndex =
872
+ childIndex +
873
+ Number(item22.colspan && item22.colspan > 1 ? item22.colspan : 1);
874
+ cols[i1 + 1][i22] = item22;
875
+ }
876
+ }
877
+ item2.CHILD_COLS = CHILD_COLS;
878
+ if (!item2.PARENT_COL_INDEX) {
879
+ colArrays.push(item2);
880
+ }
881
+ cols[i1][i2] = item2;
882
+ }
883
+ }
884
+
885
+ // 遍历嵌套结构 cols 的方法
886
+ const eachCols = function (callback: Function, arr: Array<any>) {
887
+ if (!arr) {
888
+ arr = colArrays;
889
+ }
890
+ for (let i = 0; i < arr.length; i++) {
891
+ const item = arr[i];
892
+ callback && callback(i, item);
893
+ if (item.CHILD_COLS) {
894
+ eachCols(callback, item.CHILD_COLS);
895
+ }
896
+ }
897
+ };
898
+
899
+ // 计算表格宽度
900
+ let maxWidth = 1;
901
+ let needSetWidth = true;
902
+ const colgroupHtml = [] as any;
903
+ eachCols((_i: any, c: any) => {
904
+ if (!c.colGroup) {
905
+ colgroupHtml.push('<col');
906
+ if (c.width) {
907
+ colgroupHtml.push(` width="${c.width}"`);
908
+ }
909
+ colgroupHtml.push('/>');
910
+ if (c.width && !/\d+%$/.test(String(c.width))) {
911
+ maxWidth += c.width + 1;
912
+ } else {
913
+ needSetWidth = false;
914
+ }
915
+ }
916
+ });
917
+
918
+ // 表头
919
+ const thHtml = cols
920
+ .map((cs) => {
921
+ const th = cs
922
+ .map((c) => {
923
+ return `<th
924
+ colspan="${c.colspan || 1}"
925
+ rowspan="${c.rowspan || 1}"
926
+ align="${c.thAlign || c.align || 'left'}"
927
+ style="${c.thStyle}">${c.title || ''}
928
+ </th>`;
929
+ })
930
+ .join('');
931
+ return '<tr>' + th + '</tr>';
932
+ })
933
+ .join('');
934
+ const headHtml = '<thead>' + thHtml + '</thead>';
935
+
936
+ // 主体
937
+ const trHtml = data
938
+ .map((d: any, index: any) => {
939
+ const tr = ['<tr>'];
940
+ let colIndex = 0;
941
+ eachCols((_i: any, c: any) => {
942
+ if (!c.colGroup) {
943
+ const value = c.field ? d[c.field] : '';
944
+ const content = c.templet ? c.templet(d, index, colIndex) : value;
945
+ const align = c.align || 'left';
946
+ tr.push(`<td align="${align}" style="${c.style}">${content}</td>`);
947
+ colIndex++;
948
+ }
949
+ });
950
+ tr.push('</tr>');
951
+ return tr.join('');
952
+ })
953
+ .join('');
954
+ const bodyHtml = '<tbody>' + trHtml + '</tbody>';
955
+
956
+ return `<table
957
+ style="width: ${needSetWidth ? maxWidth + 'px' : '100%'};"
958
+ class="y-printer-table">
959
+ <colgroup>${colgroupHtml.join('')}</colgroup>
960
+ ${thead ? headHtml : ''} ${bodyHtml}
961
+ </table>`;
962
+ }
963
+
964
+ /**
965
+ * 打印指定区域
966
+ * @param elem HTMLElement
967
+ * @param option 参数配置 支持 printThis 所有参数
968
+ */
969
+ export function printElement(elem: HTMLElement, option: PrintThisOptions) {
970
+ if (!elem) {
971
+ return null;
972
+ }
973
+ const bodyChilds = Array.prototype.filter.call(
974
+ document.body.children,
975
+ (el) => {
976
+ if (
977
+ typeof el?.tagName === 'string' &&
978
+ ['style', 'script', 'link'].includes(el.tagName.toLowerCase())
979
+ ) {
980
+ return false;
981
+ }
982
+ return true;
983
+ }
984
+ );
985
+ hideElem(bodyChilds, true);
986
+ const parntEl = elem.parentNode;
987
+ const nextEl = elem.nextElementSibling;
988
+ document.body.appendChild(elem);
989
+ const pWin = printThis(option);
990
+ if (nextEl) {
991
+ parntEl?.insertBefore(elem, nextEl);
992
+ } else {
993
+ parntEl?.appendChild(elem);
994
+ }
995
+ showElem(bodyChilds);
996
+ return pWin;
997
+ }