<template>
|
<div class="matnr-print-property-panel">
|
<ElScrollbar height="100%">
|
<div class="matnr-print-property-panel__content">
|
<section class="matnr-print-property-panel__section">
|
<div class="matnr-print-property-panel__section-title">
|
{{ t('pages.basicInfo.whMat.printTemplate.propertyPanel.sections.templateInfo') }}
|
</div>
|
<div class="matnr-print-property-panel__grid">
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.templateName')
|
}}</span>
|
<ElInput
|
:model-value="template.name"
|
@update:model-value="updateTemplateMeta('name', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.templateCode')
|
}}</span>
|
<ElInput
|
:model-value="template.code"
|
@update:model-value="updateTemplateMeta('code', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{ t('table.status') }}</span>
|
<ElSelect
|
:model-value="template.status"
|
@update:model-value="updateTemplateMeta('status', Number($event))"
|
>
|
<ElOption :value="1" :label="t('common.status.normal')" />
|
<ElOption :value="0" :label="t('common.status.frozen')" />
|
</ElSelect>
|
</label>
|
<label class="matnr-print-property-panel__switch">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.defaultTemplate')
|
}}</span>
|
<ElSwitch
|
:model-value="template.isDefault === 1"
|
@update:model-value="updateTemplateMeta('isDefault', $event ? 1 : 0)"
|
/>
|
</label>
|
<label class="matnr-print-property-panel__span-2">
|
<span>{{ t('table.memo') }}</span>
|
<ElInput
|
type="textarea"
|
:rows="2"
|
:model-value="template.memo"
|
@update:model-value="updateTemplateMeta('memo', $event)"
|
/>
|
</label>
|
</div>
|
</section>
|
|
<section class="matnr-print-property-panel__section">
|
<div class="matnr-print-property-panel__section-title">
|
{{ t('pages.basicInfo.whMat.printTemplate.propertyPanel.sections.canvas') }}
|
</div>
|
<div class="matnr-print-property-panel__grid">
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.widthMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="template.canvas?.width"
|
:min="10"
|
:step="1"
|
controls-position="right"
|
@update:model-value="updateCanvas('width', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.heightMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="template.canvas?.height"
|
:min="10"
|
:step="1"
|
controls-position="right"
|
@update:model-value="updateCanvas('height', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.backgroundColor')
|
}}</span>
|
<ElColorPicker
|
:model-value="template.canvas?.backgroundColor"
|
@change="updateCanvas('backgroundColor', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.gridSizeMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="template.canvas?.gridSize"
|
:min="1"
|
:step="1"
|
controls-position="right"
|
@update:model-value="updateCanvas('gridSize', $event)"
|
/>
|
</label>
|
</div>
|
</section>
|
|
<section class="matnr-print-property-panel__section">
|
<div class="matnr-print-property-panel__section-header">
|
<div class="matnr-print-property-panel__section-title">
|
{{ t('pages.basicInfo.whMat.printTemplate.propertyPanel.sections.element') }}
|
</div>
|
<ElButton
|
v-if="selectedElement"
|
type="danger"
|
text
|
@click="$emit('remove-element', selectedElement.id)"
|
>
|
{{ t('pages.basicInfo.whMat.printTemplate.propertyPanel.actions.removeElement') }}
|
</ElButton>
|
</div>
|
|
<div v-if="!selectedElement" class="matnr-print-property-panel__empty">
|
{{ t('pages.basicInfo.whMat.printTemplate.propertyPanel.empty') }}
|
</div>
|
|
<template v-else>
|
<div class="matnr-print-property-panel__grid">
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.elementType')
|
}}</span>
|
<ElInput :model-value="selectedElement.type" disabled />
|
</label>
|
<label class="matnr-print-property-panel__switch">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.visible')
|
}}</span>
|
<ElSwitch
|
:model-value="selectedElement.visible !== false"
|
@update:model-value="updateElement('visible', $event)"
|
/>
|
</label>
|
<label>
|
<span>X(mm)</span>
|
<ElInputNumber
|
:model-value="selectedElement.x"
|
:min="0"
|
controls-position="right"
|
@update:model-value="updateElement('x', $event)"
|
/>
|
</label>
|
<label>
|
<span>Y(mm)</span>
|
<ElInputNumber
|
:model-value="selectedElement.y"
|
:min="0"
|
controls-position="right"
|
@update:model-value="updateElement('y', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.widthMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.w"
|
:min="1"
|
controls-position="right"
|
@update:model-value="updateElement('w', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.heightMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.h"
|
:min="selectedElement.type === 'image' ? imageMinHeight : 0.4"
|
:step="0.2"
|
controls-position="right"
|
@update:model-value="updateElement('h', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.zIndex')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.zIndex"
|
:min="1"
|
controls-position="right"
|
@update:model-value="updateElement('zIndex', $event)"
|
/>
|
</label>
|
</div>
|
|
<template v-if="selectedElement.type === 'text'">
|
<div class="matnr-print-property-panel__grid">
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.contentMode')
|
}}</span>
|
<ElSelect
|
:model-value="selectedElement.contentMode"
|
@update:model-value="updateElement('contentMode', $event)"
|
>
|
<ElOption
|
value="static"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.staticText')
|
"
|
/>
|
<ElOption
|
value="template"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.templateText')
|
"
|
/>
|
</ElSelect>
|
</label>
|
<label class="matnr-print-property-panel__span-2">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.textContent')
|
}}</span>
|
<ElInput
|
type="textarea"
|
:rows="3"
|
:model-value="selectedElement.contentTemplate"
|
@focus="setPlaceholderTarget('contentTemplate')"
|
@update:model-value="updateElement('contentTemplate', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.fontSizeMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.style?.fontSize"
|
:min="1.8"
|
:step="0.2"
|
controls-position="right"
|
@update:model-value="updateElementStyle('fontSize', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.fontWeight')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.style?.fontWeight"
|
:min="100"
|
:max="900"
|
:step="100"
|
controls-position="right"
|
@update:model-value="updateElementStyle('fontWeight', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.textAlign')
|
}}</span>
|
<ElSelect
|
:model-value="selectedElement.style?.textAlign"
|
@update:model-value="updateElementStyle('textAlign', $event)"
|
>
|
<ElOption
|
value="left"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.alignLeft')
|
"
|
/>
|
<ElOption
|
value="center"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.alignCenter')
|
"
|
/>
|
<ElOption
|
value="right"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.alignRight')
|
"
|
/>
|
</ElSelect>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.textColor')
|
}}</span>
|
<ElColorPicker
|
:model-value="selectedElement.style?.color"
|
@change="updateElementStyle('color', $event)"
|
/>
|
</label>
|
</div>
|
</template>
|
|
<template v-else-if="selectedElement.type === 'barcode'">
|
<div class="matnr-print-property-panel__grid">
|
<label class="matnr-print-property-panel__span-2">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.valueTemplate')
|
}}</span>
|
<ElInput
|
:model-value="selectedElement.valueTemplate"
|
@focus="setPlaceholderTarget('valueTemplate')"
|
@update:model-value="updateElement('valueTemplate', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.symbology')
|
}}</span>
|
<ElInput model-value="CODE128" disabled />
|
</label>
|
<label class="matnr-print-property-panel__switch">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.showText')
|
}}</span>
|
<ElSwitch
|
:model-value="selectedElement.showText !== false"
|
@update:model-value="updateElement('showText', $event)"
|
/>
|
</label>
|
</div>
|
</template>
|
|
<template v-else-if="selectedElement.type === 'qrcode'">
|
<div class="matnr-print-property-panel__grid">
|
<label class="matnr-print-property-panel__span-2">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.valueTemplate')
|
}}</span>
|
<ElInput
|
:model-value="selectedElement.valueTemplate"
|
@focus="setPlaceholderTarget('valueTemplate')"
|
@update:model-value="updateElement('valueTemplate', $event)"
|
/>
|
</label>
|
</div>
|
</template>
|
|
<template v-else-if="selectedElement.type === 'image'">
|
<div class="matnr-print-property-panel__grid">
|
<label class="matnr-print-property-panel__span-2">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.imageSource')
|
}}</span>
|
<ElInput
|
:model-value="selectedElement.src"
|
@update:model-value="updateElement('src', $event)"
|
@change="handleImageSourceChange"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.fitMode')
|
}}</span>
|
<ElSelect
|
:model-value="selectedElement.objectFit"
|
@update:model-value="updateElement('objectFit', $event)"
|
>
|
<ElOption
|
value="contain"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.contain')
|
"
|
/>
|
<ElOption
|
value="cover"
|
:label="t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.cover')"
|
/>
|
<ElOption
|
value="fill"
|
:label="t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.fill')"
|
/>
|
</ElSelect>
|
</label>
|
<label class="matnr-print-property-panel__upload">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.actions.uploadImage')
|
}}</span>
|
<ElUpload
|
accept="image/*"
|
:auto-upload="false"
|
:show-file-list="false"
|
@change="handleImageFileChange"
|
>
|
<ElButton>
|
{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.actions.uploadImage')
|
}}
|
</ElButton>
|
</ElUpload>
|
</label>
|
<label class="matnr-print-property-panel__span-2">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.previewImage')
|
}}</span>
|
<div class="matnr-print-property-panel__image-preview">
|
<ElImage
|
v-if="selectedElement.src"
|
:src="selectedElement.src"
|
fit="contain"
|
preview-teleported
|
class="matnr-print-property-panel__image-preview-inner"
|
/>
|
<div v-else class="matnr-print-property-panel__image-preview-empty"></div>
|
</div>
|
</label>
|
</div>
|
</template>
|
|
<template v-else-if="selectedElement.type === 'line'">
|
<div class="matnr-print-property-panel__grid">
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.direction')
|
}}</span>
|
<ElSelect
|
:model-value="selectedElement.direction"
|
@update:model-value="updateLineDirection($event)"
|
>
|
<ElOption
|
value="horizontal"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.horizontal')
|
"
|
/>
|
<ElOption
|
value="vertical"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.vertical')
|
"
|
/>
|
</ElSelect>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.lineWidthMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.borderWidth"
|
:min="0.2"
|
:step="0.2"
|
controls-position="right"
|
@update:model-value="updateElement('borderWidth', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.lineColor')
|
}}</span>
|
<ElColorPicker
|
:model-value="selectedElement.color"
|
@change="updateElement('color', $event)"
|
/>
|
</label>
|
</div>
|
</template>
|
|
<template v-else-if="selectedElement.type === 'rect'">
|
<div class="matnr-print-property-panel__grid">
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.borderWidthMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.borderWidth"
|
:min="0.2"
|
:step="0.2"
|
controls-position="right"
|
@update:model-value="updateElement('borderWidth', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.radiusMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.radius"
|
:min="0"
|
:step="0.5"
|
controls-position="right"
|
@update:model-value="updateElement('radius', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.borderColor')
|
}}</span>
|
<ElColorPicker
|
:model-value="selectedElement.borderColor"
|
@change="updateElement('borderColor', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.fillColor')
|
}}</span>
|
<ElColorPicker
|
:model-value="selectedElement.backgroundColor"
|
@change="updateElement('backgroundColor', $event)"
|
/>
|
</label>
|
</div>
|
</template>
|
|
<template v-else-if="selectedElement.type === 'table'">
|
<div class="matnr-print-property-panel__grid">
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.fontSizeMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.style?.fontSize"
|
:min="1.8"
|
:step="0.2"
|
controls-position="right"
|
@update:model-value="updateElementStyle('fontSize', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.borderWidthMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="selectedElement.style?.borderWidth"
|
:min="0.2"
|
:step="0.2"
|
controls-position="right"
|
@update:model-value="updateElementStyle('borderWidth', $event)"
|
/>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.textAlign')
|
}}</span>
|
<ElSelect
|
:model-value="selectedElement.style?.textAlign"
|
@update:model-value="updateElementStyle('textAlign', $event)"
|
>
|
<ElOption
|
value="left"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.alignLeft')
|
"
|
/>
|
<ElOption
|
value="center"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.alignCenter')
|
"
|
/>
|
<ElOption
|
value="right"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.alignRight')
|
"
|
/>
|
</ElSelect>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.borderColor')
|
}}</span>
|
<ElColorPicker
|
:model-value="selectedElement.style?.borderColor"
|
@change="updateElementStyle('borderColor', $event)"
|
/>
|
</label>
|
</div>
|
|
<div class="matnr-print-property-panel__section-subtitle">
|
{{ t('pages.basicInfo.whMat.printTemplate.propertyPanel.sections.fieldList') }}
|
</div>
|
<div class="matnr-print-property-panel__table-rows">
|
<div
|
v-for="(row, rowIndex) in tableRows"
|
:key="row.id"
|
class="matnr-print-property-panel__table-row"
|
>
|
<div class="matnr-print-property-panel__table-row-header">
|
<span>
|
{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.rowTitle', {
|
index: rowIndex + 1
|
})
|
}}
|
</span>
|
<ElButton type="danger" text @click="removeTableRow(rowIndex)">
|
{{ t('common.actions.delete') }}
|
</ElButton>
|
</div>
|
<div class="matnr-print-property-panel__grid">
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.leftMode')
|
}}</span>
|
<ElSelect
|
:model-value="row.labelMode"
|
@update:model-value="updateTableRow(rowIndex, 'labelMode', $event)"
|
>
|
<ElOption
|
value="static"
|
:label="
|
t(
|
'pages.basicInfo.whMat.printTemplate.propertyPanel.options.staticText'
|
)
|
"
|
/>
|
<ElOption
|
value="template"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.template')
|
"
|
/>
|
</ElSelect>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.rightMode')
|
}}</span>
|
<ElSelect
|
:model-value="row.valueMode"
|
@update:model-value="updateTableRow(rowIndex, 'valueMode', $event)"
|
>
|
<ElOption
|
value="template"
|
:label="
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.options.template')
|
"
|
/>
|
<ElOption
|
value="static"
|
:label="
|
t(
|
'pages.basicInfo.whMat.printTemplate.propertyPanel.options.staticText'
|
)
|
"
|
/>
|
</ElSelect>
|
</label>
|
<label>
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.rowHeightMm')
|
}}</span>
|
<ElInputNumber
|
:model-value="row.height"
|
:min="4"
|
:step="1"
|
controls-position="right"
|
@update:model-value="updateTableRow(rowIndex, 'height', $event)"
|
/>
|
</label>
|
<label class="matnr-print-property-panel__span-2">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.leftContent')
|
}}</span>
|
<ElInput
|
:model-value="row.labelTemplate"
|
@focus="setPlaceholderTarget('table', rowIndex, 'labelTemplate')"
|
@update:model-value="updateTableRow(rowIndex, 'labelTemplate', $event)"
|
/>
|
</label>
|
<label class="matnr-print-property-panel__span-2">
|
<span>{{
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.fields.rightContent')
|
}}</span>
|
<ElInput
|
:model-value="row.valueTemplate"
|
@focus="setPlaceholderTarget('table', rowIndex, 'valueTemplate')"
|
@update:model-value="updateTableRow(rowIndex, 'valueTemplate', $event)"
|
/>
|
</label>
|
</div>
|
</div>
|
</div>
|
<ElButton size="small" @click="appendTableRow">
|
{{ t('pages.basicInfo.whMat.printTemplate.propertyPanel.actions.addRow') }}
|
</ElButton>
|
</template>
|
</template>
|
</section>
|
</div>
|
</ElScrollbar>
|
</div>
|
</template>
|
|
<script setup>
|
import { computed } from 'vue'
|
import { ElMessage } from 'element-plus'
|
import { useI18n } from 'vue-i18n'
|
import {
|
getFieldListTableRows,
|
getImageMinHeight,
|
updateFieldListTableRows
|
} from '../matnrPrintTemplate.helpers'
|
|
defineOptions({ name: 'MatnrPrintPropertyPanel' })
|
|
const { t } = useI18n()
|
|
const props = defineProps({
|
template: {
|
type: Object,
|
default: () => ({})
|
},
|
selectedElement: {
|
type: Object,
|
default: null
|
}
|
})
|
|
const emit = defineEmits([
|
'update-template-meta',
|
'update-canvas',
|
'update-element',
|
'remove-element',
|
'set-placeholder-target'
|
])
|
|
const tableRows = computed(() => getFieldListTableRows(props.selectedElement))
|
const imageMinHeight = computed(() =>
|
props.selectedElement?.type === 'image'
|
? getImageMinHeight(props.selectedElement?.w, props.selectedElement, props.selectedElement?.h)
|
: 0.4
|
)
|
|
function updateTemplateMeta(field, value) {
|
emit('update-template-meta', { field, value })
|
}
|
|
function updateCanvas(field, value) {
|
emit('update-canvas', { field, value })
|
}
|
|
function updateElement(field, value) {
|
emit('update-element', {
|
id: props.selectedElement?.id,
|
patch: {
|
[field]: value
|
}
|
})
|
}
|
|
function updateElementStyle(field, value) {
|
emit('update-element', {
|
id: props.selectedElement?.id,
|
patch: {
|
style: {
|
...(props.selectedElement?.style || {}),
|
[field]: value
|
}
|
}
|
})
|
}
|
|
function updateLineDirection(direction) {
|
const patch =
|
direction === 'vertical'
|
? {
|
direction,
|
w: Math.max(0.4, Number(props.selectedElement?.borderWidth || 0.4))
|
}
|
: {
|
direction,
|
h: Math.max(0.4, Number(props.selectedElement?.borderWidth || 0.4))
|
}
|
emit('update-element', {
|
id: props.selectedElement?.id,
|
patch
|
})
|
}
|
|
function setPlaceholderTarget(field, rowIndex, rowField) {
|
emit('set-placeholder-target', {
|
elementId: props.selectedElement?.id,
|
field,
|
rowIndex,
|
rowField
|
})
|
}
|
|
function appendTableRow() {
|
const nextRows = [
|
...tableRows.value,
|
{
|
height: 6,
|
labelTemplate: t('pages.basicInfo.whMat.printTemplate.propertyPanel.defaultFieldLabel'),
|
labelMode: 'static',
|
valueTemplate: '{code}',
|
valueMode: 'template'
|
}
|
]
|
syncTableRows(nextRows)
|
}
|
|
function removeTableRow(index) {
|
const nextRows = tableRows.value.filter((_, rowIndex) => rowIndex !== index)
|
syncTableRows(nextRows)
|
}
|
|
function updateTableRow(index, field, value) {
|
const nextRows = tableRows.value.map((row, rowIndex) =>
|
rowIndex === index
|
? {
|
...row,
|
[field]: value
|
}
|
: row
|
)
|
syncTableRows(nextRows)
|
}
|
|
function syncTableRows(rows) {
|
emit('update-element', {
|
id: props.selectedElement?.id,
|
patch: updateFieldListTableRows(props.selectedElement, rows)
|
})
|
}
|
|
function validateImageFile(rawFile) {
|
const isImageFile =
|
String(rawFile?.type || '').startsWith('image/') ||
|
/\.(png|jpe?g|gif|bmp|webp|svg)$/i.test(rawFile?.name || '')
|
if (!isImageFile) {
|
ElMessage.error(
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.messages.uploadOnlyImage')
|
)
|
return false
|
}
|
|
const isLt5MB = Number(rawFile?.size || 0) / 1024 / 1024 < 5
|
if (!isLt5MB) {
|
ElMessage.error(
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.messages.uploadSizeLimit')
|
)
|
return false
|
}
|
|
return true
|
}
|
|
function readFileAsDataUrl(file) {
|
return new Promise((resolve, reject) => {
|
const reader = new FileReader()
|
reader.onload = () => resolve(String(reader.result || ''))
|
reader.onerror = reject
|
reader.readAsDataURL(file)
|
})
|
}
|
|
function loadImageNaturalSize(src) {
|
return new Promise((resolve, reject) => {
|
const image = new Image()
|
image.onload = () => {
|
resolve({
|
naturalWidth: Number(image.naturalWidth) || 0,
|
naturalHeight: Number(image.naturalHeight) || 0
|
})
|
}
|
image.onerror = reject
|
image.src = src
|
})
|
}
|
|
async function applyImageSource(src) {
|
const nextSrc = String(src || '').trim()
|
if (!props.selectedElement?.id) {
|
return
|
}
|
if (!nextSrc) {
|
emit('update-element', {
|
id: props.selectedElement.id,
|
patch: {
|
src: '',
|
naturalWidth: 0,
|
naturalHeight: 0
|
}
|
})
|
return
|
}
|
|
const size = await loadImageNaturalSize(nextSrc)
|
const nextHeight = getImageMinHeight(props.selectedElement?.w, size, props.selectedElement?.h)
|
emit('update-element', {
|
id: props.selectedElement.id,
|
patch: {
|
src: nextSrc,
|
naturalWidth: size.naturalWidth,
|
naturalHeight: size.naturalHeight,
|
h: Math.max(Number(props.selectedElement?.h) || 0, nextHeight)
|
}
|
})
|
}
|
|
async function handleImageSourceChange(value) {
|
const nextSrc = String(value || '').trim()
|
if (!nextSrc) {
|
await applyImageSource('')
|
return
|
}
|
try {
|
await applyImageSource(nextSrc)
|
} catch (error) {
|
ElMessage.error(
|
error?.message ||
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.messages.readImageFailed')
|
)
|
}
|
}
|
|
async function handleImageFileChange(uploadFile) {
|
const rawFile = uploadFile?.raw
|
if (!rawFile || !props.selectedElement?.id) {
|
return
|
}
|
if (!validateImageFile(rawFile)) {
|
return
|
}
|
try {
|
const dataUrl = await readFileAsDataUrl(rawFile)
|
await applyImageSource(dataUrl)
|
} catch (error) {
|
ElMessage.error(
|
error?.message ||
|
t('pages.basicInfo.whMat.printTemplate.propertyPanel.messages.readImageFailed')
|
)
|
}
|
}
|
</script>
|
|
<style scoped>
|
.matnr-print-property-panel {
|
flex: 1;
|
min-height: 0;
|
overflow: hidden;
|
background: #ffffff;
|
}
|
|
.matnr-print-property-panel__content {
|
display: flex;
|
flex-direction: column;
|
gap: 16px;
|
padding: 16px;
|
}
|
|
.matnr-print-property-panel__section {
|
display: flex;
|
flex-direction: column;
|
gap: 12px;
|
padding: 14px;
|
border: 1px solid rgba(148, 163, 184, 0.18);
|
border-radius: 16px;
|
background: linear-gradient(180deg, #ffffff, #f8fafc);
|
}
|
|
.matnr-print-property-panel__section-header {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
gap: 12px;
|
}
|
|
.matnr-print-property-panel__section-title {
|
font-size: 14px;
|
font-weight: 700;
|
color: var(--art-text-primary);
|
}
|
|
.matnr-print-property-panel__section-subtitle {
|
font-size: 13px;
|
font-weight: 600;
|
color: var(--art-text-primary);
|
}
|
|
.matnr-print-property-panel__grid {
|
display: grid;
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
gap: 12px;
|
}
|
|
.matnr-print-property-panel__grid label {
|
display: flex;
|
flex-direction: column;
|
gap: 6px;
|
min-width: 0;
|
font-size: 12px;
|
color: var(--art-text-secondary);
|
}
|
|
.matnr-print-property-panel__span-2 {
|
grid-column: span 2;
|
}
|
|
.matnr-print-property-panel__switch {
|
justify-content: space-between;
|
}
|
|
.matnr-print-property-panel__empty {
|
padding: 18px 14px;
|
border-radius: 12px;
|
background: rgba(241, 245, 249, 0.85);
|
color: var(--art-text-secondary);
|
font-size: 13px;
|
line-height: 1.6;
|
}
|
|
.matnr-print-property-panel__table-rows {
|
display: flex;
|
flex-direction: column;
|
gap: 12px;
|
}
|
|
.matnr-print-property-panel__table-row {
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
padding: 12px;
|
border: 1px solid rgba(148, 163, 184, 0.2);
|
border-radius: 14px;
|
background: rgba(255, 255, 255, 0.9);
|
}
|
|
.matnr-print-property-panel__table-row-header {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
gap: 12px;
|
font-size: 13px;
|
font-weight: 600;
|
color: var(--art-text-primary);
|
}
|
|
.matnr-print-property-panel__upload {
|
justify-content: flex-end;
|
}
|
|
.matnr-print-property-panel__image-preview {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
min-height: 120px;
|
padding: 12px;
|
border: 1px dashed rgba(148, 163, 184, 0.35);
|
border-radius: 12px;
|
background: rgba(248, 250, 252, 0.75);
|
}
|
|
.matnr-print-property-panel__image-preview-inner {
|
width: 100%;
|
height: 140px;
|
border-radius: 8px;
|
overflow: hidden;
|
background: #ffffff;
|
}
|
|
.matnr-print-property-panel__image-preview-empty {
|
width: 100%;
|
height: 96px;
|
border-radius: 10px;
|
border: 1px dashed rgba(148, 163, 184, 0.5);
|
background:
|
linear-gradient(135deg, rgba(226, 232, 240, 0.75), rgba(241, 245, 249, 0.35)),
|
linear-gradient(45deg, rgba(203, 213, 225, 0.35), transparent);
|
}
|
|
@media (max-width: 1280px) {
|
.matnr-print-property-panel__grid {
|
grid-template-columns: minmax(0, 1fr);
|
}
|
|
.matnr-print-property-panel__span-2 {
|
grid-column: span 1;
|
}
|
}
|
</style>
|