diff --git a/src/api/wms/wms.js b/src/api/wms/wms.js index cb3b106..ae09987 100644 --- a/src/api/wms/wms.js +++ b/src/api/wms/wms.js @@ -17,3 +17,7 @@ export const getWarehouseList = data => createAPI(`wmsPrint/getWarehouseList`,'P export const uploadPoPartPrintExcel = data => createAPI(`wmsPrint/uploadPoPartPrintExcel`,'POST',data) // 查询文件ID export const queryFileIdWms = data => createAPI(`wmsPrint/queryFileId`,'POST',data) +// 获取标签模板列表 +export const getPartLabelTemplateList = data => createAPI(`wmsPrint/getPartLabelTemplateList`,'POST',data) +// 调用存储过程获取打印参数 +export const callUspPartLabelTemplate = data => createAPI(`wmsPrint/callUspPartLabelTemplate`,'POST',data) diff --git a/src/views/modules/print/PoPartPrint.vue b/src/views/modules/print/PoPartPrint.vue index 60fb9c9..cba7e90 100644 --- a/src/views/modules/print/PoPartPrint.vue +++ b/src/views/modules/print/PoPartPrint.vue @@ -243,6 +243,142 @@ + + +
+ + 标签打印设置 +
+ + + + +
+ @@ -255,9 +391,12 @@ import { getInboundQcResultData, getInboundQcResultOtherData, getPoOrderRollNoOutData, getPoPartLabelData, - submitPoOrderRollNo + submitPoOrderRollNo, + getPartLabelTemplateList, + callUspPartLabelTemplate } from '../../../api/wms/wms' import {poPartLabelPrint} from '../clodopLabel/poPartLabel' +import getLodop from '@/utils/LodopFuncs.js' export default { data() { return { @@ -785,6 +924,16 @@ export default { ], exportName: '采购检验合格单'+this.dayjs().format('YYYYMMDDHHmmss'), exportName2: '采购物料标签清单'+this.dayjs().format('YYYYMMDDHHmmss'), + // 标签打印对话框相关 + printDialogVisible: false, + printDialogData: { + printTimes: 1, + labelNo: '', + printerName: '' + }, + labelTemplateList: [], + printerList: [], + printLoading: false } }, /*组件*/ @@ -1026,23 +1175,322 @@ export default { // 3. 更新数据(触发 Vue 响应式) this.addModelData.rollCount = value }, - printLabels(){ + async printLabels(){ if(this.selectionDataList.length===0){ this.$message.error('未选择标签!'); return false; } - getPoPartLabelData(this.selectionDataList).then(({data}) => { + + // 检查主信息是否已选择 + if(!this.currentRow || !this.currentRow.site){ + this.$message.error('请先选择上方的检验合格单!'); + return false; + } + + // 获取标签模板列表 + await this.getLabelTemplates(); + + // 获取打印机列表 + this.getPrinterList(); + + // 打开标签打印对话框 + this.printDialogData = { + printTimes: 1, + labelNo: '', + printerName: '' + }; + this.printDialogVisible = true; + }, + + // 获取标签模板列表 + async getLabelTemplates(){ + const params = { + site: this.currentRow.site, + buNo: this.currentRow.buNo, + partNo: this.currentRow.partNo + }; + + try { + const {data} = await getPartLabelTemplateList(params); if (data && data.code === 0) { - console.log(data.rows) - poPartLabelPrint(data.rows) - this.getDetailTableList(); - }else { - - this.$message.error(data.msg); + this.labelTemplateList = data.list || []; + if(this.labelTemplateList.length > 0){ + // 默认选中第一个 + this.printDialogData.labelNo = this.labelTemplateList[0].labelNo; + } + } else { + this.$message.error(data.msg || '获取标签模板失败!'); } - - }) - + } catch (error) { + console.error('获取标签模板失败:', error); + this.$message.error('获取标签模板失败!'); + } + }, + + // 获取打印机列表 + getPrinterList(){ + try { + const LODOP = getLodop(); + if (!LODOP) { + this.$message.error('无法连接到打印控件,请确保已安装并启动 CLodop!'); + return; + } + + const printerCount = LODOP.GET_PRINTER_COUNT(); + this.printerList = []; + for (let i = 0; i < printerCount; i++) { + this.printerList.push(LODOP.GET_PRINTER_NAME(i)); + } + + if(this.printerList.length > 0){ + // 默认选中第一个打印机 + this.printDialogData.printerName = this.printerList[0]; + } + } catch (error) { + console.error('获取打印机列表失败:', error); + this.$message.error('获取打印机列表失败!'); + } + }, + + // 确认打印 + async confirmPrint(){ + // 验证必填项 + if(!this.printDialogData.labelNo){ + this.$message.error('请选择标签模板!'); + return; + } + if(!this.printDialogData.printerName){ + this.$message.error('请选择打印机!'); + return; + } + + this.printLoading = true; + + try { + // 调用存储过程获取打印参数 + const printDataList = []; + + for(let i = 0; i < this.selectionDataList.length; i++){ + const item = this.selectionDataList[i]; + const params = { + site: this.currentRow.site, + buNo: this.currentRow.buNo, + menuID: this.$route.meta.menuId, + relatedOrderNo: this.currentRow.poOrderNo, + relatedOrderLineNo: this.currentRow.poItemNo, + documentNo: this.currentRow.notifyNo, + PartNo: item.partNo, + LabelNo: this.printDialogData.labelNo, + rollNo: item.rollNo + }; + + const {data} = await callUspPartLabelTemplate(params); + if (data && data.code === 0) { + printDataList.push(data.row); + } else { + this.$message.error(`获取标签 ${item.rollNo} 的打印参数失败:${data.msg}`); + this.printLoading = false; + return; + } + } + + // 根据 labelNo 调用相应的打印方法 + this.executePrint(printDataList); + + this.printDialogVisible = false; + this.$message.success('打印任务已发送!'); + this.getDetailTableList(); + + } catch (error) { + console.error('打印失败:', error); + this.$message.error('打印失败:' + error.message); + } finally { + this.printLoading = false; + } + }, + + // 执行打印 + executePrint(printDataList){ + const LODOP = getLodop(); + if (!LODOP) { + this.$message.error('无法连接到打印控件!'); + return; + } + + // 设置打印机 + LODOP.SET_PRINTER_INDEX(this.printDialogData.printerName); + + for(let times = 0; times < this.printDialogData.printTimes; times++){ + for(let i = 0; i < printDataList.length; i++){ + const printData = printDataList[i]; + + // 根据 labelNo 调用不同的打印方法 + if(printData.labelNo === 'A001'){ + this.printLabelA001(LODOP, printData, i > 0 || times > 0); + } else if(printData.labelNo === 'A002'){ + this.printLabelA002(LODOP, printData, i > 0 || times > 0); + } else if(printData.labelNo === 'A003'){ + this.printLabelA003(LODOP, printData, i > 0 || times > 0); + } else { + this.$message.warning(`未知的标签模板:${printData.labelNo}`); + } + } + } + + // 打印 + LODOP.PRINT(); + }, + + // A001 标签打印(70mm x 30mm)- 左边二维码,右边文字信息 + printLabelA001(LODOP, printData, isNewPage){ + if(isNewPage){ + LODOP.NEWPAGE(); + } + + // 设置纸张大小 70mm x 30mm + LODOP.SET_PRINT_PAGESIZE(1, '70mm', '30mm', ''); + + // 绘制外边框 + LODOP.ADD_PRINT_RECT('2mm', '2mm', '66mm', '26mm', 0, 1); + + // 绘制左右分隔线 + LODOP.ADD_PRINT_LINE('2mm', '22mm', '28mm', '22mm', 0, 1); + + // 左侧二维码(20mm x 20mm) + const qrIndex = LODOP.ADD_PRINT_BARCODE('5mm', '3mm', '18mm', '18mm', 'QRCode', printData.rollNo || ''); + LODOP.SET_PRINT_STYLEA(qrIndex, "QRCodeVersion", 4); + LODOP.SET_PRINT_STYLEA(qrIndex, "QRCodeErrorLevel", "M"); + + // 右侧文字信息(5行) + const startX = '23mm'; + const textWidth = '43mm'; + + // 编码 + const text1 = LODOP.ADD_PRINT_TEXT('4mm', startX, textWidth, '4mm', `编码:${printData.partCode || printData.partNo || ''}`); + LODOP.SET_PRINT_STYLEA(text1, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text1, "FontSize", 8); + + // 型号 + const text2 = LODOP.ADD_PRINT_TEXT('9mm', startX, textWidth, '4mm', `型号:${printData.partModel || ''}`); + LODOP.SET_PRINT_STYLEA(text2, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text2, "FontSize", 8); + + // 数量 + const text3 = LODOP.ADD_PRINT_TEXT('14mm', startX, textWidth, '4mm', `数量:${printData.qty || printData.rollQty || ''}`); + LODOP.SET_PRINT_STYLEA(text3, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text3, "FontSize", 8); + + // 批号 + const text4 = LODOP.ADD_PRINT_TEXT('19mm', startX, textWidth, '4mm', `批号:${printData.batchNo || ''}`); + LODOP.SET_PRINT_STYLEA(text4, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text4, "FontSize", 8); + + // 日期 + const text5 = LODOP.ADD_PRINT_TEXT('24mm', startX, textWidth, '4mm', `日期:${printData.productionDate || ''}`); + LODOP.SET_PRINT_STYLEA(text5, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text5, "FontSize", 8); + }, + + // A002 标签打印(70mm x 20mm)- 其他工序用 + printLabelA002(LODOP, printData, isNewPage){ + if(isNewPage){ + LODOP.NEWPAGE(); + } + + // 设置纸张大小 70mm x 20mm + LODOP.SET_PRINT_PAGESIZE(1, '70mm', '20mm', ''); + + // 绘制外边框 + LODOP.ADD_PRINT_RECT('2mm', '2mm', '66mm', '16mm', 0, 1); + + // 标题 "其他工序用" + const title = LODOP.ADD_PRINT_TEXT('2mm', '2mm', '66mm', '4mm', '其他工序用'); + LODOP.SET_PRINT_STYLEA(title, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(title, "FontSize", 10); + LODOP.SET_PRINT_STYLEA(title, "Bold", 1); + LODOP.SET_PRINT_STYLEA(title, "Alignment", 2); // 居中 + + // 横线分隔标题 + LODOP.ADD_PRINT_LINE('6mm', '2mm', '6mm', '68mm', 0, 1); + + // 纵线分隔左右 + LODOP.ADD_PRINT_LINE('6mm', '22mm', '18mm', '22mm', 0, 1); + + // 左侧二维码 + const qrIndex = LODOP.ADD_PRINT_BARCODE('8mm', '3mm', '18mm', '9mm', 'QRCode', printData.rollNo || ''); + LODOP.SET_PRINT_STYLEA(qrIndex, "QRCodeVersion", 4); + LODOP.SET_PRINT_STYLEA(qrIndex, "QRCodeErrorLevel", "M"); + + // 右侧信息 + const startX = '23mm'; + const textWidth = '43mm'; + + const text1 = LODOP.ADD_PRINT_TEXT('7mm', startX, textWidth, '3mm', `ERP No.: ${printData.erpNo || ''}`); + LODOP.SET_PRINT_STYLEA(text1, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text1, "FontSize", 7); + + const text2 = LODOP.ADD_PRINT_TEXT('10mm', startX, textWidth, '3mm', `Batch No.: ${printData.batchNo || ''}`); + LODOP.SET_PRINT_STYLEA(text2, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text2, "FontSize", 7); + + const text3 = LODOP.ADD_PRINT_TEXT('13mm', startX, textWidth, '3mm', `Good QTY: ${printData.goodQty || ''} pcs`); + LODOP.SET_PRINT_STYLEA(text3, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text3, "FontSize", 7); + + const text4 = LODOP.ADD_PRINT_TEXT('16mm', startX, textWidth, '3mm', `Bad QTY: ${printData.badQty || ''} pcs`); + LODOP.SET_PRINT_STYLEA(text4, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text4, "FontSize", 7); + }, + + // A003 标签打印(70mm x 20mm)- 绑定用 + printLabelA003(LODOP, printData, isNewPage){ + if(isNewPage){ + LODOP.NEWPAGE(); + } + + // 设置纸张大小 70mm x 20mm + LODOP.SET_PRINT_PAGESIZE(1, '70mm', '20mm', ''); + + // 绘制外边框 + LODOP.ADD_PRINT_RECT('2mm', '2mm', '66mm', '16mm', 0, 1); + + // 标题 "绑定用" + const title = LODOP.ADD_PRINT_TEXT('2mm', '2mm', '66mm', '4mm', '绑定用'); + LODOP.SET_PRINT_STYLEA(title, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(title, "FontSize", 10); + LODOP.SET_PRINT_STYLEA(title, "Bold", 1); + LODOP.SET_PRINT_STYLEA(title, "Alignment", 2); // 居中 + + // 横线分隔标题 + LODOP.ADD_PRINT_LINE('6mm', '2mm', '6mm', '68mm', 0, 1); + + // 纵线分隔左右 + LODOP.ADD_PRINT_LINE('6mm', '22mm', '18mm', '22mm', 0, 1); + + // 左侧二维码 + const qrIndex = LODOP.ADD_PRINT_BARCODE('8mm', '3mm', '18mm', '9mm', 'QRCode', printData.rollNo || ''); + LODOP.SET_PRINT_STYLEA(qrIndex, "QRCodeVersion", 4); + LODOP.SET_PRINT_STYLEA(qrIndex, "QRCodeErrorLevel", "M"); + + // 右侧信息 + const startX = '23mm'; + const textWidth = '43mm'; + + const text1 = LODOP.ADD_PRINT_TEXT('7mm', startX, textWidth, '3mm', `ERP No.: ${printData.erpNo || ''}`); + LODOP.SET_PRINT_STYLEA(text1, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text1, "FontSize", 7); + + const text2 = LODOP.ADD_PRINT_TEXT('10mm', startX, textWidth, '3mm', `Batch No.: ${printData.batchNo || ''} Reel No.: ${printData.reelNo || ''}`); + LODOP.SET_PRINT_STYLEA(text2, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text2, "FontSize", 7); + + const text3 = LODOP.ADD_PRINT_TEXT('13mm', startX, textWidth, '3mm', `Good QTY: ${printData.goodQty || ''} pcs`); + LODOP.SET_PRINT_STYLEA(text3, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text3, "FontSize", 7); + + const text4 = LODOP.ADD_PRINT_TEXT('16mm', startX, textWidth, '3mm', `Bad QTY: ${printData.badQty || ''} pcs`); + LODOP.SET_PRINT_STYLEA(text4, "FontName", "Microsoft YaHei"); + LODOP.SET_PRINT_STYLEA(text4, "FontSize", 7); }, deleteLabels(){ if(this.selectionDataList.length===0){ @@ -1132,6 +1580,173 @@ export default { color: #c0c4cc; } +/* 标签打印对话框样式 */ +.print-dialog { + /deep/ .el-dialog__header { + background: linear-gradient(135deg, #9ac3d0 20%, #b6c7dd 80%); + padding: 20px 20px 20px 20px; + border-radius: 4px 4px 0 0; + } + + /deep/ .el-dialog__title { + color: #ffffff; + } + + /deep/ .el-dialog__headerbtn .el-dialog__close { + color: #ffffff; + font-size: 20px; + font-weight: bold; + + &:hover { + color: #f0f0f0; + } + } + + /deep/ .el-dialog__body { + padding: 0; + } + + .dialog-title-wrapper { + color: #ffffff; + display: flex; + align-items: center; + } + + .print-dialog-content { + padding: 25px 30px; + } + + .print-info-banner { + background: linear-gradient(135deg, #e8f4f8 0%, #f0f5fb 100%); + border-left: 4px solid #60aeff; + padding: 12px 16px; + border-radius: 4px; + color: #606266; + font-size: 14px; + display: flex; + align-items: center; + box-shadow: 0 2px 4px rgba(0,0,0,0.05); + } + + .form-label { + font-size: 14px; + font-weight: 600; + color: #303133; + display: flex; + align-items: center; + } + + .form-tip { + font-size: 12px; + color: #909399; + margin-top: 5px; + line-height: 1.5; + } + + .print-summary { + background: linear-gradient(135deg, #e1f0f5 0%, #dae8f3 100%); + border-radius: 8px; + padding: 16px 20px; + margin-top: 20px; + display: flex; + justify-content: space-around; + box-shadow: 0 2px 8px rgba(96, 174, 255, 0.15); + border: 1px solid #c8dff0; + + .summary-item { + display: flex; + flex-direction: column; + align-items: center; + + .summary-label { + font-size: 12px; + color: #5a7a8f; + margin-bottom: 5px; + font-weight: 500; + } + + .summary-value { + font-size: 20px; + font-weight: bold; + color: #3a7ba8; + } + } + } + + /deep/ .el-form-item { + margin-bottom: 18px; + } + + /deep/ .el-input-number { + width: 100%; + + .el-input__inner { + text-align: left; + } + } + + /deep/ .el-select { + .el-input__inner { + border: 1px solid #DCDFE6; + transition: all 0.3s; + + &:hover { + border-color: #409EFF; + } + + &:focus { + border-color: #409EFF; + } + } + } + + /deep/ .dialog-footer { + padding: 15px 30px 25px 30px; + text-align: center; + background-color: #fafafa; + border-top: 1px solid #e8e8e8; + + .el-button { + min-width: 120px; + height: 40px; + font-weight: 500; + transition: all 0.3s; + font-size: 15px; + } + + .el-button--success { + background: linear-gradient(135deg, #67C23A 0%, #85ce61 100%); + border: none; + box-shadow: 0 2px 4px rgba(103, 194, 58, 0.3); + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(103, 194, 58, 0.4); + } + + &:active { + transform: translateY(0); + } + } + } +} + +/* 选项样式优化 */ +/deep/ .el-select-dropdown__item { + padding: 10px 20px; + transition: all 0.2s; + + &:hover { + background-color: #f5f7fa; + } +} + +/* 输入框聚焦效果 */ +/deep/ .el-input__inner:focus, +/deep/ .el-textarea__inner:focus { + border-color: #409EFF; + box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1); +}