From 6e4f4da0ba334b82e1fa6ba1221f707814b602d4 Mon Sep 17 00:00:00 2001 From: "han\\hanst" Date: Thu, 7 Aug 2025 17:00:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=81=E6=B0=B4=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/zplGenerator.js | 20 ++++ .../modules/labelSetting/LabelDesigner.vue | 110 +++++++++++------- .../components/DataSourceDialog.vue | 16 ++- .../labelSetting/components/DesignCanvas.vue | 41 ++++++- .../labelSetting/components/DesignElement.vue | 46 ++++++++ .../components/HorizontalToolbar.vue | 6 + .../labelSetting/components/PropertyForm.vue | 97 ++++++++++++++- .../labelSetting/components/ToolItem.vue | 8 ++ 8 files changed, 294 insertions(+), 50 deletions(-) diff --git a/src/utils/zplGenerator.js b/src/utils/zplGenerator.js index df68758..7f1db20 100644 --- a/src/utils/zplGenerator.js +++ b/src/utils/zplGenerator.js @@ -101,6 +101,8 @@ export class ZPLGenerator { return this.generateHorizontalLineZPL(element, x, y) case 'vLine': return this.generateVerticalLineZPL(element, x, y) + case 'serialNumber': + return this.generateSerialNumberZPL(element, x, y) default: return '' } @@ -201,6 +203,24 @@ export class ZPLGenerator { return `^FO${x},${y}^GB1,${element.height},${element.width},B^FS` } } + + /** + * 生成流水号ZPL代码 + */ + generateSerialNumberZPL(element, x, y) { + const zpl = [] + const bold = element.bold || false // 加粗(可选) + const serialStr = '流水号' + const base = `^FO${x},${y}^FD${element.data}^FS` + zpl.push(base) + // 可选:加粗效果(重复打印) + if (bold) { + zpl.push(`^FO${x+1},${y}^FD${serialStr}^FS`) + zpl.push(`^FO${x},${y+1}^FD${serialStr}^FS`) + zpl.push(`^FO${x+1},${y+1}^FD${serialStr}^FS`) + } + return zpl.join('\n') + } } /** diff --git a/src/views/modules/labelSetting/LabelDesigner.vue b/src/views/modules/labelSetting/LabelDesigner.vue index 4a23925..0d54487 100644 --- a/src/views/modules/labelSetting/LabelDesigner.vue +++ b/src/views/modules/labelSetting/LabelDesigner.vue @@ -133,6 +133,7 @@ :visible="dataSourceVisible" :data-keys="dataKeys" :current-text="currentElementText" + :source-type="sourceType" @update:visible="dataSourceVisible = $event" @confirm="handleDataSourceConfirm" /> @@ -172,6 +173,7 @@ export default { }, data() { return { + sourceType: 'text', // 数据源类型,默认为文本 labelNo: '', showGrid: true, snapToGrid: true, @@ -440,6 +442,8 @@ export default { }, handleDrop(dropData) { + console.log('主设计器接收到拖拽数据:', dropData) // 调试信息 + if (!this.labelNo) { this.$alert('标签编号不可为空!', '错误', { confirmButtonText: '确定' @@ -448,10 +452,17 @@ export default { } const newElement = this.createNewElement(dropData) + console.log('创建的新元素:', newElement) // 调试信息 + this.elements.push(newElement) + + // 自动选中新添加的元素 + this.selectedIndex = this.elements.length - 1 }, createNewElement({ type, x, y }) { + console.log('创建新元素:', { type, x, y }) // 调试信息 + const baseElement = { type, x, @@ -461,24 +472,65 @@ export default { bold: false, newline: false, lineRows: 2, - lineWidth: 200 + lineWidth: 200, + digits: 6, + step: 1, } - // 根据类型设置默认尺寸 + // 根据类型设置默认尺寸和特殊属性 const sizeConfig = { - text: { width: 100, height: 30 }, - barcode: { width: 3, height: 50 }, - onecode: { width: 3, height: 50 }, - qrcode: { width: 10, height: 10 }, - pic: { width: 100, height: 100 }, - hLine: { width: 400, height: 3 }, - vLine: { width: 3, height: 400 } + text: { + width: 100, + height: 30, + data: '文本元素' + }, + barcode: { + width: 3, + height: 50, + data: '123456789' + }, + onecode: { + width: 3, + height: 50, + data: '123456789' + }, + qrcode: { + width: 10, + height: 10, + data: 'QR Code' + }, + pic: { + width: 100, + height: 100 + }, + hLine: { + width: 400, + height: 3 + }, + vLine: { + width: 3, + height: 400 + }, + serialNumber: { + width: 120, + height: 30, + digits: 6, + step: 1, + data: '流水号', // 默认显示值 + fontSize: 30 + } } - return { + const config = sizeConfig[type] || { width: 100, height: 30 } + + const newElement = { ...baseElement, - ...sizeConfig[type] + ...config } + + console.log('新元素配置:', newElement) // 调试信息 + + return newElement }, handleElementSelect(index) { @@ -639,7 +691,7 @@ export default { // 预览逻辑由PropertyPanel处理 }, - async handleDataSource(currentText) { + async handleDataSource(inData) { const response = await getViewFieldsByLabelType({ labelType: this.labelSettings.labelType, site: this.$store.state.user.site @@ -650,42 +702,18 @@ export default { ...field, fieldDescription: field.fieldDescription || '' })); - this.currentElementText = currentText || '' + this.currentElementText = inData.data || '' + this.sourceType = inData.type || 'text' this.dataSourceVisible = true } else { this.$message.error(response.data.msg || '获取字段信息失败'); } - - /* if (this.elements.length > 0) { - this.dataKeys = Object.keys(this.elements[0]) - this.currentElementText = currentText || '' - this.dataSourceVisible = true - }*/ - }, - - async loadViewFields() { - try { - const response = await getViewFieldsByLabelType({ - labelType: this.labelSettings.labelType, - site: this.$store.state.user.site - }); - - if (response.data && response.data.code === 200) { - this.viewFields = response.data.data.map(field => ({ - ...field, - fieldDescription: field.fieldDescription || '' - })); - } else { - this.$message.error(response.data.msg || '获取字段信息失败'); - } - } catch (error) { - console.error('获取字段信息失败:', error); - } }, - handleDataSourceConfirm(selectedKeys) { + handleDataSourceConfirm(selectedKeys, sourceType) { if (this.selectedElement) { - this.selectedElement.data = selectedKeys.map(key => `#{${key}}`).join('') + this.selectedElement.data = sourceType==='serialNumber'?selectedKeys.map(key => `${key}`).join('+'): + selectedKeys.map(key => `#{${key}}`).join('') } }, diff --git a/src/views/modules/labelSetting/components/DataSourceDialog.vue b/src/views/modules/labelSetting/components/DataSourceDialog.vue index a7757a6..c8b4f0f 100644 --- a/src/views/modules/labelSetting/components/DataSourceDialog.vue +++ b/src/views/modules/labelSetting/components/DataSourceDialog.vue @@ -47,6 +47,10 @@ export default { currentText: { type: String, default: '' + }, + sourceType: { + type: String, + default: 'text' // 默认是文本类型 } }, emits: ['update:visible', 'confirm'], @@ -81,7 +85,17 @@ export default { foundKeys.push(key.fieldName) } }) + if (this.sourceType==='serialNumber'){ + this.dataKeys.forEach(key => { + // 构建字段匹配的正则,确保全字匹配 + const pattern = new RegExp(`\\b${key.fieldName}\\b`, 'g') + if (pattern.test(this.currentText)) { + foundKeys.push(key.fieldName) + } + }) + + } this.selectedKeys = foundKeys }, @@ -90,7 +104,7 @@ export default { }, handleConfirm() { - this.$emit('confirm', this.selectedKeys) + this.$emit('confirm', this.selectedKeys, this.sourceType) this.handleClose() } } diff --git a/src/views/modules/labelSetting/components/DesignCanvas.vue b/src/views/modules/labelSetting/components/DesignCanvas.vue index 99f8d71..fb7e1f9 100644 --- a/src/views/modules/labelSetting/components/DesignCanvas.vue +++ b/src/views/modules/labelSetting/components/DesignCanvas.vue @@ -3,7 +3,8 @@ class="design-canvas" :class="{ 'show-grid': showGrid }" :style="canvasStyle" - @dragover.prevent + @dragover="handleDragOver" + @dragenter="handleDragEnter" @drop="handleDrop" > @@ -134,14 +135,35 @@ export default { } }, methods: { + handleDragOver(e) { + e.preventDefault() + e.stopPropagation() + e.dataTransfer.dropEffect = 'copy' + }, + + handleDragEnter(e) { + e.preventDefault() + e.stopPropagation() + }, + handleDrop(e) { - const type = e.dataTransfer.getData('type') - if (!type) return + e.preventDefault() + e.stopPropagation() + + const type = e.dataTransfer.getData('type') || e.dataTransfer.getData('text/plain') + console.log('画布接收到拖拽类型:', type) // 调试信息 + + if (!type) { + console.warn('未获取到拖拽类型数据') + return + } const rect = e.currentTarget.getBoundingClientRect() const x = e.clientX - rect.left const y = e.clientY - rect.top + console.log('拖拽位置:', { x, y }) // 调试信息 + this.$emit('drop', { type, x, y }) }, @@ -335,6 +357,19 @@ export default { } } + // 对于流水号元素 + if (element.type === 'serialNumber') { + const fontSize = element.fontSize || 30 + const prefix = element.prefix || '' + const digits = parseInt(element.digits) || 6 + const estimatedWidth = Math.max((prefix.length + digits) * (fontSize * 0.6), 80) + + return { + width: Math.min(estimatedWidth + 16, 200), // 加上padding,限制最大宽度 + height: Math.max(fontSize + 8, 30) // 加上padding,最小高度30px + } + } + return baseSize } } diff --git a/src/views/modules/labelSetting/components/DesignElement.vue b/src/views/modules/labelSetting/components/DesignElement.vue index 0e572c6..2780235 100644 --- a/src/views/modules/labelSetting/components/DesignElement.vue +++ b/src/views/modules/labelSetting/components/DesignElement.vue @@ -78,6 +78,12 @@ }" > + + +
+ +
流水号
+
@@ -169,6 +175,17 @@ export default { this.isDragging = false document.removeEventListener('mousemove', this.handleMouseMove) document.removeEventListener('mouseup', this.handleMouseUp) + }, + + getSerialNumberDisplay() { + if (this.element.type !== 'serialNumber') return '' + + const prefix = this.element.prefix || 'SN' + const startValue = parseInt(this.element.startValue) || 1 + const digits = parseInt(this.element.digits) || 6 + const paddedNumber = startValue.toString().padStart(digits, '0') + + return `${prefix}${paddedNumber}` } } } @@ -341,6 +358,35 @@ export default { border-color: rgba(46, 204, 113, 0.4); } +.design-element[data-type="serialNumber"] { + border-color: rgba(114, 46, 209, 0.4); +} + +.serial-number-element { + display: flex; + flex-direction: column; + align-items: center; + padding: 4px 6px; + background: linear-gradient(135deg, #f3e8ff, #f3e8ff); + border-radius: 6px; + min-width: 60px; +} + +.serial-number-element .serial-display { + font-size: 12px; + font-weight: 600; + color: #2c3e50; + padding: 6px 4px; + background: linear-gradient(135deg, #fff, #f8f9fa); + border: 1px solid rgba(114, 46, 209, 0.3); + border-radius: 4px; + min-width: 70px; + text-align: center; + font-family: 'Courier New', monospace; + letter-spacing: 0.5px; + box-shadow: 0 1px 3px rgba(114, 46, 209, 0.1); +} + /* 响应式调整 */ @media (max-width: 1200px) { .design-element { diff --git a/src/views/modules/labelSetting/components/HorizontalToolbar.vue b/src/views/modules/labelSetting/components/HorizontalToolbar.vue index fb9f76b..e65512e 100644 --- a/src/views/modules/labelSetting/components/HorizontalToolbar.vue +++ b/src/views/modules/labelSetting/components/HorizontalToolbar.vue @@ -98,6 +98,12 @@ export default { label: '竖线', rotate: true, color: '#909399' + }, + { + type: 'serialNumber', + icon: 'el-icon-setting', + label: '流水号', + color: '#909399' } ] } diff --git a/src/views/modules/labelSetting/components/PropertyForm.vue b/src/views/modules/labelSetting/components/PropertyForm.vue index 087adcb..19e71a6 100644 --- a/src/views/modules/labelSetting/components/PropertyForm.vue +++ b/src/views/modules/labelSetting/components/PropertyForm.vue @@ -6,7 +6,7 @@
- + 数据源
@@ -59,7 +59,7 @@
- + 数据源
@@ -95,7 +95,7 @@
- + 数据源
@@ -168,10 +168,69 @@ + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+
+ + + + + + 查看 + + +
+ +
+
+ +