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/views/productManagement/productIdentifier/index.vue |  819 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 819 insertions(+), 0 deletions(-)

diff --git a/src/views/productManagement/productIdentifier/index.vue b/src/views/productManagement/productIdentifier/index.vue
new file mode 100644
index 0000000..519f745
--- /dev/null
+++ b/src/views/productManagement/productIdentifier/index.vue
@@ -0,0 +1,819 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+      <!-- 鎼滅储鍖哄煙 -->
+      <el-row :gutter="20"
+              class="search-row">
+        <el-col :span="6">
+          <el-input v-model="searchForm.productName"
+                    placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+                    clearable
+                    @keyup.enter="handleSearch">
+            <template #prefix>
+              <el-icon>
+                <Search />
+              </el-icon>
+            </template>
+          </el-input>
+        </el-col>
+        <el-col :span="6">
+          <el-select v-model="searchForm.identifierType"
+                     placeholder="璇烽�夋嫨鏍囪瘑绫诲瀷"
+                     clearable>
+            <el-option label="浜岀淮鐮�"
+                       value="浜岀淮鐮�"></el-option>
+            <el-option label="闃蹭吉鐮�"
+                       value="闃蹭吉鐮�"></el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="6">
+          <el-select v-model="searchForm.status"
+                     placeholder="璇烽�夋嫨鐘舵��"
+                     clearable>
+            <el-option label="宸茬敓鎴�"
+                       value="宸茬敓鎴�"></el-option>
+            <el-option label="宸插垎閰�"
+                       value="宸插垎閰�"></el-option>
+            <el-option label="宸蹭娇鐢�"
+                       value="宸蹭娇鐢�"></el-option>
+            <el-option label="宸蹭綔搴�"
+                       value="宸蹭綔搴�"></el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="6">
+          <el-button type="primary"
+                     @click="handleSearch">鎼滅储</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+          <el-button style="float: right;"
+                     type="primary"
+                     @click="handleAdd">
+            鏂板鏍囪瘑
+          </el-button>
+        </el-col>
+      </el-row>
+      <!-- 浜у搧鏍囪瘑鍒楄〃 -->
+      <el-table :data="filteredList"
+                style="width: 100%"
+                v-loading="loading"
+                border
+                stripe
+                height="calc(100vh - 22em)">
+        <el-table-column prop="id"
+                         label="ID"
+                         width="80"
+                         align="center" />
+        <el-table-column prop="productName"
+                         label="浜у搧鍚嶇О"
+                         width="150" />
+        <el-table-column prop="productCode"
+                         label="浜у搧缂栫爜"
+                         width="120" />
+        <el-table-column prop="batchNo"
+                         label="鎵规鍙�"
+                         width="120" />
+        <el-table-column prop="identifierType"
+                         label="鏍囪瘑绫诲瀷"
+                         width="100">
+          <template #default="scope">
+            <el-tag :type="getIdentifierTypeType(scope.row.identifierType)">
+              {{ scope.row.identifierType }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="identifierCode"
+                         label="鏍囪瘑鐮�" />
+        <el-table-column prop="status"
+                         label="鐘舵��"
+                         width="100">
+          <template #default="scope">
+            <el-tag :type="getStatusType(scope.row.status)">
+              {{ scope.row.status }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="generateTime"
+                         label="鐢熸垚鏃堕棿"
+                         width="160" />
+        <el-table-column label="鎿嶄綔"
+                         fixed="right"
+                         align="center"
+                         width="280">
+          <template #default="scope">
+            <el-button link
+                       type="primary"
+                       @click="handleView(scope.row)">鏌ョ湅</el-button>
+            <el-button link
+                       type="primary"
+                       @click="handleEdit(scope.row)">缂栬緫</el-button>
+            <el-button link
+                       type="success"
+                       @click="generateQRCode(scope.row)">鐢熸垚浜岀淮鐮�</el-button>
+            <el-button link
+                       type="primary"
+                       @click="handleExport(scope.row)">瀵煎嚭</el-button>
+            <el-button link
+                       type="primary"
+                       @click="handleReassign(scope.row)"
+                       v-if="scope.row.status === '宸插垎閰�'">閲嶆柊鍒嗛厤</el-button>
+            <el-button link
+                       type="danger"
+                       @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 鍒嗛〉 -->
+      <pagination :total="pagination.total"
+                  layout="total, sizes, prev, pager, next, jumper"
+                  :page="pagination.currentPage"
+                  :limit="pagination.pageSize"
+                  @pagination="handleCurrentChange" />
+    </el-card>
+    <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
+    <el-dialog v-model="dialogVisible"
+               :title="dialogTitle"
+               width="700px">
+      <el-form :model="form"
+               :rules="rules"
+               ref="formRef"
+               label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="浜у搧鍚嶇О"
+                          prop="productName">
+              <el-input v-model="form.productName"
+                        placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="浜у搧缂栫爜"
+                          prop="productCode">
+              <el-input v-model="form.productCode"
+                        placeholder="璇疯緭鍏ヤ骇鍝佺紪鐮�"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鎵规鍙�"
+                          prop="batchNo">
+              <el-input v-model="form.batchNo"
+                        placeholder="璇疯緭鍏ユ壒娆″彿"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏍囪瘑绫诲瀷"
+                          prop="identifierType">
+              <el-select v-model="form.identifierType"
+                         placeholder="璇烽�夋嫨鏍囪瘑绫诲瀷"
+                         style="width: 100%">
+                <el-option label="浜岀淮鐮�"
+                           value="浜岀淮鐮�"></el-option>
+                <el-option label="闃蹭吉鐮�"
+                           value="闃蹭吉鐮�"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鐢熸垚鏁伴噺"
+                          prop="quantity">
+              <el-input-number v-model="form.quantity"
+                               :min="1"
+                               :max="10000"
+                               style="width: 100%"></el-input-number>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鐘舵��"
+                          prop="status">
+              <el-select v-model="form.status"
+                         placeholder="璇烽�夋嫨鐘舵��"
+                         style="width: 100%">
+                <el-option label="宸茬敓鎴�"
+                           value="宸茬敓鎴�"></el-option>
+                <el-option label="宸插垎閰�"
+                           value="宸插垎閰�"></el-option>
+                <el-option label="宸蹭娇鐢�"
+                           value="宸蹭娇鐢�"></el-option>
+                <el-option label="宸蹭綔搴�"
+                           value="宸蹭綔搴�"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="澶囨敞"
+                          prop="remark">
+              <el-input type="textarea"
+                        v-model="form.remark"
+                        placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
+                        rows="3"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary"
+                     @click="handleSubmit">纭� 瀹�</el-button>
+          <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <!-- 鏍囪瘑鐢熸垚瀵硅瘽妗� -->
+    <el-dialog v-model="generateDialogVisible"
+               title="鏍囪瘑鐢熸垚"
+               width="500px">
+      <el-form label-width="100px">
+        <el-form-item label="浜у搧鍚嶇О">
+          <span>{{ currentProduct.productName }}</span>
+        </el-form-item>
+        <el-form-item label="浜у搧缂栫爜">
+          <span>{{ currentProduct.productCode }}</span>
+        </el-form-item>
+        <el-form-item label="鎵规鍙�">
+          <span>{{ currentProduct.batchNo }}</span>
+        </el-form-item>
+        <el-form-item label="鏍囪瘑绫诲瀷">
+          <span>{{ currentProduct.identifierType }}</span>
+        </el-form-item>
+        <el-form-item label="鐢熸垚鏁伴噺"
+                      prop="generateQuantity">
+          <el-input-number v-model="generateQuantity"
+                           :min="1"
+                           :max="10000"
+                           style="width: 100%"></el-input-number>
+        </el-form-item>
+        <el-form-item label="缂栫爜瑙勫垯"
+                      prop="codeRule">
+          <el-select v-model="codeRule"
+                     placeholder="璇烽�夋嫨缂栫爜瑙勫垯"
+                     style="width: 100%">
+            <el-option label="浜у搧缂栫爜+鎵规鍙�+搴忓彿"
+                       value="浜у搧缂栫爜+鎵规鍙�+搴忓彿"></el-option>
+            <el-option label="鏃堕棿鎴�+闅忔満鏁�"
+                       value="鏃堕棿鎴�+闅忔満鏁�"></el-option>
+            <el-option label="鑷畾涔夎鍒�"
+                       value="鑷畾涔夎鍒�"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鑷畾涔夊墠缂�"
+                      prop="customPrefix"
+                      v-if="codeRule === '鑷畾涔夎鍒�'">
+          <el-input v-model="customPrefix"
+                    placeholder="璇疯緭鍏ヨ嚜瀹氫箟鍓嶇紑"></el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary"
+                     @click="generateIdentifiers">鐢� 鎴�</el-button>
+          <el-button @click="generateDialogVisible = false">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <!-- 閲嶆柊鍒嗛厤瀵硅瘽妗� -->
+    <el-dialog v-model="reassignDialogVisible"
+               title="閲嶆柊鍒嗛厤鏍囪瘑"
+               width="500px">
+      <el-form label-width="100px">
+        <el-form-item label="浜у搧鍚嶇О">
+          <span>{{ currentProduct.productName }}</span>
+        </el-form-item>
+        <el-form-item label="鏍囪瘑鐮�">
+          <span>{{ currentProduct.identifierCode }}</span>
+        </el-form-item>
+        <el-form-item label="鏂版壒娆″彿"
+                      prop="newBatchNo">
+          <el-input v-model="newBatchNo"
+                    placeholder="璇疯緭鍏ユ柊鎵规鍙�"></el-input>
+        </el-form-item>
+        <el-form-item label="鍒嗛厤鍘熷洜"
+                      prop="reassignReason">
+          <el-input type="textarea"
+                    v-model="reassignReason"
+                    rows="3"
+                    placeholder="璇疯緭鍏ラ噸鏂板垎閰嶅師鍥�"></el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary"
+                     @click="saveReassign">纭� 瀹�</el-button>
+          <el-button @click="reassignDialogVisible = false">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <!-- 浜岀淮鐮侀瑙堝璇濇 -->
+    <el-dialog v-model="qrCodeDialogVisible"
+               title="浜岀淮鐮侀瑙�"
+               width="500px"
+               center>
+      <div class="qr-preview-container">
+        <div v-if="qrCodeUrl"
+             class="qr-image-container">
+          <img :src="qrCodeUrl"
+               alt="浜岀淮鐮�"
+               class="qr-image" />
+          <div class="qr-info">
+            <p><strong>浜у搧鍚嶇О锛�</strong>{{ currentQRProduct.productName }}</p>
+            <p><strong>浜у搧缂栫爜锛�</strong>{{ currentQRProduct.productCode }}</p>
+            <p><strong>鎵规鍙凤細</strong>{{ currentQRProduct.batchNo }}</p>
+            <p><strong>鏍囪瘑鐮侊細</strong>{{ currentQRProduct.identifierCode }}</p>
+            <p><strong>鏍囪瘑绫诲瀷锛�</strong>{{ currentQRProduct.identifierType }}</p>
+          </div>
+        </div>
+        <div v-else
+             class="qr-loading">
+          <el-icon class="is-loading">
+            <Loading />
+          </el-icon>
+          <p>姝e湪鐢熸垚浜岀淮鐮�...</p>
+        </div>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="qrCodeDialogVisible = false">鍏抽棴</el-button>
+          <el-button v-if="qrCodeUrl"
+                     type="primary"
+                     @click="copyQRContent"
+                     icon="CopyDocument">
+            澶嶅埗鍐呭
+          </el-button>
+          <el-button v-if="qrCodeUrl"
+                     type="success"
+                     @click="downloadQRCode"
+                     icon="Download">
+            涓嬭浇浜岀淮鐮�
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+  import { ref, reactive, computed } from "vue";
+  import { ElMessage, ElMessageBox } from "element-plus";
+  import { Plus, Search, Loading, Download } from "@element-plus/icons-vue";
+  import Pagination from "@/components/PIMTable/Pagination.vue";
+  import QRCode from "qrcode";
+
+  // 鍝嶅簲寮忔暟鎹�
+  const loading = ref(false);
+  const searchForm = reactive({
+    productName: "",
+    identifierType: "",
+    status: "",
+  });
+
+  const identifierList = ref([
+    {
+      id: 1,
+      productName: "宸ヤ笟浼犳劅鍣ˋ鍨�",
+      productCode: "SENSOR001",
+      batchNo: "B202312001",
+      identifierType: "浜岀淮鐮�",
+      identifierCode: "QR_SENSOR001_B202312001_001",
+      status: "宸插垎閰�",
+      generateTime: "2023-12-01 10:00:00",
+      remark: "閲嶈浜у搧鏍囪瘑",
+    },
+    {
+      id: 2,
+      productName: "鎺у埗闈㈡澘B鍨�",
+      productCode: "PANEL002",
+      batchNo: "B202312002",
+      identifierType: "闃蹭吉鐮�",
+      identifierCode: "SEC_PANEL002_B202312002_001",
+      status: "宸茬敓鎴�",
+      generateTime: "2023-12-02 14:30:00",
+      remark: "甯歌浜у搧鏍囪瘑",
+    },
+    {
+      id: 3,
+      productName: "鏁版嵁閲囬泦鍣–鍨�",
+      productCode: "COLLECTOR003",
+      batchNo: "B202312003",
+      identifierType: "闃蹭吉鐮�",
+      identifierCode: "SEC_COLLECTOR003_B202312003_001",
+      status: "宸蹭娇鐢�",
+      generateTime: "2023-12-03 09:15:00",
+      remark: "娴嬭瘯浜у搧鏍囪瘑",
+    },
+  ]);
+
+  const pagination = reactive({
+    total: 3,
+    currentPage: 1,
+    pageSize: 10,
+  });
+
+  const dialogVisible = ref(false);
+  const dialogTitle = ref("鏂板鏍囪瘑");
+  const form = reactive({
+    productName: "",
+    productCode: "",
+    batchNo: "",
+    identifierType: "",
+    quantity: 1,
+    status: "宸茬敓鎴�",
+    remark: "",
+  });
+
+  const rules = {
+    productName: [{ required: true, message: "璇疯緭鍏ヤ骇鍝佸悕绉�", trigger: "blur" }],
+    productCode: [{ required: true, message: "璇疯緭鍏ヤ骇鍝佺紪鐮�", trigger: "blur" }],
+    batchNo: [{ required: true, message: "璇疯緭鍏ユ壒娆″彿", trigger: "blur" }],
+    identifierType: [
+      { required: true, message: "璇烽�夋嫨鏍囪瘑绫诲瀷", trigger: "change" },
+    ],
+    quantity: [{ required: true, message: "璇疯緭鍏ョ敓鎴愭暟閲�", trigger: "blur" }],
+    status: [{ required: true, message: "璇烽�夋嫨鐘舵��", trigger: "change" }],
+  };
+
+  const isEdit = ref(false);
+  const editId = ref(null);
+  const generateDialogVisible = ref(false);
+  const reassignDialogVisible = ref(false);
+  const currentProduct = ref({});
+  const generateQuantity = ref(1);
+  const codeRule = ref("");
+  const customPrefix = ref("");
+  const newBatchNo = ref("");
+  const reassignReason = ref("");
+  const formRef = ref();
+
+  // 浜岀淮鐮佺浉鍏冲彉閲�
+  const qrCodeDialogVisible = ref(false);
+  const qrCodeUrl = ref("");
+  const currentQRProduct = ref({});
+
+  // 璁$畻灞炴��
+  const filteredList = computed(() => {
+    let list = identifierList.value;
+    if (searchForm.productName) {
+      list = list.filter(item =>
+        item.productName.includes(searchForm.productName)
+      );
+    }
+    if (searchForm.identifierType) {
+      list = list.filter(
+        item => item.identifierType === searchForm.identifierType
+      );
+    }
+    if (searchForm.status) {
+      list = list.filter(item => item.status === searchForm.status);
+    }
+    return list;
+  });
+
+  // 鏂规硶
+  const getIdentifierTypeType = type => {
+    const typeMap = {
+      浜岀淮鐮�: "success",
+      闃蹭吉鐮�: "warning",
+    };
+    return typeMap[type] || "info";
+  };
+
+  const getStatusType = status => {
+    const statusMap = {
+      宸茬敓鎴�: "info",
+      宸插垎閰�: "primary",
+      宸蹭娇鐢�: "success",
+      宸蹭綔搴�: "danger",
+    };
+    return statusMap[status] || "info";
+  };
+
+  const handleSearch = () => {
+    // 鎼滅储閫昏緫宸插湪computed涓鐞�
+  };
+
+  const resetSearch = () => {
+    searchForm.productName = "";
+    searchForm.identifierType = "";
+    searchForm.status = "";
+  };
+
+  const handleAdd = () => {
+    dialogTitle.value = "鏂板鏍囪瘑";
+    isEdit.value = false;
+    form.productName = "";
+    form.productCode = "";
+    form.batchNo = "";
+    form.identifierType = "";
+    form.quantity = 1;
+    form.status = "宸茬敓鎴�";
+    form.remark = "";
+    dialogVisible.value = true;
+  };
+
+  const handleView = row => {
+    // 鏌ョ湅鏍囪瘑璇︽儏
+    ElMessage.info("鏌ョ湅鏍囪瘑璇︽儏鍔熻兘寰呭疄鐜�");
+  };
+
+  const handleEdit = row => {
+    dialogTitle.value = "缂栬緫鏍囪瘑";
+    isEdit.value = true;
+    editId.value = row.id;
+    Object.assign(form, row);
+    dialogVisible.value = true;
+  };
+
+  const handleExport = row => {
+    // 瀵煎嚭鏍囪瘑
+    ElMessage.success(`宸插鍑烘爣璇�: ${row.identifierCode}`);
+  };
+
+  const handleReassign = row => {
+    currentProduct.value = row;
+    newBatchNo.value = "";
+    reassignReason.value = "";
+    reassignDialogVisible.value = true;
+  };
+
+  const handleDelete = row => {
+    ElMessageBox.confirm("纭鍒犻櫎璇ユ爣璇嗗悧锛�", "鎻愮ず", {
+      confirmButtonText: "纭畾",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    }).then(() => {
+      const index = identifierList.value.findIndex(item => item.id === row.id);
+      if (index > -1) {
+        identifierList.value.splice(index, 1);
+        pagination.total--;
+        ElMessage.success("鍒犻櫎鎴愬姛");
+      }
+    });
+  };
+
+  // 鐢熸垚浜岀淮鐮�
+  const generateQRCode = async row => {
+    try {
+      // 妫�鏌ュ繀瑕佸瓧娈�
+      if (!row.productName || !row.productCode || !row.batchNo) {
+        ElMessage.warning("浜у搧淇℃伅涓嶅畬鏁达紝鏃犳硶鐢熸垚浜岀淮鐮�");
+        return;
+      }
+
+      currentQRProduct.value = row;
+      qrCodeUrl.value = "";
+      qrCodeDialogVisible.value = true;
+
+      // 鏋勫缓浜岀淮鐮佸唴瀹�
+      let qrContent = "";
+      if (row.identifierType === "浜岀淮鐮�") {
+        qrContent = `${row.productName}|${row.productCode}|${row.batchNo}|${row.identifierCode}`;
+      } else if (row.identifierType === "闃蹭吉鐮�") {
+        // 闃蹭吉鐮佹牸寮忥細SEC_浜у搧缂栫爜_鎵规鍙穇鏃堕棿鎴砡闅忔満鏁�
+        const timestamp = Date.now();
+        const random = Math.random().toString(36).substr(2, 8);
+        qrContent = `SEC_${row.productCode}_${row.batchNo}_${timestamp}_${random}`;
+      }
+
+      // 鐢熸垚浜岀淮鐮�
+      qrCodeUrl.value = await QRCode.toDataURL(qrContent, {
+        width: 256,
+        margin: 2,
+        color: {
+          dark: "#000000",
+          light: "#FFFFFF",
+        },
+        errorCorrectionLevel: row.identifierType === "闃蹭吉鐮�" ? "H" : "M",
+      });
+
+      ElMessage.success("浜岀淮鐮佺敓鎴愭垚鍔燂紒");
+    } catch (error) {
+      console.error("鐢熸垚浜岀淮鐮佸け璐�:", error);
+      ElMessage.error("鐢熸垚浜岀淮鐮佸け璐ワ細" + error.message);
+      qrCodeDialogVisible.value = false;
+    }
+  };
+
+  // 涓嬭浇浜岀淮鐮�
+  const downloadQRCode = () => {
+    if (!qrCodeUrl.value) {
+      ElMessage.warning("璇峰厛鐢熸垚浜岀淮鐮�");
+      return;
+    }
+
+    const a = document.createElement("a");
+    a.href = qrCodeUrl.value;
+    a.download = `${currentQRProduct.value.productName}_${
+      currentQRProduct.value.identifierType
+    }_${new Date().getTime()}.png`;
+    document.body.appendChild(a);
+    a.click();
+    document.body.removeChild(a);
+    ElMessage.success("涓嬭浇鎴愬姛锛�");
+  };
+
+  // 澶嶅埗浜岀淮鐮佸唴瀹�
+  const copyQRContent = async () => {
+    if (!currentQRProduct.value) {
+      ElMessage.warning("娌℃湁鍙鍒剁殑鍐呭");
+      return;
+    }
+
+    try {
+      let content = "";
+      if (currentQRProduct.value.identifierType === "浜岀淮鐮�") {
+        content = `${currentQRProduct.value.productName}|${currentQRProduct.value.productCode}|${currentQRProduct.value.batchNo}|${currentQRProduct.value.identifierCode}`;
+      } else if (currentQRProduct.value.identifierType === "闃蹭吉鐮�") {
+        const timestamp = Date.now();
+        const random = Math.random().toString(36).substr(2, 8);
+        content = `SEC_${currentQRProduct.value.productCode}_${currentQRProduct.value.batchNo}_${timestamp}_${random}`;
+      }
+
+      await navigator.clipboard.writeText(content);
+      ElMessage.success("鍐呭宸插鍒跺埌鍓创鏉�");
+    } catch (error) {
+      // 闄嶇骇鏂规
+      const textArea = document.createElement("textarea");
+      textArea.value = content;
+      document.body.appendChild(textArea);
+      textArea.select();
+      document.execCommand("copy");
+      document.body.removeChild(textArea);
+      ElMessage.success("鍐呭宸插鍒跺埌鍓创鏉�");
+    }
+  };
+
+  const generateIdentifiers = () => {
+    if (!codeRule.value) {
+      ElMessage.warning("璇烽�夋嫨缂栫爜瑙勫垯");
+      return;
+    }
+
+    // 鐢熸垚鏍囪瘑鐨勯�昏緫
+    const newIdentifiers = [];
+    for (let i = 1; i <= generateQuantity.value; i++) {
+      let identifierCode = "";
+      if (codeRule.value === "浜у搧缂栫爜+鎵规鍙�+搴忓彿") {
+        identifierCode = `${currentProduct.value.productCode}_${
+          currentProduct.value.batchNo
+        }_${String(i).padStart(3, "0")}`;
+      } else if (codeRule.value === "鏃堕棿鎴�+闅忔満鏁�") {
+        identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
+      } else if (codeRule.value === "鑷畾涔夎鍒�") {
+        identifierCode = `${customPrefix.value || "CUSTOM"}_${Date.now()}_${i}`;
+      }
+
+      newIdentifiers.push({
+        id: Math.max(...identifierList.value.map(item => item.id)) + i,
+        productName: currentProduct.value.productName,
+        productCode: currentProduct.value.productCode,
+        batchNo: currentProduct.value.batchNo,
+        identifierType: currentProduct.value.identifierType,
+        identifierCode: identifierCode,
+        status: "宸茬敓鎴�",
+        generateTime: new Date().toLocaleString(),
+        remark: "鎵归噺鐢熸垚",
+      });
+    }
+
+    identifierList.value.push(...newIdentifiers);
+    pagination.total += newIdentifiers.length;
+    ElMessage.success(`鎴愬姛鐢熸垚 ${newIdentifiers.length} 涓爣璇哷);
+    generateDialogVisible.value = false;
+  };
+
+  const saveReassign = () => {
+    if (!newBatchNo.value) {
+      ElMessage.warning("璇疯緭鍏ユ柊鎵规鍙�");
+      return;
+    }
+
+    const index = identifierList.value.findIndex(
+      item => item.id === currentProduct.value.id
+    );
+    if (index > -1) {
+      identifierList.value[index].batchNo = newBatchNo.value;
+      identifierList.value[index].status = "宸插垎閰�";
+      ElMessage.success("鏍囪瘑閲嶆柊鍒嗛厤鎴愬姛");
+      reassignDialogVisible.value = false;
+    }
+  };
+
+  const handleSubmit = () => {
+    formRef.value.validate(valid => {
+      if (valid) {
+        if (isEdit.value) {
+          // 缂栬緫
+          const index = identifierList.value.findIndex(
+            item => item.id === editId.value
+          );
+          if (index > -1) {
+            identifierList.value[index] = { ...form, id: editId.value };
+            ElMessage.success("缂栬緫鎴愬姛");
+          }
+        } else {
+          // 鏂板
+          const newId =
+            Math.max(...identifierList.value.map(item => item.id)) + 1;
+
+          // 鏍规嵁鏍囪瘑绫诲瀷鐢熸垚涓嶅悓鐨勬爣璇嗙爜
+          let identifierCode = "";
+          if (form.identifierType === "浜岀淮鐮�") {
+            identifierCode = `QR_${form.productCode}_${form.batchNo}_001`;
+          } else if (form.identifierType === "闃蹭吉鐮�") {
+            identifierCode = `SEC_${form.productCode}_${form.batchNo}_001`;
+          }
+
+          identifierList.value.push({
+            ...form,
+            id: newId,
+            identifierCode: identifierCode,
+            generateTime: new Date().toLocaleString(),
+          });
+          pagination.total++;
+          ElMessage.success("鏂板鎴愬姛");
+        }
+        dialogVisible.value = false;
+      }
+    });
+  };
+
+  const handleCurrentChange = val => {
+    pagination.currentPage = val.page;
+    pagination.pageSize = val.limit;
+  };
+</script>
+
+<style scoped>
+  .search-row {
+    margin-bottom: 20px;
+  }
+
+  .quick-actions-row {
+    margin-bottom: 20px;
+  }
+
+  .quick-actions-row .el-alert {
+    margin-bottom: 0;
+  }
+
+  .quick-actions-row .el-alert p {
+    margin: 5px 0;
+    font-size: 14px;
+    line-height: 1.5;
+  }
+
+  /* 浜岀淮鐮侀瑙堟牱寮� */
+  .qr-preview-container {
+    text-align: center;
+    padding: 20px;
+  }
+
+  .qr-image-container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 20px;
+  }
+
+  .qr-image {
+    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 {
+    text-align: left;
+    background: #f8f9fa;
+    padding: 15px;
+    border-radius: 8px;
+    min-width: 300px;
+  }
+
+  .qr-info p {
+    margin: 8px 0;
+    color: #666;
+    font-size: 14px;
+  }
+
+  .qr-loading {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 15px;
+    padding: 40px 0;
+  }
+
+  .qr-loading .el-icon {
+    font-size: 32px;
+    color: #409eff;
+  }
+
+  .qr-loading p {
+    color: #666;
+    margin: 0;
+  }
+</style>

--
Gitblit v1.9.3