|
|
|
|
@ -78,6 +78,17 @@
|
|
|
|
|
</div>
|
|
|
|
|
<div class="hiprint-right">
|
|
|
|
|
<div :id="settingContainerId"></div>
|
|
|
|
|
<div v-if="selectedIconElement" class="hiprint-custom-setting">
|
|
|
|
|
<div class="hiprint-title hiprint-title-inline">图标属性</div>
|
|
|
|
|
<el-form label-position="top" size="small">
|
|
|
|
|
<el-form-item label="图标">
|
|
|
|
|
<IconSelect v-model="selectedIconName" :persistent="false" :teleported="false" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="颜色">
|
|
|
|
|
<el-color-picker v-model="selectedIconColor" show-alpha />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
@ -90,6 +101,7 @@
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { defaultElementTypeProvider, hiprint } from 'vue-plugin-hiprint'
|
|
|
|
|
import Iconify from '@purge-icons/generated'
|
|
|
|
|
import { PrintTemplateApi } from '@/api/mes/printtemplate'
|
|
|
|
|
import { getSimpleDictDataList } from '@/api/system/dict/dict.data'
|
|
|
|
|
import qrCodeImg from '@/assets/imgs/qrCode.png'
|
|
|
|
|
@ -101,6 +113,7 @@ const baseElements = [
|
|
|
|
|
{ tid: 'defaultModule.text', label: '文本' },
|
|
|
|
|
{ tid: 'defaultModule.image', label: '图片' },
|
|
|
|
|
{ tid: 'qrcodeModule.qrcode', label: '二维码' },
|
|
|
|
|
{ tid: 'iconModule.icon', label: '图标' },
|
|
|
|
|
{ tid: 'defaultModule.longText', label: '长文' },
|
|
|
|
|
{ tid: 'defaultModule.table', label: '表格' },
|
|
|
|
|
{ tid: 'defaultModule.hline', label: '横线' },
|
|
|
|
|
@ -109,6 +122,42 @@ const baseElements = [
|
|
|
|
|
{ tid: 'defaultModule.oval', label: '圆形' }
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const defaultIconName = 'ep:star-filled'
|
|
|
|
|
const defaultIconColor = '#409EFF'
|
|
|
|
|
|
|
|
|
|
const buildIconHtml = (iconName?: string, color?: string) => {
|
|
|
|
|
const finalIconName = iconName || defaultIconName
|
|
|
|
|
const finalColor = color || defaultIconColor
|
|
|
|
|
const svg = Iconify.renderSVG(finalIconName, {
|
|
|
|
|
height: '100%',
|
|
|
|
|
width: '100%'
|
|
|
|
|
})
|
|
|
|
|
if (svg) {
|
|
|
|
|
svg.setAttribute('color', finalColor)
|
|
|
|
|
svg.style.color = finalColor
|
|
|
|
|
svg.style.display = 'block'
|
|
|
|
|
svg.style.width = '100%'
|
|
|
|
|
svg.style.height = '100%'
|
|
|
|
|
return svg.outerHTML
|
|
|
|
|
}
|
|
|
|
|
return `<span class="iconify" data-icon="${finalIconName}" data-width="100%" data-height="100%" style="display:inline-block;width:100%;height:100%;color:${finalColor};"></span>`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const buildIconFormatter = () => {
|
|
|
|
|
return `function(value, options) {
|
|
|
|
|
const iconName = options.iconName || '${defaultIconName}';
|
|
|
|
|
const color = options.color || '${defaultIconColor}';
|
|
|
|
|
if (window.__hiprintBuildIconHtml) {
|
|
|
|
|
return window.__hiprintBuildIconHtml(iconName, color);
|
|
|
|
|
}
|
|
|
|
|
return '<span class="iconify" data-icon="' + iconName + '" data-width="100%" data-height="100%" style="display:inline-block;width:100%;height:100%;color:' + color + ';"></span>';
|
|
|
|
|
}`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ensureIconRuntime = () => {
|
|
|
|
|
;(window as any).__hiprintBuildIconHtml = buildIconHtml
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const barcodeElements = ref<{ tid: string; label: string }[]>([])
|
|
|
|
|
const barcodeDictData = ref<any[]>([])
|
|
|
|
|
|
|
|
|
|
@ -199,6 +248,45 @@ const qrcodeProvider = function () {
|
|
|
|
|
return { addElementTypes }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const iconProvider = function () {
|
|
|
|
|
const addElementTypes = function (context: any) {
|
|
|
|
|
context.removePrintElementTypes('iconModule')
|
|
|
|
|
context.addPrintElementTypes('iconModule', [
|
|
|
|
|
new hiprint.PrintElementTypeGroup('图标', [
|
|
|
|
|
{
|
|
|
|
|
tid: 'iconModule.icon',
|
|
|
|
|
title: '图标',
|
|
|
|
|
type: 'html',
|
|
|
|
|
options: {
|
|
|
|
|
left: 12,
|
|
|
|
|
top: 12,
|
|
|
|
|
width: 28,
|
|
|
|
|
height: 28,
|
|
|
|
|
iconName: defaultIconName,
|
|
|
|
|
color: defaultIconColor,
|
|
|
|
|
formatter: buildIconFormatter()
|
|
|
|
|
},
|
|
|
|
|
onRendered: function (target: any) {
|
|
|
|
|
const iconify = (window as any).Iconify
|
|
|
|
|
if (iconify?.scan) {
|
|
|
|
|
iconify.scan(target?.[0] || target)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
supportOptions: [
|
|
|
|
|
{ name: 'iconName' },
|
|
|
|
|
{ name: 'color' },
|
|
|
|
|
{ name: 'widthHeight' },
|
|
|
|
|
{ name: 'coordinate' },
|
|
|
|
|
{ name: 'transform' },
|
|
|
|
|
{ name: 'zIndex' }
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
}
|
|
|
|
|
return { addElementTypes }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const dialogVisible = ref(false)
|
|
|
|
|
const dialogTitle = ref('模板配置')
|
|
|
|
|
const saveLoading = ref(false)
|
|
|
|
|
@ -244,20 +332,111 @@ const scaleMin = 0.5
|
|
|
|
|
|
|
|
|
|
const previewVisible = ref(false)
|
|
|
|
|
const previewHtml = ref('')
|
|
|
|
|
const selectedIconElement = shallowRef<any>(null)
|
|
|
|
|
const selectedIconName = ref(defaultIconName)
|
|
|
|
|
const selectedIconColor = ref(defaultIconColor)
|
|
|
|
|
|
|
|
|
|
let hiprintInited = false
|
|
|
|
|
let hiprintTemplate: any
|
|
|
|
|
let iconSelectEventKey = ''
|
|
|
|
|
let iconSelectHandler: ((payload: any) => void) | undefined
|
|
|
|
|
let clearSettingHandler: (() => void) | undefined
|
|
|
|
|
|
|
|
|
|
const ensureInit = () => {
|
|
|
|
|
if (hiprintInited) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
ensureIconRuntime()
|
|
|
|
|
hiprint.init({
|
|
|
|
|
providers: [new defaultElementTypeProvider(), qrcodeProvider(), barcodeProvider()]
|
|
|
|
|
providers: [new defaultElementTypeProvider(), qrcodeProvider(), barcodeProvider(), iconProvider()]
|
|
|
|
|
})
|
|
|
|
|
hiprintInited = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isIconPrintElement = (printElement: any) => {
|
|
|
|
|
if (!printElement) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
if (printElement?.printElementType?.tid === 'iconModule.icon') {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
const formatter = String(printElement?.options?.formatter || printElement?.printElementType?.formatter || '')
|
|
|
|
|
return Boolean(
|
|
|
|
|
printElement?.printElementType?.type === 'html'
|
|
|
|
|
&& (
|
|
|
|
|
typeof printElement?.options?.iconName === 'string'
|
|
|
|
|
|| formatter.includes('__hiprintBuildIconHtml')
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const normalizeIconPrintElement = (printElement: any) => {
|
|
|
|
|
if (!printElement?.options) {
|
|
|
|
|
return printElement
|
|
|
|
|
}
|
|
|
|
|
if (!printElement.options.iconName) {
|
|
|
|
|
printElement.options.iconName = defaultIconName
|
|
|
|
|
}
|
|
|
|
|
if (!printElement.options.color) {
|
|
|
|
|
printElement.options.color = defaultIconColor
|
|
|
|
|
}
|
|
|
|
|
if (!printElement.options.formatter) {
|
|
|
|
|
printElement.options.formatter = buildIconFormatter()
|
|
|
|
|
}
|
|
|
|
|
return printElement
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setSelectedIconState = (printElement: any | null) => {
|
|
|
|
|
const normalizedPrintElement = printElement ? normalizeIconPrintElement(printElement) : null
|
|
|
|
|
selectedIconElement.value = normalizedPrintElement
|
|
|
|
|
selectedIconName.value = normalizedPrintElement?.options?.iconName || defaultIconName
|
|
|
|
|
selectedIconColor.value = normalizedPrintElement?.options?.color || defaultIconColor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const updateSelectedIconElement = () => {
|
|
|
|
|
const printElement = selectedIconElement.value
|
|
|
|
|
if (!printElement) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
printElement.options.iconName = selectedIconName.value || defaultIconName
|
|
|
|
|
printElement.options.color = selectedIconColor.value || defaultIconColor
|
|
|
|
|
printElement.updateDesignViewFromOptions()
|
|
|
|
|
const iconify = (window as any).Iconify
|
|
|
|
|
if (iconify?.scan) {
|
|
|
|
|
iconify.scan(printElement.designTarget?.[0] || printElement.designTarget)
|
|
|
|
|
}
|
|
|
|
|
;(window as any).hinnn?.event?.trigger(`hiprintTemplateDataChanged_${printElement.templateId}`, '元素修改')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bindIconCustomPanel = (template: any) => {
|
|
|
|
|
const event = (window as any).hinnn?.event
|
|
|
|
|
if (!event) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (iconSelectEventKey && iconSelectHandler) {
|
|
|
|
|
event.off(iconSelectEventKey, iconSelectHandler)
|
|
|
|
|
}
|
|
|
|
|
if (clearSettingHandler) {
|
|
|
|
|
event.off('clearSettingContainer', clearSettingHandler)
|
|
|
|
|
}
|
|
|
|
|
iconSelectEventKey = template?.getPrintElementSelectEventKey?.() || ''
|
|
|
|
|
iconSelectHandler = (payload: any) => {
|
|
|
|
|
const printElement = payload?.printElement
|
|
|
|
|
if (isIconPrintElement(printElement)) {
|
|
|
|
|
setSelectedIconState(printElement)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
setSelectedIconState(null)
|
|
|
|
|
}
|
|
|
|
|
clearSettingHandler = () => {
|
|
|
|
|
setSelectedIconState(null)
|
|
|
|
|
}
|
|
|
|
|
if (iconSelectEventKey) {
|
|
|
|
|
event.on(iconSelectEventKey, iconSelectHandler)
|
|
|
|
|
}
|
|
|
|
|
event.on('clearSettingContainer', clearSettingHandler)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const buildLeftElement = () => {
|
|
|
|
|
const jquery = (window as any).$
|
|
|
|
|
if (!jquery) {
|
|
|
|
|
@ -282,6 +461,7 @@ const buildDesigner = () => {
|
|
|
|
|
template,
|
|
|
|
|
settingContainer: `#${settingContainerId}`
|
|
|
|
|
})
|
|
|
|
|
bindIconCustomPanel(hiprintTemplate)
|
|
|
|
|
hiprintTemplate.design(`#${designerContainerId}`)
|
|
|
|
|
setPaper(curPaperType.value, { width: curPaper.value.width, height: curPaper.value.height })
|
|
|
|
|
hiprintTemplate.zoom(scaleValue.value)
|
|
|
|
|
@ -337,6 +517,7 @@ const clearPaper = () => {
|
|
|
|
|
if (!hiprintTemplate) return
|
|
|
|
|
try {
|
|
|
|
|
hiprintTemplate.clear()
|
|
|
|
|
setSelectedIconState(null)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.error('清空失败')
|
|
|
|
|
}
|
|
|
|
|
@ -367,6 +548,7 @@ const handleSave = async () => {
|
|
|
|
|
|
|
|
|
|
const resetState = () => {
|
|
|
|
|
scaleValue.value = 1
|
|
|
|
|
setSelectedIconState(null)
|
|
|
|
|
curPaper.value = {
|
|
|
|
|
type: 'A4',
|
|
|
|
|
width: 210,
|
|
|
|
|
@ -393,6 +575,14 @@ const open = async (row: any) => {
|
|
|
|
|
const emit = defineEmits(['success'])
|
|
|
|
|
|
|
|
|
|
defineExpose({ open })
|
|
|
|
|
|
|
|
|
|
watch(selectedIconName, () => {
|
|
|
|
|
updateSelectedIconElement()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
watch(selectedIconColor, () => {
|
|
|
|
|
updateSelectedIconElement()
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
@ -442,7 +632,7 @@ defineExpose({ open })
|
|
|
|
|
.hiprint-body {
|
|
|
|
|
height: 75vh;
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 220px 1fr 300px;
|
|
|
|
|
grid-template-columns: 220px 1fr 400px;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -463,11 +653,21 @@ defineExpose({ open })
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-custom-setting {
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
border-top: 1px solid var(--el-border-color-light);
|
|
|
|
|
padding-top: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-title {
|
|
|
|
|
padding: 10px 10px 0;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-title-inline {
|
|
|
|
|
padding: 0 0 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hiprint-drag-wrap {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
|