From 8e4c8d6ed7088e0f9e396f324796929cc79778ca Mon Sep 17 00:00:00 2001
From: chenhj <1263187585@qq.com>
Date: 星期四, 30 四月 2026 17:00:25 +0800
Subject: [PATCH] Merge branch 'dev_NEW_pro' of http://114.132.189.42:9002/r/product-inventory-management into dev_NEW_pro

---
 src/views/safeProduction/safeQualifications/index.vue                              |   40 -
 src/views/procurementManagement/procurementInvoiceLedger/index.vue                 |  159 -------
 src/views/productionManagement/processRoute/index.vue                              |    3 
 src/views/collaborativeApproval/rulesRegulationsManagement/index.vue               |   80 ---
 src/views/productionManagement/processRoute/processRouteItem/index.vue             |   20 
 src/api/productionManagement/productionOrder.js                                    |    9 
 src/components/PIMTable/PIMTable.vue                                               |    5 
 src/views/salesManagement/salesLedger/index.vue                                    |   34 
 src/views/productionManagement/workOrderManagement/index.vue                       |    7 
 src/views/financialManagement/expenseManagement/index.vue                          |  176 -------
 src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue |    5 
 src/views/procurementManagement/procurementLedger/index.vue                        |   85 ++--
 src/views/salesManagement/invoiceLedger/index.vue                                  |   25 
 src/views/productionManagement/productionOrder/index.vue                           |   53 ++
 src/components/Dialog/FileList.vue                                                 |  319 +++++++-------
 src/views/safeProduction/safetyTrainingAssessment/index.vue                        |   49 -
 src/views/customerService/afterSalesHandling/index.vue                             |  165 -------
 17 files changed, 386 insertions(+), 848 deletions(-)

diff --git a/src/api/productionManagement/productionOrder.js b/src/api/productionManagement/productionOrder.js
index 688abfc..9b5751d 100644
--- a/src/api/productionManagement/productionOrder.js
+++ b/src/api/productionManagement/productionOrder.js
@@ -45,6 +45,15 @@
   });
 }
 
+// 鐢熶骇璁㈠崟-淇敼
+export function updateProductOrder(data) {
+  return request({
+    url: "/productionOrder/updateOrder",
+    method: "post",
+    data: data,
+  });
+}
+
 export function delProductOrder(ids) {
   return request({
     url: `/productionOrder/delete`,
diff --git a/src/components/Dialog/FileList.vue b/src/components/Dialog/FileList.vue
index 1506b25..6e0ca23 100644
--- a/src/components/Dialog/FileList.vue
+++ b/src/components/Dialog/FileList.vue
@@ -5,7 +5,8 @@
              @close="handleClose"
              class="attachment-dialog">
     <!-- 宸ュ叿鏍� -->
-    <div class="toolbar">
+    <div v-if="editable"
+         class="toolbar">
       <el-button type="primary"
                  size="small"
                  @click="handleUpload">
@@ -13,12 +14,11 @@
       </el-button>
     </div>
     <!-- 涓婁紶缁勪欢寮圭獥 -->
-    <el-dialog
-        v-model="uploadDialogVisible"
-        title="涓婁紶闄勪欢"
-        width="50%"
-        @close="closeUpload">
-      <AttachmentUpload v-model:file-list="newFileList"/>
+    <el-dialog v-model="uploadDialogVisible"
+               title="涓婁紶闄勪欢"
+               width="50%"
+               @close="closeUpload">
+      <AttachmentUpload v-model:file-list="newFileList" />
       <template #footer>
         <el-button @click="saveUpload">淇濆瓨</el-button>
         <el-button @click="closeUpload">鍏抽棴</el-button>
@@ -32,7 +32,7 @@
                 :height="tableData.length > 0 ? 'auto' : '120px'">
         <el-table-column label="闄勪欢鍚嶇О"
                          prop="originalFilename"
-                         show-overflow-tooltip/>
+                         show-overflow-tooltip />
         <el-table-column v-if="showActions"
                          fixed="right"
                          label="鎿嶄綔"
@@ -46,7 +46,8 @@
                        @click="downloadFile(scope.row.downloadURL)">
               涓嬭浇
             </el-button>
-            <el-button link
+            <el-button v-if="editable"
+                       link
                        type="danger"
                        size="small"
                        @click="handleDelete(scope.row)">
@@ -60,181 +61,185 @@
 </template>
 
 <script setup>
-import {ref, computed, getCurrentInstance, onMounted, watch} from "vue";
-import AttachmentUpload from "@/components/AttachmentUpload/file/index.vue";
-import {
-  attachmentList,
-  deleteAttachment,
-  createAttachment,
-} from "@/api/basicData/storageAttachment.js";
+  import { ref, computed, getCurrentInstance, onMounted, watch } from "vue";
+  import AttachmentUpload from "@/components/AttachmentUpload/file/index.vue";
+  import {
+    attachmentList,
+    deleteAttachment,
+    createAttachment,
+  } from "@/api/basicData/storageAttachment.js";
 
-const props = defineProps({
-  visible: {
-    type: Boolean,
-    required: true,
-  },
-  recordType: {
-    type: String,
-    default: "",
-    required: true,
-  },
-  recordId: {
-    type: Number,
-    default: 0,
-    required: true,
-  },
-  title: {
-    type: String,
-    default: "闄勪欢",
-  },
-  width: {
-    type: String,
-    default: "50%",
-  },
-  showActions: {
-    type: Boolean,
-    default: true,
-  },
-});
+  const props = defineProps({
+    visible: {
+      type: Boolean,
+      required: true,
+    },
+    recordType: {
+      type: String,
+      default: "",
+      required: true,
+    },
+    recordId: {
+      type: Number,
+      default: 0,
+      required: true,
+    },
+    title: {
+      type: String,
+      default: "闄勪欢",
+    },
+    width: {
+      type: String,
+      default: "50%",
+    },
+    showActions: {
+      type: Boolean,
+      default: true,
+    },
+    editable: {
+      type: Boolean,
+      default: true,
+    },
+  });
 
-const emit = defineEmits(["close", "download", "upload", "delete"]);
+  const emit = defineEmits(["close", "download", "upload", "delete"]);
 
-const {proxy} = getCurrentInstance();
-const tableData = ref([]);
-const uploadDialogVisible = ref(false);
-const newFileList = ref([]);
+  const { proxy } = getCurrentInstance();
+  const tableData = ref([]);
+  const uploadDialogVisible = ref(false);
+  const newFileList = ref([]);
 
-const isShow = computed({
-  get() {
-    return props.visible;
-  },
-  set(val) {
-    emit("update:visible", val);
-  },
-});
+  const isShow = computed({
+    get() {
+      return props.visible;
+    },
+    set(val) {
+      emit("update:visible", val);
+    },
+  });
 
-const handleClose = () => {
-  isShow.value = false;
-};
+  const handleClose = () => {
+    isShow.value = false;
+  };
 
-const handleUpload = () => {
-  uploadDialogVisible.value = true;
-};
+  const handleUpload = () => {
+    uploadDialogVisible.value = true;
+  };
 
-const saveUpload = async () => {
-  // 妫�鏌ユ槸鍚︽湁鏂颁笂浼犵殑鏂囦欢
-  if (newFileList.value.length > 0) {
+  const saveUpload = async () => {
+    // 妫�鏌ユ槸鍚︽湁鏂颁笂浼犵殑鏂囦欢
+    if (newFileList.value.length > 0) {
+      try {
+        await createAttachment({
+          application: "file",
+          recordType: props.recordType,
+          recordId: props.recordId,
+          storageBlobDTOs: [...newFileList.value, ...tableData.value],
+        });
+        newFileList.value = [];
+        // 鍒锋柊鍒楄〃
+        setList();
+      } catch (error) {
+        proxy?.$modal?.msgError("涓婁紶澶辫触");
+      }
+    }
+    uploadDialogVisible.value = false;
+  };
+
+  const closeUpload = () => {
+    newFileList.value = [];
+    uploadDialogVisible.value = false;
+  };
+
+  const handleDelete = async (row, index) => {
     try {
-      await createAttachment({
-        application: "file",
-        recordType: props.recordType,
-        recordId: props.recordId,
-        storageBlobDTOs: [...newFileList.value, ...tableData.value],
-      });
-      newFileList.value = [];
-      // 鍒锋柊鍒楄〃
+      await deleteAttachment([row.storageAttachmentId]);
+      proxy?.$modal?.msgSuccess("鍒犻櫎鎴愬姛");
       setList();
     } catch (error) {
-      proxy?.$modal?.msgError("涓婁紶澶辫触");
+      proxy?.$modal?.msgError("鍒犻櫎澶辫触");
     }
-  }
-  uploadDialogVisible.value = false;
-};
+  };
 
-const closeUpload = () => {
-  newFileList.value = [];
-  uploadDialogVisible.value = false;
-}
+  const setList = () => {
+    attachmentList({
+      recordType: props.recordType,
+      recordId: props.recordId,
+    }).then(res => {
+      if (res && res.data) {
+        tableData.value = res.data || [];
+      }
+    });
+  };
 
-const handleDelete = async (row, index) => {
-  try {
-    await deleteAttachment([row.storageAttachmentId]);
-    proxy?.$modal?.msgSuccess("鍒犻櫎鎴愬姛");
+  const downloadFile = url => {
+    window.open(url, "_blank");
+  };
+  onMounted(() => {
     setList();
-  } catch (error) {
-    proxy?.$modal?.msgError("鍒犻櫎澶辫触");
-  }
-};
-
-const setList = () => {
-  attachmentList({
-    recordType: props.recordType,
-    recordId: props.recordId,
-  }).then(res => {
-    if (res && res.data) {
-      tableData.value = res.data || [];
-    }
   });
-};
-
-const downloadFile = (url) => {
-  window.open(url, "_blank");
-};
-onMounted(() => {
-  setList();
-});
 </script>
 
 <style scoped>
-.attachment-dialog {
-  border-radius: 12px;
-}
+  .attachment-dialog {
+    border-radius: 12px;
+  }
 
-.toolbar {
-  margin-bottom: 16px;
-  text-align: right;
-}
+  .toolbar {
+    margin-bottom: 16px;
+    text-align: right;
+  }
 
-.table-container {
-  max-height: 40vh;
-  overflow-y: auto;
-  min-height: 120px;
-  padding-bottom: 16px;
-  box-sizing: border-box;
-  will-change: scroll-position;
-  transform: translateZ(0);
-  -webkit-overflow-scrolling: touch;
-}
+  .table-container {
+    max-height: 40vh;
+    overflow-y: auto;
+    min-height: 120px;
+    padding-bottom: 16px;
+    box-sizing: border-box;
+    will-change: scroll-position;
+    transform: translateZ(0);
+    -webkit-overflow-scrolling: touch;
+  }
 
-:deep(.el-table) {
-  margin-bottom: 0;
-}
+  :deep(.el-table) {
+    margin-bottom: 0;
+  }
 
-:deep(.el-table__body-wrapper) {
-  overflow-y: auto;
-  will-change: transform;
-  transform: translateZ(0);
-}
+  :deep(.el-table__body-wrapper) {
+    overflow-y: auto;
+    will-change: transform;
+    transform: translateZ(0);
+  }
 
-:deep(.el-table__body tr) {
-  transition: none;
-}
+  :deep(.el-table__body tr) {
+    transition: none;
+  }
 
-:deep(.el-dialog__footer) {
-  padding-top: 12px;
-  border-top: 1px solid #e9ecef;
-}
+  :deep(.el-dialog__footer) {
+    padding-top: 12px;
+    border-top: 1px solid #e9ecef;
+  }
 
-.attachment-table {
-  border-radius: 8px;
-}
+  .attachment-table {
+    border-radius: 8px;
+  }
 
-:deep(.el-dialog__header) {
-  background-color: #f8f9fa;
-  border-bottom: 1px solid #e9ecef;
-  padding: 16px 20px;
-}
+  :deep(.el-dialog__header) {
+    background-color: #f8f9fa;
+    border-bottom: 1px solid #e9ecef;
+    padding: 16px 20px;
+  }
 
-:deep(.el-dialog__title) {
-  font-size: 16px;
-  font-weight: 600;
-}
+  :deep(.el-dialog__title) {
+    font-size: 16px;
+    font-weight: 600;
+  }
 
-:deep(.el-dialog__body) {
-  padding: 16px 20px;
-}
+  :deep(.el-dialog__body) {
+    padding: 16px 20px;
+  }
 
-:deep(.el-table__empty-text) {
-  color: #999;
-}
+  :deep(.el-table__empty-text) {
+    color: #999;
+  }
 </style>
\ No newline at end of file
diff --git a/src/components/PIMTable/PIMTable.vue b/src/components/PIMTable/PIMTable.vue
index 61df179..f99b1eb 100644
--- a/src/components/PIMTable/PIMTable.vue
+++ b/src/components/PIMTable/PIMTable.vue
@@ -21,6 +21,7 @@
             class="lims-table">
     <el-table-column align="center"
                      type="selection"
+                     :selectable="selectable"
                      width="55"
                      v-if="isSelection" />
     <el-table-column align="center"
@@ -258,6 +259,10 @@
       type: Boolean,
       default: false,
     },
+    selectable: {
+      type: Function,
+      default: () => true,
+    },
     isShowPagination: {
       type: Boolean,
       default: true,
diff --git a/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
index eb0802e..f7ba9d9 100644
--- a/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
+++ b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
@@ -212,14 +212,7 @@
         </el-table-column>
       </el-table>
     </el-dialog>
-    <FileListDialog ref="fileListDialogRef"
-                    v-model="fileDialogVisible"
-                    :show-upload-button="true"
-                    :show-delete-button="true"
-                    :delete-method="handleAttachmentDelete"
-                    :rules-regulations-management-id="currentFileRuleId"
-                    :name-column-label="'闄勪欢鍚嶇О'"
-                    @upload="handleAttachmentUpload"/>
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" record-type="rules_regulations_management" :record-id="recordId"  />
   </div>
 </template>
 
@@ -235,7 +228,7 @@
     addReadingStatus,
     updateReadingStatus,
   } from "@/api/collaborativeApproval/sealManagement.js";
-  import FileListDialog from "@/components/Dialog/FileListDialog.vue";
+  const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
   import {
     listRuleFiles,
     delRuleFile,
@@ -254,14 +247,7 @@
     total: 0,
   });
   // 闄勪欢寮圭獥
-  const fileDialogVisible = ref(false);
-  const fileListDialogRef = ref(null);
   const currentFileRuleId = ref(null);
-  const filePage = reactive({
-    current: 1,
-    size: 1000,
-    total: 0,
-  });
   // 瑙勭珷鍒跺害鐩稿叧
   const showRegulationDialog = ref(false);
   const showRegulationDetailDialog = ref(false);
@@ -564,63 +550,15 @@
     );
   };
 
-  // 闄勪欢锛氭煡璇�
-  const fetchRuleFiles = async rulesRegulationsManagementId => {
-    const params = {
-      current: filePage.current,
-      size: filePage.size,
-      rulesRegulationsManagementId,
-    };
-    const res = await listRuleFiles(params);
-    const records = res?.data?.records || [];
-    filePage.total = res?.data?.total || records.length;
-    const mapped = records.map(item => ({
-      id: item.id,
-      name: item.fileName || item.name,
-      url: item.fileUrl || item.url,
-      raw: item,
-    }));
-    fileListDialogRef.value?.setList(mapped);
-  };
-
   // 鎵撳紑闄勪欢寮圭獥
-  const openFileDialog = async row => {
-    currentFileRuleId.value = row.id;
-    fileDialogVisible.value = true;
-    await fetchRuleFiles(row.id);
-  };
+  const recordId =ref(0)
+  const fileDialogVisible = ref(false)
 
-  // 鍒锋柊闄勪欢鍒楄〃
-  const refreshFileList = async () => {
-    if (!currentFileRuleId.value) return;
-    await fetchRuleFiles(currentFileRuleId.value);
-  };
-
-  // 涓婁紶闄勪欢锛堢敱瀛愮粍浠惰Е鍙戯級
-  const handleAttachmentUpload = async filePayload => {
-    if (!currentFileRuleId.value) return;
-    const payload = {
-      name: filePayload?.fileName || filePayload?.name,
-      url: filePayload?.fileUrl || filePayload?.url,
-      rulesRegulationsManagementId: currentFileRuleId.value,
-    };
-    await addRuleFile(payload);
-    ElMessage.success("鏂囦欢涓婁紶鎴愬姛");
-    await refreshFileList();
-  };
-
-  // 鍒犻櫎闄勪欢
-  const handleAttachmentDelete = async row => {
-    if (!row?.id) return false;
-    try {
-      await ElMessageBox.confirm("纭鍒犻櫎璇ラ檮浠讹紵", "鎻愮ず", { type: "warning" });
-    } catch {
-      return false;
-    }
-    await delRuleFile([row.id]);
-    ElMessage.success("鍒犻櫎鎴愬姛");
-    await refreshFileList();
-  };
+  // 鎵撳紑闄勪欢寮规
+  const openFileDialog = async (row) => {
+    recordId.value = row.id
+    fileDialogVisible.value = true
+  }
 
   // 鑾峰彇瑙勭珷鍒跺害鍒楄〃鏁版嵁
   const getRegulationList = async () => {
diff --git a/src/views/customerService/afterSalesHandling/index.vue b/src/views/customerService/afterSalesHandling/index.vue
index 57cc2eb..d023f51 100644
--- a/src/views/customerService/afterSalesHandling/index.vue
+++ b/src/views/customerService/afterSalesHandling/index.vue
@@ -102,33 +102,19 @@
 			></PIMTable>
 		</div>
 		<form-dia ref="formDia" @close="handleQuery"></form-dia>
-		<FileListDialog
-			ref="fileListRef"
-			v-model="fileListDialogVisible"
-			title="鍞悗闄勪欢"
-			:show-upload-button="true"
-			:show-delete-button="true"
-			:upload-method="handleFileUpload"
-			:delete-method="handleFileDelete"
-		/>
-	</div>
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" record-type="after_sales_service" :record-id="recordId"  />
+  </div>
 </template>
 
 <script setup>
-import { onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick } from "vue";
+import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick, defineAsyncComponent} from "vue";
 import FormDia from "@/views/customerService/afterSalesHandling/components/formDia.vue";
-import FileListDialog from "@/components/Dialog/FileListDialog.vue";
 import { ElMessageBox } from "element-plus";
-import request from "@/utils/request";
-import { getToken } from "@/utils/auth";
 import {
 	afterSalesServiceListPage,
-	afterSalesServiceFileListPage,
-	afterSalesServiceFileDel,
 } from "@/api/customerService/index.js";
-import useUserStore from "@/store/modules/user.js";
 const { proxy } = getCurrentInstance();
-const userStore = useUserStore()
+const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
 const data = reactive({
 	searchForm: {
@@ -303,144 +289,15 @@
   })
 }
 
+
+// 鎵撳紑闄勪欢寮圭獥
+const recordId =ref(0)
+const fileDialogVisible = ref(false)
+
 // 鎵撳紑闄勪欢寮规
 const openFilesFormDia = async (row) => {
-	currentFileRow.value = row
-	try {
-		const res = await afterSalesServiceFileListPage({
-			afterSalesServiceId: row.id,
-			current: 1,
-			size: 100,
-		})
-		if (res.code === 200 && fileListRef.value) {
-			const fileList = (res.data?.records || []).map((item) => ({
-				name: item.name || item.fileName,
-				url: item.url || item.fileUrl,
-				id: item.id,
-				...item,
-			}))
-			fileListRef.value.open(fileList)
-			fileListDialogVisible.value = true
-		} else {
-			fileListRef.value?.open([])
-			fileListDialogVisible.value = true
-		}
-	} catch (error) {
-		proxy.$modal.msgError("鑾峰彇闄勪欢鍒楄〃澶辫触")
-		fileListRef.value?.open([])
-		fileListDialogVisible.value = true
-	}
-}
-
-// 涓婁紶闄勪欢
-const handleFileUpload = async () => {
-	if (!currentFileRow.value) {
-		proxy.$modal.msgWarning("璇峰厛閫夋嫨鏁版嵁")
-		return
-	}
-	return new Promise((resolve) => {
-		const input = document.createElement("input")
-		input.type = "file"
-		input.style.display = "none"
-		input.onchange = async (e) => {
-			const file = e.target.files[0]
-			if (!file) {
-				resolve(null)
-				return
-			}
-			try {
-				const formData = new FormData()
-				formData.append("file", file)
-				formData.append("id", currentFileRow.value.id)
-				const uploadRes = await request({
-					url: "/afterSalesService/file/upload",
-					method: "post",
-					data: formData,
-					headers: {
-						"Content-Type": "multipart/form-data",
-						Authorization: `Bearer ${getToken()}`,
-					},
-				})
-				if (uploadRes.code === 200) {
-					proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛")
-					// 閲嶆柊鑾峰彇鏂囦欢鍒楄〃
-					const listRes = await afterSalesServiceFileListPage({
-						afterSalesServiceId: currentFileRow.value.id,
-						current: 1,
-						size: 100,
-					})
-					if (listRes.code === 200 && fileListRef.value) {
-						const fileList = (listRes.data?.records || []).map((item) => ({
-							name: item.fileName,
-							url: item.fileUrl,
-							id: item.id,
-							...item,
-						}))
-						fileListRef.value.setList(fileList)
-					}
-					resolve({ name: file.name, url: "", id: null })
-				} else {
-					proxy.$modal.msgError(uploadRes.msg || "鏂囦欢涓婁紶澶辫触")
-					resolve(null)
-				}
-			} catch (err) {
-				proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触")
-				resolve(null)
-			} finally {
-				document.body.removeChild(input)
-			}
-		}
-		document.body.appendChild(input)
-		input.click()
-	})
-}
-
-// 鍒犻櫎闄勪欢
-const handleFileDelete = async (row) => {
-	try {
-		// 娣诲姞纭瀵硅瘽妗�
-		const confirmResult = await ElMessageBox.confirm(
-			'纭畾瑕佸垹闄よ繖涓檮浠跺悧锛�',
-			'鍒犻櫎纭',
-			{
-				confirmButtonText: '纭畾',
-				cancelButtonText: '鍙栨秷',
-				type: 'warning'
-			}
-		)
-
-		if (confirmResult === 'confirm') {
-			const res = await afterSalesServiceFileDel(row.id)
-			if (res.code === 200) {
-				proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
-				if (currentFileRow.value && fileListRef.value) {
-					const listRes = await afterSalesServiceFileListPage({
-						afterSalesServiceId: currentFileRow.value.id,
-						current: 1,
-						size: 100,
-					})
-					if (listRes.code === 200) {
-						const fileList = (listRes.data?.records || []).map((item) => ({
-							name: item.fileName,
-							url: item.fileUrl,
-							id: item.id,
-							...item,
-						}))
-						fileListRef.value.setList(fileList)
-					}
-				}
-			} else {
-				proxy.$modal.msgError(res.msg || "鍒犻櫎澶辫触")
-				return false
-			}
-		}
-	} catch (error) {
-		// 濡傛灉鐢ㄦ埛鍙栨秷鍒犻櫎锛屼笉鏄剧ず閿欒淇℃伅
-		if (error !== 'cancel') {
-			proxy.$modal.msgError("鍒犻櫎澶辫触")
-		}
-		return false
-	}
+  recordId.value = row.id
+  fileDialogVisible.value = true
 }
 
 // 鏌ヨ鍒楄〃
diff --git a/src/views/financialManagement/expenseManagement/index.vue b/src/views/financialManagement/expenseManagement/index.vue
index ac55d01..173f8e1 100644
--- a/src/views/financialManagement/expenseManagement/index.vue
+++ b/src/views/financialManagement/expenseManagement/index.vue
@@ -76,27 +76,18 @@
       </PIMTable>
     </div>
     <Modal ref="modalRef" @success="getTableData"></Modal>
-    <FileListDialog 
-      ref="fileListRef" 
-      v-model="fileListDialogVisible"
-      :show-upload-button="true"
-      :show-delete-button="true"
-      :upload-method="handleUpload"
-      :delete-method="handleFileDelete"
-    />
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" record-type="account_expense" :record-id="recordId"  />
   </div>
 </template>
 
 <script setup>
 import { usePaginationApi } from "@/hooks/usePaginationApi";
-import { listPage, delAccountExpense, fileListPage, fileAdd, fileDel } from "@/api/financialManagement/expenseManagement";
-import { onMounted, getCurrentInstance, ref, computed } from "vue";
+import { listPage, delAccountExpense } from "@/api/financialManagement/expenseManagement";
+import {onMounted, getCurrentInstance, ref, computed, defineAsyncComponent} from "vue";
 import Modal from "./Modal.vue";
 import { ElMessageBox, ElMessage } from "element-plus";
 import dayjs from "dayjs";
-import FileListDialog from "@/components/Dialog/FileListDialog.vue";
-import request from "@/utils/request";
-import { getToken } from "@/utils/auth";
+const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
 defineOptions({
   name: "鏀嚭绠$悊",
@@ -108,9 +99,6 @@
 const modalRef = ref();
 const { checkout_payment } = proxy.useDict("checkout_payment");
 const { expense_types } = proxy.useDict("expense_types");
-const fileListRef = ref(null);
-const fileListDialogVisible = ref(false);
-const currentFileRow = ref(null);
 const accountType = ref('鏀嚭');
 
 const {
@@ -315,156 +303,16 @@
       proxy.$modal.msg("宸插彇娑�");
     });
 };
+
+// 鎵撳紑闄勪欢寮圭獥
+const recordId =ref(0)
+const fileDialogVisible = ref(false)
+
 // 鎵撳紑闄勪欢寮规
 const openFilesFormDia = async (row) => {
-  currentFileRow.value = row;
-  accountType.value = '鏀嚭';
-  try {
-    const res = await fileListPage({
-      accountId: row.id,
-      accountType: accountType.value,
-      current: 1,
-      size: 100
-    });
-    if (res.code === 200 && fileListRef.value) {
-      // 灏嗘暟鎹浆鎹负 FileListDialog 闇�瑕佺殑鏍煎紡
-      const fileList = (res.data?.records || []).map(item => ({
-        name: item.name,
-        url: item.url,
-        id: item.id,
-        ...item
-      }));
-      fileListRef.value.open(fileList);
-      fileListDialogVisible.value = true;
-    }
-  } catch (error) {
-    proxy.$modal.msgError("鑾峰彇闄勪欢鍒楄〃澶辫触");
-  }
-};
-
-// 涓婁紶闄勪欢
-const handleUpload = async () => {
-  if (!currentFileRow.value) {
-    proxy.$modal.msgWarning("璇峰厛閫夋嫨鏁版嵁");
-    return null;
-  }
-  
-  return new Promise((resolve) => {
-    // 鍒涘缓涓�涓殣钘忕殑鏂囦欢杈撳叆鍏冪礌
-    const input = document.createElement('input');
-    input.type = 'file';
-    input.style.display = 'none';
-    input.onchange = async (e) => {
-      const file = e.target.files[0];
-      if (!file) {
-        resolve(null);
-        return;
-      }
-      
-      try {
-        // 浣跨敤 FormData 涓婁紶鏂囦欢
-        const formData = new FormData();
-        formData.append('file', file);
-        
-        const uploadRes = await request({
-          url: '/file/upload',
-          method: 'post',
-          data: formData,
-          headers: {
-            'Content-Type': 'multipart/form-data',
-            Authorization: `Bearer ${getToken()}`
-          }
-        });
-        
-        if (uploadRes.code === 200) {
-          // 淇濆瓨闄勪欢淇℃伅
-          const fileData = {
-            accountId: currentFileRow.value.id,
-            accountType: accountType.value,
-            name: uploadRes.data.originalName || file.name,
-            url: uploadRes.data.tempPath || uploadRes.data.url
-          };
-          
-          const saveRes = await fileAdd(fileData);
-          if (saveRes.code === 200) {
-            proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
-            // 閲嶆柊鍔犺浇鏂囦欢鍒楄〃
-            const listRes = await fileListPage({
-              accountId: currentFileRow.value.id,
-              accountType: accountType.value,
-              current: 1,
-              size: 100
-            });
-            if (listRes.code === 200 && fileListRef.value) {
-              const fileList = (listRes.data?.records || []).map(item => ({
-                name: item.name,
-                url: item.url,
-                id: item.id,
-                ...item
-              }));
-              fileListRef.value.setList(fileList);
-            }
-            // 杩斿洖鏂版枃浠朵俊鎭�
-            resolve({
-              name: fileData.name,
-              url: fileData.url,
-              id: saveRes.data?.id
-            });
-          } else {
-            proxy.$modal.msgError(saveRes.msg || "鏂囦欢淇濆瓨澶辫触");
-            resolve(null);
-          }
-        } else {
-          proxy.$modal.msgError(uploadRes.msg || "鏂囦欢涓婁紶澶辫触");
-          resolve(null);
-        }
-      } catch (error) {
-        proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
-        resolve(null);
-      } finally {
-        document.body.removeChild(input);
-      }
-    };
-    
-    document.body.appendChild(input);
-    input.click();
-  });
-};
-
-// 鍒犻櫎闄勪欢
-const handleFileDelete = async (row) => {
-  try {
-    const res = await fileDel([row.id]);
-    if (res.code === 200) {
-      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-      // 閲嶆柊鍔犺浇鏂囦欢鍒楄〃
-      if (currentFileRow.value && fileListRef.value) {
-        const listRes = await fileListPage({
-          accountId: currentFileRow.value.id,
-          accountType: accountType.value,
-          current: 1,
-          size: 100
-        });
-        if (listRes.code === 200) {
-          const fileList = (listRes.data?.records || []).map(item => ({
-            name: item.name,
-            url: item.url,
-            id: item.id,
-            ...item
-          }));
-          fileListRef.value.setList(fileList);
-        }
-      }
-      return true; // 杩斿洖 true 琛ㄧず鍒犻櫎鎴愬姛锛岀粍浠朵細鏇存柊鍒楄〃
-    } else {
-      proxy.$modal.msgError(res.msg || "鍒犻櫎澶辫触");
-      return false;
-    }
-  } catch (error) {
-    proxy.$modal.msgError("鍒犻櫎澶辫触");
-    return false;
-  }
-};
+  recordId.value = row.id
+  fileDialogVisible.value = true
+}
 
 onMounted(() => {
   getTableData();
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/index.vue b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
index d82e3e7..c94d8c2 100644
--- a/src/views/procurementManagement/procurementInvoiceLedger/index.vue
+++ b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
@@ -69,7 +69,7 @@
           <el-button
             type="primary"
             link
-            @click="downLoadFile(row)"
+            @click="openFileDialog(row)"
           >
             闄勪欢
           </el-button>
@@ -83,16 +83,7 @@
         </template>
       </PIMTable>
     </div>
-    <FileListDialog 
-      ref="fileListRef" 
-      v-model="fileListDialogVisible"
-      title="闄勪欢鍒楄〃"
-      :showUploadButton="true"
-      :showDeleteButton="true"
-      :deleteMethod="handleDeleteFile"
-      :uploadMethod="handleFileUpload"
-      :rulesRegulationsManagementId="currentRowId"
-    />
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" record-type="ticket_registration" :record-id="recordId"  />
     <EditModal ref="editmodalRef" @success="getTableData"></EditModal>
   </div>
 </template>
@@ -113,9 +104,9 @@
 import { onMounted } from "vue";
 import { ElMessageBox } from "element-plus";
 import EditModal from "./Modal/EditModal.vue";
-import FileListDialog from '@/components/Dialog/FileListDialog.vue';
 import useUserStore from "@/store/modules/user.js";
 const userStore = useUserStore();
+const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
 defineOptions({
   name: "鏉ョエ鍙拌处",
@@ -290,143 +281,15 @@
   onCurrentChange(page);
 };
 
-const downLoadFile = row => {
-  currentRowId.value = row.id;
-  if (fileListRef.value) {
-    fileListRef.value.open(row.commonFiles || []);
-  }
-};
+// 鎵撳紑闄勪欢寮圭獥
+const recordId =ref(0)
+const fileDialogVisible = ref(false)
 
-// 涓婁紶闄勪欢锛堣嚜瀹氫箟涓婁紶鏂规硶锛�
-const handleFileUpload = async () => {
-  if (!currentRowId.value) {
-    proxy.$modal.msgWarning("缂哄皯鐧昏ID锛屾棤娉曚繚瀛橀檮浠�");
-    return;
-  }
-  
-  return new Promise((resolve) => {
-    // 鍒涘缓涓�涓殣钘忕殑鏂囦欢杈撳叆鍏冪礌
-    const input = document.createElement('input');
-    input.type = 'file';
-    input.style.display = 'none';
-    input.onchange = async (e) => {
-      const file = e.target.files[0];
-      if (!file) {
-        resolve(null);
-        return;
-      }
-      
-      try {
-        // 浣跨敤 FormData 涓婁紶鏂囦欢
-        const formData = new FormData();
-        formData.append('file', file);
-        formData.append('type', '4'); // type 鍙傛暟锛岀敤鎴锋湭鎸囧畾鍏蜂綋鍊硷紝鍏堜紶绌哄瓧绗︿覆
-        formData.append('id', currentRowId.value); // 褰撳墠琛岀殑 id
-        
-        const uploadRes = await request({
-          url: '/file/uploadByCommon',
-          method: 'post',
-          data: formData,
-          headers: {
-            'Content-Type': 'multipart/form-data',
-            Authorization: `Bearer ${getToken()}`
-          }
-        });
-        
-        if (uploadRes.code === 200) {
-          proxy.$modal.msgSuccess("闄勪欢涓婁紶鎴愬姛");
-          
-          // 鍒锋柊鍒楄〃鑾峰彇鏈�鏂版暟鎹�
-          await new Promise((resolveRefresh) => {
-            // 璋冪敤 API 鑾峰彇鏈�鏂板垪琛ㄦ暟鎹�
-            productRecordPage({
-              ...filters,
-              current: pagination.currentPage,
-              size: pagination.pageSize
-            }).then(({ code, data }) => {
-              if (code === 200) {
-                // 鏇存柊鏁版嵁鍒楄〃
-                dataList.value = data.records;
-                pagination.total = data.total;
-                
-                // 浠庡閮ㄦ暟鎹幏鍙� commonFiles
-                const currentRow = dataList.value.find(row => row.id === currentRowId.value);
-                if (currentRow && fileListRef.value) {
-                  // 鍒锋柊闄勪欢鍒楄〃锛屼娇鐢ㄤ粠澶栭儴鑾峰彇鐨勬渶鏂� commonFiles
-                  fileListRef.value.open(currentRow.commonFiles || []);
-                }
-                resolveRefresh();
-              } else {
-                resolveRefresh();
-              }
-            }).catch(() => {
-              resolveRefresh();
-            });
-          });
-          
-          resolve({
-            name: uploadRes.data?.originalName || file.name,
-            url: uploadRes.data?.tempPath || uploadRes.data?.url,
-            id: uploadRes.data?.id
-          });
-        } else {
-          proxy.$modal.msgError(uploadRes.msg || "鏂囦欢涓婁紶澶辫触");
-          resolve(null);
-        }
-      } catch (error) {
-        console.error("闄勪欢涓婁紶澶辫触:", error);
-        proxy.$modal.msgError("闄勪欢涓婁紶澶辫触");
-        resolve(null);
-      } finally {
-        document.body.removeChild(input);
-      }
-    };
-    
-    document.body.appendChild(input);
-    input.click();
-  });
-};
-
-// 鍒犻櫎闄勪欢
-const handleDeleteFile = async (file) => {
-  try {
-    await delCommonFile([file.id]);
-    proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-    
-    // 鍒锋柊鍒楄〃鑾峰彇鏈�鏂版暟鎹�
-    await new Promise((resolveRefresh) => {
-      // 璋冪敤 API 鑾峰彇鏈�鏂板垪琛ㄦ暟鎹�
-      productRecordPage({
-        ...filters,
-        current: pagination.currentPage,
-        size: pagination.pageSize
-      }).then(({ code, data }) => {
-        if (code === 200) {
-          // 鏇存柊鏁版嵁鍒楄〃
-          dataList.value = data.records;
-          pagination.total = data.total;
-          
-          // 浠庡閮ㄦ暟鎹幏鍙� commonFiles
-          const currentRow = dataList.value.find(row => row.id === currentRowId.value);
-          if (currentRow && fileListRef.value) {
-            // 鍒锋柊闄勪欢鍒楄〃锛屼娇鐢ㄤ粠澶栭儴鑾峰彇鐨勬渶鏂� commonFiles
-            fileListRef.value.open(currentRow.commonFiles || []);
-          }
-          resolveRefresh();
-        } else {
-          resolveRefresh();
-        }
-      }).catch(() => {
-        resolveRefresh();
-      });
-    });
-    
-    return true;
-  } catch (error) {
-    proxy.$modal.msgError("鍒犻櫎澶辫触");
-    return false;
-  }
-};
+// 鎵撳紑闄勪欢寮规
+const openFileDialog = async (row) => {
+  recordId.value = row.id
+  fileDialogVisible.value = true
+}
 
 const openEdit = (row) => {
   editmodalRef.value.open(row);
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 5d60052..1991342 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -53,8 +53,7 @@
     <div class="table_list">
       <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
         <el-button type="primary"
-                   @click="openForm('add')">鏂板鍙拌处
-        </el-button>
+                   @click="openForm('add')">鏂板鍙拌处</el-button>
         <el-button type="primary" plain @click="handleImport">瀵煎叆</el-button>
         <el-button @click="handleOut">瀵煎嚭</el-button>
         <el-button type="danger"
@@ -181,8 +180,7 @@
             </el-button>
             <el-button link
                        type="primary"
-                       @click="downLoadFile(scope.row)">闄勪欢
-            </el-button>
+                       @click="openFileDialog(scope.row)">闄勪欢</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -632,51 +630,48 @@
         </el-row>
       </el-form>
     </FormDialog>
-    <FileListDialog
-        ref="fileListRef"
-        v-model="fileListDialogVisible"
-        title="闄勪欢鍒楄〃"
-    />
+    <FileList v-if="fileListDialogVisible"  v-model:visible="fileListDialogVisible" record-type="purchase_ledger" :record-id="recordId"  />
   </div>
 </template>
 
 <script setup>
-import {getToken} from "@/utils/auth";
-import pagination from "@/components/PIMTable/Pagination.vue";
-import {
-  ref,
-  onMounted,
-  reactive,
-  toRefs,
-  getCurrentInstance,
-  nextTick,
-} from "vue";
 import {Search, Delete} from "@element-plus/icons-vue";
-import {ElMessageBox, ElMessage} from "element-plus";
 import FormDialog from '@/components/Dialog/FormDialog.vue';
 import FileListDialog from '@/components/Dialog/FileListDialog.vue';
-import {
-  getSalesLedgerWithProducts,
-  addOrUpdateSalesLedgerProduct,
-  delProduct,
-  delLedgerFile,
-  getProductInfoByContractNo,
-} from "@/api/salesManagement/salesLedger.js";
-import {
-  addOrEditPurchase,
-  addPurchaseTemplate,
-  updatePurchaseTemplate,
-  createPurchaseNo,
-  delPurchase,
-  getSalesNo,
-  purchaseListPage,
-  productList,
-  getPurchaseById,
-  getOptions,
-  getPurchaseTemplateList,
-  delPurchaseTemplate,
-} from "@/api/procurementManagement/procurementLedger.js";
-import useFormData from "@/hooks/useFormData.js";
+  import { getToken } from "@/utils/auth";
+  import pagination from "@/components/PIMTable/Pagination.vue";
+  import {
+    ref,
+    onMounted,
+    reactive,
+    toRefs,
+    getCurrentInstance,
+    nextTick,
+  } from "vue";
+  import { Search, Delete } from "@element-plus/icons-vue";
+  import { ElMessageBox, ElMessage } from "element-plus";
+  import {
+    addOrUpdateSalesLedgerProduct,
+    delProduct,
+    delLedgerFile,
+    getProductInfoByContractNo,
+  } from "@/api/salesManagement/salesLedger.js";
+  import {
+    addOrEditPurchase,
+    addPurchaseTemplate,
+    updatePurchaseTemplate,
+    createPurchaseNo,
+    delPurchase,
+    getSalesNo,
+    purchaseListPage,
+    productList,
+    getPurchaseById,
+    getOptions,
+    getPurchaseTemplateList,
+    delPurchaseTemplate,
+  } from "@/api/procurementManagement/procurementLedger.js";
+  import useFormData from "@/hooks/useFormData.js";
+  const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
 const {proxy} = getCurrentInstance();
 const tableData = ref([]);
@@ -1760,6 +1755,12 @@
   }
 };
 
+// 鎵撳紑闄勪欢寮规
+const openFileDialog = async (row) => {
+  recordId.value = row.id
+  fileListDialogVisible.value = true
+}
+
 // 鍒犻櫎妯℃澘
 const handleDeleteTemplate = async (item) => {
   if (!item.id) {
diff --git a/src/views/productionManagement/processRoute/index.vue b/src/views/productionManagement/processRoute/index.vue
index 4a713dc..43425c6 100644
--- a/src/views/productionManagement/processRoute/index.vue
+++ b/src/views/productionManagement/processRoute/index.vue
@@ -61,7 +61,8 @@
   import EditProcess from "@/views/productionManagement/processRoute/Edit.vue";
   import RouteItemForm from "@/views/productionManagement/processRoute/ItemsForm.vue";
   import { listPage, del } from "@/api/productionManagement/processRoute.js";
-  import FileList from "@/components/Dialog/FileList.vue";
+  const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
+
   import { useRouter } from "vue-router";
   import { ElMessage, ElMessageBox } from "element-plus";
 
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index fd1a6a8..6d64c30 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -68,7 +68,8 @@
                    style="margin-right: 10px;">
           鍗$墖瑙嗗浘
         </el-button>
-        <el-button type="primary"
+        <el-button v-if="editable"
+                   type="primary"
                    @click="handleAdd">鏂板</el-button>
       </div>
     </div>
@@ -133,12 +134,12 @@
                      link
                      size="small"
                      @click="handleEdit(scope.row)"
-                     :disabled="scope.row.isComplete">缂栬緫</el-button>
+                     :disabled="scope.row.isComplete || !editable">缂栬緫</el-button>
           <el-button type="danger"
                      link
                      size="small"
                      @click="handleDelete(scope.row)"
-                     :disabled="scope.row.isComplete">鍒犻櫎</el-button>
+                     :disabled="scope.row.isComplete || !editable">鍒犻櫎</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -152,7 +153,8 @@
                      style="margin-right: 10px;">
             琛ㄦ牸瑙嗗浘
           </el-button>
-          <el-button type="primary"
+          <el-button v-if="editable"
+                     type="primary"
                      @click="handleAdd">鏂板</el-button>
         </div>
       </div>
@@ -196,7 +198,7 @@
                          link
                          size="small"
                          @click="handleEdit(item)"
-                         :disabled="item.isComplete">缂栬緫</el-button>
+                         :disabled="item.isComplete || !editable">缂栬緫</el-button>
               <el-button type="info"
                          link
                          size="small"
@@ -205,7 +207,7 @@
                          link
                          size="small"
                          @click="handleDelete(item)"
-                         :disabled="item.isComplete">鍒犻櫎</el-button>
+                         :disabled="item.isComplete || !editable">鍒犻櫎</el-button>
             </div>
           </div>
         </div>
@@ -216,7 +218,7 @@
          style="margin-top: 20px;">
       <div class="section-title">BOM 缁撴瀯</div>
       <div class="section-actions"
-           v-if="pageType === 'order'">
+           v-if="pageType === 'order' && editable">
         <el-button v-if="!bomDataValue.isEdit"
                    type="primary"
                    @click="bomDataValue.isEdit = true">
@@ -447,7 +449,6 @@
                          @confirm="handleProductSelect"
                          single />
     <!-- 鍙傛暟鍒楄〃瀵硅瘽妗� -->
-    <!-- :editable="!routeInfo.status" -->
     <ProcessParamListDialog v-model="showParamListDialog"
                             :title="`${currentProcess ? (currentProcess.processName || currentProcess.technologyOperationName || currentProcess.operationName) : ''} - 鍙傛暟鍒楄〃`"
                             :route-id="routeId"
@@ -455,6 +456,7 @@
                             :process="currentProcess"
                             :page-type="pageType"
                             :param-list="paramList"
+                            :editable="editable"
                             @getsyncProcessParamItem="getsyncProcessParamItem"
                             @refresh="refreshParamList" />
   </div>
@@ -509,6 +511,7 @@
   const routeId = computed(() => route.query.id);
   const orderId = computed(() => route.query.orderId);
   const pageType = computed(() => route.query.type);
+  const editable = computed(() => route.query.editable !== "false");
 
   const tableLoading = ref(false);
   const tableData = ref([]);
@@ -878,6 +881,7 @@
   // 鍒濆鍖栨嫋鎷芥帓搴�
   const initSortable = () => {
     destroySortable();
+    if (!editable.value) return;
 
     if (viewMode.value === "table") {
       // 琛ㄦ牸瑙嗗浘鐨勬嫋鎷芥帓搴�
diff --git a/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
index e9b2646..370815e 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue
@@ -55,14 +55,15 @@
                              controls-position="right"
                              placeholder="杈撳叆瀹為檯鏁伴噺"
                              style="width: 100%;"
-                             :disabled="row.returned"
+                             :disabled="row.returned || orderRow?.end"
                              @change="val => handleActualQtyChange(row, val)" />
           </template>
         </el-table-column>
       </el-table>
       <template #footer>
         <span class="dialog-footer">
-          <el-button type="warning"
+          <el-button v-if="!orderRow?.end"
+                     type="warning"
                      :loading="materialReturnConfirming"
                      :disabled="!canOpenReturnSummary"
                      @click="openReturnSummaryDialog">
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 00996ba..93fc177 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -40,6 +40,8 @@
                        value="3" />
             <el-option label="宸插彇娑�"
                        value="4" />
+            <el-option label="宸茬粨鏉�"
+                       value="5" />
           </el-select>
         </el-form-item>
         <el-form-item>
@@ -65,6 +67,7 @@
                 :tableLoading="tableLoading"
                 :row-class-name="tableRowClassName"
                 :isSelection="true"
+                :selectable="row => !row.endOrder"
                 @selection-change="handleSelectionChange"
                 @pagination="pagination">
         <template #completionStatus="{ row }">
@@ -210,6 +213,7 @@
     listProcessBom,
     delProductOrder,
     getProductOrderSource,
+    updateProductOrder,
   } from "@/api/productionManagement/productionOrder.js";
   import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
   import MaterialLedgerDialog from "@/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue";
@@ -243,7 +247,7 @@
       prop: "npsNo",
       width: "150px",
     },
-    // 1.寰呭紑濮嬨��2.杩涜涓��3.宸插畬鎴愩��4.宸插彇娑�
+    // 1.寰呭紑濮嬨��2.杩涜涓��3.宸插畬鎴愩��4.宸插彇娑堛��5.宸茬粨鏉�
     {
       label: "鐘舵��",
       prop: "status",
@@ -256,6 +260,8 @@
           ? "杩涜涓�"
           : val === 3
           ? "宸插畬鎴�"
+          : val === 5
+          ? "宸茬粨鏉�"
           : "宸插彇娑�",
       formatType: val =>
         val === 1
@@ -264,7 +270,9 @@
           ? "warning"
           : val === 3
           ? "success"
-          : "danger",
+          : val === 5
+          ? "danger"
+          : "info",
     },
     {
       label: "浜у搧鍚嶇О",
@@ -319,7 +327,7 @@
       label: "鎿嶄綔",
       align: "center",
       fixed: "right",
-      width: 260,
+      width: 280,
       operation: [
         {
           name: "宸ヨ壓璺嚎",
@@ -332,7 +340,7 @@
         {
           name: "缁戝畾宸ヨ壓璺嚎",
           type: "text",
-          showHide: row => !row.processRouteCode,
+          showHide: row => !row.processRouteCode && !row.endOrder,
           clickFun: row => {
             openBindRouteDialog(row, "add");
           },
@@ -340,7 +348,7 @@
         {
           name: "鏇存崲宸ヨ壓璺嚎",
           type: "text",
-          showHide: row => row.processRouteCode,
+          showHide: row => row.processRouteCode && !row.endOrder,
           clickFun: row => {
             openBindRouteDialog(row, "change");
           },
@@ -356,6 +364,7 @@
           name: "棰嗘枡",
           type: "text",
           color: "#5EC7AB",
+          showHide: row => !row.endOrder,
           clickFun: row => {
             openMaterialDialog(row);
           },
@@ -364,6 +373,7 @@
           name: "琛ユ枡",
           type: "text",
           color: "#5EC7AB",
+          showHide: row => !row.endOrder,
           clickFun: row => {
             openMaterialSupplementDialog(row);
           },
@@ -379,7 +389,8 @@
         {
           name: "鎵撳嵃棰嗘枡鍗�",
           type: "text",
-          color: "#409eff",
+          color: "#5EC7AB",
+          showHide: row => !row.endOrder,
           clickFun: row => {
             handlePrint(row);
           },
@@ -397,6 +408,15 @@
                 model: row.model,
               },
             });
+          },
+        },
+        {
+          name: "缁撴潫璁㈠崟",
+          type: "text",
+          color: "red",
+          showHide: row => !row.endOrder,
+          clickFun: row => {
+            handleEndOrder(row);
           },
         },
       ],
@@ -642,6 +662,7 @@
           quantity: row.quantity || 0,
           orderId,
           type: "order",
+          editable: !row.endOrder,
         },
       });
     } catch (e) {
@@ -736,6 +757,26 @@
       });
   };
 
+  // 缁撴潫璁㈠崟
+  const handleEndOrder = row => {
+    ElMessageBox.confirm(`鏄惁纭缁撴潫璁㈠崟锛�${row.npsNo}锛焋, "鎻愮ず", {
+      confirmButtonText: "纭畾",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(() => {
+        const params = {
+          id: row.id,
+          endOrder: true,
+        };
+        updateProductOrder(params).then(() => {
+          proxy.$modal.msgSuccess("缁撴潫璁㈠崟鎴愬姛");
+          getList();
+        });
+      })
+      .catch(() => {});
+  };
+
   const handleConfirmRoute = () => {};
 
   onMounted(() => {
diff --git a/src/views/productionManagement/workOrderManagement/index.vue b/src/views/productionManagement/workOrderManagement/index.vue
index bb09a10..dda27fc 100644
--- a/src/views/productionManagement/workOrderManagement/index.vue
+++ b/src/views/productionManagement/workOrderManagement/index.vue
@@ -244,6 +244,7 @@
                     @refresh="getList" />
     <FileList v-if="fileDialogVisible"
               v-model:visible="fileDialogVisible"
+              :editable="!currentWorkOrderRow?.endOrder"
               :record-type="'production_operation_task'"
               :record-id="currentWorkOrderId" />
   </div>
@@ -264,7 +265,8 @@
   import QRCode from "qrcode";
   import { getCurrentInstance, reactive, toRefs } from "vue";
   import MaterialDialog from "./components/MaterialDialog.vue";
-  import FileList from "@/components/Dialog/FileList.vue";
+  const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
+
   import useUserStore from "@/store/modules/user";
   const { proxy } = getCurrentInstance();
   const userStore = useUserStore();
@@ -370,6 +372,7 @@
           clickFun: row => {
             showReportDialog(row);
           },
+          showHide: row => !row.endOrder,
           disabled: row => {
             if (row.planQuantity <= 0) return true;
             if (!row.userIds) return false;
@@ -631,9 +634,11 @@
   const printTransferCard = () => {
     window.print();
   };
+  const currentWorkOrderRow = ref(null);
 
   const openWorkOrderFiles = row => {
     currentWorkOrderId.value = row.id;
+    currentWorkOrderRow.value = row;
     fileDialogVisible.value = true;
   };
 
diff --git a/src/views/safeProduction/safeQualifications/index.vue b/src/views/safeProduction/safeQualifications/index.vue
index 819c6da..39111be 100644
--- a/src/views/safeProduction/safeQualifications/index.vue
+++ b/src/views/safeProduction/safeQualifications/index.vue
@@ -110,7 +110,7 @@
             <el-button link
                        type="primary"
                        size="small"
-                       @click="downLoadFile(scope.row)">闄勪欢</el-button>
+                       @click="openFileDialog(scope.row)">闄勪欢</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -203,16 +203,7 @@
       </el-form>
     </FormDialog>
 <!-- todo 闄勪欢棰勮鐩稿叧 -->
-    <FileListDialog ref="fileListRef"
-                    v-model="fileListDialogVisible"
-                    :show-upload-button="true"
-                    :show-delete-button="true"
-                    :is-show-pagination="true"
-                    :page="filePagination"
-                    :upload-method="handleUpload"
-                    :delete-method="handleFileDelete"
-                    @pagination="paginationSearch"
-                    title="闄勪欢鍒楄〃" />
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" record-type="safe_certification" :record-id="recordId"  />
   </div>
 </template>
 
@@ -223,7 +214,6 @@
   import { ElMessageBox, ElMessage } from "element-plus";
   import useUserStore from "@/store/modules/user";
   import { userListNoPage } from "@/api/system/user.js";
-  import FileListDialog from "@/components/Dialog/FileListDialog.vue";
   import FormDialog from "@/components/Dialog/FormDialog.vue";
   import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
   import {
@@ -238,7 +228,7 @@
   import useFormData from "@/hooks/useFormData.js";
   import request from "@/utils/request";
   import dayjs from "dayjs";
-
+  const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
   const userStore = useUserStore();
   const { proxy } = getCurrentInstance();
   const tableData = ref([]);
@@ -524,19 +514,17 @@
     size: 10,
     total: 0,
   });
-  const downLoadFile = row => {
-    currentFileRow.value = row;
-    fileListPage({
-      safeCertificationId: row.id,
-      current: filePagination.value.current,
-      size: filePagination.value.size,
-    }).then(res => {
-      if (fileListRef.value) {
-        fileListRef.value.open(res.data.records);
-      }
-      filePagination.value.total = res.data.total || 0;
-    });
-  };
+
+  // 鎵撳紑闄勪欢寮圭獥
+  const recordId =ref(0)
+  const fileDialogVisible = ref(false)
+
+  // 鎵撳紑闄勪欢寮规
+  const openFileDialog = async (row) => {
+    recordId.value = row.id
+    fileDialogVisible.value = true
+  }
+  
   const currentFactoryName = ref("");
   const getCurrentFactoryName = async () => {
     let res = await userStore.getInfo();
diff --git a/src/views/safeProduction/safetyTrainingAssessment/index.vue b/src/views/safeProduction/safetyTrainingAssessment/index.vue
index b595bf6..2c98308 100644
--- a/src/views/safeProduction/safetyTrainingAssessment/index.vue
+++ b/src/views/safeProduction/safetyTrainingAssessment/index.vue
@@ -239,7 +239,7 @@
           <el-descriptions-item label="闄勪欢鍒楄〃:">
             <el-button type="primary"
                        size="small"
-                       @click="downLoadFile(endform)">闄勪欢鍒楄〃</el-button>
+                       @click="openFileDialog(endform)">闄勪欢鍒楄〃</el-button>
           </el-descriptions-item>
         </el-descriptions>
         <!-- <el-divider style="margin: 20px 0;" /> -->
@@ -359,22 +359,12 @@
       </template>
     </el-dialog>
     <!--  todo 闄勪欢棰勮鐩稿叧 -->
-    <FileListDialog ref="fileListRef"
-                    v-model="fileListDialogVisible"
-                    :show-upload-button="true"
-                    :show-delete-button="true"
-                    :is-show-pagination="true"
-                    :page="filePagination"
-                    :upload-method="handleUpload"
-                    :delete-method="handleFileDelete"
-                    @pagination="paginationSearch"
-                    title="闄勪欢鍒楄〃" />
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" record-type="safe_training" :record-id="recordId"  />
   </div>
 </template>
 
 <script setup>
   import { Search } from "@element-plus/icons-vue";
-  import FileListDialog from "@/components/Dialog/FileListDialog.vue";
   import {
     onMounted,
     ref,
@@ -403,6 +393,7 @@
   import useUserStore from "@/store/modules/user";
   import dayjs from "dayjs";
   const userStore = useUserStore();
+  const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
   // 琛ㄥ崟楠岃瘉瑙勫垯
   const rules = {
@@ -621,7 +612,7 @@
           name: "闄勪欢",
           type: "text",
           clickFun: row => {
-            downLoadFile(row);
+            openFileDialog(row);
           },
           color: "#007AFF",
         },
@@ -783,27 +774,17 @@
       form.value.principalMobile = selectedUser.phonenumber;
     }
   };
-  /**
-   * 涓嬭浇鏂囦欢
-   *
-   * @param row 涓嬭浇鏂囦欢鐨勭浉鍏充俊鎭璞�
-   */
-  const fileListRef = ref(null);
-  const fileListDialogVisible = ref(false);
-  const currentFileRow = ref(null);
-  const downLoadFile = row => {
-    currentFileRow.value = row;
-    safeTrainingFileListPage({
-      safeTrainingId: row.id,
-      current: filePagination.value.current,
-      size: filePagination.value.size,
-    }).then(res => {
-      if (fileListRef.value) {
-        fileListRef.value.open(res.data.records);
-        filePagination.value.total = res.data?.total || 0;
-      }
-    });
-  };
+
+  // 鎵撳紑闄勪欢寮圭獥
+  const recordId =ref(0)
+  const fileDialogVisible = ref(false)
+
+  // 鎵撳紑闄勪欢寮规
+  const openFileDialog = async (row) => {
+    recordId.value = row.id
+    fileDialogVisible.value = true
+  }
+  
   // 涓婁紶闄勪欢
   const handleUpload = async () => {
     if (!currentFileRow.value) {
diff --git a/src/views/salesManagement/invoiceLedger/index.vue b/src/views/salesManagement/invoiceLedger/index.vue
index 3827854..444560d 100644
--- a/src/views/salesManagement/invoiceLedger/index.vue
+++ b/src/views/salesManagement/invoiceLedger/index.vue
@@ -44,7 +44,7 @@
         <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
           <template #default="scope">
             <el-button link type="primary" @click="openForm(scope.row)">缂栬緫</el-button>
-            <el-button link type="primary" @click="downLoadFile(scope.row)">闄勪欢</el-button>
+            <el-button link type="primary" @click="openFileDialog(scope.row)">闄勪欢</el-button>
             <el-button link type="primary" @click="delInvoiceLedger(scope.row)">鍒犻櫎</el-button>
           </template>
         </el-table-column>
@@ -134,7 +134,7 @@
         </div>
       </template>
     </el-dialog>
-    <FileListDialog ref="fileListRef" v-model="fileListDialogVisible" />
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" record-type="invoice_registration_product" :record-id="recordId"  />
   </div>
 </template>
 
@@ -155,8 +155,8 @@
 import useUserStore from "@/store/modules/user.js";
 import useFormData from "@/hooks/useFormData";
 import dayjs from "dayjs";
-import FileListDialog from '@/components/Dialog/FileListDialog.vue';
 import { getCurrentDate } from "@/utils/index.js";
+const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
 const { proxy } = getCurrentInstance();
 const tableData = ref([]);
@@ -422,17 +422,14 @@
   getList();
 };
 
-//闄勪欢鐩稿叧
-const fileListRef = ref(null)
-const fileListDialogVisible = ref(false)
-//鏌ョ湅闄勪欢
-const downLoadFile = (row) => {
-	invoiceLedgerProductInfo({ id: row.id }).then((res) => {
-		if (fileListRef.value) {
-			fileListRef.value.open(res.data.fileList)
-			fileListDialogVisible.value = true
-		}
-	});
+// 鎵撳紑闄勪欢寮圭獥
+const recordId =ref(0)
+const fileDialogVisible = ref(false)
+
+// 鎵撳紑闄勪欢寮规
+const openFileDialog = async (row) => {
+  recordId.value = row.id
+  fileDialogVisible.value = true
 }
 
 onMounted(() => {
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index dc648be..1235f94 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -231,7 +231,7 @@
                        :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">缂栬緫</el-button>
             <el-button link
                        type="primary"
-                       @click="downLoadFile(scope.row)">闄勪欢</el-button>
+                       @click="openFileDialog(scope.row)">闄勪欢</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -740,9 +740,7 @@
     </FormDialog>
 <!-- // todo 闄勪欢棰勮鐩稿叧 -->
     <!-- 闄勪欢鍒楄〃寮圭獥 -->
-    <FileListDialog ref="fileListRef"
-                    v-model="fileListDialogVisible"
-                    title="闄勪欢鍒楄〃" />
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" record-type="sales_ledger" :record-id="recordId"  />
     <!-- 鎵撳嵃棰勮寮圭獥 -->
     <el-dialog v-model="printPreviewVisible"
                title="鎵撳嵃棰勮"
@@ -904,10 +902,8 @@
   import { onMounted, ref, getCurrentInstance } from "vue";
   import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
   import { ElMessageBox, ElMessage } from "element-plus";
-  import { UploadFilled, Download } from "@element-plus/icons-vue";
   import useUserStore from "@/store/modules/user";
   import { userListNoPage } from "@/api/system/user.js";
-  import FileListDialog from "@/components/Dialog/FileListDialog.vue";
   import FormDialog from "@/components/Dialog/FormDialog.vue";
   import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
   import {
@@ -929,6 +925,9 @@
   import { useRouter, useRoute } from "vue-router";
   import { listCustomerPrivatePool } from "@/api/basicData/customerFile.js";
   import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+
+  const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
+
   const router = useRouter();
   const route = useRoute();
   const userStore = useUserStore();
@@ -2440,20 +2439,15 @@
     return statusStr === "寰呭彂璐�" || statusStr === "瀹℃牳鎷掔粷";
   };
 
-  /**
-   * 涓嬭浇鏂囦欢
-   *
-   * @param row 涓嬭浇鏂囦欢鐨勭浉鍏充俊鎭璞�
-   */
-  const fileListRef = ref(null);
-  const fileListDialogVisible = ref(false);
-  const downLoadFile = row => {
-    getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
-      if (fileListRef.value) {
-        fileListRef.value.open(res.salesLedgerFiles);
-      }
-    });
-  };
+  // 鎵撳紑闄勪欢寮圭獥
+  const recordId =ref(0)
+  const fileDialogVisible = ref(false)
+
+  // 鎵撳紑闄勪欢寮规
+  const openFileDialog = async (row) => {
+    recordId.value = row.id
+    fileDialogVisible.value = true
+  }
 
   // 鎵撳紑鍙戣揣寮规
   const openDeliveryForm = row => {

--
Gitblit v1.9.3