diff --git a/src/components/QrcodeActionCard/index.vue b/src/components/QrcodeActionCard/index.vue index 7477e779..6d8eb2c6 100644 --- a/src/components/QrcodeActionCard/index.vue +++ b/src/components/QrcodeActionCard/index.vue @@ -39,6 +39,7 @@ import request from '@/config/axios' import HiprintPreviewDialog from '@/components/HiprintPreviewDialog/index.vue' import { createImageViewer } from '@/components/ImageViewer' import { ElLoading } from 'element-plus' +import { getSimpleDictDataList } from '@/api/system/dict/dict.data' const { t } = useI18n() const message = useMessage() @@ -66,6 +67,7 @@ const props = withDefaults( templateJsonUrl?: string templateJson?: any printData?: Record + printTemplateType?: string | number }>(), { imageUrl: '', @@ -88,7 +90,8 @@ const props = withDefaults( printMaxHeight: 120, templateJsonUrl: '', templateJson: undefined, - printData: () => ({}) + printData: () => ({}), + printTemplateType: undefined } ) @@ -99,14 +102,49 @@ const emit = defineEmits<{ const hiprintPreviewDialogRef = ref() const refreshLoading = ref(false) +type TemplateFieldMap = { + qrcodeField?: string + nameField?: string + codeField?: string +} + +let printTemplateDictCache: any[] | undefined + const showActionMask = computed(() => props.showPreview || props.showPrint || props.showRefresh) +const parseTemplateFieldMap = (remark: any): TemplateFieldMap | undefined => { + const parts = String(remark || '') + .split(',') + .map((item) => item.trim()) + .filter(Boolean) + if (!parts.length) return undefined + return { + qrcodeField: parts[0], + nameField: parts[1], + codeField: parts[2] || parts[1] + } +} + +const getTemplateFieldMap = async (): Promise => { + if (props.printTemplateType === undefined || props.printTemplateType === null || props.printTemplateType === '') { + return undefined + } + if (!printTemplateDictCache) { + printTemplateDictCache = await getSimpleDictDataList() + } + const matched = (printTemplateDictCache || []).find( + (item: any) => item.dictType === 'print_template_type' && String(item.value) === String(props.printTemplateType) + ) + return parseTemplateFieldMap(matched?.remark) +} + const buildQrcodeTemplateJson = ( qrcodeUrl: string, - printId: string, + printData: Record, imageWidth: number, imageHeight: number, - paperHeight: number + paperHeight: number, + fieldMap?: TemplateFieldMap ) => ({ panels: [ { @@ -124,7 +162,7 @@ const buildQrcodeTemplateJson = ( width: imageWidth, height: imageHeight, src: qrcodeUrl, - field: 'qrcodeUrl', + field: fieldMap?.qrcodeField || 'qrcodeUrl', title: '二维码图片', testData: qrcodeUrl }, @@ -133,23 +171,7 @@ const buildQrcodeTemplateJson = ( type: 'image' } }, - { - options: { - left: 0, - top: imageHeight + 2, - height: 10, - width: imageWidth, - testData: printId, - title: 'ID', - field: 'printId', - textAlign: 'center', - fontSize: 10 - }, - printElementType: { - title: '文本', - type: 'text' - } - } + ...buildDefaultTextElements(printData, imageWidth, imageHeight, fieldMap) ], paperNumberDisabled: true, paperNumberContinue: true, @@ -159,6 +181,60 @@ const buildQrcodeTemplateJson = ( ] }) +const buildDefaultTextElements = ( + printData: Record, + imageWidth: number, + imageHeight: number, + fieldMap?: TemplateFieldMap +) => { + const fields = [ + { title: '名称', field: fieldMap?.nameField }, + { title: '编码', field: fieldMap?.codeField } + ].filter((item) => item.field) + + if (!fields.length) { + const printId = printData.printId === undefined || printData.printId === null ? '' : String(printData.printId) + if (!printId) return [] + return [ + { + options: { + left: 0, + top: imageHeight + 2, + height: 10, + width: imageWidth, + testData: printId, + title: 'ID', + field: 'printId', + textAlign: 'center', + fontSize: 10 + }, + printElementType: { + title: '文本', + type: 'text' + } + } + ] + } + + return fields.map((item, index) => ({ + options: { + left: 0, + top: imageHeight + 2 + index * 12, + height: 10, + width: imageWidth, + testData: printData[item.field!] === undefined || printData[item.field!] === null ? '' : String(printData[item.field!]), + title: item.title, + field: item.field, + textAlign: 'center', + fontSize: 10 + }, + printElementType: { + title: '文本', + type: 'text' + } + })) +} + const getImageSize = (src: string) => new Promise<{ width: number; height: number }>((resolve, reject) => { const img = new Image() @@ -208,33 +284,44 @@ const handlePreview = () => { }) } -const replaceTemplateValues = (templateJson: any, printData: Record) => { +const resolveElementFieldKey = (element: any, fieldMap?: TemplateFieldMap) => { + const fieldKey = typeof element?.options?.field === 'string' ? element.options.field.trim() : '' + const qidKey = typeof element?.options?.qid === 'string' ? element.options.qid.trim() : '' + const title = String(element?.options?.title || element?.printElementType?.title || '').trim() + + if (fieldMap) { + if (title.includes('二维码')) return fieldMap.qrcodeField || fieldKey || qidKey + if (title.includes('名称')) return fieldMap.nameField || fieldKey || qidKey + if (title.includes('编码') || title.includes('条码') || title.includes('文本')) return fieldMap.codeField || fieldKey || qidKey + } + + return fieldKey || qidKey +} + +const replaceTemplateValues = (templateJson: any, printData: Record, fieldMap?: TemplateFieldMap) => { if (!templateJson?.panels) return templateJson - + return { ...templateJson, panels: templateJson.panels.map((panel: any) => ({ ...panel, printElements: panel.printElements?.map((element: any) => { - if (!element?.options?.qid) return element - - const qid = element.options.qid - const value = printData[qid] - + const valueKey = resolveElementFieldKey(element, fieldMap) + if (!valueKey) return element + + const value = printData[valueKey] if (value === undefined || value === null) return element - + const newOptions = { ...element.options } - - if (qid === 'qrcodeUrl') { + + if (element?.printElementType?.type === 'image') { newOptions.src = value newOptions.testData = value } else { - newOptions.field = qid - if (newOptions.testData === undefined || newOptions.testData === '') { - newOptions.testData = String(value) - } + newOptions.field = valueKey + newOptions.testData = String(value) } - + return { ...element, options: newOptions @@ -249,6 +336,7 @@ const handlePrint = async () => { let templateJson: any let printData: Record + const templateFieldMap = await getTemplateFieldMap() printData = { qrcodeUrl: props.imageUrl, @@ -257,12 +345,12 @@ const handlePrint = async () => { } if (props.templateJson) { - templateJson = replaceTemplateValues(props.templateJson, printData) + templateJson = replaceTemplateValues(props.templateJson, printData, templateFieldMap) } else if (props.templateJsonUrl) { try { const response = await request.get({ url: props.templateJsonUrl }) templateJson = typeof response.data === 'string' ? JSON.parse(response.data) : response.data - templateJson = replaceTemplateValues(templateJson, printData) + templateJson = replaceTemplateValues(templateJson, printData, templateFieldMap) } catch (error) { console.error('获取打印模板失败', error) message.error('获取打印模板失败') @@ -273,10 +361,11 @@ const handlePrint = async () => { const imageWidth = printSize.width const imageHeight = printSize.height const printId = props.printId === undefined || props.printId === null ? '' : String(props.printId) - const idAreaHeight = printId ? 14 : 0 - const paperHeight = imageHeight + idAreaHeight - - templateJson = buildQrcodeTemplateJson(props.imageUrl, printId, imageWidth, imageHeight, paperHeight) + const hasMappedFields = Boolean(templateFieldMap?.nameField || templateFieldMap?.codeField) + const textLineCount = hasMappedFields ? [templateFieldMap?.nameField, templateFieldMap?.codeField].filter(Boolean).length : (printId ? 1 : 0) + const paperHeight = imageHeight + textLineCount * 12 + (textLineCount ? 4 : 0) + + templateJson = buildQrcodeTemplateJson(props.imageUrl, printData, imageWidth, imageHeight, paperHeight, templateFieldMap) } const paperSize = templateJson?.panels?.[0] ? { diff --git a/src/views/erp/component/product/ProductForm.vue b/src/views/erp/component/product/ProductForm.vue index 6ee2127b..4c4566c8 100644 --- a/src/views/erp/component/product/ProductForm.vue +++ b/src/views/erp/component/product/ProductForm.vue @@ -109,6 +109,7 @@ {{ item.label }} -
条码类型
-
-
- +
+
+
{{ group.label }}
+
+
+ {{ item.label }} +
+
@@ -158,7 +162,18 @@ const ensureIconRuntime = () => { ;(window as any).__hiprintBuildIconHtml = buildIconHtml } -const barcodeElements = ref<{ tid: string; label: string }[]>([]) +type BarcodeElementItem = { + tid: string + label: string +} + +type BarcodeElementGroup = { + value: string | number + label: string + elements: BarcodeElementItem[] +} + +const barcodeGroups = ref([]) const barcodeDictData = ref([]) const loadBarcodeDictData = async () => { @@ -166,12 +181,15 @@ const loadBarcodeDictData = async () => { const res = await getSimpleDictDataList() const filtered = (res || []).filter((item: any) => item.dictType === 'print_template_type') barcodeDictData.value = filtered - const elements: { tid: string; label: string }[] = [] - filtered.forEach((item: any) => { - elements.push({ tid: `barcodeModule.${item.value}_qrcode`, label: `${item.label}
二维码` }) - elements.push({ tid: `barcodeModule.${item.value}_text`, label: `${item.label}
文本` }) - }) - barcodeElements.value = elements + barcodeGroups.value = filtered.map((item: any) => ({ + value: item.value, + label: item.label, + elements: [ + { tid: `barcodeModule.${item.value}_qrcode`, label: '二维码' }, + { tid: `barcodeModule.${item.value}_name`, label: '名称' }, + { tid: `barcodeModule.${item.value}_code`, label: '编码' } + ] + })) } catch (e) { console.error('加载条码字典数据失败', e) } @@ -186,12 +204,13 @@ const barcodeProvider = function () { const remark = item.remark || '' const parts = remark.split(',').map((s: string) => s.trim()) const qrcodeField = parts[0] || '' - const textField = parts[1] || '' + const nameField = parts[1] || '' + const codeField = parts[2] || parts[1] || '' groups.push( new hiprint.PrintElementTypeGroup(item.label, [ { tid: `barcodeModule.${item.value}_qrcode`, - title: `${item.label}`, + title: '二维码', type: 'image', options: { field: qrcodeField, @@ -199,17 +218,31 @@ const barcodeProvider = function () { testData: qrCodeImg, width: 80, height: 80, - title: `${item.label}
二维码` + title: '二维码' } }, { - tid: `barcodeModule.${item.value}_text`, - title: `${item.label}`, + tid: `barcodeModule.${item.value}_name`, + title: '名称', type: 'text', options: { - field: textField, + field: nameField, testData: '', - title: `${item.label}
文本`, + title: '名称', + fontSize: 10, + textAlign: 'center', + width: 80, + height: 16 + } + }, + { + tid: `barcodeModule.${item.value}_code`, + title: '编码', + type: 'text', + options: { + field: codeField, + testData: '', + title: '编码', fontSize: 10, textAlign: 'center', width: 80, @@ -472,7 +505,7 @@ const buildLeftElement = () => { return } hiprint.PrintElementTypeManager.buildByHtml(jquery(`#${dragContainerId} .ep-draggable-item`)) - if (barcodeElements.value.length) { + if (barcodeGroups.value.length) { hiprint.PrintElementTypeManager.buildByHtml(jquery(`#${barcodeDragContainerId} .ep-draggable-item`)) } } @@ -687,10 +720,18 @@ watch(selectedIconColor, () => { font-weight: 600; } +.hiprint-title-group { + padding-top: 12px; +} + .hiprint-title-inline { padding: 0 0 12px; } +.hiprint-barcode-groups { + padding-bottom: 10px; +} + .hiprint-drag-wrap { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); @@ -698,6 +739,11 @@ watch(selectedIconColor, () => { padding: 10px; } +.hiprint-drag-wrap-compact { + grid-template-columns: repeat(3, minmax(0, 1fr)); + padding-top: 8px; +} + .hiprint-item { min-height: 56px; display: flex;