From d9ed7cc8ec13a59b69bd643a9c3e2ccd907fabd1 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期三, 20 八月 2025 15:36:51 +0800
Subject: [PATCH] 档案管理

---
 src/views/fileManagement/document/index.vue             | 1262 ++++++++++++++++++
 src/views/fileManagement/bookshelf/detail.vue           |  110 +
 src/api/fileManagement/borrow.js                        |   47 
 src/views/fileManagement/bookshelf/index.vue            |  688 ++++++++++
 src/views/fileManagement/return/index.vue               |  599 ++++++++
 src/views/fileManagement/borrow/index.vue               |  584 ++++++++
 src/api/fileManagement/return.js                        |   54 
 vite.config.js                                          |    6 
 src/api/fileManagement/document.js                      |  164 ++
 src/api/fileManagement/bookshelf.js                     |  128 +
 src/views/fileManagement/document/attachmentManager.vue |  426 ++++++
 11 files changed, 4,065 insertions(+), 3 deletions(-)

diff --git a/src/api/fileManagement/bookshelf.js b/src/api/fileManagement/bookshelf.js
new file mode 100644
index 0000000..0a4a748
--- /dev/null
+++ b/src/api/fileManagement/bookshelf.js
@@ -0,0 +1,128 @@
+import request from "@/utils/request";
+
+/**
+ * 涔︽灦绠$悊鐩稿叧API鎺ュ彛
+ * 鍖呭惈浠撳簱绠$悊銆佽揣鏋剁鐞嗐�佸浘涔︾鐞嗙瓑鍔熻兘鐨勬帴鍙�
+ */
+
+/**
+ * 鑾峰彇浠撳簱鍒楄〃
+ * @description 鑾峰彇鎵�鏈変粨搴撶殑鍩烘湰淇℃伅鍒楄〃
+ * @returns {Promise} 杩斿洖浠撳簱鍒楄〃鏁版嵁
+ */
+export function getWarehouseList() {
+  return request({
+    url: "/warehouse/tree",
+    method: "get",
+  });
+}
+
+/**
+ * 鏂板浠撳簱
+ * @description 鍒涘缓鏂扮殑浠撳簱璁板綍
+ * @param {Object} data 浠撳簱淇℃伅瀵硅薄锛屽寘鍚粨搴撳悕绉扮瓑瀛楁
+ * @returns {Promise} 杩斿洖鏂板缁撴灉
+ */
+export function addWarehouse(data) {
+  return request({
+    url: "/warehouse/add",
+    method: "post",
+    data,
+  });
+}
+
+/**
+ * 鏇存柊浠撳簱淇℃伅
+ * @description 淇敼鐜版湁浠撳簱鐨勫熀鏈俊鎭�
+ * @param {Object} data 浠撳簱淇℃伅瀵硅薄锛屽繀椤诲寘鍚粨搴揑D
+ * @returns {Promise} 杩斿洖鏇存柊缁撴灉
+ */
+export function updateWarehouse(data) {
+  return request({
+    url: "/warehouse/update",
+    method: "put",
+    data,
+  });
+}
+
+/**
+ * 鍒犻櫎浠撳簱
+ * @description 鏍规嵁浠撳簱ID鍒犻櫎鎸囧畾鐨勪粨搴撹褰�
+ * @param {string|number} id 浠撳簱ID
+ * @returns {Promise} 杩斿洖鍒犻櫎缁撴灉
+ */
+export function deleteWarehouse(data) {
+  return request({
+    url: `/warehouse/delete/`,
+    method: "delete",
+    data,
+  });
+}
+
+/**
+ * 鑾峰彇璐ф灦鍒楄〃
+ * @description 鏍规嵁浠撳簱ID鑾峰彇璇ヤ粨搴撲笅鐨勬墍鏈夎揣鏋朵俊鎭�
+ * @param {string|number} warehouseId 浠撳簱ID
+ * @returns {Promise} 杩斿洖璐ф灦鍒楄〃鏁版嵁
+ */
+export function getShelfList(warehouseId) {
+  return request({
+    url: `/shelf/list/${warehouseId}`,
+    method: "get",
+  });
+}
+
+/**
+ * 鏂板璐ф灦
+ * @description 鍦ㄦ寚瀹氫粨搴撲笅鍒涘缓鏂扮殑璐ф灦璁板綍
+ * @param {Object} data 璐ф灦淇℃伅瀵硅薄锛屽寘鍚揣鏋跺悕绉般�佸眰鏁般�佸垪鏁扮瓑瀛楁
+ * @returns {Promise} 杩斿洖鏂板缁撴灉
+ */
+export function addShelf(data) {
+  return request({
+    url: "/warehouse/goodsShelves/add",
+    method: "post",
+    data,
+  });
+}
+
+/**
+ * 鏇存柊璐ф灦淇℃伅
+ * @description 淇敼鐜版湁璐ф灦鐨勫熀鏈俊鎭�
+ * @param {Object} data 璐ф灦淇℃伅瀵硅薄锛屽繀椤诲寘鍚揣鏋禝D
+ * @returns {Promise} 杩斿洖鏇存柊缁撴灉
+ */
+export function updateShelf(data) {
+  return request({
+    url: "/warehouse/goodsShelves/update",
+    method: "put",
+    data,
+  });
+}
+
+/**
+ * 鍒犻櫎璐ф灦
+ * @description 鏍规嵁璐ф灦ID鍒犻櫎鎸囧畾鐨勮揣鏋惰褰�
+ * @param {string|number} id 璐ф灦ID
+ * @returns {Promise} 杩斿洖鍒犻櫎缁撴灉
+ */
+export function deleteShelf(id) {
+  return request({
+    url: `/warehouse/goodsShelves/delete/${id}`,
+    method: "delete",
+  });
+}
+
+/**
+ * 鑾峰彇浠撳簱缁撴瀯
+ * @description 鑾峰彇鎸囧畾浠撳簱鐨勫畬鏁寸粨鏋勪俊鎭紝鍖呮嫭璐ф灦銆佸眰鏁般�佸垪鏁扮瓑
+ * @param {string|number} warehouseId 浠撳簱ID
+ * @returns {Promise} 杩斿洖浠撳簱鐨勫畬鏁寸粨鏋勬暟鎹�
+ */
+export function getWarehouseStructure(data) {
+  return request({
+    url: `/warehouse/goodsShelvesRowcol/list`,
+    method: "get",
+    params: data,
+  });
+}
diff --git a/src/api/fileManagement/borrow.js b/src/api/fileManagement/borrow.js
new file mode 100644
index 0000000..1f4c72c
--- /dev/null
+++ b/src/api/fileManagement/borrow.js
@@ -0,0 +1,47 @@
+import request from "@/utils/request";
+
+// 鏂囨。鍊熼槄绠$悊鐩稿叧鎺ュ彛
+
+// 鑾峰彇鏂囨。鍒楄〃锛堢敤浜庡�熼槄涔︾睄閫夋嫨锛�
+export function getDocumentList() {
+  return request({
+    url: "/documentation/list",
+    method: "get",
+  });
+}
+
+// 鍊熼槄鍒嗛〉鏌ヨ
+export function getBorrowList(params) {
+  return request({
+    url: "/documentationBorrowManagement/listPage",
+    method: "get",
+    params: params,
+  });
+}
+
+// 鏂板鍊熼槄
+export function addBorrow(data) {
+  return request({
+    url: "/documentationBorrowManagement/add",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏇存柊鍊熼槄
+export function updateBorrow(data) {
+  return request({
+    url: "/documentationBorrowManagement/update",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鍒犻櫎鍊熼槄
+export function deleteBorrow(ids) {
+  return request({
+    url: "/documentationBorrowManagement/delete",
+    method: "delete",
+    data: ids,
+  });
+}
diff --git a/src/api/fileManagement/document.js b/src/api/fileManagement/document.js
new file mode 100644
index 0000000..49b156e
--- /dev/null
+++ b/src/api/fileManagement/document.js
@@ -0,0 +1,164 @@
+import request from "@/utils/request";
+
+// 鑾峰彇鍒嗙被鏍�
+export function getCategoryTree() {
+  return request({
+    url: "/warehouse/documentClassification/getList",
+    method: "get",
+  });
+}
+
+// 鏂板鍒嗙被
+export function addCategory(data) {
+  return request({
+    url: "/warehouse/documentClassification/add",
+    method: "post",
+    data: {
+      category: data.category,
+      parentId: data.parentId,
+    },
+  });
+}
+
+// 淇敼鍒嗙被
+export function updateCategory(data) {
+  return request({
+    url: "/warehouse/documentClassification/update",
+    method: "put",
+    data: {
+      id: data.id,
+      category: data.category,
+    },
+  });
+}
+
+// 鍒犻櫎鍒嗙被
+export function deleteCategory(ids) {
+  return request({
+    url: "/warehouse/documentClassification/delete",
+    method: "delete",
+    data: ids,
+  });
+}
+
+// 鑾峰彇鏂囨。鍒楄〃锛堝垎椤碉級
+export function getDocumentList(query) {
+  return request({
+    url: "/documentation/listPage",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏂板鏂囨。
+export function addDocument(data) {
+  return request({
+    url: "/documentation/add",
+    method: "post",
+    data: data,
+  });
+}
+
+// 淇敼鏂囨。
+export function updateDocument(data) {
+  return request({
+    url: "/documentation/update",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鍒犻櫎鏂囨。
+export function deleteDocument(ids) {
+  return request({
+    url: "/documentation/delete",
+    method: "delete",
+    data: ids,
+  });
+}
+
+// 鑾峰彇鏂囨。璇︽儏
+export function getDocumentDetail(id) {
+  return request({
+    url: "/document/" + id,
+    method: "get",
+  });
+}
+
+// 鎼滅储鏂囨。
+export function searchDocument(query) {
+  return request({
+    url: "/document/search",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鑾峰彇浠撳簱缁撴瀯
+export function getWarehouseStructure() {
+  return request({
+    url: "/document/warehouse/structure",
+    method: "get",
+  });
+}
+
+// 闄勪欢绠$悊鐩稿叧鎺ュ彛
+// 娣诲姞闄勪欢
+export function addDocumentationFile(data) {
+  return request({
+    url: "/documentation/documentationFile/add",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鑾峰彇闄勪欢鍒楄〃
+export function getDocumentationFileList(params) {
+  return request({
+    url: "/documentation/documentationFile/listPage",
+    method: "get",
+    params: params,
+  });
+}
+
+// 鍒犻櫎闄勪欢
+export function deleteDocumentationFile(ids) {
+  return request({
+    url: "/documentation/documentationFile/del",
+    method: "delete",
+    data: ids,
+  });
+}
+
+// 鏂囨。鍊熼槄绠$悊鐩稿叧鎺ュ彛
+export function getBorrowList(params) {
+  return request({
+    url: "/documentationBorrowManagement/listPage",
+    method: "get",
+    params: params,
+  });
+}
+
+export function addBorrow(data) {
+  return request({
+    url: "/documentationBorrowManagement/add",
+    method: "post",
+    data: data,
+  });
+}
+
+export function updateBorrow(data) {
+  return request({
+    url: "/documentationBorrowManagement/update",
+    method: "put",
+    data: data,
+  });
+}
+
+export function deleteBorrow(ids) {
+  return request({
+    url: "/documentationBorrowManagement/delete",
+    method: "delete",
+    data: ids,
+  });
+}
diff --git a/src/api/fileManagement/return.js b/src/api/fileManagement/return.js
new file mode 100644
index 0000000..2e0c0e7
--- /dev/null
+++ b/src/api/fileManagement/return.js
@@ -0,0 +1,54 @@
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ褰掕繕璁板綍
+export function getReturnListPage(query) {
+  return request({
+    url: "/documentationBorrowManagement/listPageReturn",
+    method: "get",
+    params: query,
+  });
+}
+
+// 褰掕繕鎿嶄綔
+export function returnDocument(data) {
+  return request({
+    url: "/documentationBorrowManagement/revent",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鍒犻櫎褰掕繕璁板綍
+export function deleteReturn(ids) {
+  return request({
+    url: "/documentationBorrowManagement/reventDelete",
+    method: "delete",
+    data: ids,
+  });
+}
+
+// 鏇存柊鍊熼槄璁板綍
+export function updateBorrow(data) {
+  return request({
+    url: "/documentationBorrowManagement/update",
+    method: "put",
+    data: data,
+  });
+}
+
+// 褰掕繕鏇存柊
+export function reventUpdate(data) {
+  return request({
+    url: "/documentationBorrowManagement/reventUpdate",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鑾峰彇鏂囨。鍒楄〃
+export function getDocumentList() {
+  return request({
+    url: "/documentationBorrowManagement/list",
+    method: "get",
+  });
+}
diff --git a/src/views/fileManagement/bookshelf/detail.vue b/src/views/fileManagement/bookshelf/detail.vue
new file mode 100644
index 0000000..5d7d3ac
--- /dev/null
+++ b/src/views/fileManagement/bookshelf/detail.vue
@@ -0,0 +1,110 @@
+<template>
+  <div class="detail-container">
+    <div class="header">
+      <el-button @click="handleBack" type="primary" size="small">杩斿洖</el-button>
+      <h2>鍥句功璇︽儏</h2>
+    </div>
+    
+    <div class="content" v-loading="loading">
+      <el-card v-if="current">
+        <template #header>
+          <div class="card-header">
+            <span>鍩烘湰淇℃伅</span>
+          </div>
+        </template>
+        
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="鍥句功缂栧彿">{{ current.docNumber }}</el-descriptions-item>
+          <el-descriptions-item label="鍥句功鍚嶇О">{{ current.docName }}</el-descriptions-item>
+          <el-descriptions-item label="鍏ュ簱鏃堕棿">{{ current.createTime }}</el-descriptions-item>
+          <!-- <el-descriptions-item label="褰撳墠浣嶇疆">{{ current.currentLocation }}</el-descriptions-item> -->
+          <el-descriptions-item label="鐘舵��">{{ current.docStatus }}</el-descriptions-item>
+        </el-descriptions>
+        
+        <!-- <div class="additional-info" v-if="current.description">
+          <h4>鍥句功绠�浠�</h4>
+          <p>{{ current.description }}</p>
+        </div> -->
+      </el-card>
+      
+      <el-empty v-else description="鏆傛棤鏁版嵁" />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+
+// 瀹氫箟props
+const props = defineProps({
+  current: {
+    type: Object,
+    required: true
+  }
+})
+
+// 瀹氫箟emits
+const emit = defineEmits(['hanldeBack'])
+
+// 鍝嶅簲寮忔暟鎹�
+const loading = ref(false)
+// const bookInfo = ref(null)
+
+// 鏂规硶
+const handleBack = () => {
+  emit('hanldeBack')
+}
+
+</script>
+
+<style scoped>
+.detail-container {
+  padding: 20px;
+  height: 100%;
+  background-color: #f5f5f5;
+}
+
+.header {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20px;
+  background-color: #fff;
+  padding: 15px 20px;
+  border-radius: 4px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.header h2 {
+  margin: 0 0 0 20px;
+  color: #333;
+}
+
+.content {
+  background-color: #fff;
+  border-radius: 4px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.card-header {
+  font-weight: bold;
+  color: #333;
+}
+
+.additional-info {
+  margin-top: 20px;
+  padding-top: 20px;
+  border-top: 1px solid #ebeef5;
+}
+
+.additional-info h4 {
+  margin: 0 0 10px 0;
+  color: #333;
+  font-size: 16px;
+}
+
+.additional-info p {
+  margin: 0;
+  color: #666;
+  line-height: 1.6;
+}
+</style>
diff --git a/src/views/fileManagement/bookshelf/index.vue b/src/views/fileManagement/bookshelf/index.vue
new file mode 100644
index 0000000..2689900
--- /dev/null
+++ b/src/views/fileManagement/bookshelf/index.vue
@@ -0,0 +1,688 @@
+<template>
+  <div class="sample">
+    <div class="main-content" v-if="!isDetail">
+      <div class="search">
+                 <div class="search_thing">
+           <div class="search_label">浠撳簱鍚嶇О锛�</div>
+           <div class="search_input">
+             <el-select v-model="entity.warehouseId" placeholder="閫夋嫨浠撳簱" size="small" @change="warehouseChange">
+               <el-option v-for="item in warehouse" :key="item.id" :label="item.label" :value="item.id">
+               </el-option>
+             </el-select>
+           </div>
+         </div>
+        <div class="search_thing">
+          <div class="search_label">璐ф灦锛�</div>
+          <div class="search_input">
+            <el-select v-model="entity.shelfId" placeholder="閫夋嫨璐ф灦" size="small" @change="handleShelf">
+              <el-option v-for="item in shelf" :key="item.id" :label="item.label" :value="item.id">
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+          <!-- <div class="search_thing">
+           <el-button size="small" @click="handleShelf(entity.shelfId,'')">閲嶇疆</el-button>
+           <el-button size="small" type="primary" @click="handleShelf(entity.shelfId)">鏌ヨ</el-button>
+         </div> -->
+        <div class="btns">
+          <el-button size="small" style="color:#3A7BFA" @click="keepVisible=true">缁存姢</el-button>
+          <el-button size="small" style="color:#3A7BFA" @click="warehouseVisible=true,isEdit=false">娣诲姞浠撳簱</el-button>
+          <el-button size="small" style="color:#3A7BFA" @click="shelvesVisible=true,isEdit=false"
+            :disabled="entity.warehouseId==null">娣诲姞璐ф灦</el-button>
+        </div>
+      </div>
+      <div class="table" v-loading="tableLoading">
+        <table class="tables" style="table-layout:fixed;" v-if="tableList.length>0">
+          <tbody>
+            <tr v-for="(item,index) in tableList" :key="index">
+              <td v-for="(m,i) in item" :key="i" class="content">
+                <h4 v-if="m.row!=undefined">{{ m.row }} - {{ m.col }}</h4>
+                <ul>
+                  <el-tooltip
+                  effect="dark"
+                  placement="top"
+                  v-for="(n,j) in m.documentationDtoList"
+                  :key="j">
+                    <template #content><span>{{ n.docName }}</span>
+                      <span>&nbsp;[{{ n.docNumber }}]</span></template>
+                    <li class="green"
+                      @click="handelDetail(n)">
+                      <i></i>
+                      <span>{{ n.docName }}</span>
+                      <span>&nbsp;[{{ n.docNumber }}] <span :style="{ color: getStatusColor(n.docStatus) }">锛坽{ n.docStatus }}锛�</span></span>
+                    </li>
+                  </el-tooltip>
+                </ul>
+              </td>
+            </tr>
+            <tr>
+              <td v-for="(item,index) in rowList" :key="index" style="background: ghostwhite;height: 20px;">{{ item }}
+              </td>
+            </tr>
+          </tbody>
+        </table>
+        <span v-else style="color: rgb(144, 147, 153);display: inline-block;position: absolute;top: 60%;left: 50%;transform: translate(-50%,-50%);">鏆傛棤鏁版嵁</span>
+      </div>
+    </div>
+    <Detail v-else @hanldeBack="isDetail=false" :current="current" />
+    
+    <!-- 搴撲綅缁存姢瀵硅瘽妗� -->
+    <el-dialog v-model="keepVisible" title="搴撲綅缁存姢" width="350px" :append-to-body="true">
+                                                       <el-tree :data="warehouse" ref="tree" node-key="id"
+           highlight-current v-if="keepVisible"
+           empty-text="鏆傛棤鏁版嵁">
+        <template #default="{ node, data }">
+          <div class="custom-tree-node" style="width: 100%;">
+            <el-row style="width: 100%;display: flex;align-items: center;">
+              <el-col :span="14">
+                <span>
+                  <el-icon v-if="node.level < 2" class="folder-icon">
+                    <FolderOpened />
+                  </el-icon>
+                  <el-icon v-else class="file-icon">
+                    <Document />
+                  </el-icon>
+                  {{ data.label }}
+                </span>
+              </el-col>
+              <el-col :span="10" v-if="node.level<3">
+                <el-button type="link" size="small" :icon="Edit" @click.stop="handleEdit(data,node.level)">
+                </el-button>
+                <el-button type="danger" size="small" :icon="Delete" @click.stop="handleDelete(data,node.level)">
+                </el-button>
+              </el-col>
+            </el-row>
+          </div>
+        </template>
+      </el-tree>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="keepVisible = false">鍙� 娑�</el-button>
+          <el-button type="primary" @click="keepVisible = false" >纭� 瀹�</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    
+    <!-- 浠撳簱鏂板/淇敼瀵硅瘽妗� -->
+    <el-dialog v-model="warehouseVisible" :title="isEdit?'浠撳簱淇敼':'浠撳簱鏂板'" width="350px">
+      <el-row>
+        <el-col class="search_thing" :span="24">
+          <div class="search_label"><span class="required-span">* </span>浠撳簱鍚嶇О锛�</div>
+          <div class="search_input">
+            <el-input v-model="name" size="small" @keyup.enter="confirmWarehouse"></el-input>
+          </div>
+        </el-col>
+      </el-row>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="warehouseVisible = false">鍙� 娑�</el-button>
+          <el-button type="primary" @click="confirmWarehouse" :loading="upLoadWarehouse">纭� 瀹�</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    
+    <!-- 璐ф灦鏂板/淇敼瀵硅瘽妗� -->
+    <el-dialog v-model="shelvesVisible" :title="isEdit?'璐ф灦淇敼':'璐ф灦鏂板'" width="350px">
+      <el-row>
+        <el-col class="search_thing" :span="24">
+          <div class="search_label"><span class="required-span">* </span>璐ф灦鍚嶇О锛�</div>
+          <div class="search_input">
+            <el-input v-model="shelves.name" size="small"></el-input>
+          </div>
+        </el-col>
+      </el-row>
+      <el-row>
+        <el-col class="search_thing" :span="24">
+          <div class="search_label"><span class="required-span">* </span>璐ф灦灞傛暟锛�</div>
+          <div class="search_input">
+            <el-input v-model="shelves.row" size="small"></el-input>
+          </div>
+        </el-col>
+      </el-row>
+      <el-row>
+        <el-col class="search_thing" :span="24">
+          <div class="search_label"><span class="required-span">* </span>璐ф灦鍒楁暟锛�</div>
+          <div class="search_input">
+            <el-input v-model="shelves.col" size="small"></el-input>
+          </div>
+        </el-col>
+      </el-row>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="shelvesVisible = false">鍙� 娑�</el-button>
+          <el-button type="primary" @click="confirmShelves" :loading="upLoadShelves">纭� 瀹�</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    
+    
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, watch } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Edit, Delete, FolderOpened, Document } from '@element-plus/icons-vue'
+import { getWarehouseList, addWarehouse, updateWarehouse, deleteWarehouse, getWarehouseStructure, addShelf, updateShelf, deleteShelf } from '@/api/fileManagement/bookshelf'
+import Detail from './detail.vue'
+
+// 鍝嶅簲寮忔暟鎹�
+const entity = reactive({
+  warehouseId: null,
+  shelfId: null
+})
+
+const warehouse = ref([])
+const shelf = ref([])
+const keepVisible = ref(false)
+const warehouseVisible = ref(false)
+const shelvesVisible = ref(false)
+const upLoadWarehouse = ref(false)
+const upLoadShelves = ref(false)
+const tableList = ref([])
+const rowList = ref([])
+const value = ref('')
+const name = ref('')
+const shelves = reactive({})
+const isEdit = ref(false)
+const isDetail = ref(false)
+const currentEdit = ref(null)
+const tableLoading = ref(false)
+const current = ref({})
+
+// 妯℃澘寮曠敤
+const organization = ref(null)
+
+// 鐩戝惉鍣�
+watch(isEdit, (newVal) => {
+  if (!newVal) {
+    Object.keys(shelves).forEach(key => delete shelves[key])
+  }
+})
+
+// 鏂规硶
+
+const selectList = async () => {
+  // 杩欓噷闇�瑕佹浛鎹负瀹為檯鐨凙PI璋冪敤
+  const res = await getWarehouseList()
+  warehouse.value = res.data
+  
+  if (warehouse.value.length == 0) {
+    entity.warehouseId = ''
+    entity.shelfId = ''
+    tableList.value = []
+  }
+  
+           
+  
+  if (!entity.warehouseId && warehouse.value.length > 0) {
+    entity.warehouseId = warehouse.value[0].id
+    warehouseChange(entity.warehouseId)
+    if (shelf.value.length > 0) {
+      entity.shelfId = shelf.value[0].id
+      handleShelf(entity.shelfId)
+    } else {
+      tableList.value = []
+    }
+  } else if (warehouse.value.length > 0) {
+    warehouseChange(entity.warehouseId)
+    if (shelf.value.length > 0) {
+      entity.shelfId = shelf.value[0].id
+      handleShelf(entity.shelfId)
+    } else {
+      tableList.value = []
+    }
+  }
+}
+
+const confirmWarehouse = () => {
+  if (!name.value) {
+    ElMessage.error('璇峰~鍐欎粨搴撳悕绉�')
+    return
+  }
+  upLoadWarehouse.value = true
+  
+  if (currentEdit.value && currentEdit.value.id) {
+    // 淇敼浠撳簱
+    // 杩欓噷闇�瑕佹浛鎹负瀹為檯鐨凙PI璋冪敤
+    updateWarehouse({
+      id: currentEdit.value.id,
+      warehouseName: name.value
+    }).then(res => {
+      upLoadWarehouse.value = false
+      warehouseVisible.value = false
+      currentEdit.value = null
+      ElMessage.success('淇敼鎴愬姛')
+      selectList()
+      name.value = ''
+      warehouseChange(entity.warehouseId)
+    })
+    
+  } else {
+    // 鏂板浠撳簱
+    // 杩欓噷闇�瑕佹浛鎹负瀹為檯鐨凙PI璋冪敤
+    addWarehouse({
+      warehouseName: name.value
+    }).then(res => {
+      upLoadWarehouse.value = false
+      warehouseVisible.value = false
+      ElMessage.success('娣诲姞鎴愬姛')
+      selectList()
+      name.value = ''
+      warehouseChange(entity.warehouseId)
+    })
+  }
+}
+
+const confirmShelves = () => {
+  if (!shelves.name) {
+    ElMessage.error('璇峰~鍐欒揣鏋跺悕绉�')
+    return
+  }
+  if (!shelves.row) {
+    ElMessage.error('璇峰~鍐欒揣鏋跺眰鏁�')
+    return
+  }
+  if (!shelves.col) {
+    ElMessage.error('璇峰~鍐欒揣鏋跺垪鏁�')
+    return
+  }
+  upLoadShelves.value = true
+  
+  if (currentEdit.value && currentEdit.value.id) {
+    // 淇敼
+    updateShelf({
+      id: currentEdit.value.id,
+      name: shelves.name,
+      row: Number(shelves.row),
+      col: Number(shelves.col),
+      warehouseId: entity.warehouseId
+    }).then(res => {
+      upLoadShelves.value = false
+      shelvesVisible.value = false
+      ElMessage.success('淇敼鎴愬姛')
+      selectList()
+      currentEdit.value = {}
+    }).catch(err => {
+      upLoadShelves.value = false
+      shelvesVisible.value = false
+      ElMessage.error('淇敼澶辫触')
+    })
+    
+  } else {
+    // 鏂板
+    // 杩欓噷闇�瑕佹浛鎹负瀹為檯鐨凙PI璋冪敤
+      addShelf({
+      name: shelves.name,
+      row: Number(shelves.row),
+      col: Number(shelves.col),
+      warehouseId: entity.warehouseId
+    }).then(res => {
+      upLoadShelves.value = false
+      shelvesVisible.value = false
+      ElMessage.success('娣诲姞鎴愬姛')
+      selectList()
+      Object.keys(shelves).forEach(key => delete shelves[key])
+    }).catch(err => {
+      upLoadShelves.value = false
+      shelvesVisible.value = false
+      ElMessage.error('娣诲姞澶辫触')
+    })
+  }
+  warehouseChange(entity.warehouseId)
+}
+
+
+
+const handleDelete = (row, level) => {
+  ElMessageBox.confirm('鏄惁鍒犻櫎褰撳墠鏁版嵁?', "璀﹀憡", {
+    confirmButtonText: "纭畾",
+    cancelButtonText: "鍙栨秷",
+    type: "warning"
+  }).then(() => {
+    if (level == 1) {
+      // 鍒犻櫎浠撳簱
+      deleteWarehouse([row.id]).then(res => {
+        ElMessage.success('鍒犻櫎鎴愬姛')
+        selectList()
+      })
+    } else {
+      // 鍒犻櫎璐ф灦
+      deleteShelf({
+        id: row.id
+      }).then(res => {
+        ElMessage.success('鍒犻櫎鎴愬姛')
+        selectList()
+      })
+    }
+    warehouseChange(entity.warehouseId)
+  }).catch(() => {})
+}
+
+const handleEdit = (data, level) => {
+  isEdit.value = true
+  if (level == 1) {
+    warehouseVisible.value = true
+    currentEdit.value = data
+    name.value = data.label
+  } else {
+    shelvesVisible.value = true
+    currentEdit.value = data
+    Object.assign(shelves, {
+      name: data.label,
+      row: data.row,
+      col: data.col,
+      warehouseId: data.warehouseId
+    })
+  }
+}
+
+const handelDetail = (row) => {
+  current.value = row
+  isDetail.value = true
+}
+
+// 鏍规嵁鏂囨。鐘舵�佽繑鍥炲搴旂殑棰滆壊
+const getStatusColor = (status) => {
+  if (status === '姝e父') {
+    return '#34BD66' // 缁胯壊
+  } else if (status === '鍊熷嚭') {
+    return '#F56C6C' // 绾㈣壊
+  }
+  return '#606266' // 榛樿棰滆壊
+}
+
+const warehouseChange = (val) => {
+tableList.value = []
+let map = warehouse.value.find(a => {
+  return a && a.id === val ? a : null
+})
+if (map && map.children) {
+  shelf.value = map.children
+  entity.shelfId = ''
+} else {
+  shelf.value = []
+}
+currentEdit.value = null
+}
+
+const handleShelf = async(e) => {
+  if (e) {
+    tableLoading.value = true
+    let data = []
+    const res = await getWarehouseStructure({warehouseGoodsShelvesId:e})
+    if(res.code == 200){
+      data = res.data.map(m=>{
+        m.books = m.documentationDtoList|[]
+        return m
+      })
+    }else{
+      ElMessage.error(res.message)
+    }
+    setTimeout(() => {
+      tableLoading.value = false
+      let set = new Set()
+      tableList.value = []
+      let arr = []
+      
+      if (data && data.length > 0) {
+        data.forEach(m => {
+          if (m && m.row && m.col) {
+            set.add(m.col)
+            if (arr.length > 0) {
+              if (arr.find(n => n.row == m.row)) {
+                arr.push(m)
+              } else {
+                tableList.value.push(arr)
+                arr = []
+                arr.push(m)
+              }
+            } else {
+              arr.push(m)
+            }
+          }
+        })
+        
+        if (arr.length > 0) {
+          tableList.value.push(arr)
+        }
+      }
+      
+      rowList.value = []
+      for (let i = 0; i < set.size; i++) {
+        rowList.value.push(`${i + 1} 鍒梎)
+      }
+      console.log(6666, tableList.value,rowList.value,data)
+    }, 1000)
+  }
+}
+
+
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+  selectList()
+})
+</script>
+
+<style scoped>
+  .main-content {
+    width: 100%;
+    height: 100%;
+    padding: 20px;
+    box-sizing: border-box;
+  }
+
+  .title {
+    height: 20px;
+    line-height: 20px;
+    margin-bottom: 20px;
+  }
+
+  .search {
+    background-color: #fff;
+    height: 80px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 20px;
+    border-radius: 8px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+    margin-bottom: 20px;
+  }
+
+  .search_thing {
+    display: flex;
+    align-items: center;
+    height: 50px;
+    margin-right: 20px;
+  }
+
+  .search_label {
+    width: 90px;
+    font-size: 14px;
+    text-align: right;
+    color: #606266;
+    font-weight: 500;
+    margin-right: 10px;
+  }
+
+  .search_input {
+    width: 200px;
+  }
+
+  .table {
+    background-color: #fff;
+    width: 100%;
+    height: calc(100% - 100px);
+    padding: 20px;
+    overflow-y: auto;
+    border-radius: 8px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  }
+
+  .el-form-item {
+    margin-bottom: 16px;
+  }
+
+  .btns {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+  }
+
+  .tables {
+    width: 100%;
+    height: 100%;
+    border-collapse: collapse;
+    border: 1px solid #e4e7ed;
+  }
+
+  .tables th {
+    font-size: 14px;
+    border: 1px solid #e4e7ed;
+    background-color: #fafafa;
+    padding: 8px;
+    font-weight: 500;
+  }
+
+  .tables td {
+    font-size: 12px;
+    text-align: center;
+    vertical-align: top;
+    border: 1px solid #e4e7ed;
+    padding: 8px;
+    box-sizing: border-box;
+    height: 120px;
+    background-color: #fff;
+  }
+
+  .tables ul {
+    list-style-type: none;
+  }
+
+  .tables ul li {
+    border-radius: 3px;
+    padding: 4px 10px;
+    box-sizing: border-box;
+    margin-bottom: 5px;
+    font-size: 12px;
+    display: flex;
+    align-items: center;
+    justify-content: start;
+    color: #333333;
+    cursor: pointer;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+
+  .tables h4 {
+    color: #999999;
+    font-size: 14px;
+    font-weight: 400;
+    padding: 6px 0;
+  }
+
+  .tables i {
+    display: inline-block;
+    width: 6px;
+    height: 6px;
+    border-radius: 50%;
+    margin-right: 6px;
+  }
+
+  li:hover {
+    background: rgba(58, 123, 250, 0.18);
+  }
+
+  li:hover i {
+    background: #3A7BFA;
+  }
+
+  li:hover .num {
+    color: #3A7BFA;
+  }
+
+  .green {
+    background: #E0F6EA;
+  }
+
+  .green i {
+    background: #34BD66;
+  }
+
+  .green .num {
+    color: #34BD66;
+  }
+
+  .el-dialog {
+    position: relative;
+  }
+
+  .shaoma {
+    display: flex;
+    align-items: center;
+    font-size: 14px;
+    color: #3A7BFA;
+    position: absolute;
+    top: 23px;
+    right: 54px;
+    cursor: pointer;
+  }
+
+  .folder-icon {
+    color: #409eff;
+    font-size: 16px;
+    margin-right: 6px;
+  }
+
+  .file-icon {
+    color: #67c23a;
+    font-size: 16px;
+    margin-right: 6px;
+  }
+
+  .node_i {
+    color: orange;
+    font-size: 18px;
+  }
+
+  .custom-tree-node .el-button {
+    opacity: 0;
+  }
+
+  .custom-tree-node:hover .el-button {
+    opacity: 1;
+  }
+
+  :deep(.el-loading-mask) {
+    z-index: 10;
+  }
+
+  .required-span {
+    color: #f56c6c;
+  }
+
+  .table-row {
+    border-bottom: 1px solid #e4e7ed;
+  }
+
+  .table-row:last-child {
+    border-bottom: none;
+  }
+
+  .column-header {
+    background-color: #fafafa !important;
+    font-weight: 500;
+    color: #606266;
+  }
+
+  .content {
+    transition: background-color 0.2s ease;
+  }
+
+  .content:hover {
+    background-color: #f5f7fa;
+  }
+</style>
diff --git a/src/views/fileManagement/borrow/index.vue b/src/views/fileManagement/borrow/index.vue
new file mode 100644
index 0000000..9a9ee81
--- /dev/null
+++ b/src/views/fileManagement/borrow/index.vue
@@ -0,0 +1,584 @@
+<template>
+  <div class="app-container borrow-view">
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="search-container">
+      <el-form :model="searchForm" :inline="true" class="search-form">
+                 <el-form-item label="鍊熼槄鐘舵�侊細">
+           <el-select v-model="searchForm.borrowStatus" placeholder="璇烽�夋嫨鍊熼槄鐘舵��" clearable style="width: 150px">
+             <el-option label="鍊熼槄" value="鍊熼槄" />
+             <el-option label="褰掕繕" value="褰掕繕" />
+           </el-select>
+         </el-form-item>
+        <el-form-item label="鍊熼槄浜猴細">
+          <el-input
+            v-model="searchForm.borrower"
+            placeholder="璇疯緭鍏ュ�熼槄浜�"
+            clearable
+            style="width: 200px"
+          />
+        </el-form-item>
+        <el-form-item label="鍊熼槄鏃ユ湡鑼冨洿锛�">
+          <el-date-picker
+            v-model="searchForm.dateRange"
+            type="daterange"
+            range-separator="鑷�"
+            start-placeholder="寮�濮嬫棩鏈�"
+            end-placeholder="缁撴潫鏃ユ湡"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+            style="width: 300px"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">
+            <el-icon><Search /></el-icon>
+            鏌ヨ
+          </el-button>
+          <el-button @click="handleReset">
+            <el-icon><Refresh /></el-icon>
+            閲嶇疆
+          </el-button>
+        </el-form-item>
+        <el-form-item style="margin-left: auto;">
+          <el-button type="primary" @click="openBorrowDia('add')">
+            <el-icon><Plus /></el-icon>
+            鏂板鍊熼槄
+          </el-button>
+          <el-button
+            type="danger"
+            @click="handleBatchDelete"
+            :disabled="selectedRows.length === 0"
+          >
+            <el-icon><Delete /></el-icon>
+            鎵归噺鍒犻櫎 ({{ selectedRows.length }})
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 琛ㄦ牸鍖哄煙 -->
+    <div class="table-container">
+      <PIMTable
+        :table-data="borrowList"
+        :column="tableColumns"
+        :is-selection="true"
+        :border="true"
+        :table-loading="tableLoading"
+        :page="{
+          current: pagination.currentPage,
+          size: pagination.pageSize,
+          total: pagination.total,
+          layout: 'total, sizes, prev, pager, next, jumper'
+        }"
+        @selection-change="handleSelectionChange"
+        @pagination="handlePagination"
+      />
+    </div>
+
+    <!-- 鍊熼槄鏂板/缂栬緫瀵硅瘽妗� -->
+    <el-dialog
+      v-model="borrowDia"
+      :title="borrowOperationType === 'add' ? '鏂板鍊熼槄' : '缂栬緫鍊熼槄'"
+      width="800px"
+      @close="closeBorrowDia"
+      @keydown.enter.prevent
+    >
+      <el-form
+        :model="borrowForm"
+        label-width="140px"
+        :rules="borrowRules"
+        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="璇疯緭鍏ュ�熼槄浜�" />
+             </el-form-item>
+           </el-col>
+           <el-col :span="12">
+             <el-form-item label="鍊熼槄涔︾睄锛�" prop="documentationId">
+               <el-select v-model="borrowForm.documentationId" placeholder="璇烽�夋嫨鍊熼槄涔︾睄" style="width: 100%">
+                 <el-option 
+                   v-for="item in documentList" 
+                   :key="item.id" 
+                   :label="item.docName || item.name" 
+                   :value="item.id"
+                 />
+               </el-select>
+             </el-form-item>
+           </el-col>
+         </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鍊熼槄鏃ユ湡锛�" prop="borrowDate">
+              <el-date-picker
+                v-model="borrowForm.borrowDate"
+                type="date"
+                placeholder="閫夋嫨鍊熼槄鏃ユ湡"
+                style="width: 100%"
+                format="YYYY-MM-DD"
+                value-format="YYYY-MM-DD"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="搴斿綊杩樻棩鏈燂細" prop="dueReturnDate">
+              <el-date-picker
+                v-model="borrowForm.dueReturnDate"
+                type="date"
+                placeholder="閫夋嫨搴斿綊杩樻棩鏈�"
+                style="width: 100%"
+                format="YYYY-MM-DD"
+                value-format="YYYY-MM-DD"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+                 <el-row :gutter="20">
+           <el-col :span="24">
+             <el-form-item label="鍊熼槄鐩殑锛�" prop="borrowPurpose">
+               <el-input v-model="borrowForm.borrowPurpose" placeholder="璇疯緭鍏ュ�熼槄鐩殑" />
+             </el-form-item>
+           </el-col>
+         </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="澶囨敞锛�" prop="remark">
+              <el-input
+                v-model="borrowForm.remark"
+                type="textarea"
+                :rows="3"
+                placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitBorrowForm">纭</el-button>
+          <el-button @click="closeBorrowDia">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+import { ElMessageBox, ElMessage } from "element-plus";
+import { Search, Refresh, Plus, Delete } from '@element-plus/icons-vue';
+import PIMTable from '@/components/PIMTable/PIMTable.vue';
+import { getBorrowList, addBorrow, updateBorrow, deleteBorrow, getDocumentList } from '@/api/fileManagement/borrow';
+
+const { proxy } = getCurrentInstance();
+
+// 鍝嶅簲寮忔暟鎹�
+const borrowDia = ref(false);
+const borrowOperationType = ref("");
+const tableLoading = ref(false);
+const borrowList = ref([]);
+const selectedRows = ref([]);
+const documentList = ref([]); // 鏂囨。鍒楄〃锛岀敤浜庡�熼槄涔︾睄閫夋嫨
+
+// 鍒嗛〉鐩稿叧
+const pagination = reactive({
+  currentPage: 1,
+  pageSize: 10,
+  total: 0,
+});
+
+// 鏌ヨ琛ㄥ崟
+const searchForm = reactive({
+  documentationId: "",
+  borrowStatus: "",
+  borrower: "",
+  returnerId: "",
+  dateRange: []
+});
+
+// 鍊熼槄琛ㄥ崟
+const borrowForm = reactive({
+  id: "",
+  documentationId: "",
+  borrower: "",
+  returnerId: "",
+  borrowPurpose: "",
+  borrowDate: "",
+  dueReturnDate: "",
+  returnDate: "",
+  borrowStatus: "",
+  remark: ""
+});
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const borrowRules = reactive({
+  documentationId: [{ required: true, message: "璇烽�夋嫨鍊熼槄涔︾睄", trigger: "change" }],
+  borrower: [{ required: true, message: "璇疯緭鍏ュ�熼槄浜�", trigger: "blur" }],
+  borrowPurpose: [{ required: true, message: "璇疯緭鍏ュ�熼槄鐩殑", trigger: "blur" }],
+  borrowDate: [{ required: true, message: "璇烽�夋嫨鍊熼槄鏃ユ湡", trigger: "change" }],
+  dueReturnDate: [{ required: true, message: "璇烽�夋嫨搴斿綊杩樻棩鏈�", trigger: "change" }],
+  borrowStatus: [{ required: true, message: "璇烽�夋嫨鍊熼槄鐘舵��", trigger: "change" }]
+});
+
+// 琛ㄦ牸鍒楅厤缃�
+const tableColumns = ref([
+  { 
+    label: '鏂囨。鍚嶇О', 
+    prop: 'documentationId',
+    width: '200',
+    formatData: (params) => {
+      if (!params) return '-';
+      const doc = documentList.value.find(item => item.id === params);
+      return doc ? (doc.docName || doc.name) : params;
+    }
+  },
+  { label: '鍊熼槄浜�', prop: 'borrower' },
+  { label: '鍊熼槄鐩殑', prop: 'borrowPurpose' },
+  { label: '鍊熼槄鏃ユ湡', prop: 'borrowDate' },
+  { label: '搴斿綊杩樻棩鏈�', prop: 'dueReturnDate' },
+  { 
+    label: '鍊熼槄鐘舵��', 
+    prop: 'borrowStatus', 
+    width: '100',
+    dataType: 'tag',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      return params;
+    },
+         formatType: (params) => {
+       if (params === '褰掕繕') return 'success';
+       if (params === '鍊熼槄') return 'warning';
+       return 'info';
+     }
+  },
+  { label: '澶囨敞', prop: 'remark', width: '150' },
+  { 
+    dataType: "action",
+    label: "鎿嶄綔",
+    align: "center",
+    fixed: 'right',
+    width: '150',
+    operation: [
+      {
+        name: "缂栬緫",
+        type: "text",
+        clickFun: (row) => {
+          openBorrowDia('edit', row)
+        },
+      },
+      {
+        name: "鍒犻櫎",
+        type: "text",
+        clickFun: (row) => {
+          handleDelete(row)
+        },
+      },
+    ],
+  }
+]);
+
+// 鍒濆鍖栨暟鎹�
+const initData = async () => {
+  await Promise.all([
+    loadDocumentList(),
+    loadBorrowList()
+  ]);
+};
+
+// 鍔犺浇鏂囨。鍒楄〃
+const loadDocumentList = async () => {
+  try {
+    const res = await getDocumentList();
+    if (res.code === 200) {
+      documentList.value = res.data || [];
+    } else {
+      ElMessage.error(res.msg || "鑾峰彇鏂囨。鍒楄〃澶辫触");
+      documentList.value = [];
+    }
+  } catch (error) {
+    ElMessage.error("鑾峰彇鏂囨。鍒楄〃澶辫触锛岃閲嶈瘯");
+    documentList.value = [];
+  }
+};
+
+// 鍔犺浇鍊熼槄鍒楄〃
+const loadBorrowList = async () => {
+  try {
+    tableLoading.value = true;
+    
+    // 鏋勫缓鏌ヨ鍙傛暟
+    const query = {
+      page: pagination.currentPage,
+      size: pagination.pageSize,
+      documentationId: searchForm.documentationId || undefined,
+      borrowStatus: searchForm.borrowStatus || undefined,
+      borrower: searchForm.borrower || undefined,
+      returnerId: searchForm.returnerId || undefined,
+      entryDateStart: searchForm.dateRange && searchForm.dateRange.length > 0 ? searchForm.dateRange[0] : undefined,
+      entryDateEnd: searchForm.dateRange && searchForm.dateRange.length > 1 ? searchForm.dateRange[1] : undefined
+    };
+    
+    // 绉婚櫎undefined鐨勫弬鏁�
+    Object.keys(query).forEach(key => {
+      if (query[key] === undefined) {
+        delete query[key];
+      }
+    });
+    
+    const res = await getBorrowList(query);
+    if (res.code === 200) {
+      borrowList.value = res.data.records || [];
+      pagination.total = res.data.total || 0;
+    } else {
+      ElMessage.error(res.msg || "鑾峰彇鍊熼槄鍒楄〃澶辫触");
+      borrowList.value = [];
+      pagination.total = 0;
+    }
+    
+    // 閲嶇疆閫夋嫨鐘舵��
+    selectedRows.value = [];
+  } catch (error) {
+    ElMessage.error("鑾峰彇鍊熼槄鍒楄〃澶辫触锛岃閲嶈瘯");
+    borrowList.value = [];
+    pagination.total = 0;
+  } finally {
+    tableLoading.value = false;
+  }
+};
+
+// 鏌ヨ
+const handleSearch = () => {
+  pagination.currentPage = 1;
+  loadBorrowList();
+};
+
+// 閲嶇疆鏌ヨ
+const handleReset = () => {
+  searchForm.documentationId = "";
+  searchForm.borrowStatus = "";
+  searchForm.borrower = "";
+  searchForm.returnerId = "";
+  searchForm.dateRange = [];
+  pagination.currentPage = 1;
+  loadBorrowList();
+  ElMessage.success("鏌ヨ鏉′欢宸查噸缃�");
+};
+
+// 鎵撳紑鍊熼槄寮规
+const openBorrowDia = (type, data) => {
+  borrowOperationType.value = type;
+  borrowDia.value = true;
+  
+  if (type === "edit") {
+    // 缂栬緫妯″紡锛屽姞杞界幇鏈夋暟鎹�
+    Object.assign(borrowForm, data);
+  } else {
+    // 鏂板妯″紡锛屾竻绌鸿〃鍗�
+    Object.keys(borrowForm).forEach(key => {
+      borrowForm[key] = "";
+    });
+         // 璁剧疆榛樿鐘舵��
+     borrowForm.borrowStatus = "鍊熼槄";
+    // 璁剧疆褰撳墠鏃ユ湡涓哄�熼槄鏃ユ湡
+    borrowForm.borrowDate = new Date().toISOString().split('T')[0];
+  }
+};
+
+// 鍏抽棴鍊熼槄寮规
+const closeBorrowDia = () => {
+  proxy.$refs.borrowFormRef.resetFields();
+  borrowDia.value = false;
+};
+
+// 鎻愪氦鍊熼槄琛ㄥ崟
+const submitBorrowForm = () => {
+  proxy.$refs.borrowFormRef.validate(async (valid) => {
+    if (valid) {
+      try {
+        if (borrowOperationType.value === "edit") {
+          // 缂栬緫妯″紡锛屾洿鏂扮幇鏈夋暟鎹�
+          const res = await updateBorrow({
+            borrower:borrowForm.borrower,
+            id: borrowForm.id,
+            borrowPurpose: borrowForm.borrowPurpose,
+            borrowDate: borrowForm.borrowDate,
+            dueReturnDate: borrowForm.dueReturnDate,
+            returnDate: borrowForm.returnDate,
+            remark: borrowForm.remark
+          });
+          
+          if (res.code === 200) {
+            ElMessage.success("缂栬緫鎴愬姛");
+            await loadBorrowList();
+            closeBorrowDia();
+          } else {
+            ElMessage.error(res.msg || "缂栬緫澶辫触");
+          }
+        } else {
+          // 鏂板妯″紡锛屾坊鍔犳柊鏁版嵁
+          const res = await addBorrow({
+            documentationId: borrowForm.documentationId,
+            borrower: borrowForm.borrower,
+            returnerId: borrowForm.returnerId,
+            borrowPurpose: borrowForm.borrowPurpose,
+            borrowDate: borrowForm.borrowDate,
+            dueReturnDate: borrowForm.dueReturnDate,
+            returnDate: borrowForm.returnDate,
+            borrowStatus: borrowForm.borrowStatus,
+            remark: borrowForm.remark
+          });
+          
+          if (res.code === 200) {
+            ElMessage.success("鏂板鎴愬姛");
+            await loadBorrowList();
+            closeBorrowDia();
+          } else {
+            ElMessage.error(res.msg || "鏂板澶辫触");
+          }
+        }
+      } catch (error) {
+        ElMessage.error("鎿嶄綔澶辫触锛岃閲嶈瘯");
+      }
+    }
+  });
+};
+
+// 鍒犻櫎鍊熼槄璁板綍
+const handleDelete = (row) => {
+  ElMessageBox.confirm(
+    `纭畾瑕佸垹闄よ繖鏉″�熼槄璁板綍鍚楋紵`,
+    "鍒犻櫎鎻愮ず",
+    {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    }
+  ).then(async () => {
+    try {
+      const res = await deleteBorrow([row.id]);
+      if (res.code === 200) {
+        ElMessage.success("鍒犻櫎鎴愬姛");
+        await loadBorrowList();
+      } else {
+        ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+      }
+    } catch (error) {
+      ElMessage.error("鍒犻櫎澶辫触锛岃閲嶈瘯");
+    }
+  }).catch(() => {
+    ElMessage.info("宸插彇娑堝垹闄�");
+  });
+};
+
+// 鎵归噺鍒犻櫎
+const handleBatchDelete = () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑璁板綍");
+    return;
+  }
+  
+  ElMessageBox.confirm(
+    `纭畾瑕佸垹闄ら�変腑鐨� ${selectedRows.value.length} 鏉″�熼槄璁板綍鍚楋紵`,
+    "鎵归噺鍒犻櫎鎻愮ず",
+    {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    }
+  ).then(async () => {
+    try {
+      const selectedIds = selectedRows.value.map(row => row.id);
+      const res = await deleteBorrow(selectedIds);
+      if (res.code === 200) {
+        ElMessage.success("鎵归噺鍒犻櫎鎴愬姛");
+        await loadBorrowList();
+      } else {
+        ElMessage.error(res.msg || "鎵归噺鍒犻櫎澶辫触");
+      }
+    } catch (error) {
+      ElMessage.error("鎵归噺鍒犻櫎澶辫触锛岃閲嶈瘯");
+    }
+  }).catch(() => {
+    ElMessage.info("宸插彇娑堝垹闄�");
+  });
+};
+
+// 閫夋嫨鍙樺寲浜嬩欢
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+
+// 澶勭悊鍒嗛〉鍙樺寲
+const handlePagination = (current, size) => {
+  pagination.currentPage = current;
+  pagination.pageSize = size;
+  loadBorrowList();
+};
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+  initData();
+});
+</script>
+
+<style scoped>
+.borrow-view {
+  padding: 20px;
+}
+
+.search-container {
+  background: #ffffff;
+  padding: 20px;
+  border-radius: 8px;
+  margin-bottom: 20px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.search-form {
+  margin: 0;
+}
+
+.table-container {
+  background: #ffffff;
+  border-radius: 8px;
+  overflow: hidden;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.empty-data {
+  text-align: center;
+  color: #909399;
+  padding: 40px;
+  font-size: 14px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+:deep(.el-form-item__label) {
+  font-weight: 500;
+  color: #303133;
+}
+
+:deep(.el-input__wrapper) {
+  box-shadow: 0 0 0 1px #dcdfe6 inset;
+}
+
+:deep(.el-input__wrapper:hover) {
+  box-shadow: 0 0 0 1px #c0c4cc inset;
+}
+
+:deep(.el-input__wrapper.is-focus) {
+  box-shadow: 0 0 0 1px #409eff inset;
+}
+</style>
diff --git a/src/views/fileManagement/document/attachmentManager.vue b/src/views/fileManagement/document/attachmentManager.vue
new file mode 100644
index 0000000..a4e1d43
--- /dev/null
+++ b/src/views/fileManagement/document/attachmentManager.vue
@@ -0,0 +1,426 @@
+<template>
+  <el-dialog v-model="dialogVisible" title="闄勪欢绠$悊" width="60%" :before-close="handleClose">
+    <div class="attachment-manager">
+      <!-- 涓婁紶鍖哄煙 -->
+      <div class="upload-section">
+        <el-upload 
+          ref="uploadRef"
+          :action="uploadUrl" 
+          :headers="uploadHeaders"
+          :before-upload="handleBeforeUpload"
+          :on-success="handleUploadSuccess"
+          :on-error="handleUploadError"
+          :on-remove="handleRemove"
+          :file-list="fileList"
+          multiple
+          :limit="10"
+          :show-file-list="false"
+          :data="{documentId: currentDocumentId}"
+          accept=".doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.txt,.xml,.jpg,.jpeg,.png,.gif,.bmp,.rar,.zip,.7z"
+        >
+          <el-button type="primary" :icon="Plus">涓婁紶闄勪欢</el-button>
+          <template #tip>
+            <div class="el-upload__tip">
+              鏀寔鏍煎紡锛歞oc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z
+              <br>鍗曚釜鏂囦欢澶у皬涓嶈秴杩�50MB
+            </div>
+          </template>
+        </el-upload>
+      </div>
+
+      <!-- 闄勪欢鍒楄〃 -->
+      <div class="attachment-list">
+        <el-table :data="fileList" border height="400px" v-loading="loading">
+          <el-table-column label="搴忓彿" type="index" width="60" align="center" />
+          <el-table-column label="闄勪欢鍚嶇О" prop="name" min-width="200" show-overflow-tooltip />
+          <el-table-column label="鏂囦欢澶у皬" prop="size" width="100" align="center">
+            <template #default="scope">
+              {{ formatFileSize(scope.row.size) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="涓婁紶鏃堕棿" prop="uploadTime" width="160" align="center">
+            <template #default="scope">
+              {{ formatDate(scope.row.uploadTime) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="鐘舵��" prop="status" width="80" align="center">
+            <template #default="scope">
+              <el-tag :type="scope.row.status === 'success' ? 'success' : 'danger'" size="small">
+                {{ scope.row.status === 'success' ? '鎴愬姛' : '澶辫触' }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center">
+            <template #default="scope">
+              <el-button link type="primary" size="small" @click="previewFile(scope.row)">
+                棰勮
+              </el-button>
+              <el-button link type="primary" size="small" @click="downloadFile(scope.row)">
+                涓嬭浇
+              </el-button>
+              <el-button link type="danger" size="small" @click="removeFile(scope.row)">
+                鍒犻櫎
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+
+    <!-- 鏂囦欢棰勮缁勪欢 -->
+    <filePreview ref="filePreviewRef" />
+  </el-dialog>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Plus } from '@element-plus/icons-vue'
+import { getToken } from "@/utils/auth"
+import { addDocumentationFile, getDocumentationFileList, deleteDocumentationFile } from '@/api/fileManagement/document'
+import filePreview from '@/components/filePreview/index.vue'
+
+const props = defineProps({
+  // documentId 閫氳繃 open 浜嬩欢浼犲叆锛屼笉闇�瑕佷綔涓� props
+})
+
+const emit = defineEmits(['update:attachments'])
+
+const dialogVisible = ref(false)
+const loading = ref(false)
+const fileList = ref([])
+const uploadRef = ref()
+const filePreviewRef = ref()
+const currentDocumentId = ref('') // 鍐呴儴绠$悊褰撳墠鏂囨。ID
+
+// 涓婁紶閰嶇疆
+const uploadUrl = import.meta.env.VITE_APP_BASE_API + "/file/upload"
+const uploadHeaders = computed(() => ({
+  Authorization: "Bearer " + getToken()
+}))
+
+// 鎵撳紑寮规
+const open = (attachments = [], documentId = '') => {
+  dialogVisible.value = true
+  currentDocumentId.value = documentId // 璁剧疆褰撳墠鏂囨。ID
+  // 濡傛灉鏈夋枃妗D锛屽垯鍔犺浇闄勪欢鍒楄〃
+  if (documentId) {
+    loadAttachmentList(documentId)
+  } else {
+    fileList.value = attachments || []
+    // total.value = fileList.value.length // Removed total.value
+  }
+  // currentPage.value = 1 // Removed currentPage.value
+}
+
+// 鍔犺浇闄勪欢鍒楄〃
+const loadAttachmentList = async (documentId) => {
+  try {
+    loading.value = true
+    const params = {
+      page: 1, // Always load from page 1
+      size: 1000, // Load all for now
+      documentationId: documentId
+    }
+    
+    const res = await getDocumentationFileList(params)
+    if (res.code === 200) {
+      const records = res.data
+      
+      // 杞崲鏁版嵁鏍煎紡
+      fileList.value = records.map(item => ({
+        id: item.id,
+        name: item.name,
+        size: item.fileSize,
+        url: item.url,
+        uploadTime: item.createTime || item.uploadTime,
+        status: 'success',
+        uid: item.id
+      }))
+      
+      // total.value = totalCount // Removed total.value
+    } else {
+      ElMessage.error(res.msg || '鑾峰彇闄勪欢鍒楄〃澶辫触')
+      fileList.value = []
+      // total.value = 0 // Removed total.value
+    }
+  } catch (error) {
+    console.error('鑾峰彇闄勪欢鍒楄〃澶辫触:', error)
+    ElMessage.error('鑾峰彇闄勪欢鍒楄〃澶辫触')
+    fileList.value = []
+    // total.value = 0 // Removed total.value
+  } finally {
+    loading.value = false
+  }
+}
+
+// 鍏抽棴寮规
+const handleClose = () => {
+  dialogVisible.value = false
+  emit('update:attachments', fileList.value)
+}
+
+// 鏂囦欢涓婁紶鍓嶆牎楠�
+const handleBeforeUpload = (file) => {
+  // 妫�鏌ユ枃浠跺ぇ灏忥紙50MB锛�
+  const isLt50M = file.size / 1024 / 1024 < 50
+  if (!isLt50M) {
+    ElMessage.error('鏂囦欢澶у皬涓嶈兘瓒呰繃50MB!')
+    return false
+  }
+  
+  // 妫�鏌ユ枃浠剁被鍨�
+  const allowedTypes = [
+    'application/msword',
+    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+    'application/vnd.ms-excel',
+    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+    'application/vnd.ms-powerpoint',
+    'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+    'application/pdf',
+    'text/plain',
+    'text/xml',
+    'image/jpeg',
+    'image/png',
+    'image/gif',
+    'image/bmp',
+    'application/x-rar-compressed',
+    'application/zip',
+    'application/x-7z-compressed'
+  ]
+  
+  if (!allowedTypes.includes(file.type)) {
+    ElMessage.error('涓嶆敮鎸佺殑鏂囦欢绫诲瀷!')
+    return false
+  }
+  
+  return true
+}
+
+// 鏂囦欢涓婁紶鎴愬姛
+const handleUploadSuccess = (response, file, fileList) => {
+  console.log('鏂囦欢涓婁紶鎴愬姛鍝嶅簲:', response);
+  console.log('鏂囦欢淇℃伅:', file);
+  
+  if (response.code === 200) {
+    // 鏋勫缓闄勪欢鏁版嵁 - 纭繚姝g‘鑾峰彇URL
+    const attachmentData = {
+      name: file.name,
+      url: response.data.url || response.data.path || response.data.tempPath || file.url,
+      fileSize: file.size,
+      documentationId: currentDocumentId.value
+    };
+    
+    console.log('鏋勫缓鐨勯檮浠舵暟鎹�:', attachmentData);
+    
+    // 璋冪敤淇濆瓨闄勪欢鎺ュ彛
+    saveAttachment(attachmentData, file, fileList);
+  } else {
+    ElMessage.error(response.msg || '鏂囦欢涓婁紶澶辫触')
+  }
+}
+
+// 淇濆瓨闄勪欢淇℃伅
+const saveAttachment = async (attachmentData, file, fileList) => {
+  try {
+    console.log('寮�濮嬩繚瀛橀檮浠讹紝鏁版嵁:', attachmentData);
+    
+    // 纭繚URL瀛楁瀛樺湪涓旀湁鏁�
+    if (!attachmentData.url) {
+      console.error('闄勪欢URL涓虹┖锛屾棤娉曚繚瀛�');
+      ElMessage.error('鏂囦欢URL鑾峰彇澶辫触锛屾棤娉曚繚瀛橀檮浠�');
+      return;
+    }
+    
+    const res = await addDocumentationFile(attachmentData);
+    console.log('淇濆瓨闄勪欢鎺ュ彛鍝嶅簲:', res);
+    
+    if (res.code === 200) {
+      const newFile = {
+        id: res.data.id || Date.now(),
+        name: attachmentData.name,
+        size: attachmentData.fileSize,
+        url: attachmentData.url,
+        uploadTime: new Date().toISOString(),
+        status: 'success',
+        uid: file.uid
+      }
+      
+      console.log('鍒涘缓鐨勬柊鏂囦欢瀵硅薄:', newFile);
+      fileList.push(newFile)
+      ElMessage.success('鏂囦欢涓婁紶骞朵繚瀛樻垚鍔�')
+      
+      // 淇濆瓨鎴愬姛鍚庡埛鏂伴檮浠跺垪琛�
+      if (currentDocumentId.value) {
+        await loadAttachmentList(currentDocumentId.value);
+      }
+    } else {
+      ElMessage.error(res.msg || '淇濆瓨闄勪欢淇℃伅澶辫触')
+      // 淇濆瓨澶辫触鏃剁Щ闄ゆ枃浠�
+      const index = fileList.findIndex(item => item.uid === file.uid)
+      if (index > -1) {
+        fileList.splice(index, 1)
+      }
+    }
+  } catch (error) {
+    console.error('淇濆瓨闄勪欢澶辫触:', error)
+    ElMessage.error('淇濆瓨闄勪欢淇℃伅澶辫触')
+    // 淇濆瓨澶辫触鏃剁Щ闄ゆ枃浠�
+    const index = fileList.findIndex(item => item.uid === file.uid)
+    if (index > -1) {
+      fileList.splice(index, 1)
+    }
+  }
+}
+
+// 鏂囦欢涓婁紶澶辫触
+const handleUploadError = (error, file, fileList) => {
+  console.error('鏂囦欢涓婁紶澶辫触:', error);
+  console.error('澶辫触鐨勬枃浠�:', file);
+  console.error('褰撳墠鏂囦欢鍒楄〃:', fileList);
+  
+  ElMessage.error('鏂囦欢涓婁紶澶辫触锛岃妫�鏌ョ綉缁滆繛鎺ユ垨鏂囦欢鏍煎紡')
+}
+
+// 绉婚櫎鏂囦欢
+const handleRemove = (file, fileList) => {
+  const index = fileList.findIndex(item => item.uid === file.uid)
+  if (index > -1) {
+    fileList.splice(index, 1)
+    // total.value = fileList.length // Removed total.value
+  }
+}
+
+// 鍒犻櫎鏂囦欢
+const removeFile = (file) => {
+  ElMessageBox.confirm(`纭畾瑕佸垹闄ゆ枃浠� "${file.name}" 鍚楋紵`, '鍒犻櫎纭', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(async () => {
+    try {
+      // 璋冪敤鍒犻櫎鎺ュ彛
+      const res = await deleteDocumentationFile([file.id]);
+      if (res.code === 200) {
+        // 浠庢湰鍦板垪琛ㄤ腑绉婚櫎
+        const index = fileList.value.findIndex(item => item.id === file.id);
+        if (index > -1) {
+          fileList.value.splice(index, 1);
+        }
+        ElMessage.success('鍒犻櫎鎴愬姛');
+        
+        // 濡傛灉鏈夋枃妗D锛屽埛鏂伴檮浠跺垪琛�
+        if (currentDocumentId.value) {
+          await loadAttachmentList(currentDocumentId.value);
+        }
+      } else {
+        ElMessage.error(res.msg || '鍒犻櫎澶辫触');
+      }
+    } catch (error) {
+      console.error('鍒犻櫎闄勪欢澶辫触:', error);
+      ElMessage.error('鍒犻櫎闄勪欢澶辫触');
+    }
+  }).catch(() => {
+    // 鍙栨秷鍒犻櫎
+  })
+}
+
+// 棰勮鏂囦欢
+const previewFile = (file) => {
+  if (file.url) {
+    filePreviewRef.value.open(file.url)
+  } else {
+    ElMessage.warning('鏂囦欢鍦板潃鏃犳晥锛屾棤娉曢瑙�')
+  }
+}
+
+// 涓嬭浇鏂囦欢
+const downloadFile = (file) => {
+  if (file.url) {
+    // 鍒涘缓涓嬭浇閾炬帴
+    const link = document.createElement('a')
+    link.href = file.url
+    link.download = file.name
+    document.body.appendChild(link)
+    link.click()
+    document.body.removeChild(link)
+    ElMessage.success('寮�濮嬩笅杞芥枃浠�')
+  } else {
+    ElMessage.warning('鏂囦欢鍦板潃鏃犳晥锛屾棤娉曚笅杞�')
+  }
+}
+
+// 鏍煎紡鍖栨枃浠跺ぇ灏�
+const formatFileSize = (bytes) => {
+  if (bytes === 0) return '0 B'
+  const k = 1024
+  const sizes = ['B', 'KB', 'MB', 'GB']
+  const i = Math.floor(Math.log(bytes) / Math.log(k))
+  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
+}
+
+// 鏍煎紡鍖栨棩鏈�
+const formatDate = (dateString) => {
+  if (!dateString) return ''
+  const date = new Date(dateString)
+  return date.toLocaleString('zh-CN', {
+    year: 'numeric',
+    month: '2-digit',
+    day: '2-digit',
+    hour: '2-digit',
+    minute: '2-digit'
+  })
+}
+
+// 娴嬭瘯鏂囦欢涓婁紶
+const testUpload = () => {
+  console.log('褰撳墠鏂囨。ID:', currentDocumentId.value);
+  console.log('涓婁紶URL:', uploadUrl);
+  console.log('涓婁紶Headers:', uploadHeaders.value);
+}
+
+// 鏆撮湶鏂规硶
+defineExpose({
+  open,
+  loadAttachmentList,
+  testUpload
+})
+</script>
+
+<style scoped>
+.attachment-manager {
+  padding: 20px;
+}
+
+.upload-section {
+  margin-bottom: 20px;
+  padding: 20px;
+  background-color: #f8f9fa;
+  border-radius: 8px;
+  border: 2px dashed #d9d9d9;
+}
+
+.upload-section:hover {
+  border-color: #409eff;
+}
+
+.attachment-list {
+  margin-bottom: 20px;
+}
+
+.el-upload__tip {
+  margin-top: 10px;
+  color: #666;
+  font-size: 12px;
+  line-height: 1.5;
+}
+
+:deep(.el-upload) {
+  width: 100%;
+}
+
+:deep(.el-upload-dragger) {
+  width: 100%;
+  height: 120px;
+}
+</style>
diff --git a/src/views/fileManagement/document/index.vue b/src/views/fileManagement/document/index.vue
new file mode 100644
index 0000000..7a8b27e
--- /dev/null
+++ b/src/views/fileManagement/document/index.vue
@@ -0,0 +1,1262 @@
+<template>
+  <div class="app-container document-view">
+    <div class="left">
+      <div>
+        <el-input
+          v-model="search"
+          style="width: 210px"
+          placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�"
+          @change="searchFilter"
+          @clear="searchFilter"
+          clearable
+          prefix-icon="Search"
+        />
+        <el-button
+          type="primary"
+          @click="openCategoryDia('addOne')"
+          style="margin-left: 10px"
+          >鏂板鍒嗙被</el-button
+        >
+      </div>
+      <div ref="containerRef">
+        <el-tree
+          ref="tree"
+          v-loading="treeLoad"
+          :data="categoryList"
+          @node-click="handleNodeClick"
+          :expand-on-click-node="false"
+          default-expand-all
+          :default-expanded-keys="expandedKeys"
+          :draggable="true"
+          :filter-node-method="filterNode"
+          :props="{ children: 'children', label: 'category' }"
+          highlight-current
+          node-key="id"
+          style="
+            height: calc(100vh - 190px);
+            overflow-y: scroll;
+            scrollbar-width: none;
+            margin-top: 10px;
+          "
+        >
+          <template #default="{ node, data }">
+            <div class="custom-tree-node">
+              <span class="tree-node-content">
+                <el-icon class="orange-icon">
+                  <component :is="data.children && data.children.length > 0
+                  ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" />
+                </el-icon>
+                {{ data.category }}
+              </span>
+              <div>
+                <el-button
+                  type="primary"
+                  link
+                  @click="openCategoryDia('edit', data)"
+                >
+                  缂栬緫
+                </el-button>
+                <el-button 
+                  type="primary" 
+                  link 
+                  @click="openCategoryDia('addSub', data)"
+                  v-if="node.level < 2"
+                >
+                  娣诲姞瀛愬垎绫�
+                </el-button>
+                <el-button
+                  v-if="!node.childNodes.length"
+                  style="margin-left: 4px"
+                  type="danger"
+                  link
+                  @click="removeCategory(node, data)"
+                >
+                  鍒犻櫎
+                </el-button>
+              </div>
+            </div>
+          </template>
+        </el-tree>
+      </div>
+    </div>
+    <div class="right">
+      <div style="margin-bottom: 10px" v-if="isShowButton">
+        <el-button type="primary" @click="openDocumentDia('add')">
+          鏂板鏂囨。
+        </el-button>
+        <el-button
+          type="danger"
+          @click="handleDelete"
+          style="margin-left: 10px"
+          plain
+          :disabled="selectedRows.length === 0"
+        >
+          鍒犻櫎 ({{ selectedRows.length }})
+        </el-button>
+      </div>
+      <div class="table-container">
+        
+        <!-- PIMTable 缁勪欢 -->
+        <PIMTable
+          :table-data="documentList"
+          :column="tableColumns"
+          :is-selection="true"
+          :border="true"
+          :table-loading="tableLoading"
+          :page="{
+            current: pagination.currentPage,
+            size: pagination.pageSize,
+            total: pagination.total,
+            layout: 'total, sizes, prev, pager, next, jumper'
+          }"
+          @selection-change="handleSelectionChange"
+          @pagination="handlePagination"
+        />
+      </div>
+    </div>
+
+    <!-- 鍒嗙被鏂板/淇敼瀵硅瘽妗� -->
+    <el-dialog v-model="categoryDia" title="鍒嗙被" width="400px" @keydown.enter.prevent>
+      <el-form
+        :model="categoryForm"
+        label-width="140px"
+        label-position="top"
+        :rules="categoryRules"
+        ref="categoryFormRef"
+      >
+        <el-row :gutter="30">
+          <el-col :span="24" v-if="categoryOperationType === 'addSub'">
+            <el-form-item label="鐖跺垎绫伙細" prop="parentName">
+              <el-input
+                v-model="categoryForm.parentName"
+                placeholder="鐖跺垎绫诲悕绉�"
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="鍒嗙被鍚嶇О锛�" prop="category">
+              <el-input
+                v-model="categoryForm.category"
+                placeholder="璇疯緭鍏ュ垎绫诲悕绉�"
+                clearable
+                @keydown.enter.prevent
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitCategoryForm">纭</el-button>
+          <el-button @click="closeCategoryDia">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 鏂囨。鏂板/淇敼瀵硅瘽妗� -->
+    <el-dialog
+      v-model="documentDia"
+      :title="documentOperationType === 'add' ? '鏂板鏂囨。' : '缂栬緫鏂囨。'"
+      width="600px"
+      @close="closeDocumentDia"
+      @keydown.enter.prevent
+    >
+      <el-form
+        :model="documentForm"
+        label-width="140px"
+        label-position="top"
+        :rules="documentRules"
+        ref="documentFormRef"
+      >
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鏂囨。鍚嶇О锛�" prop="docName">
+              <el-input v-model="documentForm.docName" placeholder="璇疯緭鍏�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="骞村害锛�" prop="year">
+              <el-date-picker
+                v-model="documentForm.year"
+                type="year"
+                value-format="YYYY"
+                format="YYYY"
+                placeholder="閫夋嫨骞村害"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鏂囨。缂栧彿锛�" prop="docNumber">
+              <el-input v-model="documentForm.docNumber" placeholder="璇疯緭鍏�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="璐d换浜猴細" prop="responsiblePerson">
+              <el-input v-model="documentForm.responsiblePerson" placeholder="璇疯緭鍏�" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鏂囨。鍒嗙被锛�" prop="documentClassificationId">
+              <el-select v-model="documentForm.documentClassificationId" placeholder="璇烽�夋嫨鏂囨。鍒嗙被" style="width: 100%">
+                <el-option 
+                  v-for="item in categoryList" 
+                  :key="item.id" 
+                  :label="item.category" 
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏂囨。鏀剧疆浣嶇疆锛�" prop="warehouseGoodsShelvesRowcolId">
+              <el-tree-select
+                v-model="documentForm.warehouseGoodsShelvesRowcolId"
+                :data="locationTree"
+                placeholder="璇烽�夋嫨鏂囦欢鏀剧疆浣嶇疆"
+                clearable
+                check-strictly
+                :render-after-expand="false"
+                :props="{ children: 'children', label: 'label', value: 'value' }"
+                style="width: 100%"
+                @change="handleLocationChange"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鏂囨。鏃ユ湡锛�" prop="docData">
+              <el-date-picker
+                v-model="documentForm.docData"
+                type="date"
+                value-format="YYYY-MM-DD"
+                format="YYYY-MM-DD"
+                placeholder="閫夋嫨鏃ユ湡"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="淇濈鏈熼檺锛�" prop="retentionPeriod">
+              <el-select v-model="documentForm.retentionPeriod" placeholder="璇烽�夋嫨">
+                <el-option 
+                  v-for="item in retention_period" 
+                  :key="item.value" 
+                  :label="item.label" 
+                  :value="item.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="淇濆瘑绾у埆锛�" prop="securityLevel">
+              <el-select v-model="documentForm.securityLevel" placeholder="璇烽�夋嫨">
+                <el-option 
+                  v-for="item in confidentiality_level" 
+                  :key="item.value" 
+                  :label="item.label" 
+                  :value="item.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍒嗘暟锛�" prop="copyCount">
+              <el-input v-model="documentForm.copyCount" placeholder="璇疯緭鍏�" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="椤垫暟锛�" prop="pageCount">
+              <el-input v-model="documentForm.pageCount" placeholder="璇疯緭鍏�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏂囨。绫诲埆锛�" prop="docCategory">
+              <el-select v-model="documentForm.docCategory" placeholder="璇烽�夋嫨">
+                <el-option 
+                  v-for="item in document_type" 
+                  :key="item.value" 
+                  :label="item.label" 
+                  :value="item.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鏂囨。绉嶇被锛�" prop="docType">
+              <el-select v-model="documentForm.docType" placeholder="璇烽�夋嫨">
+                <el-option 
+                  v-for="item in document_categories" 
+                  :key="item.value" 
+                  :label="item.label" 
+                  :value="item.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="绱ф�ョ▼搴︼細" prop="urgencyLevel">
+              <el-select v-model="documentForm.urgencyLevel" placeholder="璇烽�夋嫨">
+                <el-option 
+                  v-for="item in document_urgency" 
+                  :key="item.value" 
+                  :label="item.label" 
+                  :value="item.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鏂囨。鐘舵�侊細" prop="docStatus">
+              <el-select v-model="documentForm.docStatus" placeholder="璇烽�夋嫨">
+                <el-option 
+                  v-for="item in document_status" 
+                  :key="item.value" 
+                  :label="item.label" 
+                  :value="item.value"
+                />
+              </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 
+                v-model="documentForm.remark" 
+                type="textarea" 
+                :rows="3"
+                placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" 
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+       </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitDocumentForm">纭</el-button>
+          <el-button @click="closeDocumentDia">鍙栨秷</el-button>
+        </div>
+             </template>
+     </el-dialog>
+             <AttachmentManager ref="attachmentManagerRef" />
+     </div>
+   </template>
+
+<script setup>
+import { ref, reactive, onMounted, getCurrentInstance, toRefs, watch } from "vue";
+import { ElMessageBox, ElMessage } from "element-plus";
+import { ArrowRight, Folder, FolderOpened, Tickets, Document } from '@element-plus/icons-vue';
+import PIMTable from '@/components/PIMTable/PIMTable.vue';
+import { getToken } from "@/utils/auth";
+import { getCategoryTree, addCategory, updateCategory, deleteCategory, getDocumentList, addDocument, updateDocument, deleteDocument, getDocumentDetail, searchDocument, getWarehouseStructure } from '@/api/fileManagement/document'
+import { getWarehouseList } from '@/api/fileManagement/bookshelf'
+import AttachmentManager from './attachmentManager.vue'
+import { useDict } from '@/utils/dict'
+
+const { proxy } = getCurrentInstance();
+const tree = ref(null);
+const containerRef = ref(null);
+
+// 浣跨敤瀛楀吀鏁版嵁
+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')
+
+// 鐩戝惉瀛楀吀鏁版嵁鍙樺寲
+watch([confidentiality_level, document_urgency, document_status, document_type, document_categories, retention_period], () => {
+  // 瀛楀吀鏁版嵁宸叉洿鏂�
+}, { immediate: true, deep: true });
+
+const categoryDia = ref(false);
+const documentDia = ref(false);
+const categoryOperationType = ref("");
+const documentOperationType = ref("");
+const search = ref("");
+const currentId = ref("");
+const currentParentId = ref("");
+const treeLoad = ref(false);
+const categoryList = ref([]);
+const expandedKeys = ref([]);
+const documentList = ref([]);
+const isShowButton = ref(false);
+const selectedRows = ref([]);
+const selectAll = ref(false);
+const isIndeterminate = ref(false);
+const tableLoading = ref(false);
+const attachmentManagerRef = ref(null);
+
+// 鏂囦欢涓婁紶閰嶇疆
+const upload = reactive({
+  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+  headers: { Authorization: "Bearer " + getToken() },
+});
+
+// 浣嶇疆鏍戞暟鎹�
+const locationTree = ref([]);
+
+// 琛ㄦ牸鍒楅厤缃�
+const tableColumns = ref([
+  { label: '鏂囨。鍚嶇О', prop: 'docName', width: '200' },
+  { label: '鏂囨。缂栧彿', prop: 'docNumber', width: '120' },
+  { label: '骞村害', prop: 'year', width: '80' },
+  { label: '璐d换浜�', prop: 'responsiblePerson', width: '100' },
+  { 
+    label: '鏂囨。鏀剧疆浣嶇疆', 
+    prop: 'warehouseGoodsShelvesRowcolId', 
+    width: '150',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      return getLocationName(params);
+    }
+  },
+  { label: '鏂囨。鏃ユ湡', prop: 'docData', width: '120' },
+  { 
+    label: '淇濈鏈熼檺', 
+    prop: 'retentionPeriod', 
+    width: '100',
+    dataType: 'tag',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      if (!retention_period.value || retention_period.value.length === 0) {
+        return params;
+      }
+      const item = retention_period.value.find(item => item.value == params);
+      return item ? item.label : params;
+    },
+    formatType: (params) => {
+      if (params === null || params === undefined || params === '') return 'info';
+      if (!retention_period.value || retention_period.value.length === 0) {
+        return 'info';
+      }
+      const item = retention_period.value.find(item => item.value == params);
+      const validTypes = ['success', 'warning', 'danger', 'info'];
+      return item && validTypes.includes(item.elTagType) ? item.elTagType : 'info';
+    }
+  },
+  { 
+    label: '淇濆瘑绾у埆', 
+    prop: 'securityLevel', 
+    width: '80',
+    dataType: 'tag',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      if (!confidentiality_level.value || confidentiality_level.value.length === 0) {
+        return params;
+      }
+      const item = confidentiality_level.value.find(item => item.value == params);
+      return item ? item.label : params;
+    },
+    formatType: (params) => {
+      if (params === null || params === undefined || params === '') return 'info';
+      if (!confidentiality_level.value || confidentiality_level.value.length === 0) {
+        return 'info';
+      }
+      const item = confidentiality_level.value.find(item => item.value == params);
+      const validTypes = ['success', 'warning', 'danger', 'info'];
+      return item && validTypes.includes(item.elTagType) ? item.elTagType : 'info';
+    }
+  },
+  { label: '鍒嗘暟', prop: 'copyCount', width: '80' },
+  { label: '椤垫暟', prop: 'pageCount', width: '80' },
+  { 
+    label: '鏂囨。绫诲埆', 
+    prop: 'docCategory', 
+    width: '100',
+    dataType: 'tag',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      if (!document_type.value || document_type.value.length === 0) {
+        return params;
+      }
+      const item = document_type.value.find(item => item.value == params);
+      return item ? item.label : params;
+    },
+    formatType: (params) => {
+      if (params === null || params === undefined || params === '') return 'info';
+      if (!document_type.value || document_type.value.length === 0) {
+        return 'info';
+      }
+      const item = document_type.value.find(item => item.value == params);
+      const validTypes = ['success', 'warning', 'danger', 'info'];
+      return item && validTypes.includes(item.elTagType) ? item.elTagType : 'info';
+    }
+  },
+  { 
+    label: '鏂囨。绉嶇被', 
+    prop: 'docType', 
+    width: '100',
+    dataType: 'tag',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      if (!document_categories.value || document_categories.value.length === 0) {
+        return params;
+      }
+      const item = document_categories.value.find(item => item.value == params);
+      return item ? item.label : params;
+    },
+    formatType: (params) => {
+      if (params === null || params === undefined || params === '') return 'info';
+      if (!document_categories.value || document_categories.value.length === 0) {
+        return 'info';
+      }
+      const item = document_categories.value.find(item => item.value == params);
+      const validTypes = ['success', 'warning', 'danger', 'info'];
+      return item && validTypes.includes(item.elTagType) ? item.elTagType : 'info';
+    }
+  },
+  { 
+    label: '绱ф�ョ▼搴�', 
+    prop: 'urgencyLevel', 
+    width: '100',
+    dataType: 'tag',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      if (!document_urgency.value || document_urgency.value.length === 0) {
+        return params;
+      }
+      const item = document_urgency.value.find(item => item.value == params);
+      return item ? item.label : params;
+    },
+    formatType: (params) => {
+      if (params === null || params === undefined || params === '') return 'info';
+      if (!document_urgency.value || document_urgency.value.length === 0) {
+        return 'info';
+      }
+      const item = document_urgency.value.find(item => item.value == params);
+      const validTypes = ['success', 'warning', 'danger', 'info'];
+      return item && validTypes.includes(item.elTagType) ? item.elTagType : 'info';
+    }
+  },
+  { 
+    label: '鏂囨。鐘舵��', 
+    prop: 'docStatus', 
+    width: '100',
+    dataType: 'tag',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      if (!document_status.value || document_status.value.length === 0) {
+        return params;
+      }
+      const item = document_status.value.find(item => item.value == params);
+      return item ? item.label : params;
+    },
+    formatType: (params) => {
+      if (params === null || params === undefined || params === '') return 'info';
+      if (!document_status.value || document_status.value.length === 0) {
+        return 'info';
+      }
+      const item = document_status.value.find(item => item.value == params);
+      const validTypes = ['success', 'warning', 'danger', 'info'];
+      return item && validTypes.includes(item.elTagType) ? item.elTagType : 'info';
+    }
+  },
+  { 
+    dataType: "action",
+    label: "鎿嶄綔",
+    align: "center",
+    fixed: 'right',
+    width: '150',
+    operation: [
+      {
+        name: "缂栬緫",
+        type: "text",
+        clickFun: (row) => {
+          openDocumentDia('edit', row)
+        },
+      },
+      {
+        name: "闄勪欢",
+        type: "text",
+        clickFun: (row) => {
+          openAttachment(row)
+        },
+      },
+    ],
+  }
+]);
+
+// 鍒嗙被琛ㄥ崟
+const categoryForm = reactive({
+  category: "",
+  parentId: "",
+  parentName: "",
+});
+
+const categoryRules = reactive({
+  category: [{ required: true, message: "璇疯緭鍏ュ垎绫诲悕绉�", trigger: "blur" }],
+});
+
+// 鏂囨。琛ㄥ崟
+const documentForm = reactive({
+  id: "",
+  documentClassificationId: "",
+  docName: "",
+  docNumber: "",
+  year: "",
+  responsiblePerson: "",
+  warehouseGoodsShelvesRowcolId: "",
+  docData: "",
+  retentionPeriod: "",
+  securityLevel: "",
+  copyCount: "",
+  pageCount: "",
+  docCategory: "",
+  docType: "",
+  urgencyLevel: "",
+  docStatus: "",
+  remark: "",
+  attachments: [], // 鏂板闄勪欢鏁扮粍
+});
+
+const documentRules = reactive({
+  docName: [{ required: true, message: "璇疯緭鍏ユ枃妗e悕绉�", trigger: "blur" }],
+  docNumber: [{ required: true, message: "璇疯緭鍏ユ枃妗g紪鍙�", trigger: "blur" }],
+  year: [{ required: true, message: "璇烽�夋嫨骞村害", trigger: "change" }],
+  documentClassificationId: [{ required: true, message: "璇烽�夋嫨鏂囨。鍒嗙被", trigger: "change" }],
+  warehouseGoodsShelvesRowcolId: [{ required: true, message: "璇烽�夋嫨鏂囨。鏀剧疆浣嶇疆", trigger: "change" }],
+});
+
+// 鍒嗛〉鐩稿叧
+const pagination = reactive({
+  currentPage: 1,
+  pageSize: 10,
+  total: 0,
+});
+
+// 鍒濆鍖栧垎绫绘爲鏁版嵁
+const initCategoryTree = async() => {
+  try {
+    treeLoad.value = true;
+    const res = await getCategoryTree();
+    if (res.code === 200) {
+      categoryList.value = res.data || [];
+      
+      // 璁剧疆灞曞紑鐨勮妭鐐�
+      expandedKeys.value = [];
+      categoryList.value.forEach((item) => {
+        if (item.id) {
+          expandedKeys.value.push(item.id);
+        }
+      });
+    } else {
+      ElMessage.error(res.msg || "鑾峰彇鍒嗙被鏍戝け璐�");
+    }
+  } catch (error) {
+    ElMessage.error("鑾峰彇鍒嗙被鏍戝け璐ワ紝璇烽噸璇�");
+  } finally {
+    treeLoad.value = false;
+  }
+};
+
+// 鍒濆鍖栦粨搴撲綅缃暟鎹�
+const initLocationTree = async() => {
+  try {
+    const res = await getWarehouseList();
+    if (res.code === 200) {
+      // 杞崲鏁版嵁鏍煎紡锛岄�傞厤el-tree-select缁勪欢
+      locationTree.value = transformWarehouseData(res.data || []);
+    } else {
+      ElMessage.error(res.msg || "鑾峰彇浠撳簱浣嶇疆澶辫触");
+    }
+  } catch (error) {
+    ElMessage.error("鑾峰彇浠撳簱浣嶇疆澶辫触锛岃閲嶈瘯");
+  }
+};
+
+// 杞崲浠撳簱鏁版嵁鏍煎紡
+const transformWarehouseData = (data) => {
+  return data.map(item => ({
+    id: item.id,
+    label: item.name || item.warehouseName || item.label,
+    value: item.id,
+    children: item.children ? transformWarehouseData(item.children) : []
+  }));
+};
+
+// 鏍规嵁ID鑾峰彇浣嶇疆鍚嶇О
+const getLocationName = (locationId) => {
+  if (!locationId || !locationTree.value || locationTree.value.length === 0) {
+    return locationId || '-';
+  }
+  
+  const findLocation = (tree, id) => {
+    for (let item of tree) {
+      if (item.value === locationId || item.id === locationId) {
+        return item.label;
+      }
+      if (item.children && item.children.length > 0) {
+        const result = findLocation(item.children, id);
+        if (result) return result;
+      }
+    }
+    return null;
+  };
+  
+  const locationName = findLocation(locationTree.value, locationId);
+  return locationName || locationId;
+};
+
+// 杩囨护鍒嗙被鏍�
+const searchFilter = () => {
+  if (proxy.$refs.tree) {
+    proxy.$refs.tree.filter(search.value);
+  }
+};
+
+// 鎵撳紑鍒嗙被寮规
+const openCategoryDia = (type, data) => {
+  categoryOperationType.value = type;
+  categoryDia.value = true;
+  categoryForm.category = "";
+  categoryForm.parentId ="";
+  categoryForm.parentName = "";
+  
+  if (type === "edit") {
+    categoryForm.category = data.category;
+    // 淇濆瓨褰撳墠缂栬緫鐨勫垎绫籌D
+    currentId.value = data.id;
+  } else if (type === "addSub") {
+    categoryForm.parentId = data.id;
+    categoryForm.parentName = data.category;
+  }
+};
+
+// 鎵撳紑鏂囨。寮规
+const openDocumentDia = (type, data) => {
+  documentOperationType.value = type;
+  documentDia.value = true;
+  
+  if (type === "edit") {
+    // 缂栬緫妯″紡锛屽姞杞界幇鏈夋暟鎹�
+    Object.assign(documentForm, data);
+    documentForm.retentionPeriod = String(documentForm.retentionPeriod)
+    documentForm.securityLevel = String(documentForm.securityLevel)
+    documentForm.docCategory = String(documentForm.docCategory)
+    documentForm.docType = String(documentForm.docType)
+    documentForm.urgencyLevel = String(documentForm.urgencyLevel)
+    documentForm.docStatus = String(documentForm.docStatus)
+    
+    // 鍔犺浇闄勪欢淇℃伅
+    if (data.attachments) {
+      documentForm.attachments = [...data.attachments];
+    } else {
+      documentForm.attachments = [];
+    }
+  } else {
+    // 鏂板妯″紡锛屾竻绌鸿〃鍗�
+    Object.keys(documentForm).forEach(key => {
+      documentForm[key] = "";
+    });
+    documentForm.attachments = []; // 鏂板妯″紡涓嬩篃娓呯┖闄勪欢
+    // 璁剧疆榛樿鍊� - 浣跨敤瀛楀吀鏁版嵁鐨勭涓�涓�夐」浣滀负榛樿鍊�
+    if (document_status.value && document_status.value.length > 0) {
+      documentForm.docStatus = document_status.value[0].value;
+    }
+    if (document_urgency.value && document_urgency.value.length > 0) {
+      documentForm.urgencyLevel = document_urgency.value[0].value;
+    }
+  }
+};
+
+// 鎻愪氦鍒嗙被琛ㄥ崟
+const submitCategoryForm = () => {
+  proxy.$refs.categoryFormRef.validate(async (valid) => {
+    if (valid) {
+      try {
+        if (categoryOperationType.value === "addSub") {
+          // 娣诲姞瀛愬垎绫�
+          const res = await addCategory({
+            category: categoryForm.category,
+            parentId: categoryForm.parentId
+          });
+          if (res.code === 200) {
+            ElMessage.success("娣诲姞瀛愬垎绫绘垚鍔�");
+            // 閲嶆柊鍔犺浇鍒嗙被鏍�
+            await initCategoryTree();
+          } else {
+            ElMessage.error(res.msg || "娣诲姞瀛愬垎绫诲け璐�");
+          }
+        } else if (categoryOperationType.value === "edit") {
+          // 缂栬緫鍒嗙被
+          const res = await updateCategory({
+            id: currentId.value,
+            category: categoryForm.category
+          });
+          if (res.code === 200) {
+            ElMessage.success("缂栬緫鍒嗙被鎴愬姛");
+            // 閲嶆柊鍔犺浇鍒嗙被鏍�
+            await initCategoryTree();
+          } else {
+            ElMessage.error(res.msg || "缂栬緫鍒嗙被澶辫触");
+          }
+        } else {
+          // 鏂板椤剁骇鍒嗙被
+          const res = await addCategory({
+            category: categoryForm.category,
+            parentId: null
+          });
+          if (res.code === 200) {
+            ElMessage.success("鏂板鍒嗙被鎴愬姛");
+            // 閲嶆柊鍔犺浇鍒嗙被鏍�
+            await initCategoryTree();
+          } else {
+            ElMessage.error(res.msg || "鏂板鍒嗙被澶辫触");
+          }
+        }
+        
+        closeCategoryDia();
+      } catch (error) {
+        ElMessage.error("鎿嶄綔澶辫触锛岃閲嶈瘯");
+      }
+    }
+  });
+};
+
+// 鍏抽棴鍒嗙被寮规
+const closeCategoryDia = () => {
+  proxy.$refs.categoryFormRef.resetFields();
+  categoryForm.parentId = "";
+  categoryForm.parentName = "";
+  categoryDia.value = false;
+};
+
+// 鍒犻櫎鍒嗙被
+const removeCategory = (node, data) => {
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(async () => {
+      try {
+        const res = await deleteCategory([data.id]);
+        if (res.code === 200) {
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          // 閲嶆柊鍔犺浇鍒嗙被鏍�
+          await initCategoryTree();
+        } else {
+          ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+        }
+      } catch (error) {
+        ElMessage.error("鍒犻櫎澶辫触锛岃閲嶈瘯");
+      }
+    })
+    .catch(() => {
+      ElMessage("宸插彇娑�");
+    });
+};
+
+// 閫夋嫨鍒嗙被
+const handleNodeClick = (val, node, el) => {
+  // 鍒ゆ柇鏄惁涓哄彾瀛愯妭鐐�
+  isShowButton.value = !(val.children && val.children.length > 0);
+  // 鍙湁鍙跺瓙鑺傜偣鎵嶆墽琛屼互涓嬮�昏緫
+  currentId.value = val.id;
+  currentParentId.value = val.parentId;
+  
+  // 娓呯┖閫夋嫨鐘舵��
+  selectedRows.value = [];
+  selectAll.value = false;
+  isIndeterminate.value = false;
+  
+  // 閲嶇疆鍒嗛〉
+  pagination.currentPage = 1;
+  pagination.total = 0;
+  
+  // 鍔犺浇鏂囨。鍒楄〃
+  if (isShowButton.value) {
+    loadDocumentList();
+  } else {
+    // 濡傛灉涓嶆槸鍙跺瓙鑺傜偣锛屾竻绌烘枃妗e垪琛�
+    documentList.value = [];
+  }
+};
+
+// 鎻愪氦鏂囨。琛ㄥ崟
+const submitDocumentForm = () => {
+  proxy.$refs.documentFormRef.validate(async (valid) => {
+    if (valid) {
+      try {
+        // 鏋勫缓鎻愪氦鏁版嵁
+        const submitData = {
+          ...documentForm,
+          // 璁剧疆褰撳墠閫変腑鐨勫垎绫籌D
+          documentClassificationId: currentId.value || documentForm.documentClassificationId,
+          // 娣诲姞闄勪欢淇℃伅
+          // attachments: documentForm.attachments
+        };
+        
+        if (documentOperationType.value === "edit") {
+          // 缂栬緫妯″紡锛屾洿鏂扮幇鏈夋暟鎹�
+          const res = await updateDocument(submitData);
+          if (res.code === 200) {
+            ElMessage.success("缂栬緫鎴愬姛");
+            // 閲嶆柊鍔犺浇鏂囨。鍒楄〃
+            await loadDocumentList();
+            // 鍒锋柊闄勪欢鍒楄〃
+            if (attachmentManagerRef.value && documentForm.id) {
+              attachmentManagerRef.value.loadAttachmentList(documentForm.id);
+            }
+          } else {
+            ElMessage.error(res.msg || "缂栬緫澶辫触");
+          }
+        } else {
+          // 鏂板妯″紡锛屾坊鍔犳柊鏁版嵁
+          const res = await addDocument(submitData);
+          if (res.code === 200) {
+            ElMessage.success("鏂板鎴愬姛");
+            // 閲嶆柊鍔犺浇鏂囨。鍒楄〃
+            await loadDocumentList();
+            // 鍒锋柊闄勪欢鍒楄〃
+            if (attachmentManagerRef.value && res.data && res.data.id) {
+              attachmentManagerRef.value.loadAttachmentList(res.data.id);
+            }
+          } else {
+            ElMessage.error(res.msg || "鏂板澶辫触");
+          }
+        }
+        closeDocumentDia();
+      } catch (error) {
+        ElMessage.error("鎿嶄綔澶辫触锛岃閲嶈瘯");
+      }
+    }
+  });
+};
+
+// 鍏抽棴鏂囨。寮规
+const closeDocumentDia = () => {
+  proxy.$refs.documentFormRef.resetFields();
+  documentDia.value = false;
+  // 娓呯┖琛ㄥ崟鏁版嵁
+  Object.keys(documentForm).forEach(key => {
+    documentForm[key] = "";
+  });
+  documentForm.attachments = []; // 鍏抽棴寮规鏃朵篃娓呯┖闄勪欢
+};
+
+// 澶勭悊浣嶇疆閫夋嫨鍙樺寲
+const handleLocationChange = (value) => {
+  if (value) {
+    // 妫�鏌ラ�夋嫨鐨勬槸鍚︿负鍙跺瓙鑺傜偣
+    const isLeafNode = checkIfLeafNode(locationTree.value, value);
+    if (!isLeafNode) {
+      ElMessage.warning("璇烽�夋嫨鏈�搴曞眰鐨勪綅缃紙濡傦細鏌滃眰锛�");
+      documentForm.warehouseGoodsShelvesRowcolId = "";
+      return;
+    }
+  }
+};
+
+// 妫�鏌ユ槸鍚︿负鍙跺瓙鑺傜偣
+const checkIfLeafNode = (tree, value) => {
+  for (let item of tree) {
+    if (item.value === value || item.id === value) {
+      // 濡傛灉娌℃湁瀛愯妭鐐癸紝鍒欎负鍙跺瓙鑺傜偣
+      return !item.children || item.children.length === 0;
+    }
+    if (item.children && item.children.length > 0) {
+      const result = checkIfLeafNode(item.children, value);
+      if (result !== null) {
+        return result;
+      }
+    }
+  }
+  return null;
+};
+
+// 鍒犻櫎鏂囨。
+const handleDelete = () => {
+  if (selectedRows.value.length > 0) {
+    ElMessageBox.confirm(`纭畾瑕佸垹闄ら�変腑鐨� ${selectedRows.value.length} 鏉¤褰曞悧锛焋, "鍒犻櫎鎻愮ず", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(async () => {
+        try {
+          const selectedIds = selectedRows.value.map(row => row.id);
+          const res = await deleteDocument(selectedIds);
+          if (res.code === 200) {
+            ElMessage.success("鍒犻櫎鎴愬姛");
+            // 閲嶆柊鍔犺浇鏂囨。鍒楄〃
+            await loadDocumentList();
+          } else {
+            ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+          }
+        } catch (error) {
+          ElMessage.error("鍒犻櫎澶辫触锛岃閲嶈瘯");
+        }
+      })
+      .catch(() => {
+        ElMessage("宸插彇娑�");
+      });
+  } else {
+    ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
+  }
+};
+
+// PIMTable 閫夋嫨鍙樺寲浜嬩欢
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+  
+  // 鏇存柊鍏ㄩ�夌姸鎬�
+  const selectedCount = selection.length;
+  const totalCount = documentList.value.length;
+  
+  if (selectedCount === 0) {
+    selectAll.value = false;
+    isIndeterminate.value = false;
+  } else if (selectedCount === totalCount) {
+    selectAll.value = true;
+    isIndeterminate.value = false;
+  } else {
+    selectAll.value = false;
+    isIndeterminate.value = true;
+  }
+};
+
+// 鍔犺浇鏂囨。鍒楄〃
+const loadDocumentList = async () => {
+  try {
+    tableLoading.value = true;
+    
+    // 鏋勫缓鏌ヨ鍙傛暟
+    const query = {
+      page: pagination.currentPage,
+      size: pagination.pageSize,
+      documentClassificationId:currentId.value
+    };
+    
+    const res = await getDocumentList(query);
+    if (res.code === 200) {
+      documentList.value = res.data.records || [];
+      pagination.total = res.data.total || 0;
+    } else {
+      ElMessage.error(res.msg || "鑾峰彇鏂囨。鍒楄〃澶辫触");
+      documentList.value = [];
+      pagination.total = 0;
+    }
+    
+    // 閲嶇疆閫夋嫨鐘舵��
+    selectedRows.value = [];
+    selectAll.value = false;
+    isIndeterminate.value = false;
+  } catch (error) {
+    ElMessage.error("鑾峰彇鏂囨。鍒楄〃澶辫触锛岃閲嶈瘯");
+    documentList.value = [];
+    pagination.total = 0;
+  } finally {
+    tableLoading.value = false;
+  }
+};
+
+// 澶勭悊鍒嗛〉鍙樺寲
+const handlePagination = (current, size) => {
+  pagination.currentPage = current;
+  pagination.pageSize = size;
+  loadDocumentList();
+};
+
+// 璋冪敤tree杩囨护鏂规硶
+const filterNode = (value, data, node) => {
+  if (!value) {
+    return true;
+  }
+  let val = value.toLowerCase();
+  return chooseNode(val, data, node);
+};
+
+// 杩囨护鐖惰妭鐐� / 瀛愯妭鐐�
+const chooseNode = (value, data, node) => {
+  if (data.category && data.category.toLowerCase().indexOf(value) !== -1) {
+    return true;
+  }
+  const level = node.level;
+  if (level === 1) {
+    return false;
+  }
+  let parentData = node.parent;
+  let index = 0;
+  while (index < level - 1) {
+    if (parentData.data.category && parentData.data.category.toLowerCase().indexOf(value) !== -1) {
+      return true;
+    }
+    parentData = parentData.parent;
+    index++;
+  }
+  return false;
+};
+
+// 鎵撳紑闄勪欢
+const openAttachment = (row) => {
+  attachmentManagerRef.value.open([], row.id);
+};
+
+onMounted(() => {
+  initCategoryTree();
+  initLocationTree();
+  
+  // 涓嶅湪鍒濆鍖栨椂鍔犺浇鏂囨。鍒楄〃锛岀瓑寰呯敤鎴烽�夋嫨鍒嗙被鍚庡啀鍔犺浇
+});
+</script>
+
+<style scoped>
+.document-view {
+  display: flex;
+  height: 100%;
+}
+
+.left {
+  width: 380px;
+  padding: 16px;
+  background: #ffffff;
+  border-right: 1px solid #e4e7ed;
+}
+
+.right {
+  width: calc(100% - 380px);
+  padding: 16px;
+  background: #ffffff;
+}
+
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+}
+
+.tree-node-content {
+  display: flex;
+  align-items: center;
+  height: 100%;
+}
+
+.orange-icon {
+  color: orange;
+  font-size: 18px;
+  margin-right: 8px;
+}
+
+.table-container {
+  background: #ffffff;
+  border-radius: 8px;
+  overflow: hidden;
+  position: relative;
+}
+
+.add-row {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  background-color: #f5f7fa;
+  cursor: pointer;
+  transition: background-color 0.2s ease;
+  padding: 12px 16px;
+  margin-bottom: 16px;
+  border-radius: 6px;
+  border: 1px dashed #d9d9d9;
+}
+
+.add-row:hover {
+  background-color: #e4e7ed;
+  border-color: #c0c4cc;
+}
+
+.add-icon {
+  color: #909399;
+  font-size: 16px;
+}
+
+.add-row span {
+  color: #606266;
+  font-size: 14px;
+}
+
+.empty-data {
+  text-align: center;
+  color: #909399;
+  padding: 40px;
+  font-size: 14px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+.operation-column {
+  position: absolute;
+  right: 0;
+  top: 0;
+  width: 120px;
+  background: #ffffff;
+  border-left: 1px solid #e4e7ed;
+  z-index: 1;
+  box-shadow: -2px 0 4px rgba(0, 0, 0, 0.1);
+}
+
+.operation-header {
+  height: 40px;
+  line-height: 40px;
+  text-align: center;
+  background: #fafafa;
+  border-bottom: 1px solid #e4e7ed;
+  font-weight: 500;
+  color: #606266;
+}
+
+.operation-cell {
+  height: 40px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-bottom: 1px solid #e4e7ed;
+}
+
+.operation-cell:last-child {
+  border-bottom: none;
+}
+
+.attachment-section {
+  width: 100%;
+}
+
+.attachment-list {
+  margin-bottom: 10px;
+}
+
+.attachment-item {
+  display: flex;
+  align-items: center;
+  padding: 8px 12px;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  margin-bottom: 8px;
+}
+
+.file-icon {
+  margin-right: 8px;
+  color: #409eff;
+}
+
+.file-name {
+  flex: 1;
+  color: #606266;
+  font-size: 14px;
+}
+</style>
diff --git a/src/views/fileManagement/return/index.vue b/src/views/fileManagement/return/index.vue
new file mode 100644
index 0000000..80724ea
--- /dev/null
+++ b/src/views/fileManagement/return/index.vue
@@ -0,0 +1,599 @@
+<template>
+  <div class="app-container return-view">
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="search-container">
+      <el-form :model="searchForm" :inline="true" class="search-form">
+        <!-- <el-form-item label="鍊熼槄鐘舵�侊細">
+          <el-select v-model="searchForm.borrowStatus" placeholder="璇烽�夋嫨鍊熼槄鐘舵��" clearable style="width: 150px">
+            <el-option label="鍊熼槄" value="鍊熼槄" />
+            <el-option label="褰掕繕" value="褰掕繕" />
+          </el-select>
+        </el-form-item> -->
+        <el-form-item label="鍊熼槄浜猴細">
+          <el-input
+            v-model="searchForm.borrower"
+            placeholder="璇疯緭鍏ュ�熼槄浜�"
+            clearable
+            style="width: 200px"
+          />
+        </el-form-item>
+        <el-form-item label="褰掕繕浜猴細">
+          <el-input
+            v-model="searchForm.returner"
+            placeholder="璇疯緭鍏ュ綊杩樹汉"
+            clearable
+            style="width: 200px"
+          />
+        </el-form-item>
+        <el-form-item label="褰掕繕鏃ユ湡鑼冨洿锛�">
+          <el-date-picker
+            v-model="searchForm.dateRange"
+            type="daterange"
+            range-separator="鑷�"
+            start-placeholder="寮�濮嬫棩鏈�"
+            end-placeholder="缁撴潫鏃ユ湡"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+            style="width: 300px"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">
+            <el-icon><Search /></el-icon>
+            鏌ヨ
+          </el-button>
+          <el-button @click="handleReset">
+            <el-icon><Refresh /></el-icon>
+            閲嶇疆
+          </el-button>
+        </el-form-item>
+        <el-form-item style="margin-left: auto;">
+          <el-button type="primary" @click="openReturnDia('add')">
+            <el-icon><Plus /></el-icon>
+            鏂板褰掕繕
+          </el-button>
+          <el-button
+            type="danger"
+            @click="handleBatchDelete"
+            :disabled="selectedRows.length === 0"
+          >
+            <el-icon><Delete /></el-icon>
+            鎵归噺鍒犻櫎 ({{ selectedRows.length }})
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 琛ㄦ牸鍖哄煙 -->
+    <div class="table-container">
+      <PIMTable
+        :table-data="returnList"
+        :column="tableColumns"
+        :is-selection="true"
+        :border="true"
+        :table-loading="tableLoading"
+        :page="{
+          current: pagination.currentPage,
+          size: pagination.pageSize,
+          total: pagination.total,
+          layout: 'total, sizes, prev, pager, next, jumper'
+        }"
+        @selection-change="handleSelectionChange"
+        @pagination="handlePagination"
+      />
+      
+      <div v-if="returnList.length === 0" class="empty-data">
+        鏆傛棤鏁版嵁
+      </div>
+    </div>
+
+    <!-- 褰掕繕鏂板/缂栬緫瀵硅瘽妗� -->
+    <el-dialog
+      v-model="returnDia"
+      :title="returnOperationType === 'add' ? '鏂板褰掕繕' : '缂栬緫褰掕繕'"
+      width="800px"
+      @close="closeReturnDia"
+      @keydown.enter.prevent
+    >
+      <el-form
+        :model="returnForm"
+        label-width="140px"
+        :rules="returnRules"
+        ref="returnFormRef"
+      >
+                 <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-option 
+                   v-for="item in documentList" 
+                   :key="item.id" 
+                   :label="item.docName || item.name" 
+                   :value="item.id"
+                 />
+               </el-select>
+             </el-form-item>
+           </el-col>
+           <el-col :span="12">
+             <el-form-item label="鍊熼槄浜猴細" prop="borrower">
+               <el-input v-model="returnForm.borrower" placeholder="鍊熼槄浜哄皢鏍规嵁鏂囨。閫夋嫨鑷姩甯﹀嚭" disabled />
+             </el-form-item>
+           </el-col>
+         </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="褰掕繕浜猴細" prop="returner">
+              <el-input v-model="returnForm.returner" placeholder="璇疯緭鍏ュ綊杩樹汉" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="褰掕繕鏃ユ湡锛�" prop="returnDate">
+              <el-date-picker
+                v-model="returnForm.returnDate"
+                type="date"
+                placeholder="閫夋嫨褰掕繕鏃ユ湡"
+                style="width: 100%"
+                format="YYYY-MM-DD"
+                value-format="YYYY-MM-DD"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+                 <el-row :gutter="20">
+           <el-col :span="24">
+             <el-form-item label="搴斿綊杩樻棩鏈燂細" prop="dueReturnDate">
+               <el-date-picker
+                 v-model="returnForm.dueReturnDate"
+                 type="date"
+                 placeholder="搴斿綊杩樻棩鏈熷皢鏍规嵁鏂囨。閫夋嫨鑷姩甯﹀嚭"
+                 style="width: 100%"
+                 format="YYYY-MM-DD"
+                 value-format="YYYY-MM-DD"
+                 disabled
+               />
+             </el-form-item>
+           </el-col>
+         </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="澶囨敞璇存槑锛�" prop="remark">
+              <el-input
+                v-model="returnForm.remark"
+                type="textarea"
+                :rows="3"
+                placeholder="璇疯緭鍏ュ娉ㄨ鏄�"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitReturnForm">纭</el-button>
+          <el-button @click="closeReturnDia">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+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';
+
+const { proxy } = getCurrentInstance();
+
+// 鍝嶅簲寮忔暟鎹�
+const returnDia = ref(false);
+const returnOperationType = ref("");
+const tableLoading = ref(false);
+const returnList = ref([]);
+const selectedRows = ref([]);
+const documentList = ref([]); // 鏂囨。鍒楄〃
+
+// 鍒嗛〉鐩稿叧
+const pagination = reactive({
+  currentPage: 1,
+  pageSize: 10,
+  total: 0,
+});
+
+// 鏌ヨ琛ㄥ崟
+const searchForm = reactive({
+  borrowStatus: "",
+  borrower: "",
+  returner: "",
+  dateRange: []
+});
+
+// 褰掕繕琛ㄥ崟
+const returnForm = reactive({
+  id: "",
+  borrowId: "",
+  borrower: "",
+  returner: "",
+  borrowStatus: "",
+  returnDate: "",
+  dueReturnDate: "",
+  remark: ""
+});
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const returnRules = reactive({
+  borrowId: [{ required: true, message: "璇烽�夋嫨鏂囨。", trigger: "change" }],
+  returner: [{ required: true, message: "璇疯緭鍏ュ綊杩樹汉", trigger: "blur" }],
+  returnDate: [{ required: true, message: "璇烽�夋嫨褰掕繕鏃ユ湡", trigger: "change" }]
+});
+
+// 琛ㄦ牸鍒楅厤缃�
+const tableColumns = ref([
+  { 
+    label: '鏂囨。鍚嶇О', 
+    prop: 'docName',
+    width: '200',
+  },
+  { label: '鍊熼槄浜�', prop: 'borrower' },
+  { label: '褰掕繕浜�', prop: 'returner' },
+  { 
+    label: '鍊熼槄鐘舵��', 
+    prop: 'borrowStatus', 
+    dataType: 'tag',
+    formatData: (params) => {
+      if (params === null || params === undefined || params === '') return '-';
+      return params;
+    },
+    formatType: (params) => {
+      if (params === '褰掕繕') return 'success';
+      if (params === '鍊熼槄') return 'warning';
+      return 'info';
+    }
+  },
+  { label: '褰掕繕鏃ユ湡', prop: 'returnDate' },
+  { label: '搴斿綊杩樻棩鏈�', prop: 'dueReturnDate' },
+  { label: '澶囨敞', prop: 'remark', width: '150' },
+  { 
+    dataType: "action",
+    label: "鎿嶄綔",
+    align: "center",
+    fixed: 'right',
+    width: '150',
+    operation: [
+      {
+        name: "缂栬緫",
+        type: "text",
+        clickFun: (row) => {
+          openReturnDia('edit', row)
+        },
+      },
+      {
+        name: "鍒犻櫎",
+        type: "text",
+        clickFun: (row) => {
+          handleDelete(row)
+        },
+      },
+    ],
+  }
+]);
+
+// 鍒濆鍖栨暟鎹�
+const initData = async () => {
+  await Promise.all([
+    loadDocumentList(),
+    loadReturnList()
+  ]);
+};
+
+// 鍔犺浇鏂囨。鍒楄〃
+const loadDocumentList = async () => {
+  try {
+    const res = await getDocumentList();
+    if (res.code === 200) {
+      documentList.value = res.data || [];
+    } else {
+      ElMessage.error(res.msg || "鑾峰彇鏂囨。鍒楄〃澶辫触");
+      documentList.value = [];
+    }
+  } catch (error) {
+    ElMessage.error("鑾峰彇鏂囨。鍒楄〃澶辫触锛岃閲嶈瘯");
+    documentList.value = [];
+  }
+};
+
+// 鍔犺浇褰掕繕鍒楄〃
+const loadReturnList = async () => {
+  try {
+    tableLoading.value = true;
+    
+    // 鏋勫缓鏌ヨ鍙傛暟
+    const query = {
+      page: pagination.currentPage,
+      size: pagination.pageSize,
+      borrowStatus: searchForm.borrowStatus || undefined,
+      borrower: searchForm.borrower || undefined,
+      returner: searchForm.returner || undefined,
+      entryDateStart: searchForm.dateRange && searchForm.dateRange.length > 0 ? searchForm.dateRange[0] : undefined,
+      entryDateEnd: searchForm.dateRange && searchForm.dateRange.length > 1 ? searchForm.dateRange[1] : undefined
+    };
+    
+    // 绉婚櫎undefined鐨勫弬鏁�
+    Object.keys(query).forEach(key => {
+      if (query[key] === undefined) {
+        delete query[key];
+      }
+    });
+    
+    const res = await getReturnListPage(query);
+    if (res.code === 200) {
+      returnList.value = res.data.records || [];
+      pagination.total = res.data.total || 0;
+    } else {
+      ElMessage.error(res.msg || "鑾峰彇褰掕繕鍒楄〃澶辫触");
+      returnList.value = [];
+      pagination.total = 0;
+    }
+    
+    // 閲嶇疆閫夋嫨鐘舵��
+    selectedRows.value = [];
+  } catch (error) {
+    ElMessage.error("鑾峰彇褰掕繕鍒楄〃澶辫触锛岃閲嶈瘯");
+    returnList.value = [];
+    pagination.total = 0;
+  } finally {
+    tableLoading.value = false;
+  }
+};
+
+// 鏌ヨ
+const handleSearch = () => {
+  pagination.currentPage = 1;
+  loadReturnList();
+};
+
+// 閲嶇疆鏌ヨ
+const handleReset = () => {
+  searchForm.borrowStatus = "";
+  searchForm.borrower = "";
+  searchForm.returner = "";
+  searchForm.dateRange = [];
+  pagination.currentPage = 1;
+  loadReturnList();
+  ElMessage.success("鏌ヨ鏉′欢宸查噸缃�");
+};
+
+// 鎵撳紑褰掕繕寮规
+const openReturnDia = (type, data) => {
+  returnOperationType.value = type;
+  returnDia.value = true;
+  
+  if (type === "edit") {
+    // 缂栬緫妯″紡锛屽姞杞界幇鏈夋暟鎹�
+    Object.assign(returnForm, data);
+    // 缂栬緫妯″紡涓嬶紝鏂囨。閫夋嫨鍚庤嚜鍔ㄥ~鍏呭�熼槄浜哄拰搴斿綊杩樻棩鏈�
+    if (returnForm.borrowId) {
+      handleDocumentChange(returnForm.borrowId);
+    }
+  } else {
+    // 鏂板妯″紡锛屾竻绌鸿〃鍗�
+    Object.keys(returnForm).forEach(key => {
+      returnForm[key] = "";
+    });
+    // 璁剧疆榛樿鐘舵��
+    returnForm.borrowStatus = "褰掕繕";
+    // 璁剧疆褰撳墠鏃ユ湡涓哄綊杩樻棩鏈�
+    returnForm.returnDate = new Date().toISOString().split('T')[0];
+  }
+};
+
+// 鍏抽棴褰掕繕寮规
+const closeReturnDia = () => {
+  proxy.$refs.returnFormRef.resetFields();
+  returnDia.value = false;
+};
+
+// 鎻愪氦褰掕繕琛ㄥ崟
+const submitReturnForm = () => {
+  proxy.$refs.returnFormRef.validate(async (valid) => {
+    if (valid) {
+      try {
+                 if (returnOperationType.value === "edit") {
+           // 缂栬緫妯″紡锛岃皟鐢ㄥ綊杩樻洿鏂版帴鍙�
+           const res = await reventUpdate({
+             id: returnForm.id,
+             documentationId: returnForm.documentationId,
+             borrower: returnForm.borrower,
+             returner: returnForm.returner,
+             borrowStatus: returnForm.borrowStatus,
+             returnDate: returnForm.returnDate,
+             dueReturnDate: returnForm.dueReturnDate,
+             remark: returnForm.remark
+           });
+          
+          if (res.code === 200) {
+            ElMessage.success("缂栬緫鎴愬姛");
+            await loadReturnList();
+            closeReturnDia();
+          } else {
+            ElMessage.error(res.msg || "缂栬緫澶辫触");
+          }
+        } else {
+          // 鏂板妯″紡锛岃皟鐢ㄥ綊杩樻帴鍙�
+          const res = await returnDocument({
+            borrowId: returnForm.borrowId,
+            borrower: returnForm.borrower,
+            returner: returnForm.returner,
+            borrowStatus: returnForm.borrowStatus,
+            returnDate: returnForm.returnDate,
+            dueReturnDate: returnForm.dueReturnDate,
+            remark: returnForm.remark
+          });
+          
+          if (res.code === 200) {
+            ElMessage.success("鏂板鎴愬姛");
+            await loadReturnList();
+            closeReturnDia();
+          } else {
+            ElMessage.error(res.msg || "鏂板澶辫触");
+          }
+        }
+      } catch (error) {
+        ElMessage.error("鎿嶄綔澶辫触锛岃閲嶈瘯");
+      }
+    }
+  });
+};
+
+// 鍒犻櫎褰掕繕璁板綍
+const handleDelete = (row) => {
+  ElMessageBox.confirm(
+    `纭畾瑕佸垹闄よ繖鏉″綊杩樿褰曞悧锛焋,
+    "鍒犻櫎鎻愮ず",
+    {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    }
+  ).then(async () => {
+    try {
+      const res = await deleteReturn([row.id]);
+      if (res.code === 200) {
+        ElMessage.success("鍒犻櫎鎴愬姛");
+        await loadReturnList();
+      } else {
+        ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+      }
+    } catch (error) {
+      ElMessage.error("鍒犻櫎澶辫触锛岃閲嶈瘯");
+    }
+  }).catch(() => {
+    ElMessage.info("宸插彇娑堝垹闄�");
+  });
+};
+
+// 鎵归噺鍒犻櫎
+const handleBatchDelete = () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑璁板綍");
+    return;
+  }
+  
+  ElMessageBox.confirm(
+    `纭畾瑕佸垹闄ら�変腑鐨� ${selectedRows.value.length} 鏉″綊杩樿褰曞悧锛焋,
+    "鎵归噺鍒犻櫎鎻愮ず",
+    {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    }
+  ).then(async () => {
+    try {
+      const selectedIds = selectedRows.value.map(row => row.id);
+      const res = await deleteReturn(selectedIds);
+      if (res.code === 200) {
+        ElMessage.success("鎵归噺鍒犻櫎鎴愬姛");
+        await loadReturnList();
+      } else {
+        ElMessage.error(res.msg || "鎵归噺鍒犻櫎澶辫触");
+      }
+    } catch (error) {
+      ElMessage.error("鎵归噺鍒犻櫎澶辫触锛岃閲嶈瘯");
+    }
+  }).catch(() => {
+    ElMessage.info("宸插彇娑堝垹闄�");
+  });
+};
+
+// 閫夋嫨鍙樺寲浜嬩欢
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+
+// 澶勭悊鍒嗛〉鍙樺寲
+const handlePagination = (current, size) => {
+  pagination.currentPage = current;
+  pagination.pageSize = size;
+  loadReturnList();
+};
+
+// 澶勭悊鏂囨。閫夋嫨鍙樺寲
+const handleDocumentChange = (documentId) => {
+  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(() => {
+  initData();
+});
+</script>
+
+<style scoped>
+.return-view {
+  padding: 20px;
+}
+
+.search-container {
+  background: #ffffff;
+  padding: 20px;
+  border-radius: 8px;
+  margin-bottom: 20px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.search-form {
+  margin: 0;
+}
+
+.table-container {
+  background: #ffffff;
+  border-radius: 8px;
+  overflow: hidden;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.empty-data {
+  text-align: center;
+  color: #909399;
+  padding: 40px;
+  font-size: 14px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+:deep(.el-form-item__label) {
+  font-weight: 500;
+  color: #303133;
+}
+
+:deep(.el-input__wrapper) {
+  box-shadow: 0 0 0 1px #dcdfe6 inset;
+}
+
+:deep(.el-input__wrapper:hover) {
+  box-shadow: 0 0 0 1px #c0c4cc inset;
+}
+
+:deep(.el-input__wrapper.is-focus) {
+  box-shadow: 0 0 0 1px #409eff inset;
+}
+</style>
diff --git a/vite.config.js b/vite.config.js
index b96c1d4..6d04eb7 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -8,8 +8,8 @@
   const { VITE_APP_ENV } = env;
   const baseUrl =
     VITE_APP_ENV == "development"
-      ? "http://114.132.189.42:8092" // 寮�鍙戠幆澧冨悗绔帴鍙�
-      : "http://114.132.189.42:8092"; // 鐢熶骇鐜鍚庣鎺ュ彛
+      ? "http://192.168.1.138:7788" // 寮�鍙戠幆澧冨悗绔帴鍙�
+      : "http://114.132.189.42:7003"; // 鐢熶骇鐜鍚庣鎺ュ彛
 
   return {
     // 閮ㄧ讲鐢熶骇鐜鍜屽紑鍙戠幆澧冧笅鐨刄RL銆�
@@ -45,7 +45,7 @@
     },
     // vite 鐩稿叧閰嶇疆
     server: {
-      port: 80,
+      port: 8001,
       host: true,
       open: true,
       proxy: {

--
Gitblit v1.9.3