From 1021003321fe54f3f45d77457db86105d206551a Mon Sep 17 00:00:00 2001
From: yaowanxin <3588231647@qq.com>
Date: 星期五, 26 九月 2025 14:04:34 +0800
Subject: [PATCH] 档案管理-书籍二维码生成,借阅-归还扫瞄

---
 src/views/fileManagement/document/index.vue |  164 ++++++++++++++++++++++++++
 src/views/fileManagement/return/index.vue   |  110 ++++++++++++++++--
 src/views/fileManagement/borrow/index.vue   |   61 ++++++++-
 src/api/fileManagement/return.js            |    7 +
 4 files changed, 317 insertions(+), 25 deletions(-)

diff --git a/src/api/fileManagement/return.js b/src/api/fileManagement/return.js
index 2e0c0e7..9021ac9 100644
--- a/src/api/fileManagement/return.js
+++ b/src/api/fileManagement/return.js
@@ -26,6 +26,13 @@
     data: ids,
   });
 }
+//鏍规嵁涔︾睄id鏌ヨ鍊熼槄璁板綍
+export function getBorrowListByDocumentationId(id) {
+  return request({
+    url: "/documentationBorrowManagement/getByDocumentationId/"+id,
+    method: "get"
+  });
+}
 
 // 鏇存柊鍊熼槄璁板綍
 export function updateBorrow(data) {
diff --git a/src/views/fileManagement/borrow/index.vue b/src/views/fileManagement/borrow/index.vue
index 6875571..531feb6 100644
--- a/src/views/fileManagement/borrow/index.vue
+++ b/src/views/fileManagement/borrow/index.vue
@@ -90,10 +90,6 @@
         ref="borrowFormRef"
       >
         <el-row :gutter="20">
-          
-        </el-row>
-        
-                 <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="鍊熼槄浜猴細" prop="borrower">
                <el-input v-model="borrowForm.borrower" placeholder="璇疯緭鍏ュ�熼槄浜�" />
@@ -101,14 +97,31 @@
            </el-col>
            <el-col :span="12">
              <el-form-item label="鍊熼槄涔︾睄锛�" prop="documentationId">
-               <el-select v-model="borrowForm.documentationId" placeholder="璇烽�夋嫨鍊熼槄涔︾睄" style="width: 100%">
+               <!-- <el-select v-model="borrowForm.documentationId" placeholder="璇烽�夋嫨鍊熼槄涔︾睄" style="width: 100%" @change="handleScanContent">
                  <el-option 
                    v-for="item in documentList" 
                    :key="item.id" 
                    :label="item.docName || item.name" 
                    :value="item.id"
                  />
-               </el-select>
+               </el-select> -->
+               <div style="display: flex; gap: 10px;">
+                <el-select v-model="borrowForm.documentationId" placeholder="璇烽�夋嫨鍊熼槄涔︾睄" style="flex: 1;width: 100px;" @change="handleSelectChange">
+                  <el-option 
+                    v-for="item in documentList" 
+                    :key="item.id" 
+                    :label="item.docName || item.name" 
+                    :value="item.id"
+                  />
+                </el-select>
+                <el-input
+                  v-model="scanContent"
+                  placeholder="鎵爜杈撳叆"
+                  style="width: 100px;"
+                  @input="handleScanContent"
+                  clearable
+                />
+              </div>
              </el-form-item>
            </el-col>
          </el-row>
@@ -188,7 +201,7 @@
 const borrowList = ref([]);
 const selectedRows = ref([]);
 const documentList = ref([]); // 鏂囨。鍒楄〃锛岀敤浜庡�熼槄涔︾睄閫夋嫨
-
+const scanContent = ref('') // 鎵爜鍐呭
 // 鍒嗛〉鐩稿叧
 const pagination = reactive({
   currentPage: 1,
@@ -368,6 +381,36 @@
   ElMessage.success("鏌ヨ鏉′欢宸查噸缃�");
 };
 
+// 澶勭悊涓嬫媺閫夋嫨鍙樺寲
+const handleSelectChange = (value) => {
+  // 褰撲笅鎷夋閫夋嫨鏃讹紝娓呯┖鎵爜杈撳叆妗�
+  scanContent.value = '';
+};
+
+// 澶勭悊鎵爜鍐呭
+const handleScanContent = async (value) => {
+if (!value) return;
+  
+  try {
+    // 鏌ユ壘鎵弿鍐呭瀵瑰簲鐨勬枃妗�
+    // 鍋囪浜岀淮鐮佸寘鍚殑鏄枃妗D鎴栨枃妗e悕绉�
+    const matchedDoc = documentList.value.find(item => 
+      item.documentationId === value 
+    );
+    
+    if (matchedDoc) {
+      // 鎵惧埌鍖归厤鐨勬枃妗o紝璁剧疆琛ㄥ崟鍊�
+      borrowForm.documentationId = matchedDoc.documentationId;
+      ElMessage.success(`宸查�夋嫨: ${matchedDoc.docName || matchedDoc.name}`);
+    } else {
+      // 鏈壘鍒板尮閰嶇殑鏂囨。锛屾彁绀虹敤鎴�
+      ElMessage.warning('鏈壘鍒板搴旂殑涔︾睄锛岃妫�鏌ユ壂鐮佸唴瀹规垨鎵嬪姩閫夋嫨');
+    }
+  } catch (error) {
+    ElMessage.error('鎵爜澶勭悊澶辫触锛岃閲嶈瘯');
+    console.error('鎵爜澶勭悊閿欒:', error);
+  }
+}
 // 鎵撳紑鍊熼槄寮规
 const openBorrowDia = async (type, data) => {
   // 鍏堝埛鏂版枃妗e垪琛�
@@ -375,7 +418,8 @@
   
   borrowOperationType.value = type;
   borrowDia.value = true;
-  
+  scanContent.value = ''; // 娓呯┖鎵爜鍐呭
+
   if (type === "edit") {
     // 缂栬緫妯″紡锛屽姞杞界幇鏈夋暟鎹�
     Object.assign(borrowForm, data);
@@ -395,6 +439,7 @@
 const closeBorrowDia = () => {
   proxy.$refs.borrowFormRef.resetFields();
   borrowDia.value = false;
+  scanContent.value = ''; // 娓呯┖鎵爜鍐呭
 };
 
 // 鎻愪氦鍊熼槄琛ㄥ崟
diff --git a/src/views/fileManagement/document/index.vue b/src/views/fileManagement/document/index.vue
index 7cf352c..a0d824a 100644
--- a/src/views/fileManagement/document/index.vue
+++ b/src/views/fileManagement/document/index.vue
@@ -153,7 +153,39 @@
         </div>
       </template>
     </el-dialog>
-
+<el-dialog
+    v-model="qrCodeDialogVisible"
+    title="鏂囨。浜岀淮鐮�"
+    width="400px"
+    @close="closeQrCodeDialog"
+  >
+    <div class="qr-code-container">
+      <div v-if="qrCodeUrl" class="qr-code-image">
+        <img :src="qrCodeUrl" alt="鏂囨。浜岀淮鐮�" class="qr-image" />
+        <div class="qr-info">
+          <p><strong>鏂囨。鍚嶇О锛�</strong>{{ currentDocument.docName }}</p>
+          <p><strong>鏂囨。缂栧彿锛�</strong>{{ currentDocument.docNumber }}</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="closeQrCodeDialog">鍏抽棴</el-button>
+        <el-button 
+          v-if="qrCodeUrl"
+          type="primary" 
+          @click="downloadQRCode"
+          icon="Download"
+        >
+          涓嬭浇浜岀淮鐮�
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
     <!-- 鏂囨。鏂板/淇敼瀵硅瘽妗� -->
     <el-dialog
       v-model="documentDia"
@@ -352,8 +384,8 @@
           <el-button @click="closeDocumentDia">鍙栨秷</el-button>
         </div>
              </template>
-     </el-dialog>
-             <AttachmentManager ref="attachmentManagerRef" />
+    </el-dialog>
+     <AttachmentManager ref="attachmentManagerRef" />
      </div>
    </template>
 
@@ -371,7 +403,9 @@
 const { proxy } = getCurrentInstance();
 const tree = ref(null);
 const containerRef = ref(null);
-
+// 瀵煎叆qrcode搴�
+import QRCode from 'qrcode'
+import { Loading, Download } from '@element-plus/icons-vue'
 // 浣跨敤瀛楀吀鏁版嵁
 const { confidentiality_level, document_urgency, document_status, document_type, document_categories, retention_period } = useDict('confidentiality_level', 'document_urgency', 'document_status', 'document_type', 'document_categories', 'retention_period')
 
@@ -407,6 +441,10 @@
 // 浣嶇疆鏍戞暟鎹�
 const locationTree = ref([]);
 
+// 浜岀淮鐮佺浉鍏冲彉閲�
+const qrCodeDialogVisible = ref(false)
+const qrCodeUrl = ref('')
+const currentDocument = ref({})
 // 琛ㄦ牸鍒楅厤缃�
 const tableColumns = ref([
   { label: '鏂囨。鍚嶇О', prop: 'docName', width: '200' },
@@ -568,7 +606,7 @@
     label: "鎿嶄綔",
     align: "center",
     fixed: 'right',
-    width: '150',
+    width: '200',
     operation: [
       {
         name: "缂栬緫",
@@ -584,10 +622,74 @@
           openAttachment(row)
         },
       },
+      {
+        name: "鐢熸垚浜岀淮鐮�",
+        type: "text",
+        clickFun: (row) => {
+          generateQRCode(row)
+        },
+      },
     ],
   }
 ]);
+// 鐢熸垚浜岀淮鐮�
+const generateQRCode = async (row) => {
+  try {
+    // 妫�鏌ュ繀瑕佸瓧娈�
+    if (!row.docName || !row.docNumber) {
+      ElMessage.warning('鏂囨。淇℃伅涓嶅畬鏁达紝鏃犳硶鐢熸垚浜岀淮鐮�')
+      return
+    }
+    
+    currentDocument.value = row
+    qrCodeUrl.value = ''
+    qrCodeDialogVisible.value = true
+    
+    // 鏋勫缓浜岀淮鐮佸唴瀹�
+    // const qrContent = `${row.id}|${row.docName}|${row.docNumber}`
+    const qrContent = `${row.id}`
+    // 鐢熸垚浜岀淮鐮�
+    qrCodeUrl.value = await QRCode.toDataURL(qrContent, {
+      width: 256,
+      margin: 2,
+      color: {
+        dark: '#000000',
+        light: '#FFFFFF'
+      },
+      errorCorrectionLevel: '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 = `${currentDocument.value.docName}_浜岀淮鐮乢${new Date().getTime()}.png`
+  document.body.appendChild(a)
+  a.click()
+  document.body.removeChild(a)
+  ElMessage.success('涓嬭浇鎴愬姛锛�')
+}
+
+// 鍏抽棴浜岀淮鐮佸脊绐�
+const closeQrCodeDialog = () => {
+  qrCodeDialogVisible.value = false
+  qrCodeUrl.value = ''
+  currentDocument.value = {}
+}
 // 鍒嗙被琛ㄥ崟
 const categoryForm = reactive({
   category: "",
@@ -1259,4 +1361,56 @@
   color: #606266;
   font-size: 14px;
 }
+/* 浜岀淮鐮侀瑙堟牱寮� */
+.qr-code-container {
+  text-align: center;
+  padding: 20px;
+}
+
+.qr-code-image {
+  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>
diff --git a/src/views/fileManagement/return/index.vue b/src/views/fileManagement/return/index.vue
index a95c8af..3c14dc5 100644
--- a/src/views/fileManagement/return/index.vue
+++ b/src/views/fileManagement/return/index.vue
@@ -100,14 +100,31 @@
                  <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="鏂囨。锛�" prop="borrowId">
-               <el-select v-model="returnForm.borrowId" placeholder="璇烽�夋嫨鏂囨。" style="width: 100%" @change="handleDocumentChange">
+               <!-- <el-select v-model="returnForm.borrowId" placeholder="璇烽�夋嫨鏂囨。" style="flex: 1;" @change="handleDocumentChange">
                  <el-option 
                    v-for="item in documentList" 
                    :key="item.id" 
                    :label="item.docName || item.name" 
                    :value="item.id"
                  />
-               </el-select>
+               </el-select> -->
+               <div style="display: flex; gap: 10px;">
+                <el-select v-model="returnForm.borrowId" placeholder="璇烽�夋嫨鏂囨。" style="width: 120px;" @change="handleDocumentChange">
+                  <el-option 
+                    v-for="item in documentList" 
+                    :key="item.id" 
+                    :label="item.docName || item.name" 
+                    :value="item.id"
+                  />
+                </el-select>
+                <el-input
+                  v-model="scanContent"
+                  placeholder="鎵爜杈撳叆"
+                  style="flex: 1;"
+                  @input="handleScanContent"
+                  clearable
+                />
+              </div>
              </el-form-item>
            </el-col>
            <el-col :span="12">
@@ -182,7 +199,7 @@
 import { ElMessageBox, ElMessage } from "element-plus";
 import { Search, Refresh, Plus, Delete } from '@element-plus/icons-vue';
 import PIMTable from '@/components/PIMTable/PIMTable.vue';
-import { getReturnListPage, returnDocument, deleteReturn, getDocumentList, updateBorrow, reventUpdate } from '@/api/fileManagement/return';
+import { getReturnListPage, returnDocument, deleteReturn, getDocumentList, updateBorrow, reventUpdate,getBorrowListByDocumentationId } from '@/api/fileManagement/return';
 
 const { proxy } = getCurrentInstance();
 
@@ -193,6 +210,8 @@
 const returnList = ref([]);
 const selectedRows = ref([]);
 const documentList = ref([]); // 鏂囨。鍒楄〃
+const borrowInfoList = ref([]); // 鍊熼槄淇℃伅鍒楄〃
+const scanContent = ref(''); // 鎵爜鍐呭
 
 // 鍒嗛〉鐩稿叧
 const pagination = reactive({
@@ -368,7 +387,9 @@
 const openReturnDia = (type, data) => {
   returnOperationType.value = type;
   returnDia.value = true;
-  
+  scanContent.value = ''; // 娓呯┖鎵爜鍐呭
+  borrowInfoList.value = []; // 娓呯┖鍊熼槄淇℃伅鍒楄〃
+
   if (type === "edit") {
     // 缂栬緫妯″紡锛屽姞杞界幇鏈夋暟鎹�
     Object.assign(returnForm, data);
@@ -392,6 +413,8 @@
 const closeReturnDia = () => {
   proxy.$refs.returnFormRef.resetFields();
   returnDia.value = false;
+  scanContent.value = ''; // 娓呯┖鎵爜鍐呭
+  borrowInfoList.value = []; // 娓呯┖鍊熼槄淇℃伅鍒楄〃
 };
 
 // 鎻愪氦褰掕繕琛ㄥ崟
@@ -517,16 +540,62 @@
   pagination.pageSize = size;
   loadReturnList();
 };
-
+// 澶勭悊鎵爜鍐呭
+const handleScanContent = async (value) => {
+  if (!value) return;
+  
+  try {
+    // 璋冪敤API鏍规嵁涔︾睄ID鑾峰彇鍊熼槄淇℃伅
+    const res = await getBorrowListByDocumentationId(value);
+    
+    if (res.code === 200 && res.data && res.data.length > 0) {
+      // 淇濆瓨鑾峰彇鍒扮殑鍊熼槄淇℃伅鍒楄〃
+      borrowInfoList.value = res.data;
+      
+      // 濡傛灉鍙湁涓�鏉¤褰曪紝鐩存帴閫夋嫨
+      if (res.data.length === 1) {
+        const borrowInfo = res.data[0];
+        returnForm.borrowId = borrowInfo.id;
+        returnForm.borrower = borrowInfo.borrower || borrowInfo.borrowerName || '';
+        returnForm.dueReturnDate = borrowInfo.dueReturnDate || borrowInfo.expectedReturnDate || '';
+        ElMessage.success(`宸查�夋嫨: ${borrowInfo.docName || borrowInfo.name}`);
+      } else {
+        // 濡傛灉鏈夊鏉¤褰曪紝鏄剧ず閫夋嫨鎻愮ず
+        ElMessage.success(`鎵惧埌 ${res.data.length} 鏉$浉鍏冲�熼槄璁板綍锛岃浠庝笅鎷夊垪琛ㄤ腑閫夋嫨`);
+        // 閲嶆柊鍔犺浇鏂囨。鍒楄〃锛屽寘鍚渶鏂扮殑鍊熼槄淇℃伅
+        await loadDocumentList();
+      }
+    } else {
+      // 鏈壘鍒板尮閰嶇殑鍊熼槄璁板綍
+      ElMessage.warning('鏈壘鍒板搴旂殑鍊熼槄璁板綍锛岃妫�鏌ユ壂鐮佸唴瀹规垨鎵嬪姩閫夋嫨');
+    }
+  } catch (error) {
+    ElMessage.error('鎵爜澶勭悊澶辫触锛岃閲嶈瘯');
+    console.error('鎵爜澶勭悊閿欒:', error);
+  }
+};
 // 澶勭悊鏂囨。閫夋嫨鍙樺寲
-const handleDocumentChange = (documentId) => {
-  if (documentId) {
-    // 鏍规嵁閫夋嫨鐨勬枃妗D锛屼粠鏂囨。鍒楄〃涓煡鎵惧搴旂殑鏂囨。淇℃伅
-    const selectedDoc = documentList.value.find(doc => doc.id === documentId);
-    if (selectedDoc) {
+// 澶勭悊鏂囨。閫夋嫨鍙樺寲
+const handleDocumentChange = (borrowId) => {
+  // 褰撲笅鎷夋閫夋嫨鏃讹紝娓呯┖鎵爜杈撳叆妗�
+  scanContent.value = '';
+  
+  if (borrowId) {
+    // 浼樺厛浠庡�熼槄淇℃伅鍒楄〃涓煡鎵�
+    let selectedInfo;
+    if (borrowInfoList.value.length > 0) {
+      selectedInfo = borrowInfoList.value.find(info => info.id === borrowId);
+    }
+    
+    // 濡傛灉鍊熼槄淇℃伅鍒楄〃涓病鏈夋壘鍒帮紝浠庢枃妗e垪琛ㄤ腑鏌ユ壘
+    if (!selectedInfo) {
+      selectedInfo = documentList.value.find(doc => doc.id === borrowId);
+    }
+    
+    if (selectedInfo) {
       // 鑷姩濉厖鍊熼槄浜哄拰搴斿綊杩樻棩鏈�
-      returnForm.borrower = selectedDoc.borrower || selectedDoc.borrowerName || '';
-      returnForm.dueReturnDate = selectedDoc.dueReturnDate || selectedDoc.expectedReturnDate || '';
+      returnForm.borrower = selectedInfo.borrower || selectedInfo.borrowerName || '';
+      returnForm.dueReturnDate = selectedInfo.dueReturnDate || selectedInfo.expectedReturnDate || '';
     }
   } else {
     // 娓呯┖鐩稿叧瀛楁
@@ -534,6 +603,23 @@
     returnForm.dueReturnDate = '';
   }
 };
+// const handleDocumentChange = (documentId) => {
+//   // 褰撲笅鎷夋閫夋嫨鏃讹紝娓呯┖鎵爜杈撳叆妗�
+//   scanContent.value = '';
+//   if (documentId) {
+//     // 鏍规嵁閫夋嫨鐨勬枃妗D锛屼粠鏂囨。鍒楄〃涓煡鎵惧搴旂殑鏂囨。淇℃伅
+//     const selectedDoc = documentList.value.find(doc => doc.id === documentId);
+//     if (selectedDoc) {
+//       // 鑷姩濉厖鍊熼槄浜哄拰搴斿綊杩樻棩鏈�
+//       returnForm.borrower = selectedDoc.borrower || selectedDoc.borrowerName || '';
+//       returnForm.dueReturnDate = selectedDoc.dueReturnDate || selectedDoc.expectedReturnDate || '';
+//     }
+//   } else {
+//     // 娓呯┖鐩稿叧瀛楁
+//     returnForm.borrower = '';
+//     returnForm.dueReturnDate = '';
+//   }
+// };
 
 // 鐢熷懡鍛ㄦ湡
 onMounted(() => {

--
Gitblit v1.9.3