| | |
| | | <template> |
| | | <div class="qr-code-generator"> |
| | | <!-- 二维码生成表单 --> |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="qr-form"> |
| | | <el-form :model="form" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | label-width="120px" |
| | | class="qr-form"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="标识类型" prop="type"> |
| | | <el-select v-model="form.type" placeholder="请选择标识类型" style="width: 100%"> |
| | | <el-option label="二维码" value="qrcode"></el-option> |
| | | <el-option label="防伪码" value="security"></el-option> |
| | | <el-form-item label="标识类型" |
| | | prop="type"> |
| | | <el-select v-model="form.type" |
| | | placeholder="请选择标识类型" |
| | | style="width: 100%"> |
| | | <el-option label="二维码" |
| | | value="qrcode"></el-option> |
| | | <el-option label="防伪码" |
| | | value="security"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="内容" prop="content"> |
| | | <el-input |
| | | v-model="form.content" |
| | | <el-form-item label="内容" |
| | | prop="content"> |
| | | <el-input v-model="form.content" |
| | | placeholder="请输入要编码的内容" |
| | | :type="form.type === 'security' ? 'textarea' : 'text'" |
| | | :rows="form.type === 'security' ? 3 : 1" |
| | | ></el-input> |
| | | :rows="form.type === 'security' ? 3 : 1"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="尺寸" prop="size"> |
| | | <el-input-number |
| | | v-model="form.size" |
| | | <el-form-item label="尺寸" |
| | | prop="size"> |
| | | <el-input-number v-model="form.size" |
| | | :min="100" |
| | | :max="500" |
| | | :step="50" |
| | | style="width: 100%" |
| | | ></el-input-number> |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="边距" prop="margin"> |
| | | <el-input-number |
| | | v-model="form.margin" |
| | | <el-form-item label="边距" |
| | | prop="margin"> |
| | | <el-input-number v-model="form.margin" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | style="width: 100%" |
| | | ></el-input-number> |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="前景色" prop="foregroundColor"> |
| | | <el-color-picker v-model="form.foregroundColor" style="width: 100%"></el-color-picker> |
| | | <el-form-item label="前景色" |
| | | prop="foregroundColor"> |
| | | <el-color-picker v-model="form.foregroundColor" |
| | | style="width: 100%"></el-color-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="背景色" prop="backgroundColor"> |
| | | <el-color-picker v-model="form.backgroundColor" style="width: 100%"></el-color-picker> |
| | | <el-form-item label="背景色" |
| | | prop="backgroundColor"> |
| | | <el-color-picker v-model="form.backgroundColor" |
| | | style="width: 100%"></el-color-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="generateCode" :loading="generating"> |
| | | <el-button type="primary" |
| | | @click="generateCode" |
| | | :loading="generating"> |
| | | 生成{{ form.type === 'qrcode' ? '二维码' : '防伪码' }} |
| | | </el-button> |
| | | <el-button @click="resetForm">重置</el-button> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <!-- 生成的码显示区域 --> |
| | | <div v-if="generatedCodeUrl" class="code-display"> |
| | | <div v-if="generatedCodeUrl" |
| | | class="code-display"> |
| | | <el-divider content-position="center"> |
| | | {{ form.type === 'qrcode' ? '生成的二维码' : '生成的防伪码' }} |
| | | </el-divider> |
| | | |
| | | <div class="code-container"> |
| | | <div class="code-image"> |
| | | <img :src="generatedCodeUrl" :alt="form.type === 'qrcode' ? '二维码' : '防伪码'" /> |
| | | <img :src="generatedCodeUrl" |
| | | :alt="form.type === 'qrcode' ? '二维码' : '防伪码'" /> |
| | | </div> |
| | | |
| | | <div class="code-info"> |
| | | <p><strong>内容:</strong>{{ form.content }}</p> |
| | | <p><strong>类型:</strong>{{ form.type === 'qrcode' ? '二维码' : '防伪码' }}</p> |
| | |
| | | <p><strong>生成时间:</strong>{{ generateTime }}</p> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="code-actions"> |
| | | <el-button type="success" @click="downloadCode" icon="Download"> |
| | | <el-button type="success" |
| | | @click="downloadCode" |
| | | icon="Download"> |
| | | 下载图片 |
| | | </el-button> |
| | | <el-button type="primary" @click="copyToClipboard" icon="CopyDocument"> |
| | | <el-button type="primary" |
| | | @click="copyToClipboard" |
| | | icon="CopyDocument"> |
| | | 复制内容 |
| | | </el-button> |
| | | <el-button @click="printCode" icon="Printer"> |
| | | <el-button @click="printCode" |
| | | icon="Printer"> |
| | | 打印 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 批量生成对话框 --> |
| | | <el-dialog v-model="batchDialogVisible" title="批量生成" width="600px"> |
| | | <el-form :model="batchForm" label-width="120px"> |
| | | <el-dialog v-model="batchDialogVisible" |
| | | title="批量生成" |
| | | width="600px"> |
| | | <el-form :model="batchForm" |
| | | label-width="120px"> |
| | | <el-form-item label="生成数量"> |
| | | <el-input-number v-model="batchForm.quantity" :min="1" :max="100" style="width: 100%"></el-input-number> |
| | | <el-input-number v-model="batchForm.quantity" |
| | | :min="1" |
| | | :max="100" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | <el-form-item label="前缀"> |
| | | <el-input v-model="batchForm.prefix" placeholder="请输入前缀,如:PROD_"></el-input> |
| | | <el-input v-model="batchForm.prefix" |
| | | placeholder="请输入前缀,如:PROD_"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="起始编号"> |
| | | <el-input-number v-model="batchForm.startNumber" :min="1" style="width: 100%"></el-input-number> |
| | | <el-input-number v-model="batchForm.startNumber" |
| | | :min="1" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="generateBatchCodes">开始生成</el-button> |
| | | <el-button @click="batchDialogVisible = false">取消</el-button> |
| | | <el-button type="primary" @click="generateBatchCodes">开始生成</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 批量生成结果 --> |
| | | <div v-if="batchCodes.length > 0" class="batch-results"> |
| | | <div v-if="batchCodes.length > 0" |
| | | class="batch-results"> |
| | | <el-divider content-position="center">批量生成结果</el-divider> |
| | | |
| | | <div class="batch-grid"> |
| | | <div |
| | | v-for="(code, index) in batchCodes" |
| | | <div v-for="(code, index) in batchCodes" |
| | | :key="index" |
| | | class="batch-item" |
| | | > |
| | | <img :src="code.url" :alt="code.content" /> |
| | | class="batch-item"> |
| | | <img :src="code.url" |
| | | :alt="code.content" /> |
| | | <p class="batch-content">{{ code.content }}</p> |
| | | <el-button size="small" @click="downloadSingleCode(code)">下载</el-button> |
| | | <el-button size="small" |
| | | @click="downloadSingleCode(code)">下载</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="batch-actions"> |
| | | <el-button type="success" @click="downloadAllCodes">下载全部</el-button> |
| | | <el-button type="success" |
| | | @click="downloadAllCodes">下载全部</el-button> |
| | | <el-button @click="clearBatchCodes">清空结果</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from 'vue' |
| | | import QRCode from 'qrcode' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Download, CopyDocument, Printer } from '@element-plus/icons-vue' |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import QRCode from "qrcode"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Download, CopyDocument, Printer } from "@element-plus/icons-vue"; |
| | | |
| | | // 定义组件名称 |
| | | defineOptions({ |
| | | name: 'QRCodeGenerator' |
| | | }) |
| | | name: "QRCodeGenerator", |
| | | }); |
| | | |
| | | // 表单数据 |
| | | const form = reactive({ |
| | | type: 'qrcode', |
| | | content: '', |
| | | type: "qrcode", |
| | | content: "", |
| | | size: 200, |
| | | margin: 2, |
| | | foregroundColor: '#000000', |
| | | backgroundColor: '#FFFFFF' |
| | | }) |
| | | foregroundColor: "#000000", |
| | | backgroundColor: "#FFFFFF", |
| | | }); |
| | | |
| | | // 表单验证规则 |
| | | const rules = { |
| | | type: [{ required: true, message: '请选择标识类型', trigger: 'change' }], |
| | | content: [{ required: true, message: '请输入内容', trigger: 'blur' }] |
| | | } |
| | | type: [{ required: true, message: "请选择标识类型", trigger: "change" }], |
| | | content: [{ required: true, message: "请输入内容", trigger: "blur" }], |
| | | }; |
| | | |
| | | // 响应式数据 |
| | | const formRef = ref() |
| | | const generating = ref(false) |
| | | const generatedCodeUrl = ref('') |
| | | const generateTime = ref('') |
| | | const batchDialogVisible = ref(false) |
| | | const formRef = ref(); |
| | | const generating = ref(false); |
| | | const generatedCodeUrl = ref(""); |
| | | const generateTime = ref(""); |
| | | const batchDialogVisible = ref(false); |
| | | const batchForm = reactive({ |
| | | quantity: 10, |
| | | prefix: '', |
| | | startNumber: 1 |
| | | }) |
| | | const batchCodes = ref([]) |
| | | prefix: "", |
| | | startNumber: 1, |
| | | }); |
| | | const batchCodes = ref([]); |
| | | |
| | | // 生成二维码或防伪码 |
| | | const generateCode = async () => { |
| | | try { |
| | | await formRef.value.validate() |
| | | await formRef.value.validate(); |
| | | |
| | | if (!form.content.trim()) { |
| | | ElMessage.warning('请输入要编码的内容') |
| | | return |
| | | ElMessage.warning("请输入要编码的内容"); |
| | | return; |
| | | } |
| | | |
| | | generating.value = true |
| | | generating.value = true; |
| | | |
| | | if (form.type === 'qrcode') { |
| | | if (form.type === "qrcode") { |
| | | // 生成二维码 |
| | | generatedCodeUrl.value = await QRCode.toDataURL(form.content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | light: form.backgroundColor, |
| | | }, |
| | | errorCorrectionLevel: 'M' |
| | | }) |
| | | errorCorrectionLevel: "M", |
| | | }); |
| | | } else { |
| | | // 生成防伪码(使用二维码技术,但内容格式不同) |
| | | const securityContent = generateSecurityCode(form.content) |
| | | const securityContent = generateSecurityCode(form.content); |
| | | generatedCodeUrl.value = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | light: form.backgroundColor, |
| | | }, |
| | | errorCorrectionLevel: 'H' // 防伪码使用最高纠错级别 |
| | | }) |
| | | errorCorrectionLevel: "H", // 防伪码使用最高纠错级别 |
| | | }); |
| | | } |
| | | |
| | | generateTime.value = new Date().toLocaleString() |
| | | ElMessage.success('生成成功!') |
| | | |
| | | generateTime.value = new Date().toLocaleString(); |
| | | ElMessage.success("生成成功!"); |
| | | } catch (error) { |
| | | console.error('生成失败:', error) |
| | | ElMessage.error('生成失败:' + error.message) |
| | | console.error("生成失败:", error); |
| | | ElMessage.error("生成失败:" + error.message); |
| | | } finally { |
| | | generating.value = false |
| | | generating.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 生成防伪码内容 |
| | | const generateSecurityCode = (content) => { |
| | | const timestamp = Date.now() |
| | | const random = Math.random().toString(36).substr(2, 8) |
| | | return `SEC_${content}_${timestamp}_${random}` |
| | | } |
| | | const generateSecurityCode = content => { |
| | | const timestamp = Date.now(); |
| | | const random = Math.random().toString(36).substr(2, 8); |
| | | return `SEC_${content}_${timestamp}_${random}`; |
| | | }; |
| | | |
| | | // 下载生成的码 |
| | | const downloadCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning('请先生成码') |
| | | return |
| | | ElMessage.warning("请先生成码"); |
| | | return; |
| | | } |
| | | |
| | | const a = document.createElement('a') |
| | | a.href = generatedCodeUrl.value |
| | | a.download = `${form.type === 'qrcode' ? '二维码' : '防伪码'}_${new Date().getTime()}.png` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | ElMessage.success('下载成功!') |
| | | } |
| | | const a = document.createElement("a"); |
| | | a.href = generatedCodeUrl.value; |
| | | a.download = `${ |
| | | form.type === "qrcode" ? "二维码" : "防伪码" |
| | | }_${new Date().getTime()}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | ElMessage.success("下载成功!"); |
| | | }; |
| | | |
| | | // 复制内容到剪贴板 |
| | | const copyToClipboard = async () => { |
| | | try { |
| | | await navigator.clipboard.writeText(form.content) |
| | | ElMessage.success('内容已复制到剪贴板') |
| | | await navigator.clipboard.writeText(form.content); |
| | | ElMessage.success("内容已复制到剪贴板"); |
| | | } catch (error) { |
| | | // 降级方案 |
| | | const textArea = document.createElement('textarea') |
| | | textArea.value = form.content |
| | | document.body.appendChild(textArea) |
| | | textArea.select() |
| | | document.execCommand('copy') |
| | | document.body.removeChild(textArea) |
| | | ElMessage.success('内容已复制到剪贴板') |
| | | const textArea = document.createElement("textarea"); |
| | | textArea.value = form.content; |
| | | document.body.appendChild(textArea); |
| | | textArea.select(); |
| | | document.execCommand("copy"); |
| | | document.body.removeChild(textArea); |
| | | ElMessage.success("内容已复制到剪贴板"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 打印码 |
| | | const printCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning('请先生成码') |
| | | return |
| | | ElMessage.warning("请先生成码"); |
| | | return; |
| | | } |
| | | |
| | | const printWindow = window.open('', '_blank') |
| | | const printWindow = window.open("", "_blank"); |
| | | printWindow.document.write(` |
| | | <html> |
| | | <head> |
| | | <title>打印${form.type === 'qrcode' ? '二维码' : '防伪码'}</title> |
| | | <title>打印${form.type === "qrcode" ? "二维码" : "防伪码"}</title> |
| | | <style> |
| | | body { text-align: center; padding: 20px; } |
| | | img { max-width: 100%; height: auto; } |
| | |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <h2>${form.type === 'qrcode' ? '二维码' : '防伪码'}</h2> |
| | | <img src="${generatedCodeUrl.value}" alt="${form.type === 'qrcode' ? '二维码' : '防伪码'}" /> |
| | | <h2>${form.type === "qrcode" ? "二维码" : "防伪码"}</h2> |
| | | <img src="${generatedCodeUrl.value}" alt="${ |
| | | form.type === "qrcode" ? "二维码" : "防伪码" |
| | | }" /> |
| | | <div class="info"> |
| | | <p><strong>内容:</strong>${form.content}</p> |
| | | <p><strong>生成时间:</strong>${generateTime.value}</p> |
| | | </div> |
| | | </body> |
| | | </html> |
| | | `) |
| | | printWindow.document.close() |
| | | printWindow.print() |
| | | } |
| | | `); |
| | | printWindow.document.close(); |
| | | printWindow.print(); |
| | | }; |
| | | |
| | | // 重置表单 |
| | | const resetForm = () => { |
| | | formRef.value.resetFields() |
| | | generatedCodeUrl.value = '' |
| | | generateTime.value = '' |
| | | batchCodes.value = [] |
| | | } |
| | | formRef.value.resetFields(); |
| | | generatedCodeUrl.value = ""; |
| | | generateTime.value = ""; |
| | | batchCodes.value = []; |
| | | }; |
| | | |
| | | // 批量生成 |
| | | const generateBatchCodes = async () => { |
| | | if (!batchForm.prefix.trim()) { |
| | | ElMessage.warning('请输入前缀') |
| | | return |
| | | ElMessage.warning("请输入前缀"); |
| | | return; |
| | | } |
| | | |
| | | batchCodes.value = [] |
| | | generating.value = true |
| | | batchCodes.value = []; |
| | | generating.value = true; |
| | | |
| | | try { |
| | | for (let i = 0; i < batchForm.quantity; i++) { |
| | | const number = batchForm.startNumber + i |
| | | const content = `${batchForm.prefix}${number.toString().padStart(6, '0')}` |
| | | const number = batchForm.startNumber + i; |
| | | const content = `${batchForm.prefix}${number |
| | | .toString() |
| | | .padStart(6, "0")}`; |
| | | |
| | | let codeUrl |
| | | if (form.type === 'qrcode') { |
| | | let codeUrl; |
| | | if (form.type === "qrcode") { |
| | | codeUrl = await QRCode.toDataURL(content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | } |
| | | }) |
| | | light: form.backgroundColor, |
| | | }, |
| | | }); |
| | | } else { |
| | | const securityContent = generateSecurityCode(content) |
| | | const securityContent = generateSecurityCode(content); |
| | | codeUrl = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | } |
| | | }) |
| | | light: form.backgroundColor, |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | batchCodes.value.push({ |
| | | content, |
| | | url: codeUrl |
| | | }) |
| | | url: codeUrl, |
| | | }); |
| | | } |
| | | |
| | | ElMessage.success(`批量生成完成,共生成 ${batchForm.quantity} 个码`) |
| | | batchDialogVisible.value = false |
| | | |
| | | ElMessage.success(`批量生成完成,共生成 ${batchForm.quantity} 个码`); |
| | | batchDialogVisible.value = false; |
| | | } catch (error) { |
| | | console.error('批量生成失败:', error) |
| | | ElMessage.error('批量生成失败:' + error.message) |
| | | console.error("批量生成失败:", error); |
| | | ElMessage.error("批量生成失败:" + error.message); |
| | | } finally { |
| | | generating.value = false |
| | | generating.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 下载单个批量生成的码 |
| | | const downloadSingleCode = (code) => { |
| | | const a = document.createElement('a') |
| | | a.href = code.url |
| | | a.download = `${code.content}.png` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | } |
| | | const downloadSingleCode = code => { |
| | | const a = document.createElement("a"); |
| | | a.href = code.url; |
| | | a.download = `${code.content}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | }; |
| | | |
| | | // 下载所有批量生成的码 |
| | | const downloadAllCodes = async () => { |
| | | if (batchCodes.value.length === 0) { |
| | | ElMessage.warning('没有可下载的码') |
| | | return |
| | | ElMessage.warning("没有可下载的码"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // 使用JSZip打包下载 |
| | | const JSZip = await import('jszip') |
| | | const zip = new JSZip.default() |
| | | const JSZip = await import("jszip"); |
| | | const zip = new JSZip.default(); |
| | | |
| | | batchCodes.value.forEach((code, index) => { |
| | | // 将base64转换为blob |
| | | const base64Data = code.url.split(',')[1] |
| | | const byteCharacters = atob(base64Data) |
| | | const byteNumbers = new Array(byteCharacters.length) |
| | | const base64Data = code.url.split(",")[1]; |
| | | const byteCharacters = atob(base64Data); |
| | | const byteNumbers = new Array(byteCharacters.length); |
| | | for (let i = 0; i < byteCharacters.length; i++) { |
| | | byteNumbers[i] = byteCharacters.charCodeAt(i) |
| | | byteNumbers[i] = byteCharacters.charCodeAt(i); |
| | | } |
| | | const byteArray = new Uint8Array(byteNumbers) |
| | | const byteArray = new Uint8Array(byteNumbers); |
| | | |
| | | zip.file(`${code.content}.png`, byteArray) |
| | | }) |
| | | zip.file(`${code.content}.png`, byteArray); |
| | | }); |
| | | |
| | | const content = await zip.generateAsync({ type: 'blob' }) |
| | | const a = document.createElement('a') |
| | | a.href = URL.createObjectURL(content) |
| | | a.download = `批量${form.type === 'qrcode' ? '二维码' : '防伪码'}_${new Date().getTime()}.zip` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | URL.revokeObjectURL(a.href) |
| | | const content = await zip.generateAsync({ type: "blob" }); |
| | | const a = document.createElement("a"); |
| | | a.href = URL.createObjectURL(content); |
| | | a.download = `批量${ |
| | | form.type === "qrcode" ? "二维码" : "防伪码" |
| | | }_${new Date().getTime()}.zip`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | URL.revokeObjectURL(a.href); |
| | | |
| | | ElMessage.success('批量下载完成!') |
| | | ElMessage.success("批量下载完成!"); |
| | | } catch (error) { |
| | | console.error('批量下载失败:', error) |
| | | ElMessage.error('批量下载失败,请逐个下载') |
| | | console.error("批量下载失败:", error); |
| | | ElMessage.error("批量下载失败,请逐个下载"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 清空批量生成结果 |
| | | const clearBatchCodes = () => { |
| | | batchCodes.value = [] |
| | | } |
| | | batchCodes.value = []; |
| | | }; |
| | | |
| | | // 暴露方法给父组件 |
| | | defineExpose({ |
| | | generateCode, |
| | | downloadCode, |
| | | resetForm, |
| | | form |
| | | }) |
| | | form, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |