From f84e425bb9debb5f2af8e417bf07d2a2b0077609 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 28 四月 2026 17:00:03 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_NEW_pro

---
 src/views/equipmentManagement/upkeep/index.vue               |   88 ----------
 src/views/equipmentManagement/upkeep/Form/PlanModal.vue      |   22 ++
 src/views/equipmentManagement/repair/Modal/RepairModal.vue   |   16 +
 src/api/basicData/storageAttachment.js                       |   29 +++
 src/views/equipmentManagement/repair/index.vue               |   22 ++
 src/api/productionManagement/productionOrder.js              |    2 
 src/components/Dialog/FileList.vue                           |  253 +++++++++++++++++++++++++++++++
 src/views/productionManagement/workOrderManagement/index.vue |    1 
 8 files changed, 339 insertions(+), 94 deletions(-)

diff --git a/src/api/basicData/storageAttachment.js b/src/api/basicData/storageAttachment.js
new file mode 100644
index 0000000..56364a4
--- /dev/null
+++ b/src/api/basicData/storageAttachment.js
@@ -0,0 +1,29 @@
+// 闄勪欢椤甸潰鎺ュ彛
+import request from '@/utils/request'
+
+// 闄勪欢鏌ヨ
+export function attachmentList(query) {
+    return request({
+        url: '/basic/storage_attachment/list',
+        method: 'get',
+        params: query
+    })
+}
+
+// 闄勪欢鏂板
+export function createAttachment(data) {
+    return request({
+        url: '/basic/storage_attachment/add',
+        method: 'post',
+        data
+    })
+}
+
+// 闄勪欢鍒犻櫎
+export function deleteAttachment(data) {
+    return request({
+        url: '/basic/storage_attachment/delete',
+        method: 'delete',
+        data
+    })
+}
diff --git a/src/api/productionManagement/productionOrder.js b/src/api/productionManagement/productionOrder.js
index b87adbb..688abfc 100644
--- a/src/api/productionManagement/productionOrder.js
+++ b/src/api/productionManagement/productionOrder.js
@@ -116,7 +116,7 @@
 // 鐢熶骇璁㈠崟-琛ユ枡璁板綍鍒楄〃
 export function listMaterialSupplementRecord(query) {
   return request({
-    url: "/productOrderMaterial/supplementRecord",
+    url: "/productionOrderPickRecord/feeding",
     method: "get",
     params: query,
   });
diff --git a/src/components/Dialog/FileList.vue b/src/components/Dialog/FileList.vue
new file mode 100644
index 0000000..e373c27
--- /dev/null
+++ b/src/components/Dialog/FileList.vue
@@ -0,0 +1,253 @@
+<template>
+  <el-dialog
+      v-model="isShow"
+      :title="title"
+      :width="width"
+      @close="handleClose"
+      class="attachment-dialog"
+  >
+    <!-- 宸ュ叿鏍� -->
+    <div class="toolbar">
+      <el-button
+          type="primary"
+          size="small"
+          @click="handleUpload"
+      >
+        涓婁紶闄勪欢
+      </el-button>
+    </div>
+
+    <!-- 涓婁紶缁勪欢寮圭獥 -->
+    <el-dialog
+        v-model="uploadDialogVisible"
+        title="涓婁紶闄勪欢"
+        width="50%"
+        @close="handleUploadClose"
+    >
+      <AttachmentUpload
+          v-model:file-list="newFileList"
+      />
+      <template #footer>
+        <el-button @click="handleUploadClose">鍏抽棴</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 鏂囦欢鍒楄〃琛ㄦ牸 -->
+    <div class="table-container">
+      <el-table
+          :data="tableData"
+          border
+          class="attachment-table"
+          :height="tableData.length > 0 ? 'auto' : '120px'"
+      >
+        <el-table-column
+            label="闄勪欢鍚嶇О"
+            prop="originalFilename"
+            show-overflow-tooltip
+        />
+        <el-table-column
+            v-if="showActions"
+            fixed="right"
+            label="鎿嶄綔"
+            :width="120"
+            align="center"
+        >
+          <template #default="scope">
+            <el-button
+                link
+                type="primary"
+                size="small"
+                :href="scope.row.downloadURL"
+                class="download-link"
+            >
+              涓嬭浇
+            </el-button>
+            <el-button
+                link
+                type="danger"
+                size="small"
+                @click="handleDelete(scope.row)"
+            >
+              鍒犻櫎
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </el-dialog>
+</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";
+
+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 emit = defineEmits([
+  'close',
+  'download',
+  'upload',
+  'delete'
+])
+
+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 handleClose = () => {
+  isShow.value = false
+}
+
+const handleUpload = () => {
+  uploadDialogVisible.value = true
+}
+
+const handleUploadClose = 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 handleDelete = async (row, index) => {
+  try {
+    await deleteAttachment([row.storageAttachmentId])
+    proxy?.$modal?.msgSuccess('鍒犻櫎鎴愬姛')
+    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 || []
+    }
+  })
+}
+
+onMounted(() => {
+  setList()
+})
+</script>
+
+<style scoped>
+.attachment-dialog {
+  border-radius: 12px;
+}
+
+.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;
+}
+
+:deep(.el-table) {
+  margin-bottom: 0;
+}
+
+:deep(.el-table__body-wrapper) {
+  overflow-y: auto;
+  will-change: transform;
+  transform: translateZ(0);
+}
+
+:deep(.el-table__body tr) {
+  transition: none;
+}
+
+:deep(.el-dialog__footer) {
+  padding-top: 12px;
+  border-top: 1px solid #e9ecef;
+}
+
+.attachment-table {
+  border-radius: 8px;
+}
+
+: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__body) {
+  padding: 16px 20px;
+}
+
+:deep(.el-table__empty-text) {
+  color: #999;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/equipmentManagement/repair/Modal/RepairModal.vue b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
index 1728b37..5e31943 100644
--- a/src/views/equipmentManagement/repair/Modal/RepairModal.vue
+++ b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -49,8 +49,8 @@
           </el-form-item>
         </el-col>
         <el-col :span="12">
-          <el-form-item label="绫荤洰">
-            <el-input v-model="form.machineryCategory" placeholder="璇疯緭鍏ョ被鐩�" />
+          <el-form-item label="椤圭洰">
+            <el-input v-model="form.machineryCategory" placeholder="璇疯緭鍏ラ」鐩�" />
           </el-form-item>
         </el-col>
       </el-row>
@@ -77,12 +77,20 @@
           </el-form-item>
         </el-col>
       </el-row>
+      <el-row :gutter="30">
+        <el-col :span="24">
+          <el-form-item label="闄勪欢" prop="attachmentIds">
+            <FileUpload v-model:file-list="form.storageBlobDTOs" />
+          </el-form-item>
+        </el-col>
+      </el-row>
     </el-form>
   </FormDialog>
 </template>
 
 <script setup>
 import FormDialog from "@/components/Dialog/FormDialog.vue";
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
 import {
   addRepair,
   editRepair,
@@ -106,6 +114,7 @@
 
 const userStore = useUserStore();
 const deviceOptions = ref([]);
+const fileList = ref([]);
 
 const loadDeviceName = async () => {
   const { data } = await getDeviceLedger();
@@ -121,6 +130,7 @@
   remark: undefined, // 鏁呴殰鐜拌薄
   status: 0, // 鎶ヤ慨鐘舵��
   machineryCategory: undefined,
+  storageBlobDTOs: [],
 });
 
 const setDeviceModel = (deviceId) => {
@@ -137,6 +147,7 @@
   form.remark = data.remark;
   form.status = data.status;
   form.machineryCategory = data.machineryCategory;
+  form.storageBlobDTOs = data.storageBlobVOs || [];
 };
 
 const sendForm = async () => {
@@ -168,6 +179,7 @@
 const openAdd = async () => {
   id.value = undefined;
   visible.value = true;
+  fileList.value = [];
   await nextTick();
   await loadDeviceName();
 };
diff --git a/src/views/equipmentManagement/repair/index.vue b/src/views/equipmentManagement/repair/index.vue
index 27d0acb..f3a4330 100644
--- a/src/views/equipmentManagement/repair/index.vue
+++ b/src/views/equipmentManagement/repair/index.vue
@@ -127,22 +127,31 @@
           >
             鍒犻櫎
           </el-button>
+          <el-button
+              type="primary"
+              link
+              @click="openFileDialog(row)"
+          >
+            闄勪欢
+          </el-button>
         </template>
       </PIMTable>
     </div>
     <RepairModal ref="repairModalRef" @ok="getTableData"/>
     <MaintainModal ref="maintainModalRef" @ok="getTableData"/>
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" :record-type="'device_repair'" :record-id="recordId"  />
   </div>
 </template>
 
 <script setup>
-import { onMounted, getCurrentInstance, computed } from "vue";
+import {onMounted, getCurrentInstance, computed, ref, defineAsyncComponent} from "vue";
 import {usePaginationApi} from "@/hooks/usePaginationApi";
 import {getRepairPage, delRepair} from "@/api/equipmentManagement/repair";
 import RepairModal from "./Modal/RepairModal.vue";
 import {ElMessageBox, ElMessage} from "element-plus";
 import dayjs from "dayjs";
 import MaintainModal from "./Modal/MaintainModal.vue";
+const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
 defineOptions({
   name: "璁惧鎶ヤ慨",
@@ -188,7 +197,7 @@
         prop: "deviceModel",
       },
       {
-        label: "绫荤洰",
+        label: "椤圭洰",
         align: "center",
         prop: "machineryCategory",
       },
@@ -258,6 +267,15 @@
   getTableData();
 };
 
+// 鎵撳紑闄勪欢寮圭獥
+const recordId =ref(0)
+const fileDialogVisible = ref(false)
+
+const openFileDialog = async (row) => {
+  recordId.value = row.id
+  fileDialogVisible.value = true
+}
+
 // 澶氶�夊悗鍋氫粈涔�
 const handleSelectionChange = (selectionList) => {
   multipleList.value = selectionList;
diff --git a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
index 6fa6595..ee59ce2 100644
--- a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
+++ b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
@@ -32,10 +32,10 @@
           disabled
         />
       </el-form-item>
-      <el-form-item label="绫荤洰">
+      <el-form-item label="椤圭洰">
         <el-input
             v-model="form.machineryCategory"
-            placeholder="璇疯緭鍏ョ被鐩�"
+            placeholder="璇疯緭鍏ラ」鐩�"
         />
       </el-form-item>
       <el-form-item label="褰曞叆浜�">
@@ -73,6 +73,13 @@
           clearable
         />
       </el-form-item>
+      <el-row :gutter="30">
+        <el-col :span="24">
+          <el-form-item label="闄勪欢" prop="attachmentIds">
+            <FileUpload v-model:file-list="form.storageBlobDTOs" />
+          </el-form-item>
+        </el-col>
+      </el-row>
     </el-form>
   </FormDialog>
 </template>
@@ -90,6 +97,7 @@
 import { onMounted } from "vue";
 import dayjs from "dayjs";
 import { userListNoPage } from "@/api/system/user.js";
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
 
 defineOptions({
   name: "璁惧淇濆吇鏂板璁″垝",
@@ -115,6 +123,7 @@
   createUser: undefined, // 褰曞叆浜�
   status: 0, //淇濅慨鐘舵��
   machineryCategory: undefined,
+  storageBlobDTOs: [],
 });
 
 const setDeviceModel = (deviceId) => {
@@ -133,9 +142,12 @@
   form.createUser = Number(data.createUser);
   form.status = data.status;
   form.machineryCategory = data.machineryCategory;
-  form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
-    "YYYY-MM-DD HH:mm:ss"
-  );
+  if (data.maintenancePlanTime) {
+    form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
+      "YYYY-MM-DD HH:mm:ss"
+    );
+  }
+  form.storageBlobDTOs = data.storageBlobVOs || [];
 };
 
 // 鐢ㄦ埛鍒楄〃
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 1e65663..3b771bf 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -218,40 +218,27 @@
     <PlanModal ref="planModalRef" @ok="getTableData" />
         <MaintenanceModal ref="maintainModalRef" @ok="getTableData" />
         <FormDia ref="formDiaRef" @closeDia="getScheduledTableData" />
-    <FileListDialog 
-      ref="fileListDialogRef"
-      v-model="fileDialogVisible"
-      :show-upload-button="true"
-      :show-delete-button="true"
-      :delete-method="handleAttachmentDelete"
-      :name-column-label="'闄勪欢鍚嶇О'"
-      :rulesRegulationsManagementId="currentMaintenanceTaskId"
-      @upload="handleAttachmentUpload" />
+    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" :record-type="'device_maintenance'" :record-id="currentMaintenanceTaskId"  />
   </div>
 </template>
 
 <script setup>
-import { ref, onMounted, reactive, getCurrentInstance, nextTick, computed } from 'vue'
+import {ref, onMounted, reactive, getCurrentInstance, nextTick, computed, defineAsyncComponent} from 'vue'
 import { Search } from '@element-plus/icons-vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import PlanModal from './Form/PlanModal.vue'
 import MaintenanceModal from './Form/MaintenanceModal.vue'
 import FormDia from './Form/formDia.vue'
-import FileListDialog from '@/components/Dialog/FileListDialog.vue'
 import {
   getUpkeepPage,
   delUpkeep,
   deviceMaintenanceTaskList,
   deviceMaintenanceTaskDel,
 } from '@/api/equipmentManagement/upkeep'
-import {
-  listMaintenanceTaskFiles,
-  addMaintenanceTaskFile,
-  delMaintenanceTaskFile,
-} from '@/api/equipmentManagement/maintenanceTaskFile'
 import dayjs from 'dayjs'
 
 const { proxy } = getCurrentInstance()
+const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
 // Tab鐩稿叧
 const activeTab = ref('scheduled')
@@ -373,7 +360,7 @@
 		prop: "createUserName",
 	},
   {
-    label: "绫荤洰",
+    label: "椤圭洰",
     align: "center",
     prop: "machineryCategory",
   },
@@ -602,77 +589,10 @@
   getTableData()
 }
 
-// 闄勪欢鐩稿叧鏂规硶
-// 鏌ヨ闄勪欢鍒楄〃
-const fetchMaintenanceTaskFiles = async (deviceMaintenanceId) => {
-  try {
-    const params = {
-      current: 1,
-      size: 100,
-      deviceMaintenanceId,
-      rulesRegulationsManagementId:deviceMaintenanceId
-    }
-    const res = await listMaintenanceTaskFiles(params)
-    const records = res?.data?.records || []
-    const mapped = records.map(item => ({
-      id: item.id,
-      name: item.fileName || item.name,
-      url: item.fileUrl || item.url,
-      raw: item,
-    }))
-    fileListDialogRef.value?.setList(mapped)
-  } catch (error) {
-    ElMessage.error('鑾峰彇闄勪欢鍒楄〃澶辫触')
-  }
-}
-
 // 鎵撳紑闄勪欢寮圭獥
 const openFileDialog = async (row) => {
   currentMaintenanceTaskId.value = row.id
   fileDialogVisible.value = true
-  await fetchMaintenanceTaskFiles(row.id)
-}
-
-// 鍒锋柊闄勪欢鍒楄〃
-const refreshFileList = async () => {
-  if (!currentMaintenanceTaskId.value) return
-  await fetchMaintenanceTaskFiles(currentMaintenanceTaskId.value)
-}
-
-// 涓婁紶闄勪欢
-const handleAttachmentUpload = async (filePayload) => {
-  if (!currentMaintenanceTaskId.value) return
-  try {
-    const payload = {
-      name: filePayload?.fileName || filePayload?.name,
-      url: filePayload?.fileUrl || filePayload?.url,
-      deviceMaintenanceId: currentMaintenanceTaskId.value,
-    }
-    await addMaintenanceTaskFile(payload)
-    ElMessage.success('鏂囦欢涓婁紶鎴愬姛')
-    await refreshFileList()
-  } catch (error) {
-    ElMessage.error('鏂囦欢涓婁紶澶辫触')
-  }
-}
-
-// 鍒犻櫎闄勪欢
-const handleAttachmentDelete = async (row) => {
-  if (!row?.id) return false
-  try {
-    await ElMessageBox.confirm('纭鍒犻櫎璇ラ檮浠讹紵', '鎻愮ず', { type: 'warning' })
-  } catch {
-    return false
-  }
-  try {
-    await delMaintenanceTaskFile(row.id)
-    ElMessage.success('鍒犻櫎鎴愬姛')
-    await refreshFileList()
-    return true
-  } catch (error) {
-    ElMessage.error('鍒犻櫎澶辫触')
-    return false
-  }
 }
 
 onMounted(() => {
diff --git a/src/views/productionManagement/workOrderManagement/index.vue b/src/views/productionManagement/workOrderManagement/index.vue
index 819e3fd..d60132a 100644
--- a/src/views/productionManagement/workOrderManagement/index.vue
+++ b/src/views/productionManagement/workOrderManagement/index.vue
@@ -225,6 +225,7 @@
     {
       label: "宸ュ簭鍚嶇О",
       prop: "operationName",
+      width: "100",
     },
     {
       label: "闇�姹傛暟閲�",

--
Gitblit v1.9.3