From db42d47f5692ef64e5436c5a6d29dcb537b44596 Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期一, 26 一月 2026 16:36:13 +0800
Subject: [PATCH] 浪潮对接单点登录:mis调整

---
 src/components/QRCodeGenerator/index.vue |  566 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 566 insertions(+), 0 deletions(-)

diff --git a/src/components/QRCodeGenerator/index.vue b/src/components/QRCodeGenerator/index.vue
new file mode 100644
index 0000000..fd44f44
--- /dev/null
+++ b/src/components/QRCodeGenerator/index.vue
@@ -0,0 +1,566 @@
+<template>
+  <div class="qr-code-generator">
+    <!-- 浜岀淮鐮佺敓鎴愯〃鍗� -->
+    <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-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <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>
+          </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"
+                             :min="100"
+                             :max="500"
+                             :step="50"
+                             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"
+                             :min="0"
+                             :max="10"
+                             :step="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="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>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <el-form-item>
+            <el-button type="primary"
+                       @click="generateCode"
+                       :loading="generating">
+              鐢熸垚{{ form.type === 'qrcode' ? '浜岀淮鐮�' : '闃蹭吉鐮�' }}
+            </el-button>
+            <el-button @click="resetForm">閲嶇疆</el-button>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+    <!-- 鐢熸垚鐨勭爜鏄剧ず鍖哄煙 -->
+    <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' ? '浜岀淮鐮�' : '闃蹭吉鐮�'" />
+        </div>
+        <div class="code-info">
+          <p><strong>鍐呭锛�</strong>{{ form.content }}</p>
+          <p><strong>绫诲瀷锛�</strong>{{ form.type === 'qrcode' ? '浜岀淮鐮�' : '闃蹭吉鐮�' }}</p>
+          <p><strong>灏哄锛�</strong>{{ form.size }}x{{ form.size }}px</p>
+          <p><strong>鐢熸垚鏃堕棿锛�</strong>{{ generateTime }}</p>
+        </div>
+      </div>
+      <div class="code-actions">
+        <el-button type="success"
+                   @click="downloadCode"
+                   icon="Download">
+          涓嬭浇鍥剧墖
+        </el-button>
+        <el-button type="primary"
+                   @click="copyToClipboard"
+                   icon="CopyDocument">
+          澶嶅埗鍐呭
+        </el-button>
+        <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-form-item label="鐢熸垚鏁伴噺">
+          <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="璇疯緭鍏ュ墠缂�锛屽锛歅ROD_"></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-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>
+        </div>
+      </template>
+    </el-dialog>
+    <!-- 鎵归噺鐢熸垚缁撴灉 -->
+    <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"
+             :key="index"
+             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>
+        </div>
+      </div>
+      <div class="batch-actions">
+        <el-button type="success"
+                   @click="downloadAllCodes">涓嬭浇鍏ㄩ儴</el-button>
+        <el-button @click="clearBatchCodes">娓呯┖缁撴灉</el-button>
+      </div>
+    </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";
+
+  // 瀹氫箟缁勪欢鍚嶇О
+  defineOptions({
+    name: "QRCodeGenerator",
+  });
+
+  // 琛ㄥ崟鏁版嵁
+  const form = reactive({
+    type: "qrcode",
+    content: "",
+    size: 200,
+    margin: 2,
+    foregroundColor: "#000000",
+    backgroundColor: "#FFFFFF",
+  });
+
+  // 琛ㄥ崟楠岃瘉瑙勫垯
+  const rules = {
+    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 batchForm = reactive({
+    quantity: 10,
+    prefix: "",
+    startNumber: 1,
+  });
+  const batchCodes = ref([]);
+
+  // 鐢熸垚浜岀淮鐮佹垨闃蹭吉鐮�
+  const generateCode = async () => {
+    try {
+      await formRef.value.validate();
+
+      if (!form.content.trim()) {
+        ElMessage.warning("璇疯緭鍏ヨ缂栫爜鐨勫唴瀹�");
+        return;
+      }
+
+      generating.value = true;
+
+      if (form.type === "qrcode") {
+        // 鐢熸垚浜岀淮鐮�
+        generatedCodeUrl.value = await QRCode.toDataURL(form.content, {
+          width: form.size,
+          margin: form.margin,
+          color: {
+            dark: form.foregroundColor,
+            light: form.backgroundColor,
+          },
+          errorCorrectionLevel: "M",
+        });
+      } else {
+        // 鐢熸垚闃蹭吉鐮侊紙浣跨敤浜岀淮鐮佹妧鏈紝浣嗗唴瀹规牸寮忎笉鍚岋級
+        const securityContent = generateSecurityCode(form.content);
+        generatedCodeUrl.value = await QRCode.toDataURL(securityContent, {
+          width: form.size,
+          margin: form.margin,
+          color: {
+            dark: form.foregroundColor,
+            light: form.backgroundColor,
+          },
+          errorCorrectionLevel: "H", // 闃蹭吉鐮佷娇鐢ㄦ渶楂樼籂閿欑骇鍒�
+        });
+      }
+
+      generateTime.value = new Date().toLocaleString();
+      ElMessage.success("鐢熸垚鎴愬姛锛�");
+    } catch (error) {
+      console.error("鐢熸垚澶辫触:", error);
+      ElMessage.error("鐢熸垚澶辫触锛�" + error.message);
+    } finally {
+      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 downloadCode = () => {
+    if (!generatedCodeUrl.value) {
+      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 copyToClipboard = async () => {
+    try {
+      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 printCode = () => {
+    if (!generatedCodeUrl.value) {
+      ElMessage.warning("璇峰厛鐢熸垚鐮�");
+      return;
+    }
+
+    const printWindow = window.open("", "_blank");
+    printWindow.document.write(`
+      <html>
+        <head>
+          <title>鎵撳嵃${form.type === "qrcode" ? "浜岀淮鐮�" : "闃蹭吉鐮�"}</title>
+          <style>
+            body { text-align: center; padding: 20px; }
+            img { max-width: 100%; height: auto; }
+            .info { margin: 20px 0; }
+          </style>
+        </head>
+        <body>
+          <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();
+  };
+
+  // 閲嶇疆琛ㄥ崟
+  const resetForm = () => {
+    formRef.value.resetFields();
+    generatedCodeUrl.value = "";
+    generateTime.value = "";
+    batchCodes.value = [];
+  };
+
+  // 鎵归噺鐢熸垚
+  const generateBatchCodes = async () => {
+    if (!batchForm.prefix.trim()) {
+      ElMessage.warning("璇疯緭鍏ュ墠缂�");
+      return;
+    }
+
+    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")}`;
+
+        let codeUrl;
+        if (form.type === "qrcode") {
+          codeUrl = await QRCode.toDataURL(content, {
+            width: form.size,
+            margin: form.margin,
+            color: {
+              dark: form.foregroundColor,
+              light: form.backgroundColor,
+            },
+          });
+        } else {
+          const securityContent = generateSecurityCode(content);
+          codeUrl = await QRCode.toDataURL(securityContent, {
+            width: form.size,
+            margin: form.margin,
+            color: {
+              dark: form.foregroundColor,
+              light: form.backgroundColor,
+            },
+          });
+        }
+
+        batchCodes.value.push({
+          content,
+          url: codeUrl,
+        });
+      }
+
+      ElMessage.success(`鎵归噺鐢熸垚瀹屾垚锛屽叡鐢熸垚 ${batchForm.quantity} 涓爜`);
+      batchDialogVisible.value = false;
+    } catch (error) {
+      console.error("鎵归噺鐢熸垚澶辫触:", error);
+      ElMessage.error("鎵归噺鐢熸垚澶辫触锛�" + error.message);
+    } finally {
+      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 downloadAllCodes = async () => {
+    if (batchCodes.value.length === 0) {
+      ElMessage.warning("娌℃湁鍙笅杞界殑鐮�");
+      return;
+    }
+
+    try {
+      // 浣跨敤JSZip鎵撳寘涓嬭浇
+      const JSZip = await import("jszip");
+      const zip = new JSZip.default();
+
+      batchCodes.value.forEach((code, index) => {
+        // 灏哹ase64杞崲涓篵lob
+        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);
+        }
+        const byteArray = new Uint8Array(byteNumbers);
+
+        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);
+
+      ElMessage.success("鎵归噺涓嬭浇瀹屾垚锛�");
+    } catch (error) {
+      console.error("鎵归噺涓嬭浇澶辫触:", error);
+      ElMessage.error("鎵归噺涓嬭浇澶辫触锛岃閫愪釜涓嬭浇");
+    }
+  };
+
+  // 娓呯┖鎵归噺鐢熸垚缁撴灉
+  const clearBatchCodes = () => {
+    batchCodes.value = [];
+  };
+
+  // 鏆撮湶鏂规硶缁欑埗缁勪欢
+  defineExpose({
+    generateCode,
+    downloadCode,
+    resetForm,
+    form,
+  });
+</script>
+
+<style scoped>
+  .qr-code-generator {
+    padding: 20px;
+  }
+
+  .qr-form {
+    background: #f8f9fa;
+    padding: 20px;
+    border-radius: 8px;
+    margin-bottom: 20px;
+  }
+
+  .code-display {
+    margin-top: 30px;
+  }
+
+  .code-container {
+    display: flex;
+    justify-content: center;
+    align-items: flex-start;
+    gap: 40px;
+    margin: 20px 0;
+  }
+
+  .code-image img {
+    border: 2px solid #e0e0e0;
+    border-radius: 8px;
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  }
+
+  .code-info {
+    text-align: left;
+    min-width: 200px;
+  }
+
+  .code-info p {
+    margin: 8px 0;
+    color: #666;
+  }
+
+  .code-actions {
+    text-align: center;
+    margin: 20px 0;
+  }
+
+  .code-actions .el-button {
+    margin: 0 10px;
+  }
+
+  .batch-results {
+    margin-top: 30px;
+  }
+
+  .batch-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
+    gap: 20px;
+    margin: 20px 0;
+  }
+
+  .batch-item {
+    text-align: center;
+    padding: 15px;
+    border: 1px solid #e0e0e0;
+    border-radius: 8px;
+    background: #fff;
+  }
+
+  .batch-item img {
+    width: 100px;
+    height: 100px;
+    margin-bottom: 10px;
+  }
+
+  .batch-content {
+    font-size: 12px;
+    color: #666;
+    margin: 10px 0;
+    word-break: break-all;
+  }
+
+  .batch-actions {
+    text-align: center;
+    margin: 20px 0;
+  }
+
+  .batch-actions .el-button {
+    margin: 0 10px;
+  }
+
+  @media (max-width: 768px) {
+    .code-container {
+      flex-direction: column;
+      align-items: center;
+    }
+
+    .batch-grid {
+      grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
+    }
+  }
+</style>

--
Gitblit v1.9.3