From c7b4b9a2f4c0f05aeb60a9e3f5fba5d9a3676f3f Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 18 八月 2025 16:22:42 +0800
Subject: [PATCH] 中强恒兴设备管理页面添加

---
 src/views/tool/qrCodeGenerator/index.vue |  433 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 433 insertions(+), 0 deletions(-)

diff --git a/src/views/tool/qrCodeGenerator/index.vue b/src/views/tool/qrCodeGenerator/index.vue
new file mode 100644
index 0000000..5fff74a
--- /dev/null
+++ b/src/views/tool/qrCodeGenerator/index.vue
@@ -0,0 +1,433 @@
+<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>

--
Gitblit v1.9.3