| | |
| | | column: 1, |
| | | schema: useBarcodeDetailSchema(), |
| | | useCard: false, |
| | | labelStyle: { width: '80px', whiteSpace: 'nowrap' }, |
| | | }); |
| | | |
| | | function openModal(row: Partial<MesWmBarcodeApi.Barcode>) { |
| | |
| | | message.warning('条码生成失败,无法下载'); |
| | | return; |
| | | } |
| | | const link = document.createElement('a'); |
| | | link.href = base64; |
| | | link.download = `barcode_${barcodeData.value.bizCode || 'unknown'}_${Date.now()}.png`; |
| | | link.click(); |
| | | message.success('下载成功'); |
| | | |
| | | const canvas = document.createElement('canvas'); |
| | | const ctx = canvas.getContext('2d'); |
| | | if (!ctx) { |
| | | message.error('Canvas 初始化失败'); |
| | | return; |
| | | } |
| | | |
| | | const img = new Image(); |
| | | img.onload = () => { |
| | | const padding = 20; |
| | | const infoX = img.width + padding * 2; |
| | | const infoWidth = 320; |
| | | canvas.width = infoX + infoWidth + padding; |
| | | canvas.height = Math.max(img.height + padding * 2, 360); |
| | | |
| | | ctx.fillStyle = '#ffffff'; |
| | | ctx.fillRect(0, 0, canvas.width, canvas.height); |
| | | |
| | | ctx.drawImage(img, padding, padding); |
| | | |
| | | ctx.fillStyle = '#000000'; |
| | | let y = padding + 10; |
| | | const lineHeight = 26; |
| | | |
| | | // 获取字典文本的辅助函数 |
| | | const getFormatText = (val?: number) => { |
| | | const map: Record<number, string> = { 1: 'QR_CODE', 2: 'CODE_128', 3: 'CODE_39', 4: 'EAN_13', 5: 'UPC_A' }; |
| | | return map[val || 1] || 'QR_CODE'; |
| | | }; |
| | | const getBizTypeText = (val?: number) => { |
| | | const map: Record<number, string> = { 1: '仓库', 2: '库区', 3: '库位', 4: '物料', 5: '客户', 6: '供应商', 7: '工单', 8: '设备', 9: '工具', 10: '人员', 11: '工作站', 12: '车间', 13: '库存', 14: '流转卡', 15: '装箱单', 16: '批次' }; |
| | | return map[val || 1] || '-'; |
| | | }; |
| | | const getStatusText = (val?: number) => val === 0 ? '禁用' : '启用'; |
| | | |
| | | const items = [ |
| | | { label: '条码格式', value: getFormatText(barcodeData.value.format) }, |
| | | { label: '业务类型', value: getBizTypeText(barcodeData.value.bizType) }, |
| | | { label: '业务编码', value: barcodeData.value.bizCode }, |
| | | { label: '业务名称', value: barcodeData.value.bizName }, |
| | | { label: '条码内容', value: barcodeData.value.content }, |
| | | { label: '状态', value: getStatusText(barcodeData.value.status) }, |
| | | ]; |
| | | |
| | | items.forEach((item) => { |
| | | ctx.font = 'bold 13px Arial, sans-serif'; |
| | | ctx.fillText(`${item.label}:`, infoX, y); |
| | | y += 18; |
| | | ctx.font = '13px Arial, sans-serif'; |
| | | const text = item.value || '-'; |
| | | // 处理长文本换行 |
| | | const maxWidth = infoWidth - 10; |
| | | if (ctx.measureText(text).width > maxWidth) { |
| | | let currentText = text; |
| | | while (currentText.length > 0) { |
| | | let line = ''; |
| | | for (let i = 0; i < currentText.length; i++) { |
| | | const testLine = line + currentText[i]; |
| | | if (ctx.measureText(testLine).width > maxWidth) break; |
| | | line = testLine; |
| | | } |
| | | ctx.fillText(line, infoX + 5, y); |
| | | y += 16; |
| | | currentText = currentText.slice(line.length); |
| | | } |
| | | y += 6; |
| | | } else { |
| | | ctx.fillText(text, infoX + 5, y); |
| | | y += lineHeight; |
| | | } |
| | | }); |
| | | |
| | | const link = document.createElement('a'); |
| | | link.href = canvas.toDataURL('image/png'); |
| | | link.download = `barcode_${barcodeData.value.bizCode || 'unknown'}_${Date.now()}.png`; |
| | | link.click(); |
| | | message.success('下载成功'); |
| | | }; |
| | | img.src = base64; |
| | | } |
| | | |
| | | async function handleGenerate() { |
| | |
| | | </script> |
| | | |
| | | <template> |
| | | <Modal v-model:open="open" title="查看条码" width="500px"> |
| | | <Modal v-model:open="open" title="查看条码" width="750px"> |
| | | <div> |
| | | <div |
| | | class="mb-5 flex min-h-50 items-center justify-center rounded bg-gray-100 p-5" |
| | | > |
| | | <div |
| | | v-if="barcodeData.content" |
| | | class="flex items-center justify-center" |
| | | > |
| | | <WlsBarcode |
| | | ref="barcodeRef" |
| | | :content="barcodeData.content" |
| | | :format="barcodeData.format" |
| | | :height="150" |
| | | :width="400" |
| | | /> |
| | | <div class="mb-5 flex min-h-50 items-center rounded bg-gray-100 p-5"> |
| | | <div v-if="barcodeData.content" class="flex w-full items-center gap-6"> |
| | | <div class="flex-shrink-0"> |
| | | <WlsBarcode |
| | | ref="barcodeRef" |
| | | :content="barcodeData.content" |
| | | :format="barcodeData.format" |
| | | :height="150" |
| | | :width="280" |
| | | /> |
| | | </div> |
| | | <div class="flex-1"> |
| | | <Descriptions :data="barcodeData"> |
| | | <template #content> |
| | | <Tooltip :title="barcodeData.content"> |
| | | <span |
| | | class="inline-block max-w-60 overflow-hidden text-ellipsis whitespace-nowrap" |
| | | > |
| | | {{ barcodeData.content }} |
| | | </span> |
| | | </Tooltip> |
| | | </template> |
| | | </Descriptions> |
| | | </div> |
| | | </div> |
| | | <Empty v-else description="暂无条码数据" /> |
| | | <Empty v-else description="暂无条码数据" class="flex-1" /> |
| | | </div> |
| | | <Descriptions :data="barcodeData"> |
| | | <template #content> |
| | | <Tooltip :title="barcodeData.content"> |
| | | <span |
| | | class="inline-block max-w-75 overflow-hidden text-ellipsis whitespace-nowrap" |
| | | > |
| | | {{ barcodeData.content }} |
| | | </span> |
| | | </Tooltip> |
| | | </template> |
| | | </Descriptions> |
| | | </div> |
| | | <template #footer> |
| | | <Button v-if="!barcodeData.content" @click="handleGenerate"> |