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/qrCodeSimple/index.vue |  526 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 526 insertions(+), 0 deletions(-)

diff --git a/src/views/tool/qrCodeSimple/index.vue b/src/views/tool/qrCodeSimple/index.vue
new file mode 100644
index 0000000..6f84fce
--- /dev/null
+++ b/src/views/tool/qrCodeSimple/index.vue
@@ -0,0 +1,526 @@
+<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