yh-hiprint 2.2.8 → 2.2.10

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.
package/designer.vue CHANGED
@@ -1,742 +1,742 @@
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
- <el-select
226
- v-model="listCode"
227
- @change="tableFieldChange">
228
- <el-option
229
- v-for="d in dataSourceList"
230
- :label="d.label"
231
- :value="d.value"></el-option>
232
- </el-select>
233
- </el-form-item>
234
- <el-row gutter="10">
235
- <el-col
236
- :span="12"
237
- v-for="col in currentElementObjColumns">
238
- <el-form-item :label="col.title">
239
- <el-select v-model="col.field">
240
- <el-option
241
- v-for="d in listColumns"
242
- :value="d"></el-option>
243
- </el-select>
244
- </el-form-item>
245
- </el-col>
246
- </el-row>
247
- <el-row gutter="10">
248
- <el-col :span="12">
249
- <el-button
250
- @click="tableColumnCancel"
251
- type="warning">
252
- 取消
253
- </el-button>
254
- </el-col>
255
- </el-row>
256
- </el-form>
257
- </template>
258
- </aside>
259
- </main>
260
- </section>
261
- <el-dialog v-model="previewShow">
262
- <div
263
- class="print-preview"
264
- v-html="previewHtml"></div>
265
- </el-dialog>
266
- </template>
267
- <script setup>
268
- import { onMounted, ref, onActivated, onDeactivated, computed, watch, nextTick } from "vue";
269
- import { hiprint, defaultElementTypeProvider, fontSize, scale, zIndex, panel, usePaper, useScale, useDataSource, jquery as $ } from "yh-hiprint";
270
- import { useRoute, onBeforeRouteUpdate } from "vue-router/dist/vue-router";
271
- import { ElMessageBox } from "element-plus";
272
- import axios from "@/libs/api.request";
273
-
274
- const route = useRoute();
275
- const { paperType, paperWidth, paperHeight, setPaper } = usePaper();
276
- function setPaperHandler(type) {
277
- setPaper(type, () => {
278
- hiprintTemplate.value.setPaper(paperWidth.value, paperHeight.value);
279
- });
280
- }
281
-
282
- const hiprintTemplate = ref(null);
283
- const canvasRef = ref();
284
- const { scaleValue, scalePercentage, canZoomIn, canZoomOut, zoomIn, zoomOut } = useScale(() => {
285
- hiprintTemplate.value.zoom(scaleValue.value);
286
- canvasRef?.value.update();
287
- });
288
-
289
- const previewShow = ref(false);
290
- const previewHtml = ref("");
291
- async function previewPrint() {
292
- let {
293
- data: { list, json },
294
- } = await axios.request({
295
- url: `/printTemplate/data/${detailData.value.code}`,
296
- method: "post",
297
- type: "json",
298
- data: [
299
- {
300
- code: "50101820",
301
- },
302
- ],
303
- });
304
- if (json) {
305
- if (Array.isArray(list) && list.length > 0) {
306
- list = list.map((item) => {
307
- let printData = {};
308
- let datas = Object.entries(item);
309
- datas.forEach((arr) => {
310
- if (Array.isArray(arr[1])) {
311
- printData[arr[0]] = arr[1];
312
- } else {
313
- if (arr[1] !== null) {
314
- let itemsEntries = Object.entries(arr[1]);
315
- itemsEntries.forEach((cArr) => {
316
- printData[`$${arr[0]}[${cArr[0]}]`] = cArr[1];
317
- });
318
- }
319
- }
320
- });
321
- return printData;
322
- });
323
- } else {
324
- list = [];
325
- }
326
- previewHtml.value = new hiprint.PrintTemplate({ template: JSON.parse(json) }).getHtml(list)[0].innerHTML;
327
- previewShow.value = true;
328
- } else {
329
- ElMessage.warning({
330
- title: "警告",
331
- message: "模板配置不存在,请检查",
332
- });
333
- }
334
- }
335
-
336
- function saveConfig() {
337
- let arr = [].concat(formCode.value);
338
- let json = hiprintTemplate.value.getJson();
339
- json.panels[0].printElements.forEach((item) => {
340
- if (item.printElementType.type === "table") {
341
- arr.push(item.options.field);
342
- }
343
- });
344
-
345
- axios
346
- .request({
347
- url: "/printTemplate/save",
348
- method: "post",
349
- type: "json",
350
- data: {
351
- id: detailData.value.id,
352
- json: JSON.stringify(json),
353
- dsIds: arr.join(","),
354
- },
355
- })
356
- .then((res) => {
357
- ElMessage.success({
358
- message: "恭喜模板保存成功",
359
- });
360
- });
361
- }
362
-
363
- function clearPrint() {
364
- hiprintTemplate.value?.clear();
365
- }
366
-
367
- const { detailData, getDetail, listCode, dataSourceList, listColumns, formCode, formColumns, dataSourceForm, getDataSourceList } = useDataSource(axios);
368
-
369
- watch(
370
- () => formColumns.value,
371
- (val) => {
372
- if (val && val.length && hiprintTemplate.value) {
373
- hiprintTemplate.value.setFields(
374
- val.map((item) => {
375
- return {
376
- field: item,
377
- text: item,
378
- };
379
- })
380
- );
381
- }
382
- },
383
- {
384
- deep: true,
385
- immediate: true,
386
- }
387
- );
388
- let currentElementObj = ref(null);
389
- let currentElementObjColumns = computed(() => {
390
- if (currentElementObj.value?.printElementType.type === "table") {
391
- return currentElementObj.value.options.columns[0]["columns"] || [];
392
- } else {
393
- return [];
394
- }
395
- });
396
-
397
- function tableFieldChange(val) {
398
- currentElementObj.value.updateOption("field", val);
399
- }
400
-
401
- function tableColumnCancel() {
402
- currentElementObj.value = null;
403
- }
404
-
405
- function init() {
406
- try {
407
- hiprint.init({
408
- providers: [new defaultElementTypeProvider()],
409
- });
410
- hiprint.setConfig();
411
- hiprint.setConfig({
412
- optionItems: [fontSize, scale, zIndex],
413
- movingDistance: 2.5,
414
- text: {
415
- tabs: [
416
- {
417
- options: [],
418
- },
419
- {
420
- name: "样式",
421
- options: [
422
- {
423
- name: "scale",
424
- after: "transform",
425
- hidden: false,
426
- },
427
- ],
428
- },
429
- ],
430
- supportOptions: [
431
- {
432
- name: "styler",
433
- hidden: true,
434
- },
435
- {
436
- name: "scale",
437
- after: "transform",
438
- hidden: false,
439
- },
440
- {
441
- name: "formatter",
442
- hidden: true,
443
- },
444
- ],
445
- },
446
- image: {
447
- tabs: [
448
- {
449
- replace: true,
450
- name: "基本",
451
- options: [
452
- {
453
- name: "field",
454
- hidden: false,
455
- },
456
- {
457
- name: "src",
458
- hidden: false,
459
- },
460
- {
461
- name: "fit",
462
- hidden: false,
463
- },
464
- ],
465
- },
466
- ],
467
- },
468
- table: {
469
- tabs: [{ options: [{ name: "field", hidden: true }] }],
470
- },
471
- });
472
-
473
- hiprint.PrintElementTypeManager.buildByHtml($(".ep-draggable-item"));
474
- $("#hiprint-printTemplate").empty();
475
- let template = JSON.parse(detailData.value.json) || panel;
476
- hiprintTemplate.value = new hiprint.PrintTemplate({
477
- template,
478
- onImageChooseClick: (target) => {
479
- // 测试 3秒后修改图片地址值
480
- setTimeout(() => {
481
- target.refresh("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtAAAAIIAQMAAAB99EudAAAABlBMVEUmf8vG2O41LStnAAABD0lEQVR42u3XQQqCQBSAYcWFS4/QUTpaHa2jdISWLUJjjMpclJoPGvq+1WsYfiJCZ4oCAAAAAAAAAAAAAAAAAHin6pL9c6H/fOzHbRrP0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0u/SY9LS0tLS0tLS0tLS0n+edm+UlpaWlpaWlpaWlpaW/tl0Ndyzbno7/+tPTJdd1wal69dNa6abx+Lq6TSeYtK7BX/Diek0XULSZZrakPRtV0i6Hu/KIt30q4fM0pvBqvR9mvsQkZaW9gyJT+f5lsnzjR54xAk8mAUeJyMPwYFH98ALx5Jr0kRLLndT7b64UX9QR/0eAAAAAAAAAAAAAAAAAAD/4gpryzr/bja4QgAAAABJRU5ErkJggg==", {
482
- real: true,
483
- });
484
- }, 3000);
485
- },
486
- fontList: [
487
- { title: "微软雅黑", value: "Microsoft YaHei" },
488
- { title: "黑体", value: "STHeitiSC-Light" },
489
- { title: "思源黑体", value: "SourceHanSansCN-Normal" },
490
- { title: "王羲之书法体", value: "王羲之书法体" },
491
- { title: "宋体", value: "SimSun" },
492
- { title: "华为楷体", value: "STKaiti" },
493
- { title: "cursive", value: "cursive" },
494
- ],
495
- dataMode: 1,
496
- history: true,
497
- onDataChanged: (type, json) => {
498
- // console.log(type); // 新增、移动、删除、修改(参数调整)、大小、旋转
499
- // console.log(json); // 返回 template
500
- },
501
- onUpdateError: (e) => {
502
- // console.error(e);
503
- },
504
- settingContainer: "#PrintElementOptionSetting",
505
- paginationContainer: ".hiprint-printPagination",
506
- });
507
-
508
- hiprintTemplate.value.design("#hiprint-printTemplate", { grid: true });
509
- scaleValue.value = hiprintTemplate.value.editingPanel.scale || 1;
510
- window.ht = hiprintTemplate.value;
511
-
512
- if (formColumns.value) {
513
- hiprintTemplate.value.setFields(
514
- formColumns.value.map((item) => {
515
- return {
516
- field: item,
517
- text: item,
518
- };
519
- })
520
- );
521
- }
522
- $(".hiprint-designer").on("mousedown", ".hiprint-printElement", (e) => {
523
- let t = e.currentTarget;
524
- let pes = hiprintTemplate.value.editingPanel.printElements;
525
- let index = pes.map((item) => item.designTarget[0]).indexOf(t);
526
- let pe = pes[index];
527
- currentElementObj.value = pe;
528
- if (pe.options.field) {
529
- listCode.value = pe.options.field;
530
- }
531
- });
532
- } catch (error) {
533
- console.log(error.message);
534
- clearPrint();
535
- hiprintTemplate.value = null;
536
- if (error.message.indexOf("setTemplateId") > -1) {
537
- ElMessageBox.alert("模板有错误,请返回列表手动修改或这清空模板!");
538
- }
539
- }
540
- }
541
-
542
- let updateing = false;
543
- async function updateTemplate() {
544
- if (updateing === true) {
545
- return false;
546
- }
547
- updateing = true;
548
- if (hiprintTemplate.value) {
549
- await getDetail(route.query.code);
550
- if (detailData.value && detailData.value.json) {
551
- let jsonObj = JSON.parse(detailData.value.json);
552
- hiprintTemplate.value.update(jsonObj);
553
- let { width, height } = jsonObj.panels[0];
554
- paperWidth.value = width;
555
- paperHeight.value = height;
556
- hiprintTemplate.value.setPaper(width, height);
557
- } else {
558
- hiprintTemplate.value.update({
559
- panels: [
560
- {
561
- index: 0,
562
- name: 1,
563
- height: 297,
564
- width: 210,
565
- paperHeader: 125,
566
- paperFooter: 272.5,
567
- paperNumberLeft: 430,
568
- paperNumberTop: 5,
569
- printElements: [],
570
- watermarkOptions: { content: "", rotate: 25, timestamp: false, format: "YYYY-MM-DD HH:mm" },
571
- },
572
- ],
573
- });
574
- }
575
- } else {
576
- if (detailData.value?.json) {
577
- init();
578
- }
579
- }
580
- updateing = false;
581
- }
582
- onActivated(async () => {
583
- updateTemplate();
584
- });
585
-
586
- onBeforeRouteUpdate(() => {
587
- updateTemplate();
588
- });
589
-
590
- onDeactivated(() => {
591
- hiprintTemplate.value = null;
592
- });
593
- onMounted(async () => {
594
- await getDataSourceList();
595
- await getDetail(route.query.code);
596
- if (!hiprintTemplate.value) {
597
- init();
598
- }
599
- });
600
- </script>
601
- <style lang="scss">
602
- .hiprint-designer {
603
- width: calc(100% + 32px);
604
- height: calc(100% - 30px);
605
- overflow: hidden;
606
- display: flex;
607
- flex-direction: column;
608
- background-color: var(--el-bg-color-page);
609
- margin: 0 -16px;
610
- &__header {
611
- padding: 0 16px;
612
- height: 50px;
613
- display: flex;
614
- background-color: var(--el-bg-color);
615
- align-items: center;
616
- box-shadow: var(--el-box-shadow-lighter);
617
- position: relative;
618
- z-index: 1;
619
- // > * {
620
- // margin-right: 10px;
621
- // margin-left: 0 !important;
622
- // }
623
- .percentage {
624
- width: 165px;
625
- }
626
- .el-select {
627
- --el-select-width: auto;
628
- }
629
- .el-form-item {
630
- margin-bottom: 0;
631
- margin-right: 10px;
632
- .el-input {
633
- width: 140px;
634
- .el-input-group__prepend,
635
- .el-input-group__append {
636
- padding: 0 9px;
637
- }
638
- }
639
- }
640
- }
641
- &_title {
642
- font-size: 18px;
643
- font-weight: bold;
644
- line-height: 1.7em;
645
- margin-bottom: 10px;
646
- }
647
- .ep-draggable-item {
648
- user-select: none;
649
- width: 100%;
650
- height: 70px;
651
- display: inline-flex;
652
- flex-direction: column;
653
- align-items: center;
654
- margin-bottom: 10px;
655
- .iconfont {
656
- font-size: 30px;
657
- width: 40px;
658
- height: 40px;
659
- text-align: center;
660
- line-height: 40px;
661
- }
662
- }
663
- &__main {
664
- flex: 1;
665
- overflow: hidden;
666
- display: flex;
667
- &_left {
668
- width: 300px;
669
- overflow: hidden;
670
- background-color: var(--el-color-white);
671
- box-shadow: var(--el-box-shadow-lighter);
672
- .el-scrollbar__view {
673
- padding: 16px;
674
- }
675
- }
676
- &_canvas {
677
- flex: 1;
678
- overflow: hidden;
679
- .el-scrollbar__view {
680
- padding: 20px 10px 40px 20px;
681
- }
682
- }
683
- &_right {
684
- width: 340px;
685
- overflow: hidden;
686
- background-color: var(--el-color-white);
687
- box-shadow: var(--el-box-shadow-lighter);
688
- display: flex;
689
- flex-direction: column;
690
- .prop-tabs {
691
- height: 100%;
692
- overflow: hidden;
693
- display: flex;
694
- flex-direction: column;
695
- .prop-tab-items {
696
- display: flex;
697
- height: 43px;
698
- box-sizing: border-box;
699
- .prop-tab-item {
700
- height: 40px;
701
- line-height: 40px;
702
- flex: 1;
703
- text-align: center;
704
- }
705
- }
706
- .hiprint-option-items.active {
707
- display: block;
708
- padding: 0 6px 0 12px;
709
- }
710
- }
711
- .hiprint-option-items {
712
- height: 100%;
713
- overflow: auto;
714
- padding: 16px;
715
- box-sizing: border-box;
716
- &::-webkit-scrollbar {
717
- width: 4px;
718
- height: 4px;
719
- }
720
-
721
- &::-webkit-scrollbar-thumb {
722
- border-radius: 4px;
723
- background: #bbb;
724
- }
725
- }
726
- .hiprint-designer_title {
727
- padding: 0 10px;
728
- }
729
- #PrintElementOptionSetting {
730
- flex: 1;
731
- overflow: hidden;
732
- }
733
- .el-form {
734
- padding: 10px;
735
- .el-button {
736
- width: 100%;
737
- }
738
- }
739
- }
740
- }
741
- }
742
- </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
+ <el-select
226
+ v-model="listCode"
227
+ @change="tableFieldChange">
228
+ <el-option
229
+ v-for="d in dataSourceList"
230
+ :label="d.label"
231
+ :value="d.value"></el-option>
232
+ </el-select>
233
+ </el-form-item>
234
+ <el-row gutter="10">
235
+ <el-col
236
+ :span="12"
237
+ v-for="col in currentElementObjColumns">
238
+ <el-form-item :label="col.title">
239
+ <el-select v-model="col.field">
240
+ <el-option
241
+ v-for="d in listColumns"
242
+ :value="d"></el-option>
243
+ </el-select>
244
+ </el-form-item>
245
+ </el-col>
246
+ </el-row>
247
+ <el-row gutter="10">
248
+ <el-col :span="12">
249
+ <el-button
250
+ @click="tableColumnCancel"
251
+ type="warning">
252
+ 取消
253
+ </el-button>
254
+ </el-col>
255
+ </el-row>
256
+ </el-form>
257
+ </template>
258
+ </aside>
259
+ </main>
260
+ </section>
261
+ <el-dialog v-model="previewShow">
262
+ <div
263
+ class="print-preview"
264
+ v-html="previewHtml"></div>
265
+ </el-dialog>
266
+ </template>
267
+ <script setup>
268
+ import { onMounted, ref, onActivated, onDeactivated, computed, watch, nextTick } from "vue";
269
+ import { hiprint, defaultElementTypeProvider, fontSize, scale, zIndex, panel, usePaper, useScale, useDataSource, jquery as $ } from "yh-hiprint";
270
+ import { useRoute, onBeforeRouteUpdate } from "vue-router/dist/vue-router";
271
+ import { ElMessageBox } from "element-plus";
272
+ import axios from "@/libs/api.request";
273
+
274
+ const route = useRoute();
275
+ const { paperType, paperWidth, paperHeight, setPaper } = usePaper();
276
+ function setPaperHandler(type) {
277
+ setPaper(type, () => {
278
+ hiprintTemplate.value.setPaper(paperWidth.value, paperHeight.value);
279
+ });
280
+ }
281
+
282
+ const hiprintTemplate = ref(null);
283
+ const canvasRef = ref();
284
+ const { scaleValue, scalePercentage, canZoomIn, canZoomOut, zoomIn, zoomOut } = useScale(() => {
285
+ hiprintTemplate.value.zoom(scaleValue.value);
286
+ canvasRef?.value.update();
287
+ });
288
+
289
+ const previewShow = ref(false);
290
+ const previewHtml = ref("");
291
+ async function previewPrint() {
292
+ let {
293
+ data: { list, json },
294
+ } = await axios.request({
295
+ url: `/printTemplate/data/${detailData.value.code}`,
296
+ method: "post",
297
+ type: "json",
298
+ data: [
299
+ {
300
+ code: "50101820",
301
+ },
302
+ ],
303
+ });
304
+ if (json) {
305
+ if (Array.isArray(list) && list.length > 0) {
306
+ list = list.map((item) => {
307
+ let printData = {};
308
+ let datas = Object.entries(item);
309
+ datas.forEach((arr) => {
310
+ if (Array.isArray(arr[1])) {
311
+ printData[arr[0]] = arr[1];
312
+ } else {
313
+ if (arr[1] !== null) {
314
+ let itemsEntries = Object.entries(arr[1]);
315
+ itemsEntries.forEach((cArr) => {
316
+ printData[`$${arr[0]}[${cArr[0]}]`] = cArr[1];
317
+ });
318
+ }
319
+ }
320
+ });
321
+ return printData;
322
+ });
323
+ } else {
324
+ list = [];
325
+ }
326
+ previewHtml.value = new hiprint.PrintTemplate({ template: JSON.parse(json) }).getHtml(list)[0].innerHTML;
327
+ previewShow.value = true;
328
+ } else {
329
+ ElMessage.warning({
330
+ title: "警告",
331
+ message: "模板配置不存在,请检查",
332
+ });
333
+ }
334
+ }
335
+
336
+ function saveConfig() {
337
+ let arr = [].concat(formCode.value);
338
+ let json = hiprintTemplate.value.getJson();
339
+ json.panels[0].printElements.forEach((item) => {
340
+ if (item.printElementType.type === "table") {
341
+ arr.push(item.options.field);
342
+ }
343
+ });
344
+
345
+ axios
346
+ .request({
347
+ url: "/printTemplate/save",
348
+ method: "post",
349
+ type: "json",
350
+ data: {
351
+ id: detailData.value.id,
352
+ json: JSON.stringify(json),
353
+ dsIds: arr.join(","),
354
+ },
355
+ })
356
+ .then((res) => {
357
+ ElMessage.success({
358
+ message: "恭喜模板保存成功",
359
+ });
360
+ });
361
+ }
362
+
363
+ function clearPrint() {
364
+ hiprintTemplate.value?.clear();
365
+ }
366
+
367
+ const { detailData, getDetail, listCode, dataSourceList, listColumns, formCode, formColumns, dataSourceForm, getDataSourceList } = useDataSource(axios);
368
+
369
+ watch(
370
+ () => formColumns.value,
371
+ (val) => {
372
+ if (val && val.length && hiprintTemplate.value) {
373
+ hiprintTemplate.value.setFields(
374
+ val.map((item) => {
375
+ return {
376
+ field: item,
377
+ text: item,
378
+ };
379
+ })
380
+ );
381
+ }
382
+ },
383
+ {
384
+ deep: true,
385
+ immediate: true,
386
+ }
387
+ );
388
+ let currentElementObj = ref(null);
389
+ let currentElementObjColumns = computed(() => {
390
+ if (currentElementObj.value?.printElementType.type === "table") {
391
+ return currentElementObj.value.options.columns[0]["columns"] || [];
392
+ } else {
393
+ return [];
394
+ }
395
+ });
396
+
397
+ function tableFieldChange(val) {
398
+ currentElementObj.value.updateOption("field", val);
399
+ }
400
+
401
+ function tableColumnCancel() {
402
+ currentElementObj.value = null;
403
+ }
404
+
405
+ function init() {
406
+ try {
407
+ hiprint.init({
408
+ providers: [new defaultElementTypeProvider()],
409
+ });
410
+ hiprint.setConfig();
411
+ hiprint.setConfig({
412
+ optionItems: [fontSize, scale, zIndex],
413
+ movingDistance: 2.5,
414
+ text: {
415
+ tabs: [
416
+ {
417
+ options: [],
418
+ },
419
+ {
420
+ name: "样式",
421
+ options: [
422
+ {
423
+ name: "scale",
424
+ after: "transform",
425
+ hidden: false,
426
+ },
427
+ ],
428
+ },
429
+ ],
430
+ supportOptions: [
431
+ {
432
+ name: "styler",
433
+ hidden: true,
434
+ },
435
+ {
436
+ name: "scale",
437
+ after: "transform",
438
+ hidden: false,
439
+ },
440
+ {
441
+ name: "formatter",
442
+ hidden: true,
443
+ },
444
+ ],
445
+ },
446
+ image: {
447
+ tabs: [
448
+ {
449
+ replace: true,
450
+ name: "基本",
451
+ options: [
452
+ {
453
+ name: "field",
454
+ hidden: false,
455
+ },
456
+ {
457
+ name: "src",
458
+ hidden: false,
459
+ },
460
+ {
461
+ name: "fit",
462
+ hidden: false,
463
+ },
464
+ ],
465
+ },
466
+ ],
467
+ },
468
+ table: {
469
+ tabs: [{ options: [{ name: "field", hidden: true }] }],
470
+ },
471
+ });
472
+
473
+ hiprint.PrintElementTypeManager.buildByHtml($(".ep-draggable-item"));
474
+ $("#hiprint-printTemplate").empty();
475
+ let template = JSON.parse(detailData.value.json) || panel;
476
+ hiprintTemplate.value = new hiprint.PrintTemplate({
477
+ template,
478
+ onImageChooseClick: (target) => {
479
+ // 测试 3秒后修改图片地址值
480
+ setTimeout(() => {
481
+ target.refresh("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtAAAAIIAQMAAAB99EudAAAABlBMVEUmf8vG2O41LStnAAABD0lEQVR42u3XQQqCQBSAYcWFS4/QUTpaHa2jdISWLUJjjMpclJoPGvq+1WsYfiJCZ4oCAAAAAAAAAAAAAAAAAHin6pL9c6H/fOzHbRrP0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0u/SY9LS0tLS0tLS0tLS0n+edm+UlpaWlpaWlpaWlpaW/tl0Ndyzbno7/+tPTJdd1wal69dNa6abx+Lq6TSeYtK7BX/Diek0XULSZZrakPRtV0i6Hu/KIt30q4fM0pvBqvR9mvsQkZaW9gyJT+f5lsnzjR54xAk8mAUeJyMPwYFH98ALx5Jr0kRLLndT7b64UX9QR/0eAAAAAAAAAAAAAAAAAAD/4gpryzr/bja4QgAAAABJRU5ErkJggg==", {
482
+ real: true,
483
+ });
484
+ }, 3000);
485
+ },
486
+ fontList: [
487
+ { title: "微软雅黑", value: "Microsoft YaHei" },
488
+ { title: "黑体", value: "STHeitiSC-Light" },
489
+ { title: "思源黑体", value: "SourceHanSansCN-Normal" },
490
+ { title: "王羲之书法体", value: "王羲之书法体" },
491
+ { title: "宋体", value: "SimSun" },
492
+ { title: "华为楷体", value: "STKaiti" },
493
+ { title: "cursive", value: "cursive" },
494
+ ],
495
+ dataMode: 1,
496
+ history: true,
497
+ onDataChanged: (type, json) => {
498
+ // console.log(type); // 新增、移动、删除、修改(参数调整)、大小、旋转
499
+ // console.log(json); // 返回 template
500
+ },
501
+ onUpdateError: (e) => {
502
+ // console.error(e);
503
+ },
504
+ settingContainer: "#PrintElementOptionSetting",
505
+ paginationContainer: ".hiprint-printPagination",
506
+ });
507
+
508
+ hiprintTemplate.value.design("#hiprint-printTemplate", { grid: true });
509
+ scaleValue.value = hiprintTemplate.value.editingPanel.scale || 1;
510
+ window.ht = hiprintTemplate.value;
511
+
512
+ if (formColumns.value) {
513
+ hiprintTemplate.value.setFields(
514
+ formColumns.value.map((item) => {
515
+ return {
516
+ field: item,
517
+ text: item,
518
+ };
519
+ })
520
+ );
521
+ }
522
+ $(".hiprint-designer").on("mousedown", ".hiprint-printElement", (e) => {
523
+ let t = e.currentTarget;
524
+ let pes = hiprintTemplate.value.editingPanel.printElements;
525
+ let index = pes.map((item) => item.designTarget[0]).indexOf(t);
526
+ let pe = pes[index];
527
+ currentElementObj.value = pe;
528
+ if (pe.options.field) {
529
+ listCode.value = pe.options.field;
530
+ }
531
+ });
532
+ } catch (error) {
533
+ console.log(error.message);
534
+ clearPrint();
535
+ hiprintTemplate.value = null;
536
+ if (error.message.indexOf("setTemplateId") > -1) {
537
+ ElMessageBox.alert("模板有错误,请返回列表手动修改或这清空模板!");
538
+ }
539
+ }
540
+ }
541
+
542
+ let updateing = false;
543
+ async function updateTemplate() {
544
+ if (updateing === true) {
545
+ return false;
546
+ }
547
+ updateing = true;
548
+ if (hiprintTemplate.value) {
549
+ await getDetail(route.query.code);
550
+ if (detailData.value && detailData.value.json) {
551
+ let jsonObj = JSON.parse(detailData.value.json);
552
+ hiprintTemplate.value.update(jsonObj);
553
+ let { width, height } = jsonObj.panels[0];
554
+ paperWidth.value = width;
555
+ paperHeight.value = height;
556
+ hiprintTemplate.value.setPaper(width, height);
557
+ } else {
558
+ hiprintTemplate.value.update({
559
+ panels: [
560
+ {
561
+ index: 0,
562
+ name: 1,
563
+ height: 297,
564
+ width: 210,
565
+ paperHeader: 125,
566
+ paperFooter: 272.5,
567
+ paperNumberLeft: 430,
568
+ paperNumberTop: 5,
569
+ printElements: [],
570
+ watermarkOptions: { content: "", rotate: 25, timestamp: false, format: "YYYY-MM-DD HH:mm" },
571
+ },
572
+ ],
573
+ });
574
+ }
575
+ } else {
576
+ if (detailData.value?.json) {
577
+ init();
578
+ }
579
+ }
580
+ updateing = false;
581
+ }
582
+ onActivated(async () => {
583
+ updateTemplate();
584
+ });
585
+
586
+ onBeforeRouteUpdate(() => {
587
+ updateTemplate();
588
+ });
589
+
590
+ onDeactivated(() => {
591
+ hiprintTemplate.value = null;
592
+ });
593
+ onMounted(async () => {
594
+ await getDataSourceList();
595
+ await getDetail(route.query.code);
596
+ if (!hiprintTemplate.value) {
597
+ init();
598
+ }
599
+ });
600
+ </script>
601
+ <style lang="scss">
602
+ .hiprint-designer {
603
+ width: calc(100% + 32px);
604
+ height: calc(100% - 30px);
605
+ overflow: hidden;
606
+ display: flex;
607
+ flex-direction: column;
608
+ background-color: var(--el-bg-color-page);
609
+ margin: 0 -16px;
610
+ &__header {
611
+ padding: 0 16px;
612
+ height: 50px;
613
+ display: flex;
614
+ background-color: var(--el-bg-color);
615
+ align-items: center;
616
+ box-shadow: var(--el-box-shadow-lighter);
617
+ position: relative;
618
+ z-index: 1;
619
+ // > * {
620
+ // margin-right: 10px;
621
+ // margin-left: 0 !important;
622
+ // }
623
+ .percentage {
624
+ width: 165px;
625
+ }
626
+ .el-select {
627
+ --el-select-width: auto;
628
+ }
629
+ .el-form-item {
630
+ margin-bottom: 0;
631
+ margin-right: 10px;
632
+ .el-input {
633
+ width: 140px;
634
+ .el-input-group__prepend,
635
+ .el-input-group__append {
636
+ padding: 0 9px;
637
+ }
638
+ }
639
+ }
640
+ }
641
+ &_title {
642
+ font-size: 18px;
643
+ font-weight: bold;
644
+ line-height: 1.7em;
645
+ margin-bottom: 10px;
646
+ }
647
+ .ep-draggable-item {
648
+ user-select: none;
649
+ width: 100%;
650
+ height: 70px;
651
+ display: inline-flex;
652
+ flex-direction: column;
653
+ align-items: center;
654
+ margin-bottom: 10px;
655
+ .iconfont {
656
+ font-size: 30px;
657
+ width: 40px;
658
+ height: 40px;
659
+ text-align: center;
660
+ line-height: 40px;
661
+ }
662
+ }
663
+ &__main {
664
+ flex: 1;
665
+ overflow: hidden;
666
+ display: flex;
667
+ &_left {
668
+ width: 300px;
669
+ overflow: hidden;
670
+ background-color: var(--el-color-white);
671
+ box-shadow: var(--el-box-shadow-lighter);
672
+ .el-scrollbar__view {
673
+ padding: 16px;
674
+ }
675
+ }
676
+ &_canvas {
677
+ flex: 1;
678
+ overflow: hidden;
679
+ .el-scrollbar__view {
680
+ padding: 20px 10px 40px 20px;
681
+ }
682
+ }
683
+ &_right {
684
+ width: 340px;
685
+ overflow: hidden;
686
+ background-color: var(--el-color-white);
687
+ box-shadow: var(--el-box-shadow-lighter);
688
+ display: flex;
689
+ flex-direction: column;
690
+ .prop-tabs {
691
+ height: 100%;
692
+ overflow: hidden;
693
+ display: flex;
694
+ flex-direction: column;
695
+ .prop-tab-items {
696
+ display: flex;
697
+ height: 43px;
698
+ box-sizing: border-box;
699
+ .prop-tab-item {
700
+ height: 40px;
701
+ line-height: 40px;
702
+ flex: 1;
703
+ text-align: center;
704
+ }
705
+ }
706
+ .hiprint-option-items.active {
707
+ display: block;
708
+ padding: 0 6px 0 12px;
709
+ }
710
+ }
711
+ .hiprint-option-items {
712
+ height: 100%;
713
+ overflow: auto;
714
+ padding: 16px;
715
+ box-sizing: border-box;
716
+ &::-webkit-scrollbar {
717
+ width: 4px;
718
+ height: 4px;
719
+ }
720
+
721
+ &::-webkit-scrollbar-thumb {
722
+ border-radius: 4px;
723
+ background: #bbb;
724
+ }
725
+ }
726
+ .hiprint-designer_title {
727
+ padding: 0 10px;
728
+ }
729
+ #PrintElementOptionSetting {
730
+ flex: 1;
731
+ overflow: hidden;
732
+ }
733
+ .el-form {
734
+ padding: 10px;
735
+ .el-button {
736
+ width: 100%;
737
+ }
738
+ }
739
+ }
740
+ }
741
+ }
742
+ </style>