From 00100d130c240c191d87d3b6cfb2415f47b9c2d0 Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期二, 19 八月 2025 10:17:00 +0800 Subject: [PATCH] 中强恒兴数据修改 --- /dev/null | 526 ---------------------------------------------------------- 1 files changed, 0 insertions(+), 526 deletions(-) diff --git a/src/views/tool/qrCodeDemo/index.vue b/src/views/tool/qrCodeDemo/index.vue deleted file mode 100644 index 380760a..0000000 --- a/src/views/tool/qrCodeDemo/index.vue +++ /dev/null @@ -1,405 +0,0 @@ -<template> - <div class="app-container"> - <el-card class="box-card"> - <template #header> - <div class="card-header"> - <span>浜岀淮鐮佺敓鎴愬櫒婕旂ず</span> - <el-tag type="success">鍔熻兘瀹屾暣鐗�</el-tag> - </div> - </template> - - <el-alert - title="鍔熻兘璇存槑" - type="info" - :closable="false" - show-icon - > - <p>鏈紨绀洪〉闈㈠睍绀轰簡浜岀淮鐮佺敓鎴愬櫒鐨勫畬鏁村姛鑳斤紝鍖呮嫭锛�</p> - <ul> - <li>鍩虹浜岀淮鐮佺敓鎴�</li> - <li>闃蹭吉鐮佺敓鎴�</li> - <li>鎵归噺鐢熸垚鍔熻兘</li> - <li>鍥剧墖涓嬭浇鍔熻兘</li> - </ul> - </el-alert> - - <el-divider content-position="center">蹇�熶綋楠�</el-divider> - - <!-- 蹇�熺敓鎴愮ず渚� --> - <el-row :gutter="20"> - <el-col :span="8"> - <el-card shadow="hover" class="demo-card"> - <template #header> - <div class="demo-header"> - <span>缃戝潃浜岀淮鐮�</span> - <el-button type="primary" size="small" @click="generateDemo('url')"> - 鐢熸垚 - </el-button> - </div> - </template> - <div class="demo-content"> - <p>鐢熸垚鎸囧悜鐗瑰畾缃戝潃鐨勪簩缁寸爜</p> - <p class="demo-text">https://www.example.com</p> - </div> - </el-card> - </el-col> - - <el-col :span="8"> - <el-card shadow="hover" class="demo-card"> - <template #header> - <div class="demo-header"> - <span>鑱旂郴鏂瑰紡</span> - <el-button type="primary" size="small" @click="generateDemo('contact')"> - 鐢熸垚 - </el-button> - </div> - </template> - <div class="demo-content"> - <p>鐢熸垚鍖呭惈鑱旂郴淇℃伅鐨勪簩缁寸爜</p> - <p class="demo-text">濮撳悕锛氶檲蹇楀己<br>鐢佃瘽锛�13800138000</p> - </div> - </el-card> - </el-col> - - <el-col :span="8"> - <el-card shadow="hover" class="demo-card"> - <template #header> - <div class="demo-header"> - <span>浜у搧淇℃伅</span> - <el-button type="primary" size="small" @click="generateDemo('product')"> - 鐢熸垚 - </el-button> - </div> - </template> - <div class="demo-content"> - <p>鐢熸垚浜у搧淇℃伅鐨勪簩缁寸爜</p> - <p class="demo-text">浜у搧锛氬伐涓氫紶鎰熷櫒<br>鍨嬪彿锛歋ENSOR-001</p> - </div> - </el-card> - </el-col> - </el-row> - - <el-divider content-position="center">鍔熻兘鍏ュ彛</el-divider> - - <!-- 鍔熻兘鍏ュ彛 --> - <el-row :gutter="20"> - <el-col :span="12"> - <el-card shadow="hover" class="feature-card"> - <div class="feature-content"> - <div class="feature-icon"> - <el-icon size="40" color="#409EFF"><QrCode /></el-icon> - </div> - <div class="feature-text"> - <h3>鍩虹浜岀淮鐮佺敓鎴�</h3> - <p>蹇�熺敓鎴愬悇绉嶅唴瀹圭殑浜岀淮鐮侊紝鏀寔鑷畾涔夋牱寮忓拰涓嬭浇</p> - <el-button type="primary" @click="goToSimple">寮�濮嬩娇鐢�</el-button> - </div> - </div> - </el-card> - </el-col> - - <el-col :span="12"> - <el-card shadow="hover" class="feature-card"> - <div class="feature-content"> - <div class="feature-icon"> - <el-icon size="40" color="#E6A23C"><Shield /></el-icon> - </div> - <div class="feature-text"> - <h3>闃蹭吉鐮佺敓鎴�</h3> - <p>鐢熸垚鍏锋湁闃蹭吉鍔熻兘鐨勪簩缁寸爜锛屾敮鎸佹壒閲忕敓鎴愬拰涓嬭浇</p> - <el-button type="warning" @click="goToAdvanced">寮�濮嬩娇鐢�</el-button> - </div> - </div> - </el-card> - </el-col> - </el-row> - - <el-divider content-position="center">浣跨敤璇存槑</el-divider> - - <!-- 浣跨敤璇存槑 --> - <el-collapse v-model="activeNames"> - <el-collapse-item title="浜岀淮鐮佺敓鎴愭楠�" name="1"> - <div class="instruction-content"> - <ol> - <li>閫夋嫨瑕佺敓鎴愮殑鍐呭绫诲瀷锛堟枃鏈�佺綉鍧�銆佽仈绯绘柟寮忕瓑锛�</li> - <li>杈撳叆鍏蜂綋鍐呭</li> - <li>閫夋嫨浜岀淮鐮佸昂瀵稿拰棰滆壊</li> - <li>鐐瑰嚮鐢熸垚鎸夐挳</li> - <li>棰勮鐢熸垚鐨勪簩缁寸爜</li> - <li>涓嬭浇鍥剧墖鍒版湰鍦�</li> - </ol> - </div> - </el-collapse-item> - - <el-collapse-item title="闃蹭吉鐮佺壒鐐�" name="2"> - <div class="instruction-content"> - <ul> - <li><strong>鍞竴鎬�</strong>锛氭瘡涓槻浼爜閮藉寘鍚椂闂存埑鍜岄殢鏈烘暟</li> - <li><strong>楂樼籂閿�</strong>锛氫娇鐢ㄦ渶楂樼籂閿欑骇鍒紝鎵弿鎴愬姛鐜囨洿楂�</li> - <li><strong>鎵归噺鐢熸垚</strong>锛氭敮鎸佷竴娆$敓鎴愬涓槻浼爜</li> - <li><strong>鏍煎紡瑙勮寖</strong>锛歋EC_浜у搧缂栫爜_鎵规鍙穇鏃堕棿鎴砡闅忔満鏁�</li> - </ul> - </div> - </el-collapse-item> - - <el-collapse-item title="搴旂敤鍦烘櫙" name="3"> - <div class="instruction-content"> - <div class="scenario-grid"> - <div class="scenario-item"> - <el-icon color="#67C23A"><Goods /></el-icon> - <span>浜у搧鍖呰</span> - </div> - <div class="scenario-item"> - <el-icon color="#409EFF"><Document /></el-icon> - <span>鏂囨。楠岃瘉</span> - </div> - <div class="scenario-item"> - <el-icon color="#E6A23C"><Tickets /></el-icon> - <span>绁ㄦ嵁闃蹭吉</span> - </div> - <div class="scenario-item"> - <el-icon color="#F56C6C"><Medal /></el-icon> - <span>璇佷功楠岃瘉</span> - </div> - </div> - </div> - </el-collapse-item> - </el-collapse> - </el-card> - - <!-- 鐢熸垚鐨勪簩缁寸爜棰勮 --> - <el-dialog v-model="previewVisible" title="鐢熸垚鐨勪簩缁寸爜" width="400px" center> - <div class="preview-container"> - <img v-if="previewUrl" :src="previewUrl" alt="棰勮浜岀淮鐮�" /> - <div class="preview-info"> - <p><strong>鍐呭锛�</strong>{{ previewContent }}</p> - <p><strong>绫诲瀷锛�</strong>{{ previewType }}</p> - </div> - <div class="preview-actions"> - <el-button type="success" @click="downloadPreview" icon="Download"> - 涓嬭浇鍥剧墖 - </el-button> - <el-button @click="previewVisible = false">鍏抽棴</el-button> - </div> - </div> - </el-dialog> - </div> -</template> - -<script setup> -import { ref } from 'vue' -import { useRouter } from 'vue-router' -import { ElMessage } from 'element-plus' -import { QrCode, Shield, Goods, Document, Tickets, Medal } from '@element-plus/icons-vue' -import QRCode from 'qrcode' - -defineOptions({ - name: 'QRCodeDemo' -}) - -const router = useRouter() -const activeNames = ref(['1']) -const previewVisible = ref(false) -const previewUrl = ref('') -const previewContent = ref('') -const previewType = ref('') - -// 鐢熸垚婕旂ず浜岀淮鐮� -const generateDemo = async (type) => { - try { - let content = '' - let typeName = '' - - switch (type) { - case 'url': - content = 'https://www.example.com' - typeName = '缃戝潃浜岀淮鐮�' - break - case 'contact': - content = 'BEGIN:VCARD\nVERSION:3.0\nFN:闄堝織寮篭nTEL:13800138000\nEND:VCARD' - typeName = '鑱旂郴鏂瑰紡浜岀淮鐮�' - break - case 'product': - content = '浜у搧鍚嶇О锛氬伐涓氫紶鎰熷櫒\n鍨嬪彿锛歋ENSOR-001\n瑙勬牸锛氶珮绮惧害鍨媆n鐢ㄩ�旓細宸ヤ笟鑷姩鍖�' - typeName = '浜у搧淇℃伅浜岀淮鐮�' - break - } - - const qrCodeUrl = await QRCode.toDataURL(content, { - width: 256, - margin: 2, - color: { - dark: '#000000', - light: '#FFFFFF' - } - }) - - previewUrl.value = qrCodeUrl - previewContent.value = content - previewType.value = typeName - previewVisible.value = true - - } catch (error) { - console.error('鐢熸垚婕旂ず浜岀淮鐮佸け璐�:', error) - ElMessage.error('鐢熸垚澶辫触锛�' + error.message) - } -} - -// 涓嬭浇棰勮鐨勪簩缁寸爜 -const downloadPreview = () => { - if (!previewUrl.value) { - ElMessage.warning('娌℃湁鍙笅杞界殑浜岀淮鐮�') - return - } - - const a = document.createElement('a') - a.href = previewUrl.value - a.download = `${previewType.value}_${new Date().getTime()}.png` - document.body.appendChild(a) - a.click() - document.body.removeChild(a) - ElMessage.success('涓嬭浇鎴愬姛锛�') -} - -// 璺宠浆鍒扮畝鍖栫増椤甸潰 -const goToSimple = () => { - router.push('/tool/qrCodeSimple') -} - -// 璺宠浆鍒伴珮绾х増椤甸潰 -const goToAdvanced = () => { - router.push('/tool/qrCodeGenerator') -} -</script> - -<style scoped> -.app-container { - padding: 20px; -} - -.box-card { - margin-bottom: 20px; -} - -.card-header { - display: flex; - justify-content: space-between; - align-items: center; -} - -.demo-card { - margin-bottom: 20px; -} - -.demo-header { - display: flex; - justify-content: space-between; - align-items: center; -} - -.demo-content { - text-align: center; -} - -.demo-text { - font-size: 12px; - color: #666; - background: #f8f9fa; - padding: 8px; - border-radius: 4px; - margin-top: 10px; -} - -.feature-card { - margin-bottom: 20px; -} - -.feature-content { - display: flex; - align-items: center; - gap: 20px; -} - -.feature-icon { - flex-shrink: 0; -} - -.feature-text h3 { - margin: 0 0 10px 0; - color: #303133; -} - -.feature-text p { - margin: 0 0 15px 0; - color: #606266; - line-height: 1.5; -} - -.instruction-content { - padding: 10px 0; -} - -.instruction-content ol, -.instruction-content ul { - margin: 0; - padding-left: 20px; -} - -.instruction-content li { - margin: 8px 0; - line-height: 1.6; -} - -.scenario-grid { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 20px; - margin-top: 15px; -} - -.scenario-item { - display: flex; - align-items: center; - gap: 10px; - padding: 15px; - background: #f8f9fa; - border-radius: 8px; - text-align: center; -} - -.scenario-item span { - font-weight: 500; - color: #303133; -} - -.preview-container { - text-align: center; -} - -.preview-container img { - max-width: 100%; - height: auto; - border: 2px solid #e0e0e0; - border-radius: 8px; - margin-bottom: 20px; -} - -.preview-info { - text-align: left; - background: #f8f9fa; - padding: 15px; - border-radius: 8px; - margin-bottom: 20px; -} - -.preview-info p { - margin: 8px 0; - color: #666; -} - -.preview-actions { - display: flex; - justify-content: center; - gap: 15px; -} -</style> diff --git a/src/views/tool/qrCodeGenerator/index.vue b/src/views/tool/qrCodeGenerator/index.vue deleted file mode 100644 index 5fff74a..0000000 --- a/src/views/tool/qrCodeGenerator/index.vue +++ /dev/null @@ -1,433 +0,0 @@ -<template> - <div class="app-container"> - <el-card class="box-card"> - <template #header> - <div class="card-header"> - <span>浜岀淮鐮佷笌闃蹭吉鐮佺敓鎴愬櫒</span> - <el-button type="primary" @click="showBatchDialog" icon="Plus"> - 鎵归噺鐢熸垚 - </el-button> - </div> - </template> - - <!-- 闆嗘垚浜岀淮鐮佺敓鎴愮粍浠� --> - <QRCodeGenerator ref="qrGeneratorRef" /> - </el-card> - - <!-- 鎵归噺鐢熸垚瀵硅瘽妗� --> - <el-dialog v-model="batchDialogVisible" title="鎵归噺鐢熸垚璁剧疆" width="800px"> - <el-form :model="batchForm" :rules="batchRules" ref="batchFormRef" label-width="120px"> - <el-row :gutter="20"> - <el-col :span="12"> - <el-form-item label="鏍囪瘑绫诲瀷" prop="type"> - <el-select v-model="batchForm.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="quantity"> - <el-input-number - v-model="batchForm.quantity" - :min="1" - :max="1000" - :step="10" - 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="prefix"> - <el-input v-model="batchForm.prefix" placeholder="璇疯緭鍏ュ墠缂�锛屽锛歅ROD_"></el-input> - </el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item label="璧峰缂栧彿" prop="startNumber"> - <el-input-number v-model="batchForm.startNumber" :min="1" 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="size"> - <el-input-number - v-model="batchForm.size" - :min="100" - :max="500" - :step="50" - style="width: 100%" - ></el-input-number> - </el-col> - <el-col :span="12"> - <el-form-item label="杈硅窛" prop="margin"> - <el-input-number - v-model="batchForm.margin" - :min="0" - :max="10" - :step="1" - style="width: 100%" - ></el-input-number> - </el-col> - </el-col> - </el-row> - - <el-row :gutter="20"> - <el-col :span="12"> - <el-form-item label="鍓嶆櫙鑹�" prop="foregroundColor"> - <el-color-picker v-model="batchForm.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="batchForm.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 label="澶囨敞"> - <el-input - v-model="batchForm.remark" - type="textarea" - :rows="3" - placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" - ></el-input> - </el-form-item> - </el-col> - </el-row> - </el-form> - - <template #footer> - <div class="dialog-footer"> - <el-button @click="batchDialogVisible = false">鍙栨秷</el-button> - <el-button type="primary" @click="startBatchGeneration" :loading="generating"> - 寮�濮嬬敓鎴� - </el-button> - </div> - </template> - </el-dialog> - - <!-- 鎵归噺鐢熸垚杩涘害 --> - <el-dialog v-model="progressDialogVisible" title="鎵归噺鐢熸垚杩涘害" width="500px" :close-on-click-modal="false"> - <div class="progress-container"> - <el-progress - :percentage="progressPercentage" - :status="progressStatus" - :stroke-width="20" - ></el-progress> - <p class="progress-text">{{ progressText }}</p> - <div class="progress-details"> - <p>宸茬敓鎴�: {{ generatedCount }} / {{ totalCount }}</p> - <p>褰撳墠鍐呭: {{ currentContent }}</p> - </div> - </div> - - <template #footer> - <div class="dialog-footer"> - <el-button @click="cancelGeneration" :disabled="!canCancel">鍙栨秷</el-button> - <el-button type="primary" @click="downloadBatchResults" v-if="generationCompleted"> - 涓嬭浇缁撴灉 - </el-button> - </div> - </template> - </el-dialog> - </div> -</template> - -<script setup> -import { ref, reactive, computed } from 'vue' -import { ElMessage, ElMessageBox } from 'element-plus' -import QRCodeGenerator from '@/components/QRCodeGenerator/index.vue' -import QRCode from 'qrcode' -import JSZip from 'jszip' - -defineOptions({ - name: 'QRCodeGeneratorPage' -}) - -// 缁勪欢寮曠敤 -const qrGeneratorRef = ref() - -// 鎵归噺鐢熸垚鐩稿叧 -const batchDialogVisible = ref(false) -const progressDialogVisible = ref(false) -const generating = ref(false) -const generationCompleted = ref(false) -const canCancel = ref(true) - -const batchForm = reactive({ - type: 'qrcode', - quantity: 100, - prefix: 'PROD_', - startNumber: 1, - size: 200, - margin: 2, - foregroundColor: '#000000', - backgroundColor: '#FFFFFF', - remark: '' -}) - -const batchRules = { - type: [{ required: true, message: '璇烽�夋嫨鏍囪瘑绫诲瀷', trigger: 'change' }], - quantity: [{ required: true, message: '璇疯緭鍏ョ敓鎴愭暟閲�', trigger: 'blur' }], - prefix: [{ required: true, message: '璇疯緭鍏ュ墠缂�', trigger: 'blur' }], - startNumber: [{ required: true, message: '璇疯緭鍏ヨ捣濮嬬紪鍙�', trigger: 'blur' }] -} - -// 杩涘害鐩稿叧 -const progressPercentage = ref(0) -const progressStatus = ref('') -const progressText = ref('鍑嗗涓�...') -const generatedCount = ref(0) -const totalCount = ref(0) -const currentContent = ref('') - -// 鐢熸垚缁撴灉 -const batchResults = ref([]) - -// 鏄剧ず鎵归噺鐢熸垚瀵硅瘽妗� -const showBatchDialog = () => { - batchDialogVisible.value = true - // 閲嶇疆琛ㄥ崟 - Object.assign(batchForm, { - type: 'qrcode', - quantity: 100, - prefix: 'PROD_', - startNumber: 1, - size: 200, - margin: 2, - foregroundColor: '#000000', - backgroundColor: '#FFFFFF', - remark: '' - }) -} - -// 寮�濮嬫壒閲忕敓鎴� -const startBatchGeneration = async () => { - try { - await batchFormRef.value.validate() - - if (!batchForm.prefix.trim()) { - ElMessage.warning('璇疯緭鍏ュ墠缂�') - return - } - - batchDialogVisible.value = false - progressDialogVisible.value = true - generating.value = true - generationCompleted.value = false - canCancel.value = true - - // 閲嶇疆杩涘害 - progressPercentage.value = 0 - progressStatus.value = '' - progressText.value = '寮�濮嬬敓鎴�...' - generatedCount.value = 0 - totalCount.value = batchForm.quantity - batchResults.value = [] - - await generateBatchCodes() - - } catch (error) { - console.error('鎵归噺鐢熸垚澶辫触:', error) - ElMessage.error('鎵归噺鐢熸垚澶辫触锛�' + error.message) - } -} - -// 鐢熸垚闃蹭吉鐮佸唴瀹� -const generateSecurityCode = (content) => { - const timestamp = Date.now() - const random = Math.random().toString(36).substr(2, 8) - return `SEC_${content}_${timestamp}_${random}` -} - -// 鎵归噺鐢熸垚鐮� -const generateBatchCodes = async () => { - try { - for (let i = 0; i < batchForm.quantity; i++) { - if (!canCancel.value) { - progressText.value = '鐢熸垚宸插彇娑�' - progressStatus.value = 'exception' - break - } - - const number = batchForm.startNumber + i - const content = `${batchForm.prefix}${number.toString().padStart(6, '0')}` - currentContent.value = content - - let codeUrl - if (batchForm.type === 'qrcode') { - codeUrl = await QRCode.toDataURL(content, { - width: batchForm.size, - margin: batchForm.margin, - color: { - dark: batchForm.foregroundColor, - light: batchForm.backgroundColor - }, - errorCorrectionLevel: 'M' - }) - } else { - const securityContent = generateSecurityCode(content) - codeUrl = await QRCode.toDataURL(securityContent, { - width: batchForm.size, - margin: batchForm.margin, - color: { - dark: batchForm.foregroundColor, - light: batchForm.backgroundColor - }, - errorCorrectionLevel: 'H' - }) - } - - batchResults.value.push({ - content, - url: codeUrl, - type: batchForm.type, - generateTime: new Date().toLocaleString() - }) - - generatedCount.value = i + 1 - progressPercentage.value = Math.round(((i + 1) / batchForm.quantity) * 100) - progressText.value = `姝e湪鐢熸垚绗� ${i + 1} 涓爜...` - - // 娣诲姞灏忓欢杩燂紝璁╃敤鎴风湅鍒拌繘搴� - await new Promise(resolve => setTimeout(resolve, 50)) - } - - if (canCancel.value) { - progressText.value = '鐢熸垚瀹屾垚锛�' - progressStatus.value = 'success' - generationCompleted.value = true - ElMessage.success(`鎵归噺鐢熸垚瀹屾垚锛屽叡鐢熸垚 ${batchForm.quantity} 涓爜`) - } - - } catch (error) { - console.error('鎵归噺鐢熸垚澶辫触:', error) - progressText.value = '鐢熸垚澶辫触锛�' + error.message - progressStatus.value = 'exception' - ElMessage.error('鎵归噺鐢熸垚澶辫触锛�' + error.message) - } finally { - generating.value = false - } -} - -// 鍙栨秷鐢熸垚 -const cancelGeneration = () => { - canCancel.value = false - progressText.value = '姝e湪鍙栨秷...' - setTimeout(() => { - progressDialogVisible.value = false - ElMessage.info('鐢熸垚宸插彇娑�') - }, 1000) -} - -// 涓嬭浇鎵归噺鐢熸垚缁撴灉 -const downloadBatchResults = async () => { - if (batchResults.value.length === 0) { - ElMessage.warning('娌℃湁鍙笅杞界殑缁撴灉') - return - } - - try { - const zip = new JSZip() - - // 鍒涘缓璇存槑鏂囦欢 - const readme = `鎵归噺鐢熸垚璇存槑 -绫诲瀷: ${batchForm.type === 'qrcode' ? '浜岀淮鐮�' : '闃蹭吉鐮�'} -鏁伴噺: ${batchResults.value.length} -鍓嶇紑: ${batchForm.prefix} -璧峰缂栧彿: ${batchForm.startNumber} -灏哄: ${batchForm.size}x${batchForm.size}px -鐢熸垚鏃堕棿: ${new Date().toLocaleString()} -澶囨敞: ${batchForm.remark || '鏃�'} - -鏂囦欢鍒楄〃: -${batchResults.value.map((item, index) => `${index + 1}. ${item.content}.png`).join('\n')} -` - - zip.file('README.txt', readme) - - // 娣诲姞鍥剧墖鏂囦欢 - batchResults.value.forEach((result, index) => { - const base64Data = result.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) - } - const byteArray = new Uint8Array(byteNumbers) - - zip.file(`${result.content}.png`, byteArray) - }) - - const content = await zip.generateAsync({ type: 'blob' }) - const a = document.createElement('a') - a.href = URL.createObjectURL(content) - a.download = `鎵归噺${batchForm.type === 'qrcode' ? '浜岀淮鐮�' : '闃蹭吉鐮�'}_${batchForm.prefix}_${new Date().getTime()}.zip` - document.body.appendChild(a) - a.click() - document.body.removeChild(a) - URL.revokeObjectURL(a.href) - - ElMessage.success('鎵归噺涓嬭浇瀹屾垚锛�') - progressDialogVisible.value = false - - } catch (error) { - console.error('鎵归噺涓嬭浇澶辫触:', error) - ElMessage.error('鎵归噺涓嬭浇澶辫触锛�' + error.message) - } -} - -// 琛ㄥ崟寮曠敤 -const batchFormRef = ref() -</script> - -<style scoped> -.app-container { - padding: 20px; -} - -.box-card { - margin-bottom: 20px; -} - -.card-header { - display: flex; - justify-content: space-between; - align-items: center; -} - -.progress-container { - text-align: center; - padding: 20px; -} - -.progress-text { - margin: 20px 0; - font-size: 16px; - font-weight: bold; -} - -.progress-details { - margin-top: 20px; - text-align: left; - background: #f8f9fa; - padding: 15px; - border-radius: 8px; -} - -.progress-details p { - margin: 8px 0; - color: #666; -} - -.dialog-footer { - text-align: right; -} -</style> diff --git a/src/views/tool/qrCodeSimple/index.vue b/src/views/tool/qrCodeSimple/index.vue deleted file mode 100644 index 6f84fce..0000000 --- a/src/views/tool/qrCodeSimple/index.vue +++ /dev/null @@ -1,526 +0,0 @@ -<template> - <div class="app-container"> - <el-row :gutter="20"> - <!-- 宸︿晶锛氱敓鎴愯〃鍗� --> - <el-col :span="12"> - <el-card class="box-card"> - <template #header> - <div class="card-header"> - <span>浜岀淮鐮佺敓鎴�</span> - </div> - </template> - - <el-form :model="form" :rules="rules" ref="formRef" label-width="100px"> - <el-form-item label="鍐呭" prop="content"> - <el-input - v-model="form.content" - type="textarea" - :rows="4" - placeholder="璇疯緭鍏ヨ鐢熸垚浜岀淮鐮佺殑鍐呭锛屽锛氱綉鍧�銆佹枃鏈�佽仈绯绘柟寮忕瓑" - ></el-input> - </el-form-item> - - <el-form-item label="灏哄"> - <el-select v-model="form.size" style="width: 100%"> - <el-option label="灏忓昂瀵� (128x128)" value="128"></el-option> - <el-option label="鏍囧噯灏哄 (256x256)" value="256"></el-option> - <el-option label="澶у昂瀵� (512x512)" value="512"></el-option> - <el-option label="瓒呭ぇ灏哄 (1024x1024)" value="1024"></el-option> - </el-select> - </el-form-item> - - <el-form-item label="鍓嶆櫙鑹�"> - <el-color-picker v-model="form.foregroundColor"></el-color-picker> - </el-form-item> - - <el-form-item label="鑳屾櫙鑹�"> - <el-color-picker v-model="form.backgroundColor"></el-color-picker> - </el-form-item> - - <el-form-item> - <el-button type="primary" @click="generateQRCode" :loading="generating" size="large"> - 鐢熸垚浜岀淮鐮� - </el-button> - <el-button @click="resetForm">閲嶇疆</el-button> - </el-form-item> - </el-form> - </el-card> - </el-col> - - <!-- 鍙充晶锛氶瑙堝拰涓嬭浇 --> - <el-col :span="12"> - <el-card class="box-card"> - <template #header> - <div class="card-header"> - <span>棰勮涓庝笅杞�</span> - <el-button - v-if="qrCodeUrl" - type="success" - @click="downloadQRCode" - icon="Download" - size="small" - > - 涓嬭浇鍥剧墖 - </el-button> - </div> - </template> - - <div v-if="qrCodeUrl" class="preview-container"> - <div class="qr-preview"> - <img :src="qrCodeUrl" alt="鐢熸垚鐨勪簩缁寸爜" /> - </div> - <div class="qr-info"> - <p><strong>鍐呭锛�</strong>{{ form.content }}</p> - <p><strong>灏哄锛�</strong>{{ form.size }}x{{ form.size }}px</p> - <p><strong>鐢熸垚鏃堕棿锛�</strong>{{ generateTime }}</p> - </div> - </div> - - <div v-else class="empty-preview"> - <el-empty description="璇峰厛鐢熸垚浜岀淮鐮�" :image-size="100"></el-empty> - </div> - </el-card> - </el-col> - </el-row> - - <!-- 闃蹭吉鐮佺敓鎴愬尯鍩� --> - <el-row :gutter="20" style="margin-top: 20px;"> - <el-col :span="24"> - <el-card class="box-card"> - <template #header> - <div class="card-header"> - <span>闃蹭吉鐮佺敓鎴�</span> - <el-button type="warning" @click="showSecurityDialog" icon="Shield"> - 鐢熸垚闃蹭吉鐮� - </el-button> - </div> - </template> - - <div class="security-info"> - <p>闃蹭吉鐮佺壒鐐癸細</p> - <ul> - <li>鍖呭惈鏃堕棿鎴冲拰闅忔満鏁帮紝纭繚鍞竴鎬�</li> - <li>浣跨敤鏈�楂樼籂閿欑骇鍒紝鎻愰珮鎵弿鎴愬姛鐜�</li> - <li>鏀寔鎵归噺鐢熸垚鍜屼笅杞�</li> - <li>閫傜敤浜庝骇鍝侀槻浼�佹枃妗i獙璇佺瓑鍦烘櫙</li> - </ul> - </div> - </el-card> - </el-col> - </el-row> - - <!-- 闃蹭吉鐮佺敓鎴愬璇濇 --> - <el-dialog v-model="securityDialogVisible" title="闃蹭吉鐮佺敓鎴�" width="600px"> - <el-form :model="securityForm" :rules="securityRules" ref="securityFormRef" label-width="100px"> - <el-form-item label="浜у搧鍚嶇О" prop="productName"> - <el-input v-model="securityForm.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"></el-input> - </el-form-item> - - <el-form-item label="浜у搧缂栫爜" prop="productCode"> - <el-input v-model="securityForm.productCode" placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�"></el-input> - </el-form-item> - - <el-form-item label="鎵规鍙�" prop="batchNo"> - <el-input v-model="securityForm.batchNo" placeholder="璇疯緭鍏ユ壒娆″彿"></el-input> - </el-form-item> - - <el-form-item label="鐢熸垚鏁伴噺" prop="quantity"> - <el-input-number - v-model="securityForm.quantity" - :min="1" - :max="100" - style="width: 100%" - ></el-input-number> - </el-form-item> - - <el-form-item label="灏哄"> - <el-select v-model="securityForm.size" style="width: 100%"> - <el-option label="鏍囧噯灏哄 (256x256)" value="256"></el-option> - <el-option label="澶у昂瀵� (512x512)" value="512"></el-option> - </el-select> - </el-form-item> - </el-form> - - <template #footer> - <div class="dialog-footer"> - <el-button @click="securityDialogVisible = false">鍙栨秷</el-button> - <el-button type="primary" @click="generateSecurityCodes" :loading="generatingSecurity"> - 寮�濮嬬敓鎴� - </el-button> - </div> - </template> - </el-dialog> - - <!-- 闃蹭吉鐮佺粨鏋滃睍绀� --> - <el-dialog v-model="securityResultVisible" title="闃蹭吉鐮佺敓鎴愮粨鏋�" width="80%" top="5vh"> - <div v-if="securityResults.length > 0" class="security-results"> - <div class="results-header"> - <p>鍏辩敓鎴� {{ securityResults.length }} 涓槻浼爜</p> - <el-button type="success" @click="downloadAllSecurityCodes" icon="Download"> - 涓嬭浇鍏ㄩ儴 - </el-button> - </div> - - <div class="results-grid"> - <div - v-for="(result, index) in securityResults" - :key="index" - class="result-item" - > - <img :src="result.url" :alt="result.content" /> - <p class="result-content">{{ result.content }}</p> - <el-button size="small" @click="downloadSingleSecurityCode(result)"> - 涓嬭浇 - </el-button> - </div> - </div> - </div> - </el-dialog> - </div> -</template> - -<script setup> -import { ref, reactive } from 'vue' -import { ElMessage } from 'element-plus' -import QRCode from 'qrcode' -import JSZip from 'jszip' - -defineOptions({ - name: 'QRCodeSimple' -}) - -// 浜岀淮鐮佺敓鎴愯〃鍗� -const form = reactive({ - content: '', - size: '256', - foregroundColor: '#000000', - backgroundColor: '#FFFFFF' -}) - -const rules = { - content: [{ required: true, message: '璇疯緭鍏ュ唴瀹�', trigger: 'blur' }] -} - -// 闃蹭吉鐮佺敓鎴愯〃鍗� -const securityForm = reactive({ - productName: '', - productCode: '', - batchNo: '', - quantity: 10, - size: '256' -}) - -const securityRules = { - productName: [{ required: true, message: '璇疯緭鍏ヤ骇鍝佸悕绉�', trigger: 'blur' }], - productCode: [{ required: true, message: '璇疯緭鍏ヤ骇鍝佺紪鐮�', trigger: 'blur' }], - batchNo: [{ required: true, message: '璇疯緭鍏ユ壒娆″彿', trigger: 'blur' }], - quantity: [{ required: true, message: '璇疯緭鍏ョ敓鎴愭暟閲�', trigger: 'blur' }] -} - -// 鍝嶅簲寮忔暟鎹� -const formRef = ref() -const securityFormRef = ref() -const generating = ref(false) -const generatingSecurity = ref(false) -const qrCodeUrl = ref('') -const generateTime = ref('') -const securityDialogVisible = ref(false) -const securityResultVisible = ref(false) -const securityResults = ref([]) - -// 鐢熸垚浜岀淮鐮� -const generateQRCode = async () => { - try { - await formRef.value.validate() - - if (!form.content.trim()) { - ElMessage.warning('璇疯緭鍏ヨ鐢熸垚浜岀淮鐮佺殑鍐呭') - return - } - - generating.value = true - - qrCodeUrl.value = await QRCode.toDataURL(form.content, { - width: parseInt(form.size), - margin: 2, - color: { - dark: form.foregroundColor, - light: form.backgroundColor - }, - errorCorrectionLevel: 'M' - }) - - generateTime.value = new Date().toLocaleString() - ElMessage.success('浜岀淮鐮佺敓鎴愭垚鍔燂紒') - - } catch (error) { - console.error('鐢熸垚浜岀淮鐮佸け璐�:', error) - ElMessage.error('鐢熸垚浜岀淮鐮佸け璐ワ細' + error.message) - } finally { - generating.value = false - } -} - -// 涓嬭浇浜岀淮鐮� -const downloadQRCode = () => { - if (!qrCodeUrl.value) { - ElMessage.warning('璇峰厛鐢熸垚浜岀淮鐮�') - return - } - - const a = document.createElement('a') - a.href = qrCodeUrl.value - a.download = `浜岀淮鐮乢${new Date().getTime()}.png` - document.body.appendChild(a) - a.click() - document.body.removeChild(a) - ElMessage.success('涓嬭浇鎴愬姛锛�') -} - -// 閲嶇疆琛ㄥ崟 -const resetForm = () => { - formRef.value.resetFields() - qrCodeUrl.value = '' - generateTime.value = '' -} - -// 鏄剧ず闃蹭吉鐮佸璇濇 -const showSecurityDialog = () => { - securityDialogVisible.value = true - // 閲嶇疆琛ㄥ崟 - Object.assign(securityForm, { - productName: '', - productCode: '', - batchNo: '', - quantity: 10, - size: '256' - }) -} - -// 鐢熸垚闃蹭吉鐮� -const generateSecurityCodes = async () => { - try { - await securityFormRef.value.validate() - - generatingSecurity.value = true - securityResults.value = [] - - for (let i = 1; i <= securityForm.quantity; i++) { - const timestamp = Date.now() + i // 纭繚姣忎釜鐮侀兘鏈変笉鍚岀殑鏃堕棿鎴� - const random = Math.random().toString(36).substr(2, 8) - const content = `SEC_${securityForm.productCode}_${securityForm.batchNo}_${timestamp}_${random}` - - const codeUrl = await QRCode.toDataURL(content, { - width: parseInt(securityForm.size), - margin: 2, - color: { - dark: '#000000', - light: '#FFFFFF' - }, - errorCorrectionLevel: 'H' // 鏈�楂樼籂閿欑骇鍒� - }) - - securityResults.value.push({ - content, - url: codeUrl, - productName: securityForm.productName, - productCode: securityForm.productCode, - batchNo: securityForm.batchNo, - generateTime: new Date().toLocaleString() - }) - } - - securityDialogVisible.value = false - securityResultVisible.value = true - ElMessage.success(`闃蹭吉鐮佺敓鎴愬畬鎴愶紝鍏辩敓鎴� ${securityForm.quantity} 涓猔) - - } catch (error) { - console.error('鐢熸垚闃蹭吉鐮佸け璐�:', error) - ElMessage.error('鐢熸垚闃蹭吉鐮佸け璐ワ細' + error.message) - } finally { - generatingSecurity.value = false - } -} - -// 涓嬭浇鍗曚釜闃蹭吉鐮� -const downloadSingleSecurityCode = (result) => { - const a = document.createElement('a') - a.href = result.url - a.download = `${result.content}.png` - document.body.appendChild(a) - a.click() - document.body.removeChild(a) - ElMessage.success('涓嬭浇鎴愬姛锛�') -} - -// 涓嬭浇鎵�鏈夐槻浼爜 -const downloadAllSecurityCodes = async () => { - if (securityResults.value.length === 0) { - ElMessage.warning('娌℃湁鍙笅杞界殑闃蹭吉鐮�') - return - } - - try { - const zip = new JSZip() - - // 鍒涘缓璇存槑鏂囦欢 - const readme = `闃蹭吉鐮佺敓鎴愯鏄� -浜у搧鍚嶇О: ${securityForm.productName} -浜у搧缂栫爜: ${securityForm.productCode} -鎵规鍙�: ${securityForm.batchNo} -鏁伴噺: ${securityResults.value.length} -灏哄: ${securityForm.size}x${securityForm.size}px -鐢熸垚鏃堕棿: ${new Date().toLocaleString()} - -鏂囦欢鍒楄〃: -${securityResults.value.map((item, index) => `${index + 1}. ${item.content}.png`).join('\n')} -` - - zip.file('README.txt', readme) - - // 娣诲姞鍥剧墖鏂囦欢 - securityResults.value.forEach((result) => { - const base64Data = result.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) - } - const byteArray = new Uint8Array(byteNumbers) - - zip.file(`${result.content}.png`, byteArray) - }) - - const content = await zip.generateAsync({ type: 'blob' }) - const a = document.createElement('a') - a.href = URL.createObjectURL(content) - a.download = `闃蹭吉鐮乢${securityForm.productCode}_${securityForm.batchNo}_${new Date().getTime()}.zip` - document.body.appendChild(a) - a.click() - document.body.removeChild(a) - URL.revokeObjectURL(a.href) - - ElMessage.success('鎵归噺涓嬭浇瀹屾垚锛�') - - } catch (error) { - console.error('鎵归噺涓嬭浇澶辫触:', error) - ElMessage.error('鎵归噺涓嬭浇澶辫触锛�' + error.message) - } -} -</script> - -<style scoped> -.app-container { - padding: 20px; -} - -.box-card { - margin-bottom: 20px; -} - -.card-header { - display: flex; - justify-content: space-between; - align-items: center; -} - -.preview-container { - text-align: center; -} - -.qr-preview img { - max-width: 100%; - height: auto; - border: 2px solid #e0e0e0; - border-radius: 8px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); -} - -.qr-info { - margin-top: 20px; - text-align: left; - background: #f8f9fa; - padding: 15px; - border-radius: 8px; -} - -.qr-info p { - margin: 8px 0; - color: #666; -} - -.empty-preview { - padding: 40px 0; -} - -.security-info { - padding: 20px; - background: #f8f9fa; - border-radius: 8px; -} - -.security-info p { - font-weight: bold; - margin-bottom: 10px; -} - -.security-info ul { - margin: 0; - padding-left: 20px; -} - -.security-info li { - margin: 8px 0; - color: #666; -} - -.security-results { - padding: 20px; -} - -.results-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; - padding-bottom: 15px; - border-bottom: 1px solid #e0e0e0; -} - -.results-header p { - font-size: 16px; - font-weight: bold; - margin: 0; -} - -.results-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); - gap: 20px; -} - -.result-item { - text-align: center; - padding: 15px; - border: 1px solid #e0e0e0; - border-radius: 8px; - background: #fff; -} - -.result-item img { - width: 100px; - height: 100px; - margin-bottom: 10px; -} - -.result-content { - font-size: 12px; - color: #666; - margin: 10px 0; - word-break: break-all; -} - -.dialog-footer { - text-align: right; -} -</style> -- Gitblit v1.9.3