yaowanxin
2025-09-26 1021003321fe54f3f45d77457db86105d206551a
档案管理-书籍二维码生成,借阅-归还扫瞄
已修改4个文件
328 ■■■■■ 文件已修改
src/api/fileManagement/return.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fileManagement/borrow/index.vue 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fileManagement/document/index.vue 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fileManagement/return/index.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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) {
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,7 +97,16 @@
           </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> -->
               <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" 
@@ -109,6 +114,14 @@
                   :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 {
    // 查找扫描内容对应的文档
    // 假设二维码包含的是文档ID或文档名称
    const matchedDoc = documentList.value.find(item =>
      item.documentationId === value
    );
    if (matchedDoc) {
      // 找到匹配的文档,设置表单值
      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) => {
  // 先刷新文档列表
@@ -375,6 +418,7 @@
  
  borrowOperationType.value = type;
  borrowDia.value = true;
  scanContent.value = ''; // 清空扫码内容
  
  if (type === "edit") {
    // 编辑模式,加载现有数据
@@ -395,6 +439,7 @@
const closeBorrowDia = () => {
  proxy.$refs.borrowFormRef.resetFields();
  borrowDia.value = false;
  scanContent.value = ''; // 清空扫码内容
};
// 提交借阅表单
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>正在生成二维码...</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"
@@ -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>
src/views/fileManagement/return/index.vue
@@ -100,7 +100,16 @@
                 <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> -->
               <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" 
@@ -108,6 +117,14 @@
                   :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,6 +387,8 @@
const openReturnDia = (type, data) => {
  returnOperationType.value = type;
  returnDia.value = true;
  scanContent.value = ''; // 清空扫码内容
  borrowInfoList.value = []; // 清空借阅信息列表
  
  if (type === "edit") {
    // 编辑模式,加载现有数据
@@ -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) {
    // 根据选择的文档ID,从文档列表中查找对应的文档信息
    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);
    }
    // 如果借阅信息列表中没有找到,从文档列表中查找
    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) {
//     // 根据选择的文档ID,从文档列表中查找对应的文档信息
//     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(() => {