|
|
|
|
@ -0,0 +1,765 @@
|
|
|
|
|
<template>
|
|
|
|
|
<Dialog v-model="dialogVisible" :title="dialogTitle" width="92%" :fullscreen="false" top="4vh">
|
|
|
|
|
<div class="hiprint-preview">
|
|
|
|
|
<div class="hiprint-body">
|
|
|
|
|
<div class="hiprint-left">
|
|
|
|
|
<div class="hiprint-title">基础元素</div>
|
|
|
|
|
<div :id="dragContainerId" class="hiprint-drag-wrap">
|
|
|
|
|
<div v-for="item in baseElements" :key="item.tid" class="ep-draggable-item hiprint-item" :tid="item.tid">
|
|
|
|
|
<span>{{ item.label }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="hiprint-title">报表元素</div>
|
|
|
|
|
<div :id="chartDragContainerId" class="hiprint-drag-wrap">
|
|
|
|
|
<div v-for="item in chartElements" :key="item.tid" class="ep-draggable-item hiprint-item" :tid="item.tid">
|
|
|
|
|
<span>{{ item.label }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="hiprint-right-area">
|
|
|
|
|
<div class="hiprint-toolbar">
|
|
|
|
|
<div class="hiprint-paper">
|
|
|
|
|
<el-button v-for="(value, type) in paperTypes" :key="type" size="small"
|
|
|
|
|
:type="curPaperType === type ? 'primary' : 'default'" @click="setPaper(type, value)">
|
|
|
|
|
{{ type }}
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-popover placement="bottom-start" :width="260" trigger="click" v-model:visible="paperPopVisible">
|
|
|
|
|
<template #reference>
|
|
|
|
|
<el-button size="small" :type="curPaperType === 'other' ? 'primary' : 'default'">自定义纸张</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
<div class="paper-pop">
|
|
|
|
|
<div class="paper-pop-title">设置纸张宽高(mm)</div>
|
|
|
|
|
<div class="paper-pop-form">
|
|
|
|
|
<el-input-number v-model="paperWidth" :precision="1" :min="1" controls-position="right" />
|
|
|
|
|
<span>x</span>
|
|
|
|
|
<el-input-number v-model="paperHeight" :precision="1" :min="1" controls-position="right" />
|
|
|
|
|
</div>
|
|
|
|
|
<el-button class="mt-8px" size="small" type="primary" @click="setPaperOther">确定</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</el-popover>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="hiprint-zoom">
|
|
|
|
|
<el-button size="small" @click="changeScale(false)">
|
|
|
|
|
<Icon icon="ep:zoom-out" />
|
|
|
|
|
</el-button>
|
|
|
|
|
<div class="zoom-value">{{ (scaleValue * 100).toFixed(0) }}%</div>
|
|
|
|
|
<el-button size="small" @click="changeScale(true)">
|
|
|
|
|
<Icon icon="ep:zoom-in" />
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button size="small" @click="rotatePaper">
|
|
|
|
|
<Icon icon="ep:refresh-right" class="mr-4px" />
|
|
|
|
|
旋转
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="margin-left: 40px;">
|
|
|
|
|
<el-button size="small" type="warning" @click="handlePreview">
|
|
|
|
|
<Icon icon="ep:view" class="mr-4px" />
|
|
|
|
|
预览
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-popconfirm title="是否确认清空?" @confirm="clearPaper">
|
|
|
|
|
<template #reference>
|
|
|
|
|
<el-button size="small" type="danger">
|
|
|
|
|
<Icon icon="ep:delete" class="mr-4px" />
|
|
|
|
|
清空
|
|
|
|
|
</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-popconfirm>
|
|
|
|
|
<el-button type="primary" size="small" :loading="saveLoading" @click="handleSave">
|
|
|
|
|
<Icon icon="ep:check" class="mr-4px" />
|
|
|
|
|
{{ t('common.save') }}
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="hiprint-toolbar">
|
|
|
|
|
<div class="hiprint-align">
|
|
|
|
|
<el-button-group>
|
|
|
|
|
<el-tooltip content="左对齐" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsAlign('left')">
|
|
|
|
|
<Icon icon="ep:arrow-left-bold" />
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
<el-tooltip content="水平居中" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsAlign('vertical')">
|
|
|
|
|
<Icon icon="ep:minus" />
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
<el-tooltip content="右对齐" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsAlign('right')">
|
|
|
|
|
<Icon icon="ep:arrow-right-bold" />
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
</el-button-group>
|
|
|
|
|
<el-button-group style="margin-left: 6px;">
|
|
|
|
|
<el-tooltip content="顶部对齐" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsAlign('top')">
|
|
|
|
|
<Icon icon="ep:arrow-up-bold" />
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
<el-tooltip content="垂直居中" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsAlign('horizontal')">
|
|
|
|
|
<Icon icon="ep:minus" style="transform: rotate(90deg);" />
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
<el-tooltip content="底部对齐" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsAlign('bottom')">
|
|
|
|
|
<Icon icon="ep:arrow-down-bold" />
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
</el-button-group>
|
|
|
|
|
<el-divider direction="vertical" />
|
|
|
|
|
<el-tooltip content="水平间距 10px" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsSpace(true)">
|
|
|
|
|
<Icon icon="ep:rank" class="mr-4px" />水平间距
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
<el-tooltip content="垂直间距 10px" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsSpace(false)">
|
|
|
|
|
<Icon icon="ep:rank" style="transform: rotate(90deg);" class="mr-4px" />垂直间距
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
<el-divider direction="vertical" />
|
|
|
|
|
<el-tooltip content="横向分散" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsAlign('distributeHor')">
|
|
|
|
|
<Icon icon="ep:sort" /> 横向分散
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
<el-tooltip content="纵向分散" placement="bottom">
|
|
|
|
|
<el-button size="small" @click="setElsAlign('distributeVer')">
|
|
|
|
|
<Icon icon="ep:sort" style="transform: rotate(90deg);" /> 纵向分散
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="hiprint-printPagination"></div>
|
|
|
|
|
|
|
|
|
|
<div class="hiprint-design-row">
|
|
|
|
|
<div class="hiprint-center">
|
|
|
|
|
<div :id="designerContainerId"></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="hiprint-right">
|
|
|
|
|
<div :id="settingContainerId"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<el-dialog v-model="previewVisible" title="打印预览" width="70%" top="2vh" append-to-body>
|
|
|
|
|
<div v-html="previewHtml" style="background: #fff;"></div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</Dialog>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { defaultElementTypeProvider, hiprint } from 'vue-plugin-hiprint'
|
|
|
|
|
import { PrintTemplateApi } from '@/api/mes/printtemplate'
|
|
|
|
|
import qrCodeImg from '@/assets/imgs/qrCode.png'
|
|
|
|
|
import * as echarts from 'echarts'
|
|
|
|
|
|
|
|
|
|
const { t } = useI18n()
|
|
|
|
|
const message = useMessage()
|
|
|
|
|
|
|
|
|
|
const baseElements = [
|
|
|
|
|
{ tid: 'defaultModule.text', label: '文本' },
|
|
|
|
|
{ tid: 'defaultModule.image', label: '图片' },
|
|
|
|
|
{ tid: 'qrcodeModule.qrcode', label: '二维码' },
|
|
|
|
|
{ tid: 'defaultModule.longText', label: '长文' },
|
|
|
|
|
{ tid: 'defaultModule.table', label: '表格' },
|
|
|
|
|
{ tid: 'defaultModule.hline', label: '横线' },
|
|
|
|
|
{ tid: 'defaultModule.vline', label: '竖线' },
|
|
|
|
|
{ tid: 'defaultModule.rect', label: '矩形' },
|
|
|
|
|
{ tid: 'defaultModule.oval', label: '圆形' }
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const chartElements = [
|
|
|
|
|
{ tid: 'chartModule.lineChart', label: '折线图' },
|
|
|
|
|
{ tid: 'chartModule.barChart', label: '柱状图' },
|
|
|
|
|
{ tid: 'chartModule.donutChart', label: '环形图' }
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const qrcodeProvider = function () {
|
|
|
|
|
const addElementTypes = function (context: any) {
|
|
|
|
|
context.removePrintElementTypes('qrcodeModule')
|
|
|
|
|
context.addPrintElementTypes('qrcodeModule', [
|
|
|
|
|
new hiprint.PrintElementTypeGroup('二维码', [
|
|
|
|
|
{
|
|
|
|
|
tid: 'qrcodeModule.qrcode',
|
|
|
|
|
title: '二维码',
|
|
|
|
|
type: 'image',
|
|
|
|
|
options: {
|
|
|
|
|
field: '',
|
|
|
|
|
src: qrCodeImg,
|
|
|
|
|
testData: qrCodeImg,
|
|
|
|
|
width: 80,
|
|
|
|
|
height: 80,
|
|
|
|
|
title: '二维码'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
}
|
|
|
|
|
return { addElementTypes }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const chartProvider = function () {
|
|
|
|
|
const addElementTypes = function (context: any) {
|
|
|
|
|
context.removePrintElementTypes('chartModule')
|
|
|
|
|
context.addPrintElementTypes('chartModule', [
|
|
|
|
|
new hiprint.PrintElementTypeGroup('图表', [
|
|
|
|
|
{
|
|
|
|
|
tid: 'chartModule.lineChart',
|
|
|
|
|
title: '折线图',
|
|
|
|
|
type: 'html',
|
|
|
|
|
options: {
|
|
|
|
|
left: 12,
|
|
|
|
|
top: 12,
|
|
|
|
|
height: 200,
|
|
|
|
|
width: 300,
|
|
|
|
|
formatter: `function(t, e, printData) {
|
|
|
|
|
if (window.echarts) {
|
|
|
|
|
var ptW = e.width || 300;
|
|
|
|
|
var ptH = e.height || 200;
|
|
|
|
|
var pxW = Math.round(ptW * 4 / 3);
|
|
|
|
|
var pxH = Math.round(ptH * 4 / 3);
|
|
|
|
|
var dom = document.createElement("div");
|
|
|
|
|
dom.style.width = pxW + "px";
|
|
|
|
|
dom.style.height = pxH + "px";
|
|
|
|
|
var chart = echarts.init(dom, null, {renderer: "svg"});
|
|
|
|
|
chart.setOption({
|
|
|
|
|
animation: false,
|
|
|
|
|
grid: { top: '3%', right: '3%', bottom: '8%', left: '8%', containLabel: true },
|
|
|
|
|
xAxis: { type: 'category', data: ['1月','2月','3月','4月','5月','6月'] },
|
|
|
|
|
yAxis: { type: 'value' },
|
|
|
|
|
series: [{
|
|
|
|
|
data: printData?.lineData || [120, 200, 150, 80, 70, 110],
|
|
|
|
|
type: 'line',
|
|
|
|
|
smooth: true,
|
|
|
|
|
lineStyle: { color: '#5470c6', width: 2 },
|
|
|
|
|
itemStyle: { color: '#5470c6' },
|
|
|
|
|
areaStyle: { color: 'rgba(84,112,198,0.15)' }
|
|
|
|
|
}]
|
|
|
|
|
});
|
|
|
|
|
var resizeObserver = null;
|
|
|
|
|
var tryObserve = function() {
|
|
|
|
|
if (dom.parentNode) {
|
|
|
|
|
var parentW = dom.parentNode.clientWidth;
|
|
|
|
|
var parentH = dom.parentNode.clientHeight;
|
|
|
|
|
if (parentW > 20 && parentH > 20) {
|
|
|
|
|
dom.style.width = parentW + "px";
|
|
|
|
|
dom.style.height = parentH + "px";
|
|
|
|
|
chart.resize();
|
|
|
|
|
resizeObserver = new ResizeObserver(function(entries) {
|
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
|
|
|
var entry = entries[i];
|
|
|
|
|
var w = entry.contentRect.width;
|
|
|
|
|
var h = entry.contentRect.height;
|
|
|
|
|
if (w > 20 && h > 20) {
|
|
|
|
|
dom.style.width = w + "px";
|
|
|
|
|
dom.style.height = h + "px";
|
|
|
|
|
chart.resize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
resizeObserver.observe(dom.parentNode);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
requestAnimationFrame(tryObserve);
|
|
|
|
|
};
|
|
|
|
|
requestAnimationFrame(tryObserve);
|
|
|
|
|
return dom;
|
|
|
|
|
} else {
|
|
|
|
|
return '<div style="width:100%;height:100%;border:1px dashed #ccc;display:flex;align-items:center;justify-content:center;color:#999;font-size:12px;">ECharts 未加载,请刷新页面重试</div>';
|
|
|
|
|
}
|
|
|
|
|
}`
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
tid: 'chartModule.barChart',
|
|
|
|
|
title: '柱状图',
|
|
|
|
|
type: 'html',
|
|
|
|
|
options: {
|
|
|
|
|
left: 12,
|
|
|
|
|
top: 12,
|
|
|
|
|
height: 200,
|
|
|
|
|
width: 300,
|
|
|
|
|
formatter: `function(t, e, printData) {
|
|
|
|
|
if (window.echarts) {
|
|
|
|
|
var ptW = e.width || 300;
|
|
|
|
|
var ptH = e.height || 200;
|
|
|
|
|
var pxW = Math.round(ptW * 4 / 3);
|
|
|
|
|
var pxH = Math.round(ptH * 4 / 3);
|
|
|
|
|
var dom = document.createElement("div");
|
|
|
|
|
dom.style.width = pxW + "px";
|
|
|
|
|
dom.style.height = pxH + "px";
|
|
|
|
|
var chart = echarts.init(dom, null, {renderer: "svg"});
|
|
|
|
|
chart.setOption({
|
|
|
|
|
animation: false,
|
|
|
|
|
grid: { top: '3%', right: '3%', bottom: '8%', left: '8%', containLabel: true },
|
|
|
|
|
xAxis: { type: 'category', data: ['1月','2月','3月','4月','5月','6月'] },
|
|
|
|
|
yAxis: { type: 'value' },
|
|
|
|
|
series: [{
|
|
|
|
|
data: printData?.barData || [120, 200, 150, 80, 70, 110],
|
|
|
|
|
type: 'bar',
|
|
|
|
|
itemStyle: { color: '#91cc75' }
|
|
|
|
|
}]
|
|
|
|
|
});
|
|
|
|
|
var resizeObserver = null;
|
|
|
|
|
var tryObserve = function() {
|
|
|
|
|
if (dom.parentNode) {
|
|
|
|
|
var parentW = dom.parentNode.clientWidth;
|
|
|
|
|
var parentH = dom.parentNode.clientHeight;
|
|
|
|
|
if (parentW > 20 && parentH > 20) {
|
|
|
|
|
dom.style.width = parentW + "px";
|
|
|
|
|
dom.style.height = parentH + "px";
|
|
|
|
|
chart.resize();
|
|
|
|
|
resizeObserver = new ResizeObserver(function(entries) {
|
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
|
|
|
var entry = entries[i];
|
|
|
|
|
var w = entry.contentRect.width;
|
|
|
|
|
var h = entry.contentRect.height;
|
|
|
|
|
if (w > 20 && h > 20) {
|
|
|
|
|
dom.style.width = w + "px";
|
|
|
|
|
dom.style.height = h + "px";
|
|
|
|
|
chart.resize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
resizeObserver.observe(dom.parentNode);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
requestAnimationFrame(tryObserve);
|
|
|
|
|
};
|
|
|
|
|
requestAnimationFrame(tryObserve);
|
|
|
|
|
return dom;
|
|
|
|
|
} else {
|
|
|
|
|
return '<div style="width:100%;height:100%;border:1px dashed #ccc;display:flex;align-items:center;justify-content:center;color:#999;font-size:12px;">ECharts 未加载,请刷新页面重试</div>';
|
|
|
|
|
}
|
|
|
|
|
}`
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
tid: 'chartModule.donutChart',
|
|
|
|
|
title: '环形图',
|
|
|
|
|
type: 'html',
|
|
|
|
|
options: {
|
|
|
|
|
left: 12,
|
|
|
|
|
top: 12,
|
|
|
|
|
height: 200,
|
|
|
|
|
width: 200,
|
|
|
|
|
formatter: `function(t, e, printData) {
|
|
|
|
|
if (window.echarts) {
|
|
|
|
|
var ptW = e.width || 200;
|
|
|
|
|
var ptH = e.height || 200;
|
|
|
|
|
var pxW = Math.round(ptW * 4 / 3);
|
|
|
|
|
var pxH = Math.round(ptH * 4 / 3);
|
|
|
|
|
var dom = document.createElement("div");
|
|
|
|
|
dom.style.width = pxW + "px";
|
|
|
|
|
dom.style.height = pxH + "px";
|
|
|
|
|
var chart = echarts.init(dom, null, {renderer: "svg"});
|
|
|
|
|
chart.setOption({
|
|
|
|
|
animation: false,
|
|
|
|
|
tooltip: { trigger: 'item' },
|
|
|
|
|
legend: { bottom: '3%', left: 'center' },
|
|
|
|
|
series: [{
|
|
|
|
|
type: 'pie',
|
|
|
|
|
radius: ['35%', '75%'],
|
|
|
|
|
center: ['50%', '50%'],
|
|
|
|
|
label: { show: false },
|
|
|
|
|
emphasis: { scale: false },
|
|
|
|
|
data: printData?.pieData || [
|
|
|
|
|
{ value: 1048, name: '分类一' },
|
|
|
|
|
{ value: 735, name: '分类二' },
|
|
|
|
|
{ value: 580, name: '分类三' },
|
|
|
|
|
{ value: 484, name: '分类四' },
|
|
|
|
|
{ value: 300, name: '分类五' }
|
|
|
|
|
]
|
|
|
|
|
}]
|
|
|
|
|
});
|
|
|
|
|
var resizeObserver = null;
|
|
|
|
|
var tryObserve = function() {
|
|
|
|
|
if (dom.parentNode) {
|
|
|
|
|
var parentW = dom.parentNode.clientWidth;
|
|
|
|
|
var parentH = dom.parentNode.clientHeight;
|
|
|
|
|
if (parentW > 20 && parentH > 20) {
|
|
|
|
|
dom.style.width = parentW + "px";
|
|
|
|
|
dom.style.height = parentH + "px";
|
|
|
|
|
chart.resize();
|
|
|
|
|
resizeObserver = new ResizeObserver(function(entries) {
|
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
|
|
|
var entry = entries[i];
|
|
|
|
|
var w = entry.contentRect.width;
|
|
|
|
|
var h = entry.contentRect.height;
|
|
|
|
|
if (w > 20 && h > 20) {
|
|
|
|
|
dom.style.width = w + "px";
|
|
|
|
|
dom.style.height = h + "px";
|
|
|
|
|
chart.resize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
resizeObserver.observe(dom.parentNode);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
requestAnimationFrame(tryObserve);
|
|
|
|
|
};
|
|
|
|
|
requestAnimationFrame(tryObserve);
|
|
|
|
|
return dom;
|
|
|
|
|
} else {
|
|
|
|
|
return '<div style="width:100%;height:100%;border:1px dashed #ccc;display:flex;align-items:center;justify-content:center;color:#999;font-size:12px;">ECharts 未加载,请刷新页面重试</div>';
|
|
|
|
|
}
|
|
|
|
|
}`
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
}
|
|
|
|
|
return { addElementTypes }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const dialogVisible = ref(false)
|
|
|
|
|
const dialogTitle = ref('模板配置')
|
|
|
|
|
const saveLoading = ref(false)
|
|
|
|
|
const currentRow = ref<any>(null)
|
|
|
|
|
const currentTemplateJson = ref<Record<string, any> | undefined>(undefined)
|
|
|
|
|
|
|
|
|
|
const instanceId = `hiprint-designer-${Math.random().toString(36).slice(2)}`
|
|
|
|
|
const dragContainerId = `${instanceId}-drag`
|
|
|
|
|
const chartDragContainerId = `${instanceId}-chart-drag`
|
|
|
|
|
const designerContainerId = `${instanceId}-designer`
|
|
|
|
|
const settingContainerId = `${instanceId}-setting`
|
|
|
|
|
|
|
|
|
|
const paperTypes = {
|
|
|
|
|
A3: { width: 420, height: 296.6 },
|
|
|
|
|
A4: { width: 210, height: 296.6 },
|
|
|
|
|
A5: { width: 210, height: 147.6 },
|
|
|
|
|
B3: { width: 500, height: 352.6 },
|
|
|
|
|
B4: { width: 250, height: 352.6 },
|
|
|
|
|
B5: { width: 250, height: 175.6 }
|
|
|
|
|
}
|
|
|
|
|
const curPaper = ref({
|
|
|
|
|
type: 'A4',
|
|
|
|
|
width: 210,
|
|
|
|
|
height: 296.6
|
|
|
|
|
})
|
|
|
|
|
const paperPopVisible = ref(false)
|
|
|
|
|
const paperWidth = ref(220)
|
|
|
|
|
const paperHeight = ref(80)
|
|
|
|
|
const curPaperType = computed(() => {
|
|
|
|
|
let type = 'other'
|
|
|
|
|
for (const [key, value] of Object.entries(paperTypes)) {
|
|
|
|
|
if (value.width === curPaper.value.width && value.height === curPaper.value.height) {
|
|
|
|
|
type = key
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return type
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const scaleValue = ref(1)
|
|
|
|
|
const scaleMax = 5
|
|
|
|
|
const scaleMin = 0.5
|
|
|
|
|
|
|
|
|
|
const previewVisible = ref(false)
|
|
|
|
|
const previewHtml = ref('')
|
|
|
|
|
|
|
|
|
|
let hiprintInited = false
|
|
|
|
|
let hiprintTemplate: any
|
|
|
|
|
|
|
|
|
|
const ensureInit = () => {
|
|
|
|
|
if (hiprintInited) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
;(window as any).echarts = echarts
|
|
|
|
|
hiprint.init({
|
|
|
|
|
providers: [new defaultElementTypeProvider(), qrcodeProvider(), chartProvider()]
|
|
|
|
|
})
|
|
|
|
|
hiprintInited = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const buildLeftElement = () => {
|
|
|
|
|
const jquery = (window as any).$
|
|
|
|
|
if (!jquery) {
|
|
|
|
|
message.warning('未检测到 jQuery,无法加载拖拽元素')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
hiprint.PrintElementTypeManager.buildByHtml(jquery(`#${dragContainerId} .ep-draggable-item`))
|
|
|
|
|
hiprint.PrintElementTypeManager.buildByHtml(jquery(`#${chartDragContainerId} .ep-draggable-item`))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const buildDesigner = () => {
|
|
|
|
|
const jquery = (window as any).$
|
|
|
|
|
if (!jquery) {
|
|
|
|
|
message.warning('未检测到 jQuery,无法初始化打印设计器')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
jquery(`#${designerContainerId}`).empty()
|
|
|
|
|
const template = currentTemplateJson.value || undefined
|
|
|
|
|
hiprintTemplate = new hiprint.PrintTemplate({
|
|
|
|
|
template,
|
|
|
|
|
settingContainer: `#${settingContainerId}`,
|
|
|
|
|
paginationContainer: '.hiprint-printPagination',
|
|
|
|
|
})
|
|
|
|
|
hiprintTemplate.design(`#${designerContainerId}`)
|
|
|
|
|
setPaper(curPaperType.value, { width: curPaper.value.width, height: curPaper.value.height })
|
|
|
|
|
hiprintTemplate.zoom(scaleValue.value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setPaper = (type: string, value: { width: number; height: number }) => {
|
|
|
|
|
if (!hiprintTemplate) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const width = Number(value.width)
|
|
|
|
|
const height = Number(value.height)
|
|
|
|
|
curPaper.value = { type, width, height }
|
|
|
|
|
hiprintTemplate.setPaper(width, height)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setPaperOther = () => {
|
|
|
|
|
paperPopVisible.value = false
|
|
|
|
|
setPaper('other', { width: Number(paperWidth.value), height: Number(paperHeight.value) })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const changeScale = (isZoomIn: boolean) => {
|
|
|
|
|
if (!hiprintTemplate) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
let nextScale = scaleValue.value
|
|
|
|
|
if (isZoomIn) {
|
|
|
|
|
nextScale += 0.1
|
|
|
|
|
if (nextScale > scaleMax) nextScale = scaleMax
|
|
|
|
|
} else {
|
|
|
|
|
nextScale -= 0.1
|
|
|
|
|
if (nextScale < scaleMin) nextScale = scaleMin
|
|
|
|
|
}
|
|
|
|
|
scaleValue.value = nextScale
|
|
|
|
|
hiprintTemplate.zoom(nextScale)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const rotatePaper = () => {
|
|
|
|
|
if (!hiprintTemplate) return
|
|
|
|
|
hiprintTemplate.rotatePaper()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handlePreview = () => {
|
|
|
|
|
if (!hiprintTemplate) return
|
|
|
|
|
const jquery = (window as any).$
|
|
|
|
|
const htmlResult = hiprintTemplate.getHtml({})
|
|
|
|
|
if (htmlResult && jquery) {
|
|
|
|
|
previewHtml.value = jquery('<div>').append(htmlResult).html() || ''
|
|
|
|
|
}
|
|
|
|
|
previewVisible.value = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const clearPaper = () => {
|
|
|
|
|
if (!hiprintTemplate) return
|
|
|
|
|
try {
|
|
|
|
|
hiprintTemplate.clear()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.error('清空失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setElsAlign = (e: string) => {
|
|
|
|
|
if (!hiprintTemplate) return
|
|
|
|
|
try {
|
|
|
|
|
hiprintTemplate.setElsAlign(e)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.error('对齐操作失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setElsSpace = (isHorizontal: boolean) => {
|
|
|
|
|
if (!hiprintTemplate) return
|
|
|
|
|
try {
|
|
|
|
|
hiprintTemplate.setElsSpace(10, isHorizontal)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.error('间距调整失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleSave = async () => {
|
|
|
|
|
if (!hiprintTemplate) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const templateJson = hiprintTemplate.getJson()
|
|
|
|
|
saveLoading.value = true
|
|
|
|
|
try {
|
|
|
|
|
await PrintTemplateApi.updatePrintTemplate({
|
|
|
|
|
id: currentRow.value.id,
|
|
|
|
|
templateCode: currentRow.value.templateCode,
|
|
|
|
|
templateName: currentRow.value.templateName,
|
|
|
|
|
templateType: currentRow.value.templateType,
|
|
|
|
|
templateJson: JSON.stringify(templateJson),
|
|
|
|
|
} as any)
|
|
|
|
|
message.success(t('common.updateSuccess'))
|
|
|
|
|
dialogVisible.value = false
|
|
|
|
|
emit('success')
|
|
|
|
|
} finally {
|
|
|
|
|
saveLoading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const resetState = () => {
|
|
|
|
|
scaleValue.value = 1
|
|
|
|
|
curPaper.value = {
|
|
|
|
|
type: 'A4',
|
|
|
|
|
width: 210,
|
|
|
|
|
height: 296.6
|
|
|
|
|
}
|
|
|
|
|
paperWidth.value = 220
|
|
|
|
|
paperHeight.value = 80
|
|
|
|
|
paperPopVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const open = async (row: any) => {
|
|
|
|
|
currentRow.value = row
|
|
|
|
|
dialogTitle.value = `${t('TemplateManagement.PrintTemplate.designTitle')}${row.templateName ? ' - ' + row.templateName : ''}`
|
|
|
|
|
currentTemplateJson.value = row.templateJson ? (typeof row.templateJson === 'string' ? JSON.parse(row.templateJson) : row.templateJson) : undefined
|
|
|
|
|
resetState()
|
|
|
|
|
dialogVisible.value = true
|
|
|
|
|
await nextTick()
|
|
|
|
|
ensureInit()
|
|
|
|
|
buildLeftElement()
|
|
|
|
|
buildDesigner()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['success'])
|
|
|
|
|
|
|
|
|
|
defineExpose({ open })
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.hiprint-preview {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-toolbar {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-paper {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 2px;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-align {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 2px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-printPagination {
|
|
|
|
|
:deep(.hiprint-printPagination-content) {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-zoom {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.zoom-value {
|
|
|
|
|
width: 56px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
color: var(--el-text-color-regular);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.paper-pop-title {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.paper-pop-form {
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-body {
|
|
|
|
|
height: 75vh;
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-left {
|
|
|
|
|
width: 220px;
|
|
|
|
|
background: var(--el-bg-color);
|
|
|
|
|
border: 1px solid var(--el-border-color-light);
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-right-area {
|
|
|
|
|
flex: 1;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-design-row {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
flex: 1;
|
|
|
|
|
height: 0;
|
|
|
|
|
min-height: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-center {
|
|
|
|
|
flex: 1;
|
|
|
|
|
height: 100%;
|
|
|
|
|
background: var(--el-bg-color);
|
|
|
|
|
border: 1px solid var(--el-border-color-light);
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: auto;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-right {
|
|
|
|
|
width: 300px;
|
|
|
|
|
height: 100%;
|
|
|
|
|
background: var(--el-bg-color);
|
|
|
|
|
border: 1px solid var(--el-border-color-light);
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: auto;
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-title {
|
|
|
|
|
padding: 10px 10px 0;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-drag-wrap {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
gap: 10px;
|
|
|
|
|
padding: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-item {
|
|
|
|
|
min-height: 56px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
border: 1px solid var(--el-border-color);
|
|
|
|
|
background: var(--el-fill-color-light);
|
|
|
|
|
color: var(--el-text-color-primary);
|
|
|
|
|
cursor: grab;
|
|
|
|
|
}
|
|
|
|
|
</style>
|