| | |
| | | "zoomOut": "Zoom Out", |
| | | "zoomIn": "Zoom In", |
| | | "zoomFit": "Auto Fit", |
| | | "elements": { |
| | | "text": "Text", |
| | | "barcode": "Barcode", |
| | | "qrcode": "QR Code", |
| | | "line": "Line", |
| | | "rect": "Rectangle", |
| | | "table": "Field Table" |
| | | } |
| | | "elements": { |
| | | "text": "Text", |
| | | "barcode": "Barcode", |
| | | "qrcode": "QR Code", |
| | | "image": "Image", |
| | | "line": "Line", |
| | | "rect": "Rectangle", |
| | | "table": "Field Table" |
| | | } |
| | | }, |
| | | "fieldPanel": { |
| | | "title": "Available Fields", |
| | |
| | | "fontSizeMm": "Font Size (mm)", |
| | | "fontWeight": "Font Weight", |
| | | "textAlign": "Alignment", |
| | | "textColor": "Text Color", |
| | | "valueTemplate": "Value Template", |
| | | "symbology": "Symbology", |
| | | "showText": "Show Text", |
| | | "direction": "Direction", |
| | | "textColor": "Text Color", |
| | | "valueTemplate": "Value Template", |
| | | "imageSource": "Image Source", |
| | | "fitMode": "Fit Mode", |
| | | "previewImage": "Image Preview", |
| | | "symbology": "Symbology", |
| | | "showText": "Show Text", |
| | | "direction": "Direction", |
| | | "lineWidthMm": "Line Width (mm)", |
| | | "lineColor": "Line Color", |
| | | "borderWidthMm": "Border Width (mm)", |
| | |
| | | "rightContent": "Right Content" |
| | | }, |
| | | "options": { |
| | | "staticText": "Static Text", |
| | | "templateText": "Template Placeholder", |
| | | "template": "Template", |
| | | "alignLeft": "Left", |
| | | "alignCenter": "Center", |
| | | "alignRight": "Right", |
| | | "staticText": "Static Text", |
| | | "templateText": "Template Placeholder", |
| | | "template": "Template", |
| | | "contain": "Contain", |
| | | "cover": "Cover", |
| | | "fill": "Fill", |
| | | "alignLeft": "Left", |
| | | "alignCenter": "Center", |
| | | "alignRight": "Right", |
| | | "horizontal": "Horizontal", |
| | | "vertical": "Vertical" |
| | | }, |
| | | "actions": { |
| | | "removeElement": "Delete Element", |
| | | "addRow": "Add Row" |
| | | }, |
| | | "empty": "Select an element on the canvas to edit its position, size, and content here.", |
| | | "rowTitle": "Row {index}", |
| | | "defaultFieldLabel": "Field Label" |
| | | "actions": { |
| | | "removeElement": "Delete Element", |
| | | "addRow": "Add Row", |
| | | "uploadImage": "Upload Image" |
| | | }, |
| | | "messages": { |
| | | "uploadOnlyImage": "Only image files are allowed", |
| | | "uploadSizeLimit": "Image size must be smaller than 5MB", |
| | | "readImageFailed": "Failed to read the image" |
| | | }, |
| | | "empty": "Select an element on the canvas to edit its position, size, and content here.", |
| | | "rowTitle": "Row {index}", |
| | | "defaultFieldLabel": "Field Label" |
| | | }, |
| | | "dialog": { |
| | | "title": "Print", |
| | |
| | | "zoomOut": "缩小", |
| | | "zoomIn": "放大", |
| | | "zoomFit": "自适应", |
| | | "elements": { |
| | | "text": "文本", |
| | | "barcode": "一维码", |
| | | "qrcode": "二维码", |
| | | "line": "直线", |
| | | "rect": "矩形", |
| | | "table": "字段表格" |
| | | } |
| | | "elements": { |
| | | "text": "文本", |
| | | "barcode": "一维码", |
| | | "qrcode": "二维码", |
| | | "image": "图片", |
| | | "line": "直线", |
| | | "rect": "矩形", |
| | | "table": "字段表格" |
| | | } |
| | | }, |
| | | "fieldPanel": { |
| | | "title": "可用字段", |
| | |
| | | "fontSizeMm": "字号(mm)", |
| | | "fontWeight": "字重", |
| | | "textAlign": "对齐", |
| | | "textColor": "文字颜色", |
| | | "valueTemplate": "码值模板", |
| | | "symbology": "编码制式", |
| | | "showText": "显示文字", |
| | | "direction": "方向", |
| | | "textColor": "文字颜色", |
| | | "valueTemplate": "码值模板", |
| | | "imageSource": "图片地址", |
| | | "fitMode": "填充方式", |
| | | "previewImage": "图片预览", |
| | | "symbology": "编码制式", |
| | | "showText": "显示文字", |
| | | "direction": "方向", |
| | | "lineWidthMm": "粗细(mm)", |
| | | "lineColor": "线条颜色", |
| | | "borderWidthMm": "边框宽度(mm)", |
| | |
| | | "rightContent": "右列内容" |
| | | }, |
| | | "options": { |
| | | "staticText": "静态文本", |
| | | "templateText": "占位符模板", |
| | | "template": "模板", |
| | | "alignLeft": "左对齐", |
| | | "alignCenter": "居中", |
| | | "alignRight": "右对齐", |
| | | "staticText": "静态文本", |
| | | "templateText": "占位符模板", |
| | | "template": "模板", |
| | | "contain": "完整显示", |
| | | "cover": "铺满裁切", |
| | | "fill": "拉伸铺满", |
| | | "alignLeft": "左对齐", |
| | | "alignCenter": "居中", |
| | | "alignRight": "右对齐", |
| | | "horizontal": "横线", |
| | | "vertical": "竖线" |
| | | }, |
| | | "actions": { |
| | | "removeElement": "删除元素", |
| | | "addRow": "新增一行" |
| | | }, |
| | | "empty": "选择画布中的元素后,在这里编辑位置、尺寸和字段内容。", |
| | | "rowTitle": "第 {index} 行", |
| | | "defaultFieldLabel": "字段名" |
| | | "actions": { |
| | | "removeElement": "删除元素", |
| | | "addRow": "新增一行", |
| | | "uploadImage": "上传图片" |
| | | }, |
| | | "messages": { |
| | | "uploadOnlyImage": "只能上传图片文件", |
| | | "uploadSizeLimit": "图片大小不能超过 5MB", |
| | | "readImageFailed": "读取图片失败" |
| | | }, |
| | | "empty": "选择画布中的元素后,在这里编辑位置、尺寸和字段内容。", |
| | | "rowTitle": "第 {index} 行", |
| | | "defaultFieldLabel": "字段名" |
| | | }, |
| | | "dialog": { |
| | | "title": "打印", |
| | |
| | | return color || fallback |
| | | } |
| | | |
| | | function getImageNaturalSize(element = {}) { |
| | | const naturalWidth = normalizeNumber(element?.naturalWidth, 0) |
| | | const naturalHeight = normalizeNumber(element?.naturalHeight, 0) |
| | | return { |
| | | naturalWidth, |
| | | naturalHeight |
| | | } |
| | | } |
| | | |
| | | export function getImageMinHeight(width, element = {}, fallback = 8) { |
| | | const { naturalWidth, naturalHeight } = getImageNaturalSize(element) |
| | | if (naturalWidth > 0 && naturalHeight > 0) { |
| | | return Number( |
| | | ((Math.max(1, normalizeNumber(width, 1)) * naturalHeight) / naturalWidth).toFixed(2) |
| | | ) |
| | | } |
| | | return Math.max(8, normalizeNumber(fallback, 8)) |
| | | } |
| | | |
| | | function createElementId(prefix = 'el') { |
| | | return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}` |
| | | } |
| | |
| | | |
| | | if (base.type === 'qrcode') { |
| | | base.resolvedValue = resolveTemplatePlaceholders(base.valueTemplate, record) |
| | | return base |
| | | } |
| | | |
| | | if (base.type === 'image') { |
| | | base.resolvedSrc = normalizeText(base.src) |
| | | base.objectFit = ['contain', 'cover', 'fill'].includes(base.objectFit) |
| | | ? base.objectFit |
| | | : 'contain' |
| | | return base |
| | | } |
| | | |
| | |
| | | normalized.valueTemplate = normalizeText(element?.valueTemplate) |
| | | normalized.w = Math.max(8, normalizeNumber(element?.w, 18)) |
| | | normalized.h = Math.max(8, normalizeNumber(element?.h, 18)) |
| | | return normalized |
| | | } |
| | | |
| | | if (normalized.type === 'image') { |
| | | normalized.src = normalizeText(element?.src) |
| | | normalized.objectFit = ['contain', 'cover', 'fill'].includes(element?.objectFit) |
| | | ? element.objectFit |
| | | : 'contain' |
| | | normalized.naturalWidth = Math.max(0, normalizeNumber(element?.naturalWidth, 0)) |
| | | normalized.naturalHeight = Math.max(0, normalizeNumber(element?.naturalHeight, 0)) |
| | | normalized.w = Math.max(8, normalizeNumber(element?.w, 20)) |
| | | normalized.h = Math.max( |
| | | getImageMinHeight(normalized.w, element, normalizeNumber(element?.h, 20)), |
| | | normalizeNumber(element?.h, 20) |
| | | ) |
| | | return normalized |
| | | } |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | if (type === 'image') { |
| | | return normalizeElement({ |
| | | ...common, |
| | | w: 20, |
| | | h: 20, |
| | | src: '', |
| | | naturalWidth: 0, |
| | | naturalHeight: 0, |
| | | objectFit: 'contain' |
| | | }) |
| | | } |
| | | |
| | | if (type === 'line') { |
| | | return normalizeElement({ |
| | | ...common, |
| | |
| | | /> |
| | | </div> |
| | | |
| | | <div v-else-if="element.type === 'image'" class="matnr-print-element__image"> |
| | | <img |
| | | v-if="element.resolvedSrc" |
| | | :src="element.resolvedSrc" |
| | | :style="getImageStyle(element)" |
| | | alt="" |
| | | draggable="false" |
| | | /> |
| | | <div v-else class="matnr-print-element__image-placeholder"></div> |
| | | </div> |
| | | |
| | | <div |
| | | v-else-if="element.type === 'line'" |
| | | class="matnr-print-element__line" |
| | |
| | | borderRadius: editorMode.value |
| | | ? mmToPx(element.radius || 0, props.scale) |
| | | : `${element.radius || 0}mm` |
| | | } |
| | | } |
| | | |
| | | function getImageStyle(element) { |
| | | return { |
| | | objectFit: element.objectFit || 'contain' |
| | | } |
| | | } |
| | | |
| | |
| | | .matnr-print-element__text, |
| | | .matnr-print-element__barcode, |
| | | .matnr-print-element__qrcode, |
| | | .matnr-print-element__image, |
| | | .matnr-print-element__rect, |
| | | .matnr-print-element__table { |
| | | width: 100%; |
| | |
| | | height: 100%; |
| | | } |
| | | |
| | | .matnr-print-element__image { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: rgba(248, 250, 252, 0.6); |
| | | } |
| | | |
| | | .matnr-print-element__image img { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: block; |
| | | user-select: none; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | .matnr-print-element__image-placeholder { |
| | | width: 100%; |
| | | height: 100%; |
| | | border: 1px dashed rgba(148, 163, 184, 0.65); |
| | | 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); |
| | | } |
| | | |
| | | .matnr-print-element__line { |
| | | position: absolute; |
| | | inset: 0; |
| | |
| | | }}</span> |
| | | <ElInputNumber |
| | | :model-value="selectedElement.h" |
| | | :min="0.4" |
| | | :min="selectedElement.type === 'image' ? imageMinHeight : 0.4" |
| | | :step="0.2" |
| | | controls-position="right" |
| | | @update:model-value="updateElement('h', $event)" |
| | |
| | | @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> |
| | |
| | | |
| | | <script setup> |
| | | import { computed } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { getFieldListTableRows, updateFieldListTableRows } from '../matnrPrintTemplate.helpers' |
| | | import { |
| | | getFieldListTableRows, |
| | | getImageMinHeight, |
| | | updateFieldListTableRows |
| | | } from '../matnrPrintTemplate.helpers' |
| | | |
| | | defineOptions({ name: 'MatnrPrintPropertyPanel' }) |
| | | |
| | |
| | | ]) |
| | | |
| | | 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 }) |
| | |
| | | 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> |
| | | |
| | |
| | | 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); |
| | |
| | | { type: 'text', label: t('pages.basicInfo.whMat.printTemplate.toolbar.elements.text') }, |
| | | { type: 'barcode', label: t('pages.basicInfo.whMat.printTemplate.toolbar.elements.barcode') }, |
| | | { type: 'qrcode', label: t('pages.basicInfo.whMat.printTemplate.toolbar.elements.qrcode') }, |
| | | { type: 'image', label: t('pages.basicInfo.whMat.printTemplate.toolbar.elements.image') }, |
| | | { type: 'line', label: t('pages.basicInfo.whMat.printTemplate.toolbar.elements.line') }, |
| | | { type: 'rect', label: t('pages.basicInfo.whMat.printTemplate.toolbar.elements.rect') }, |
| | | { type: 'table', label: t('pages.basicInfo.whMat.printTemplate.toolbar.elements.table') } |
| | |
| | | .matnr-print-element__text, |
| | | .matnr-print-element__barcode, |
| | | .matnr-print-element__qrcode, |
| | | .matnr-print-element__image, |
| | | .matnr-print-element__rect, |
| | | .matnr-print-element__table { |
| | | width: 100%; |
| | |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | .matnr-print-element__image { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | .matnr-print-element__image img { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: block; |
| | | } |
| | | .matnr-print-element__table { |
| | | border-collapse: collapse; |
| | | table-layout: fixed; |
| | |
| | | </style> |
| | | <scr` + |
| | | `ipt> |
| | | window.addEventListener('load', () => { |
| | | function waitForImages() { |
| | | const images = Array.from(document.images || []); |
| | | const pending = images.filter((image) => !image.complete); |
| | | if (!pending.length) { |
| | | return Promise.resolve(); |
| | | } |
| | | return Promise.all( |
| | | pending.map( |
| | | (image) => |
| | | new Promise((resolve) => { |
| | | const done = () => resolve(); |
| | | image.addEventListener('load', done, { once: true }); |
| | | image.addEventListener('error', done, { once: true }); |
| | | }) |
| | | ) |
| | | ); |
| | | } |
| | | window.addEventListener('load', async () => { |
| | | await waitForImages(); |
| | | window.focus(); |
| | | setTimeout(() => window.print(), 60); |
| | | setTimeout(() => window.print(), 120); |
| | | }); |
| | | window.addEventListener('afterprint', () => { |
| | | window.close(); |
| | |
| | | implements MatnrPrintTemplateService { |
| | | |
| | | private static final Set<String> SUPPORTED_ELEMENT_TYPES = Collections.unmodifiableSet( |
| | | new LinkedHashSet<>(Arrays.asList("text", "barcode", "qrcode", "line", "rect", "table")) |
| | | new LinkedHashSet<>(Arrays.asList("text", "barcode", "qrcode", "image", "line", "rect", "table")) |
| | | ); |
| | | |
| | | @Override |
| | |
| | | throw new CoolException("二维码元素值模板不能为空"); |
| | | } |
| | | break; |
| | | case "image": |
| | | if (normalizeText(element.getString("src")).isEmpty()) { |
| | | throw new CoolException("图片元素地址不能为空"); |
| | | } |
| | | String objectFit = normalizeText(element.getString("objectFit")); |
| | | if (!objectFit.isEmpty() && !Arrays.asList("contain", "cover", "fill").contains(objectFit)) { |
| | | throw new CoolException("图片元素填充方式仅支持 contain、cover 或 fill"); |
| | | } |
| | | break; |
| | | case "table": |
| | | if (element.getJSONArray("columns") == null) { |
| | | throw new CoolException("表格元素 columns 不能为空"); |
| | |
| | | @Autowired |
| | | private DictDataService dictDataService; |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:list')") |
| | | @PreAuthorize("hasAuthority('system:dictType:list')") |
| | | @PostMapping("/dictData/page") |
| | | public R page(@RequestBody Map<String, Object> map) { |
| | | BaseParam baseParam = buildParam(map, BaseParam.class); |
| | |
| | | return R.ok().add(buildPageRowsUtils.rowsMap(dictDataService.page(pageParam, pageParam.buildWrapper(true)))); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:list')") |
| | | @PreAuthorize("hasAuthority('system:dictType:list')") |
| | | @PostMapping("/dictData/list") |
| | | public R list(@RequestBody Map<String, Object> map) { |
| | | return R.ok().add(buildPageRowsUtils.rowsMap(dictDataService.list())); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:list')") |
| | | @PreAuthorize("hasAuthority('system:dictType:list')") |
| | | @PostMapping({"/dictData/many/{ids}", "/dictDatas/many/{ids}"}) |
| | | public R many(@PathVariable Long[] ids) { |
| | | return R.ok().add(buildPageRowsUtils.rowsMap(dictDataService.listByIds(Arrays.asList(ids)))); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:list')") |
| | | @PreAuthorize("hasAuthority('system:dictType:list')") |
| | | @GetMapping("/dictData/{id}") |
| | | public R get(@PathVariable("id") Long id) { |
| | | return R.ok().add(buildPageRowsUtils.rowsMap(dictDataService.getById(id))); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:save')") |
| | | @PreAuthorize("hasAuthority('system:dictType:save')") |
| | | @OperationLog("Create 字典数据集") |
| | | @PostMapping("/dictData/save") |
| | | public R save(@RequestBody DictData dictData) { |
| | |
| | | return R.ok("Save Success").add(buildPageRowsUtils.rowsMap(dictData)); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:update')") |
| | | @PreAuthorize("hasAuthority('system:dictType:update')") |
| | | @OperationLog("Update 字典数据集") |
| | | @PostMapping("/dictData/update") |
| | | public R update(@RequestBody DictData dictData) { |
| | |
| | | return R.ok("Update Success").add(buildPageRowsUtils.rowsMap(dictData)); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:remove')") |
| | | @PreAuthorize("hasAuthority('system:dictType:remove')") |
| | | @OperationLog("Delete 字典数据集") |
| | | @PostMapping("/dictData/remove/{ids}") |
| | | public R remove(@PathVariable Long[] ids) { |
| | |
| | | return R.ok("Delete Success").add(buildPageRowsUtils.rowsMap(ids)); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:list')") |
| | | @PreAuthorize("hasAuthority('system:dictType:list')") |
| | | @PostMapping("/dictData/query") |
| | | public R query(@RequestParam(required = false) String condition) { |
| | | List<KeyValVo> vos = new ArrayList<>(); |
| | |
| | | return R.ok().add(buildPageRowsUtils.rowsMap(vos)); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('system:dictData:list')") |
| | | @PreAuthorize("hasAuthority('system:dictType:list')") |
| | | @PostMapping("/dictData/export") |
| | | public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception { |
| | | ExcelUtil.build(ExcelUtil.create(buildPageRowsUtils.rowsMap(dictDataService.list()), DictData.class), response); |