yh-hiprint 2.2.9 → 2.3.1

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.
@@ -1,766 +1,766 @@
1
- <template>
2
- <section class="hiprint-designer">
3
- <header class="hiprint-designer__header">
4
- <el-radio-group
5
- v-model="paperType"
6
- @change="setPaperHandler">
7
- <el-radio-button label="A3">A3</el-radio-button>
8
- <el-radio-button label="A4">A4</el-radio-button>
9
- <el-radio-button label="A5">A5</el-radio-button>
10
- <el-radio-button label="B3">B3</el-radio-button>
11
- <el-radio-button label="B4">B4</el-radio-button>
12
- <el-radio-button label="B5">B5</el-radio-button>
13
- <el-radio-button label="other">自定义</el-radio-button>
14
- </el-radio-group>
15
- <el-form
16
- inline
17
- v-if="paperType === 'other'">
18
- <el-form-item>
19
- <el-input
20
- v-model="paperWidth"
21
- type="number">
22
- <template #prepend>宽</template>
23
- <template #append>px</template>
24
- </el-input>
25
- </el-form-item>
26
- <el-form-item>
27
- <el-input
28
- v-model="paperHeight"
29
- type="number">
30
- <template #prepend>高</template>
31
- <template #append>px</template>
32
- </el-input>
33
- </el-form-item>
34
- <el-form-item>
35
- <el-button
36
- type="primary"
37
- @click="setPaperHandler('other')">
38
- 设置
39
- </el-button>
40
- </el-form-item>
41
- </el-form>
42
- <el-input
43
- class="percentage"
44
- readonly
45
- v-model="scalePercentage">
46
- <template #prepend>
47
- <el-button
48
- :disabled="!canZoomIn"
49
- @click="zoomIn">
50
- <i class="iconfont icon-zoom-out"></i>
51
- </el-button>
52
- </template>
53
- <template #append>
54
- <el-button
55
- :disabled="!canZoomOut"
56
- @click="zoomOut">
57
- <i class="iconfont icon-zoom-in"></i>
58
- </el-button>
59
- </template>
60
- </el-input>
61
- <el-select
62
- placeholder="请选择数据源"
63
- multiple
64
- v-model="formCode">
65
- <el-option
66
- v-for="d in dataSourceForm"
67
- :label="d.label"
68
- :value="d.value"></el-option>
69
- </el-select>
70
- <el-button
71
- type="primary"
72
- @click="previewPrint">
73
- <i class="iconfont icon-print"></i>
74
- 预览
75
- </el-button>
76
- <el-button
77
- type="primary"
78
- @click="saveConfig">
79
- <i class="iconfont icon-save"></i>
80
- 保存
81
- </el-button>
82
- <el-button
83
- type="danger"
84
- @click="clearPrint">
85
- <i class="iconfont icon-clear"></i>
86
- 清空
87
- </el-button>
88
- </header>
89
- <main class="hiprint-designer__main">
90
- <aside class="hiprint-designer__main_left">
91
- <el-scrollbar noresize>
92
- <div class="hiprint-designer_title">基础</div>
93
- <el-row>
94
- <el-col :span="8">
95
- <a
96
- class="ep-draggable-item"
97
- tid="defaultModule.text">
98
- <i class="iconfont icon-font-size"></i>
99
- <span>文本</span>
100
- </a>
101
- </el-col>
102
- <el-col :span="8">
103
- <a
104
- class="ep-draggable-item"
105
- tid="defaultModule.textVal">
106
- <i class="iconfont icon-font-size"></i>
107
- <span>值(文本)</span>
108
- </a>
109
- </el-col>
110
- <el-col :span="8">
111
- <a
112
- class="ep-draggable-item"
113
- tid="defaultModule.image">
114
- <i class="iconfont icon-image-fill"></i>
115
- <span>图片</span>
116
- </a>
117
- </el-col>
118
- <el-col :span="8">
119
- <a
120
- class="ep-draggable-item"
121
- tid="defaultModule.longText">
122
- <i class="iconfont icon-file-text"></i>
123
- <span>长文本</span>
124
- </a>
125
- </el-col>
126
- <el-col :span="8">
127
- <a
128
- class="ep-draggable-item"
129
- tid="defaultModule.table">
130
- <i class="iconfont icon-table"></i>
131
- <span>表格</span>
132
- </a>
133
- </el-col>
134
- <el-col :span="8">
135
- <a
136
- class="ep-draggable-item"
137
- tid="defaultModule.emptyTable">
138
- <i class="iconfont icon-layout"></i>
139
- <span>空白表格</span>
140
- </a>
141
- </el-col>
142
- <el-col :span="8">
143
- <a
144
- class="ep-draggable-item"
145
- tid="defaultModule.html">
146
- <i class="iconfont icon-HTML"></i>
147
- <span>html</span>
148
- </a>
149
- </el-col>
150
- <el-col :span="8">
151
- <a
152
- class="ep-draggable-item"
153
- tid="defaultModule.customText">
154
- <i class="iconfont icon-container-fill"></i>
155
- <span>自定义文本</span>
156
- </a>
157
- </el-col>
158
- <el-col :span="8">
159
- <a
160
- class="ep-draggable-item"
161
- tid="defaultModule.barcode">
162
- <i class="iconfont icon-barcode"></i>
163
- <span>条形码</span>
164
- </a>
165
- </el-col>
166
- <el-col :span="8">
167
- <a
168
- class="ep-draggable-item"
169
- tid="defaultModule.qrcode">
170
- <i class="iconfont icon-qrcode"></i>
171
- <span>二维码</span>
172
- </a>
173
- </el-col>
174
- </el-row>
175
- <div class="hiprint-designer_title">辅助</div>
176
- <el-row>
177
- <el-col :span="8">
178
- <a
179
- class="ep-draggable-item"
180
- tid="defaultModule.hline">
181
- <i class="iconfont icon-border-verticle"></i>
182
- <span>横线</span>
183
- </a>
184
- </el-col>
185
- <el-col :span="8">
186
- <a
187
- class="ep-draggable-item"
188
- tid="defaultModule.vline">
189
- <i class="iconfont icon-border-horizontal"></i>
190
- <span>竖线</span>
191
- </a>
192
- </el-col>
193
- <el-col :span="8">
194
- <a
195
- class="ep-draggable-item"
196
- tid="defaultModule.rect">
197
- <i class="iconfont icon-border"></i>
198
- <span>矩形</span>
199
- </a>
200
- </el-col>
201
- <el-col :span="8">
202
- <a
203
- class="ep-draggable-item"
204
- tid="defaultModule.oval">
205
- <i class="iconfont icon-round"></i>
206
- <span>椭圆</span>
207
- </a>
208
- </el-col>
209
- </el-row>
210
- </el-scrollbar>
211
- </aside>
212
- <section class="hiprint-designer__main_canvas">
213
- <el-scrollbar ref="canvasRef">
214
- <div id="hiprint-printTemplate"></div>
215
- </el-scrollbar>
216
- </section>
217
- <aside class="hiprint-designer__main_right">
218
- <div id="PrintElementOptionSetting"></div>
219
- <template v-if="currentElementObjColumns.length">
220
- <div class="hiprint-designer_title">表格字段设置</div>
221
- <el-form
222
- label-position="top"
223
- size="small">
224
- <el-form-item label="表数据选择">
225
- <template v-if="hasDataSource">
226
- <el-select
227
- v-model="listCode"
228
- @change="tableFieldChange">
229
- <el-option
230
- v-for="d in dataSourceList"
231
- :label="d.label"
232
- :value="d.value"></el-option>
233
- </el-select>
234
- </template>
235
- <template v-else>
236
- <el-input
237
- v-model="listCode"
238
- @change="tableFieldChange"></el-input>
239
- </template>
240
- </el-form-item>
241
- <el-row gutter="10">
242
- <el-col
243
- :span="12"
244
- v-for="col in currentElementObjColumns">
245
- <el-form-item :label="col.title">
246
- <template v-if="hasDataSource">
247
- <el-select v-model="col.field">
248
- <el-option
249
- v-for="d in listColumns"
250
- :value="d"></el-option>
251
- </el-select>
252
- </template>
253
- <template v-else>
254
- <el-input v-model="col.field"></el-input>
255
- </template>
256
- </el-form-item>
257
- </el-col>
258
- </el-row>
259
- <el-row gutter="10">
260
- <el-col :span="12">
261
- <el-button
262
- @click="tableColumnCancel"
263
- type="warning">
264
- 取消
265
- </el-button>
266
- </el-col>
267
- </el-row>
268
- </el-form>
269
- </template>
270
- </aside>
271
- </main>
272
- </section>
273
- <el-dialog v-model="previewShow">
274
- <div
275
- class="print-preview"
276
- v-html="previewHtml"></div>
277
- </el-dialog>
278
- </template>
279
- <script setup lang="ts">
280
- // @ts-nocheck
281
- import {onMounted, ref, onActivated, onDeactivated, computed, watch} from 'vue';
282
- import {hiprint, defaultElementTypeProvider, fontSize, scale, zIndex, panel, usePaper, useScale, useDataSource, jquery as $} from 'yh-hiprint';
283
- import {useRoute, onBeforeRouteUpdate} from 'vue-router';
284
- import {ElMessageBox, ElMessage} from 'element-plus';
285
- import axios from '@/libs/api.request';
286
-
287
- interface HiprintTemplate {
288
- setPaper: (width: number, height: number) => void;
289
- zoom: (scale: number) => void;
290
- getJson: () => any;
291
- clear: () => void;
292
- }
293
-
294
- const route = useRoute();
295
- const hiprintTemplate = ref<HiprintTemplate | null>(null);
296
-
297
- const {paperType, paperWidth, paperHeight, setPaper} = usePaper();
298
- function setPaperHandler(type) {
299
- setPaper(type, () => {
300
- hiprintTemplate.value?.setPaper(paperWidth.value, paperHeight.value);
301
- });
302
- }
303
-
304
- const canvasRef = ref();
305
- const {scaleValue, scalePercentage, canZoomIn, canZoomOut, zoomIn, zoomOut} = useScale(() => {
306
- hiprintTemplate.value?.zoom(scaleValue.value);
307
- canvasRef?.value.update();
308
- });
309
-
310
- const previewShow = ref(false);
311
- const previewHtml = ref('');
312
- async function previewPrint() {
313
- let {
314
- data: {list, json},
315
- } = await axios.request({
316
- url: `/printTemplate/data/${detailData.value.code}`,
317
- method: 'post',
318
- type: 'json',
319
- data: [
320
- {
321
- code: '50101820',
322
- },
323
- ],
324
- });
325
- if (json) {
326
- if (Array.isArray(list) && list.length > 0) {
327
- list = list.map((item) => {
328
- let printData = {};
329
- let datas = Object.entries(item);
330
- datas.forEach((arr) => {
331
- if (Array.isArray(arr[1])) {
332
- printData[arr[0]] = arr[1];
333
- } else {
334
- if (arr[1] !== null) {
335
- let itemsEntries = Object.entries(arr[1]);
336
- itemsEntries.forEach((cArr) => {
337
- printData[`$${arr[0]}[${cArr[0]}]`] = cArr[1];
338
- });
339
- }
340
- }
341
- });
342
- return printData;
343
- });
344
- } else {
345
- list = [];
346
- }
347
- previewHtml.value = new hiprint.PrintTemplate({template: JSON.parse(json)}).getHtml(list)[0].innerHTML;
348
- previewShow.value = true;
349
- } else {
350
- ElMessage.warning({
351
- message: '模板配置不存在,请检查',
352
- });
353
- }
354
- }
355
-
356
- function saveConfig() {
357
- let arr = [].concat(formCode.value);
358
- let json = hiprintTemplate.value?.getJson();
359
- json.panels[0].printElements.forEach((item) => {
360
- if (item.printElementType.type === 'table') {
361
- arr.push(item.options.field);
362
- }
363
- });
364
-
365
- axios
366
- .request({
367
- url: '/printTemplate/save',
368
- method: 'post',
369
- type: 'json',
370
- data: {
371
- id: detailData.value.id,
372
- json: JSON.stringify(json),
373
- dsIds: arr.join(','),
374
- },
375
- })
376
- .then((res) => {
377
- ElMessage.success({
378
- message: '恭喜模板保存成功',
379
- });
380
- });
381
- }
382
-
383
- function clearPrint() {
384
- hiprintTemplate.value?.clear();
385
- }
386
-
387
- const {detailData, getDetail, listCode, dataSourceList, listColumns, formCode, formColumns, dataSourceForm, getDataSourceList} = useDataSource(axios);
388
-
389
- watch(
390
- () => formColumns.value,
391
- (val) => {
392
- if (val && val.length && hiprintTemplate.value) {
393
- hiprintTemplate.value.setFields(
394
- val.map((item) => {
395
- return {
396
- field: item,
397
- text: item,
398
- };
399
- })
400
- );
401
- } else {
402
- hiprintTemplate.value?.setFields('');
403
- }
404
- },
405
- {
406
- deep: true,
407
- immediate: true,
408
- }
409
- );
410
- let currentElementObj = ref(null);
411
- let currentElementObjColumns = computed(() => {
412
- if (currentElementObj.value?.printElementType.type === 'table') {
413
- return currentElementObj.value.options.columns[0]['columns'] || [];
414
- } else {
415
- return [];
416
- }
417
- });
418
-
419
- function tableFieldChange(val) {
420
- currentElementObj.value.updateOption('field', val);
421
- }
422
-
423
- function tableColumnCancel() {
424
- currentElementObj.value = null;
425
- }
426
-
427
- function init() {
428
- try {
429
- hiprint.init({
430
- providers: [new defaultElementTypeProvider()],
431
- });
432
- hiprint.setConfig();
433
- hiprint.setConfig({
434
- optionItems: [fontSize, scale, zIndex],
435
- movingDistance: 2.5,
436
- text: {
437
- tabs: [
438
- {
439
- options: [],
440
- },
441
- {
442
- name: '样式',
443
- options: [
444
- {
445
- name: 'scale',
446
- after: 'transform',
447
- hidden: false,
448
- },
449
- ],
450
- },
451
- ],
452
- supportOptions: [
453
- {
454
- name: 'styler',
455
- hidden: true,
456
- },
457
- {
458
- name: 'scale',
459
- after: 'transform',
460
- hidden: false,
461
- },
462
- {
463
- name: 'formatter',
464
- hidden: true,
465
- },
466
- ],
467
- },
468
- image: {
469
- tabs: [
470
- {
471
- replace: true,
472
- name: '基本',
473
- options: [
474
- {
475
- name: 'field',
476
- hidden: false,
477
- },
478
- {
479
- name: 'src',
480
- hidden: false,
481
- },
482
- {
483
- name: 'fit',
484
- hidden: false,
485
- },
486
- ],
487
- },
488
- ],
489
- },
490
- table: {
491
- tabs: [{options: [{name: 'field', hidden: true}]}],
492
- },
493
- });
494
-
495
- hiprint.PrintElementTypeManager.buildByHtml($('.ep-draggable-item'));
496
- $('#hiprint-printTemplate').empty();
497
- let template = JSON.parse(detailData.value.json) || panel;
498
- hiprintTemplate.value = new hiprint.PrintTemplate({
499
- template,
500
- onImageChooseClick: (target) => {},
501
- fontList: [
502
- {title: '微软雅黑', value: 'Microsoft YaHei'},
503
- {title: '黑体', value: 'STHeitiSC-Light'},
504
- {title: '宋体', value: 'SimSun'},
505
- {title: 'cursive', value: 'cursive'},
506
- ],
507
- dataMode: 1,
508
- history: true,
509
- onDataChanged: (type, json) => {},
510
- onUpdateError: (e) => {
511
- console.error(e);
512
- },
513
- settingContainer: '#PrintElementOptionSetting',
514
- paginationContainer: '.hiprint-printPagination',
515
- });
516
-
517
- hiprintTemplate.value?.design('#hiprint-printTemplate', {grid: true});
518
- scaleValue.value = hiprintTemplate.value.editingPanel.scale || 1;
519
- window.ht = hiprintTemplate.value;
520
-
521
- if (formColumns.value) {
522
- hiprintTemplate.value?.setFields(
523
- formColumns.value.map((item) => {
524
- return {
525
- field: item,
526
- text: item,
527
- };
528
- })
529
- );
530
- }
531
- $('.hiprint-designer').on('mousedown', '.hiprint-printElement', (e) => {
532
- let t = e.currentTarget;
533
- let pes = hiprintTemplate.value?.editingPanel.printElements;
534
- let index = pes.map((item) => item.designTarget[0]).indexOf(t);
535
- let pe = pes[index];
536
- currentElementObj.value = pe;
537
- if (pe.options.field) {
538
- listCode.value = pe.options.field;
539
- }
540
- });
541
- $('#PrintElementOptionSetting').on('input', 'input[type=number]', ($el) => {
542
- let val = parseInt($el.target.value);
543
- if (val < 1) {
544
- $el.target.value = 1;
545
- }
546
- if (val > 2000) {
547
- $el.target.value = 2000;
548
- }
549
- });
550
- } catch (error) {
551
- console.log(error.message);
552
- clearPrint();
553
- hiprintTemplate.value = null;
554
- if (error.message.indexOf('setTemplateId') > -1) {
555
- ElMessageBox.alert('模板有错误,请返回列表手动修改或这清空模板!');
556
- }
557
- }
558
- }
559
-
560
- let updateing = false;
561
- async function updateTemplate(code) {
562
- if (updateing === true) {
563
- return false;
564
- }
565
- updateing = true;
566
- if (hiprintTemplate.value) {
567
- await getDetail(code);
568
- if (detailData.value && detailData.value.json) {
569
- let jsonObj = JSON.parse(detailData.value.json);
570
- hiprintTemplate.value?.update(jsonObj);
571
- let {width, height} = jsonObj.panels[0];
572
- paperWidth.value = width;
573
- paperHeight.value = height;
574
- hiprintTemplate.value?.setPaper(width, height);
575
- scaleValue.value = 1;
576
- } else {
577
- hiprintTemplate.value?.update({
578
- panels: [
579
- {
580
- index: 0,
581
- name: 1,
582
- height: 297,
583
- width: 210,
584
- paperHeader: 125,
585
- paperFooter: 272.5,
586
- paperNumberLeft: 430,
587
- paperNumberTop: 5,
588
- printElements: [],
589
- watermarkOptions: {content: '', rotate: 25, timestamp: false, format: 'YYYY-MM-DD HH:mm'},
590
- },
591
- ],
592
- });
593
- paperWidth.value = 210;
594
- paperHeight.value = 297;
595
- hiprintTemplate.value?.setPaper(210, 297);
596
- scaleValue.value = 1;
597
- }
598
- } else {
599
- await getDetail(code);
600
- init();
601
- }
602
- updateing = false;
603
- }
604
-
605
- const hasDataSource = computed(() => {
606
- return Array.isArray(formCode.value) ? formCode.value.length > 0 : formCode.value;
607
- });
608
- onActivated(() => {
609
- updateTemplate(route.query.code);
610
- });
611
-
612
- onBeforeRouteUpdate((to) => {
613
- updateTemplate(to.query.code);
614
- });
615
-
616
- onDeactivated(() => {
617
- clearPrint();
618
- });
619
-
620
- onMounted(async () => {
621
- await getDataSourceList();
622
- });
623
- </script>
624
- <style lang="scss">
625
- .hiprint-designer {
626
- width: calc(100% + 32px);
627
- height: calc(100% - 30px);
628
- overflow: hidden;
629
- display: flex;
630
- flex-direction: column;
631
- background-color: var(--el-bg-color-page);
632
- margin: 0 -16px;
633
- &__header {
634
- padding: 0 16px;
635
- height: 50px;
636
- display: flex;
637
- background-color: var(--el-bg-color);
638
- align-items: center;
639
- box-shadow: var(--el-box-shadow-lighter);
640
- position: relative;
641
- z-index: 1;
642
- > * {
643
- margin-right: 10px;
644
- margin-left: 0 !important;
645
- }
646
- .percentage {
647
- width: 165px;
648
- }
649
- .el-select {
650
- --el-select-width: auto;
651
- min-width: 100px;
652
- }
653
- .el-form-item {
654
- margin-bottom: 0;
655
- margin-right: 10px;
656
- .el-input {
657
- width: 140px;
658
- .el-input-group__prepend,
659
- .el-input-group__append {
660
- padding: 0 9px;
661
- }
662
- }
663
- }
664
- }
665
- &_title {
666
- font-size: 18px;
667
- font-weight: bold;
668
- line-height: 1.7em;
669
- margin-bottom: 10px;
670
- }
671
- .ep-draggable-item {
672
- user-select: none;
673
- width: 100%;
674
- height: 70px;
675
- display: inline-flex;
676
- flex-direction: column;
677
- align-items: center;
678
- margin-bottom: 10px;
679
- .iconfont {
680
- font-size: 30px;
681
- width: 40px;
682
- height: 40px;
683
- text-align: center;
684
- line-height: 40px;
685
- }
686
- }
687
- &__main {
688
- flex: 1;
689
- overflow: hidden;
690
- display: flex;
691
- &_left {
692
- width: 300px;
693
- overflow: hidden;
694
- background-color: var(--el-color-white);
695
- box-shadow: var(--el-box-shadow-lighter);
696
- .el-scrollbar__view {
697
- padding: 16px;
698
- }
699
- }
700
- &_canvas {
701
- flex: 1;
702
- overflow: hidden;
703
- .el-scrollbar__view {
704
- padding: 20px 10px 40px 20px;
705
- }
706
- }
707
- &_right {
708
- width: 340px;
709
- overflow: hidden;
710
- background-color: var(--el-color-white);
711
- box-shadow: var(--el-box-shadow-lighter);
712
- display: flex;
713
- flex-direction: column;
714
- .prop-tabs {
715
- height: 100%;
716
- overflow: hidden;
717
- display: flex;
718
- flex-direction: column;
719
- .prop-tab-items {
720
- display: flex;
721
- height: 43px;
722
- box-sizing: border-box;
723
- .prop-tab-item {
724
- height: 40px;
725
- line-height: 40px;
726
- flex: 1;
727
- text-align: center;
728
- }
729
- }
730
- .hiprint-option-items.active {
731
- display: block;
732
- padding: 0 6px 0 12px;
733
- }
734
- }
735
- .hiprint-option-items {
736
- height: 100%;
737
- overflow: auto;
738
- padding: 16px;
739
- box-sizing: border-box;
740
- &::-webkit-scrollbar {
741
- width: 4px;
742
- height: 4px;
743
- }
744
-
745
- &::-webkit-scrollbar-thumb {
746
- border-radius: 4px;
747
- background: #bbb;
748
- }
749
- }
750
- .hiprint-designer_title {
751
- padding: 0 10px;
752
- }
753
- #PrintElementOptionSetting {
754
- flex: 1;
755
- overflow: hidden;
756
- }
757
- .el-form {
758
- padding: 10px;
759
- .el-button {
760
- width: 100%;
761
- }
762
- }
763
- }
764
- }
765
- }
766
- </style>
1
+ <template>
2
+ <section class="hiprint-designer">
3
+ <header class="hiprint-designer__header">
4
+ <el-radio-group
5
+ v-model="paperType"
6
+ @change="setPaperHandler">
7
+ <el-radio-button label="A3">A3</el-radio-button>
8
+ <el-radio-button label="A4">A4</el-radio-button>
9
+ <el-radio-button label="A5">A5</el-radio-button>
10
+ <el-radio-button label="B3">B3</el-radio-button>
11
+ <el-radio-button label="B4">B4</el-radio-button>
12
+ <el-radio-button label="B5">B5</el-radio-button>
13
+ <el-radio-button label="other">自定义</el-radio-button>
14
+ </el-radio-group>
15
+ <el-form
16
+ inline
17
+ v-if="paperType === 'other'">
18
+ <el-form-item>
19
+ <el-input
20
+ v-model="paperWidth"
21
+ type="number">
22
+ <template #prepend>宽</template>
23
+ <template #append>px</template>
24
+ </el-input>
25
+ </el-form-item>
26
+ <el-form-item>
27
+ <el-input
28
+ v-model="paperHeight"
29
+ type="number">
30
+ <template #prepend>高</template>
31
+ <template #append>px</template>
32
+ </el-input>
33
+ </el-form-item>
34
+ <el-form-item>
35
+ <el-button
36
+ type="primary"
37
+ @click="setPaperHandler('other')">
38
+ 设置
39
+ </el-button>
40
+ </el-form-item>
41
+ </el-form>
42
+ <el-input
43
+ class="percentage"
44
+ readonly
45
+ v-model="scalePercentage">
46
+ <template #prepend>
47
+ <el-button
48
+ :disabled="!canZoomIn"
49
+ @click="zoomIn">
50
+ <i class="iconfont icon-zoom-out"></i>
51
+ </el-button>
52
+ </template>
53
+ <template #append>
54
+ <el-button
55
+ :disabled="!canZoomOut"
56
+ @click="zoomOut">
57
+ <i class="iconfont icon-zoom-in"></i>
58
+ </el-button>
59
+ </template>
60
+ </el-input>
61
+ <el-select
62
+ placeholder="请选择数据源"
63
+ multiple
64
+ v-model="formCode">
65
+ <el-option
66
+ v-for="d in dataSourceForm"
67
+ :label="d.label"
68
+ :value="d.value"></el-option>
69
+ </el-select>
70
+ <el-button
71
+ type="primary"
72
+ @click="previewPrint">
73
+ <i class="iconfont icon-print"></i>
74
+ 预览
75
+ </el-button>
76
+ <el-button
77
+ type="primary"
78
+ @click="saveConfig">
79
+ <i class="iconfont icon-save"></i>
80
+ 保存
81
+ </el-button>
82
+ <el-button
83
+ type="danger"
84
+ @click="clearPrint">
85
+ <i class="iconfont icon-clear"></i>
86
+ 清空
87
+ </el-button>
88
+ </header>
89
+ <main class="hiprint-designer__main">
90
+ <aside class="hiprint-designer__main_left">
91
+ <el-scrollbar noresize>
92
+ <div class="hiprint-designer_title">基础</div>
93
+ <el-row>
94
+ <el-col :span="8">
95
+ <a
96
+ class="ep-draggable-item"
97
+ tid="defaultModule.text">
98
+ <i class="iconfont icon-font-size"></i>
99
+ <span>文本</span>
100
+ </a>
101
+ </el-col>
102
+ <el-col :span="8">
103
+ <a
104
+ class="ep-draggable-item"
105
+ tid="defaultModule.textVal">
106
+ <i class="iconfont icon-font-size"></i>
107
+ <span>值(文本)</span>
108
+ </a>
109
+ </el-col>
110
+ <el-col :span="8">
111
+ <a
112
+ class="ep-draggable-item"
113
+ tid="defaultModule.image">
114
+ <i class="iconfont icon-image-fill"></i>
115
+ <span>图片</span>
116
+ </a>
117
+ </el-col>
118
+ <el-col :span="8">
119
+ <a
120
+ class="ep-draggable-item"
121
+ tid="defaultModule.longText">
122
+ <i class="iconfont icon-file-text"></i>
123
+ <span>长文本</span>
124
+ </a>
125
+ </el-col>
126
+ <el-col :span="8">
127
+ <a
128
+ class="ep-draggable-item"
129
+ tid="defaultModule.table">
130
+ <i class="iconfont icon-table"></i>
131
+ <span>表格</span>
132
+ </a>
133
+ </el-col>
134
+ <el-col :span="8">
135
+ <a
136
+ class="ep-draggable-item"
137
+ tid="defaultModule.emptyTable">
138
+ <i class="iconfont icon-layout"></i>
139
+ <span>空白表格</span>
140
+ </a>
141
+ </el-col>
142
+ <el-col :span="8">
143
+ <a
144
+ class="ep-draggable-item"
145
+ tid="defaultModule.html">
146
+ <i class="iconfont icon-HTML"></i>
147
+ <span>html</span>
148
+ </a>
149
+ </el-col>
150
+ <el-col :span="8">
151
+ <a
152
+ class="ep-draggable-item"
153
+ tid="defaultModule.customText">
154
+ <i class="iconfont icon-container-fill"></i>
155
+ <span>自定义文本</span>
156
+ </a>
157
+ </el-col>
158
+ <el-col :span="8">
159
+ <a
160
+ class="ep-draggable-item"
161
+ tid="defaultModule.barcode">
162
+ <i class="iconfont icon-barcode"></i>
163
+ <span>条形码</span>
164
+ </a>
165
+ </el-col>
166
+ <el-col :span="8">
167
+ <a
168
+ class="ep-draggable-item"
169
+ tid="defaultModule.qrcode">
170
+ <i class="iconfont icon-qrcode"></i>
171
+ <span>二维码</span>
172
+ </a>
173
+ </el-col>
174
+ </el-row>
175
+ <div class="hiprint-designer_title">辅助</div>
176
+ <el-row>
177
+ <el-col :span="8">
178
+ <a
179
+ class="ep-draggable-item"
180
+ tid="defaultModule.hline">
181
+ <i class="iconfont icon-border-verticle"></i>
182
+ <span>横线</span>
183
+ </a>
184
+ </el-col>
185
+ <el-col :span="8">
186
+ <a
187
+ class="ep-draggable-item"
188
+ tid="defaultModule.vline">
189
+ <i class="iconfont icon-border-horizontal"></i>
190
+ <span>竖线</span>
191
+ </a>
192
+ </el-col>
193
+ <el-col :span="8">
194
+ <a
195
+ class="ep-draggable-item"
196
+ tid="defaultModule.rect">
197
+ <i class="iconfont icon-border"></i>
198
+ <span>矩形</span>
199
+ </a>
200
+ </el-col>
201
+ <el-col :span="8">
202
+ <a
203
+ class="ep-draggable-item"
204
+ tid="defaultModule.oval">
205
+ <i class="iconfont icon-round"></i>
206
+ <span>椭圆</span>
207
+ </a>
208
+ </el-col>
209
+ </el-row>
210
+ </el-scrollbar>
211
+ </aside>
212
+ <section class="hiprint-designer__main_canvas">
213
+ <el-scrollbar ref="canvasRef">
214
+ <div id="hiprint-printTemplate"></div>
215
+ </el-scrollbar>
216
+ </section>
217
+ <aside class="hiprint-designer__main_right">
218
+ <div id="PrintElementOptionSetting"></div>
219
+ <template v-if="currentElementObjColumns.length">
220
+ <div class="hiprint-designer_title">表格字段设置</div>
221
+ <el-form
222
+ label-position="top"
223
+ size="small">
224
+ <el-form-item label="表数据选择">
225
+ <template v-if="hasDataSource">
226
+ <el-select
227
+ v-model="listCode"
228
+ @change="tableFieldChange">
229
+ <el-option
230
+ v-for="d in dataSourceList"
231
+ :label="d.label"
232
+ :value="d.value"></el-option>
233
+ </el-select>
234
+ </template>
235
+ <template v-else>
236
+ <el-input
237
+ v-model="listCode"
238
+ @change="tableFieldChange"></el-input>
239
+ </template>
240
+ </el-form-item>
241
+ <el-row gutter="10">
242
+ <el-col
243
+ :span="12"
244
+ v-for="col in currentElementObjColumns">
245
+ <el-form-item :label="col.title">
246
+ <template v-if="hasDataSource">
247
+ <el-select v-model="col.field">
248
+ <el-option
249
+ v-for="d in listColumns"
250
+ :value="d"></el-option>
251
+ </el-select>
252
+ </template>
253
+ <template v-else>
254
+ <el-input v-model="col.field"></el-input>
255
+ </template>
256
+ </el-form-item>
257
+ </el-col>
258
+ </el-row>
259
+ <el-row gutter="10">
260
+ <el-col :span="12">
261
+ <el-button
262
+ @click="tableColumnCancel"
263
+ type="warning">
264
+ 取消
265
+ </el-button>
266
+ </el-col>
267
+ </el-row>
268
+ </el-form>
269
+ </template>
270
+ </aside>
271
+ </main>
272
+ </section>
273
+ <el-dialog v-model="previewShow">
274
+ <div
275
+ class="print-preview"
276
+ v-html="previewHtml"></div>
277
+ </el-dialog>
278
+ </template>
279
+ <script setup lang="ts">
280
+ // @ts-nocheck
281
+ import {onMounted, ref, onActivated, onDeactivated, computed, watch} from 'vue';
282
+ import {hiprint, defaultElementTypeProvider, fontSize, scale, zIndex, panel, usePaper, useScale, useDataSource, jquery as $} from 'yh-hiprint';
283
+ import {useRoute, onBeforeRouteUpdate} from 'vue-router';
284
+ import {ElMessageBox, ElMessage} from 'element-plus';
285
+ import axios from '@/libs/api.request';
286
+
287
+ interface HiprintTemplate {
288
+ setPaper: (width: number, height: number) => void;
289
+ zoom: (scale: number) => void;
290
+ getJson: () => any;
291
+ clear: () => void;
292
+ }
293
+
294
+ const route = useRoute();
295
+ const hiprintTemplate = ref<HiprintTemplate | null>(null);
296
+
297
+ const {paperType, paperWidth, paperHeight, setPaper} = usePaper();
298
+ function setPaperHandler(type) {
299
+ setPaper(type, () => {
300
+ hiprintTemplate.value?.setPaper(paperWidth.value, paperHeight.value);
301
+ });
302
+ }
303
+
304
+ const canvasRef = ref();
305
+ const {scaleValue, scalePercentage, canZoomIn, canZoomOut, zoomIn, zoomOut} = useScale(() => {
306
+ hiprintTemplate.value?.zoom(scaleValue.value);
307
+ canvasRef?.value.update();
308
+ });
309
+
310
+ const previewShow = ref(false);
311
+ const previewHtml = ref('');
312
+ async function previewPrint() {
313
+ let {
314
+ data: {list, json},
315
+ } = await axios.request({
316
+ url: `/printTemplate/data/${detailData.value.code}`,
317
+ method: 'post',
318
+ type: 'json',
319
+ data: [
320
+ {
321
+ code: '50101820',
322
+ },
323
+ ],
324
+ });
325
+ if (json) {
326
+ if (Array.isArray(list) && list.length > 0) {
327
+ list = list.map((item) => {
328
+ let printData = {};
329
+ let datas = Object.entries(item);
330
+ datas.forEach((arr) => {
331
+ if (Array.isArray(arr[1])) {
332
+ printData[arr[0]] = arr[1];
333
+ } else {
334
+ if (arr[1] !== null) {
335
+ let itemsEntries = Object.entries(arr[1]);
336
+ itemsEntries.forEach((cArr) => {
337
+ printData[`$${arr[0]}[${cArr[0]}]`] = cArr[1];
338
+ });
339
+ }
340
+ }
341
+ });
342
+ return printData;
343
+ });
344
+ } else {
345
+ list = [];
346
+ }
347
+ previewHtml.value = new hiprint.PrintTemplate({template: JSON.parse(json)}).getHtml(list)[0].innerHTML;
348
+ previewShow.value = true;
349
+ } else {
350
+ ElMessage.warning({
351
+ message: '模板配置不存在,请检查',
352
+ });
353
+ }
354
+ }
355
+
356
+ function saveConfig() {
357
+ let arr = [].concat(formCode.value);
358
+ let json = hiprintTemplate.value?.getJson();
359
+ json.panels[0].printElements.forEach((item) => {
360
+ if (item.printElementType.type === 'table') {
361
+ arr.push(item.options.field);
362
+ }
363
+ });
364
+
365
+ axios
366
+ .request({
367
+ url: '/printTemplate/save',
368
+ method: 'post',
369
+ type: 'json',
370
+ data: {
371
+ id: detailData.value.id,
372
+ json: JSON.stringify(json),
373
+ dsIds: arr.join(','),
374
+ },
375
+ })
376
+ .then((res) => {
377
+ ElMessage.success({
378
+ message: '恭喜模板保存成功',
379
+ });
380
+ });
381
+ }
382
+
383
+ function clearPrint() {
384
+ hiprintTemplate.value?.clear();
385
+ }
386
+
387
+ const {detailData, getDetail, listCode, dataSourceList, listColumns, formCode, formColumns, dataSourceForm, getDataSourceList} = useDataSource(axios);
388
+
389
+ watch(
390
+ () => formColumns.value,
391
+ (val) => {
392
+ if (val && val.length && hiprintTemplate.value) {
393
+ hiprintTemplate.value.setFields(
394
+ val.map((item) => {
395
+ return {
396
+ field: item,
397
+ text: item,
398
+ };
399
+ })
400
+ );
401
+ } else {
402
+ hiprintTemplate.value?.setFields('');
403
+ }
404
+ },
405
+ {
406
+ deep: true,
407
+ immediate: true,
408
+ }
409
+ );
410
+ let currentElementObj = ref(null);
411
+ let currentElementObjColumns = computed(() => {
412
+ if (currentElementObj.value?.printElementType.type === 'table') {
413
+ return currentElementObj.value.options.columns[0]['columns'] || [];
414
+ } else {
415
+ return [];
416
+ }
417
+ });
418
+
419
+ function tableFieldChange(val) {
420
+ currentElementObj.value.updateOption('field', val);
421
+ }
422
+
423
+ function tableColumnCancel() {
424
+ currentElementObj.value = null;
425
+ }
426
+
427
+ function init() {
428
+ try {
429
+ hiprint.init({
430
+ providers: [new defaultElementTypeProvider()],
431
+ });
432
+ hiprint.setConfig();
433
+ hiprint.setConfig({
434
+ optionItems: [fontSize, scale, zIndex],
435
+ movingDistance: 2.5,
436
+ text: {
437
+ tabs: [
438
+ {
439
+ options: [],
440
+ },
441
+ {
442
+ name: '样式',
443
+ options: [
444
+ {
445
+ name: 'scale',
446
+ after: 'transform',
447
+ hidden: false,
448
+ },
449
+ ],
450
+ },
451
+ ],
452
+ supportOptions: [
453
+ {
454
+ name: 'styler',
455
+ hidden: true,
456
+ },
457
+ {
458
+ name: 'scale',
459
+ after: 'transform',
460
+ hidden: false,
461
+ },
462
+ {
463
+ name: 'formatter',
464
+ hidden: true,
465
+ },
466
+ ],
467
+ },
468
+ image: {
469
+ tabs: [
470
+ {
471
+ replace: true,
472
+ name: '基本',
473
+ options: [
474
+ {
475
+ name: 'field',
476
+ hidden: false,
477
+ },
478
+ {
479
+ name: 'src',
480
+ hidden: false,
481
+ },
482
+ {
483
+ name: 'fit',
484
+ hidden: false,
485
+ },
486
+ ],
487
+ },
488
+ ],
489
+ },
490
+ table: {
491
+ tabs: [{options: [{name: 'field', hidden: true}]}],
492
+ },
493
+ });
494
+
495
+ hiprint.PrintElementTypeManager.buildByHtml($('.ep-draggable-item'));
496
+ $('#hiprint-printTemplate').empty();
497
+ let template = JSON.parse(detailData.value.json) || panel;
498
+ hiprintTemplate.value = new hiprint.PrintTemplate({
499
+ template,
500
+ onImageChooseClick: (target) => {},
501
+ fontList: [
502
+ {title: '微软雅黑', value: 'Microsoft YaHei'},
503
+ {title: '黑体', value: 'STHeitiSC-Light'},
504
+ {title: '宋体', value: 'SimSun'},
505
+ {title: 'cursive', value: 'cursive'},
506
+ ],
507
+ dataMode: 1,
508
+ history: true,
509
+ onDataChanged: (type, json) => {},
510
+ onUpdateError: (e) => {
511
+ console.error(e);
512
+ },
513
+ settingContainer: '#PrintElementOptionSetting',
514
+ paginationContainer: '.hiprint-printPagination',
515
+ });
516
+
517
+ hiprintTemplate.value?.design('#hiprint-printTemplate', {grid: true});
518
+ scaleValue.value = hiprintTemplate.value.editingPanel.scale || 1;
519
+ window.ht = hiprintTemplate.value;
520
+
521
+ if (formColumns.value) {
522
+ hiprintTemplate.value?.setFields(
523
+ formColumns.value.map((item) => {
524
+ return {
525
+ field: item,
526
+ text: item,
527
+ };
528
+ })
529
+ );
530
+ }
531
+ $('.hiprint-designer').on('mousedown', '.hiprint-printElement', (e) => {
532
+ let t = e.currentTarget;
533
+ let pes = hiprintTemplate.value?.editingPanel.printElements;
534
+ let index = pes.map((item) => item.designTarget[0]).indexOf(t);
535
+ let pe = pes[index];
536
+ currentElementObj.value = pe;
537
+ if (pe.options.field) {
538
+ listCode.value = pe.options.field;
539
+ }
540
+ });
541
+ $('#PrintElementOptionSetting').on('input', 'input[type=number]', ($el) => {
542
+ let val = parseInt($el.target.value);
543
+ if (val < 1) {
544
+ $el.target.value = 1;
545
+ }
546
+ if (val > 2000) {
547
+ $el.target.value = 2000;
548
+ }
549
+ });
550
+ } catch (error) {
551
+ console.log(error.message);
552
+ clearPrint();
553
+ hiprintTemplate.value = null;
554
+ if (error.message.indexOf('setTemplateId') > -1) {
555
+ ElMessageBox.alert('模板有错误,请返回列表手动修改或这清空模板!');
556
+ }
557
+ }
558
+ }
559
+
560
+ let updateing = false;
561
+ async function updateTemplate(code) {
562
+ if (updateing === true) {
563
+ return false;
564
+ }
565
+ updateing = true;
566
+ if (hiprintTemplate.value) {
567
+ await getDetail(code);
568
+ if (detailData.value && detailData.value.json) {
569
+ let jsonObj = JSON.parse(detailData.value.json);
570
+ hiprintTemplate.value?.update(jsonObj);
571
+ let {width, height} = jsonObj.panels[0];
572
+ paperWidth.value = width;
573
+ paperHeight.value = height;
574
+ hiprintTemplate.value?.setPaper(width, height);
575
+ scaleValue.value = 1;
576
+ } else {
577
+ hiprintTemplate.value?.update({
578
+ panels: [
579
+ {
580
+ index: 0,
581
+ name: 1,
582
+ height: 297,
583
+ width: 210,
584
+ paperHeader: 125,
585
+ paperFooter: 272.5,
586
+ paperNumberLeft: 430,
587
+ paperNumberTop: 5,
588
+ printElements: [],
589
+ watermarkOptions: {content: '', rotate: 25, timestamp: false, format: 'YYYY-MM-DD HH:mm'},
590
+ },
591
+ ],
592
+ });
593
+ paperWidth.value = 210;
594
+ paperHeight.value = 297;
595
+ hiprintTemplate.value?.setPaper(210, 297);
596
+ scaleValue.value = 1;
597
+ }
598
+ } else {
599
+ await getDetail(code);
600
+ init();
601
+ }
602
+ updateing = false;
603
+ }
604
+
605
+ const hasDataSource = computed(() => {
606
+ return Array.isArray(formCode.value) ? formCode.value.length > 0 : formCode.value;
607
+ });
608
+ onActivated(() => {
609
+ updateTemplate(route.query.code);
610
+ });
611
+
612
+ onBeforeRouteUpdate((to) => {
613
+ updateTemplate(to.query.code);
614
+ });
615
+
616
+ onDeactivated(() => {
617
+ clearPrint();
618
+ });
619
+
620
+ onMounted(async () => {
621
+ await getDataSourceList();
622
+ });
623
+ </script>
624
+ <style lang="scss">
625
+ .hiprint-designer {
626
+ width: calc(100% + 32px);
627
+ height: calc(100% - 30px);
628
+ overflow: hidden;
629
+ display: flex;
630
+ flex-direction: column;
631
+ background-color: var(--el-bg-color-page);
632
+ margin: 0 -16px;
633
+ &__header {
634
+ padding: 0 16px;
635
+ height: 50px;
636
+ display: flex;
637
+ background-color: var(--el-bg-color);
638
+ align-items: center;
639
+ box-shadow: var(--el-box-shadow-lighter);
640
+ position: relative;
641
+ z-index: 1;
642
+ > * {
643
+ margin-right: 10px;
644
+ margin-left: 0 !important;
645
+ }
646
+ .percentage {
647
+ width: 165px;
648
+ }
649
+ .el-select {
650
+ --el-select-width: auto;
651
+ min-width: 100px;
652
+ }
653
+ .el-form-item {
654
+ margin-bottom: 0;
655
+ margin-right: 10px;
656
+ .el-input {
657
+ width: 140px;
658
+ .el-input-group__prepend,
659
+ .el-input-group__append {
660
+ padding: 0 9px;
661
+ }
662
+ }
663
+ }
664
+ }
665
+ &_title {
666
+ font-size: 18px;
667
+ font-weight: bold;
668
+ line-height: 1.7em;
669
+ margin-bottom: 10px;
670
+ }
671
+ .ep-draggable-item {
672
+ user-select: none;
673
+ width: 100%;
674
+ height: 70px;
675
+ display: inline-flex;
676
+ flex-direction: column;
677
+ align-items: center;
678
+ margin-bottom: 10px;
679
+ .iconfont {
680
+ font-size: 30px;
681
+ width: 40px;
682
+ height: 40px;
683
+ text-align: center;
684
+ line-height: 40px;
685
+ }
686
+ }
687
+ &__main {
688
+ flex: 1;
689
+ overflow: hidden;
690
+ display: flex;
691
+ &_left {
692
+ width: 300px;
693
+ overflow: hidden;
694
+ background-color: var(--el-color-white);
695
+ box-shadow: var(--el-box-shadow-lighter);
696
+ .el-scrollbar__view {
697
+ padding: 16px;
698
+ }
699
+ }
700
+ &_canvas {
701
+ flex: 1;
702
+ overflow: hidden;
703
+ .el-scrollbar__view {
704
+ padding: 20px 10px 40px 20px;
705
+ }
706
+ }
707
+ &_right {
708
+ width: 340px;
709
+ overflow: hidden;
710
+ background-color: var(--el-color-white);
711
+ box-shadow: var(--el-box-shadow-lighter);
712
+ display: flex;
713
+ flex-direction: column;
714
+ .prop-tabs {
715
+ height: 100%;
716
+ overflow: hidden;
717
+ display: flex;
718
+ flex-direction: column;
719
+ .prop-tab-items {
720
+ display: flex;
721
+ height: 43px;
722
+ box-sizing: border-box;
723
+ .prop-tab-item {
724
+ height: 40px;
725
+ line-height: 40px;
726
+ flex: 1;
727
+ text-align: center;
728
+ }
729
+ }
730
+ .hiprint-option-items.active {
731
+ display: block;
732
+ padding: 0 6px 0 12px;
733
+ }
734
+ }
735
+ .hiprint-option-items {
736
+ height: 100%;
737
+ overflow: auto;
738
+ padding: 16px;
739
+ box-sizing: border-box;
740
+ &::-webkit-scrollbar {
741
+ width: 4px;
742
+ height: 4px;
743
+ }
744
+
745
+ &::-webkit-scrollbar-thumb {
746
+ border-radius: 4px;
747
+ background: #bbb;
748
+ }
749
+ }
750
+ .hiprint-designer_title {
751
+ padding: 0 10px;
752
+ }
753
+ #PrintElementOptionSetting {
754
+ flex: 1;
755
+ overflow: hidden;
756
+ }
757
+ .el-form {
758
+ padding: 10px;
759
+ .el-button {
760
+ width: 100%;
761
+ }
762
+ }
763
+ }
764
+ }
765
+ }
766
+ </style>