From 4929ce0e87c60a2786ceb3bffeea867690920127 Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期二, 24 三月 2026 17:52:46 +0800
Subject: [PATCH] feat(生产管理): 新增工序设备绑定管理功能

---
 src/views/productionManagement/productionProcess/index.vue |  204 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 203 insertions(+), 1 deletions(-)

diff --git a/src/views/productionManagement/productionProcess/index.vue b/src/views/productionManagement/productionProcess/index.vue
index f3129b6..5bf92e4 100644
--- a/src/views/productionManagement/productionProcess/index.vue
+++ b/src/views/productionManagement/productionProcess/index.vue
@@ -93,6 +93,45 @@
       </template>
     </el-dialog>
 
+    <!-- 鏌ョ湅璁惧寮规 -->
+    <el-dialog v-model="isShowDeviceModal"
+               title="璁惧鍒楄〃"
+               width="900px">
+      <div style="text-align: right"
+           class="mb10">
+        <el-button type="primary"
+                   @click="showAddDeviceModal">娣诲姞璁惧</el-button>
+      </div>
+      <PIMTable rowKey="id"
+                :column="deviceColumns"
+                :tableData="deviceTableData"
+                :page="devicePage"
+                :isSelection="false"
+                @pagination="devicePagination"
+                :total="devicePage.total"></PIMTable>
+    </el-dialog>
+
+    <!-- 娣诲姞璁惧寮规 -->
+    <el-dialog v-model="isShowSelectDeviceModal"
+               title="閫夋嫨璁惧"
+               width="900px">
+      <PIMTable rowKey="id"
+                :column="selectDeviceColumns"
+                :tableData="selectDeviceTableData"
+                :page="selectDevicePage"
+                :isSelection="true"
+                @selection-change="handleSelectDeviceChange"
+                @pagination="selectDevicePagination"
+                :total="selectDevicePage.total"></PIMTable>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary"
+                     @click="handleBindDevices">纭畾</el-button>
+          <el-button @click="isShowSelectDeviceModal = false">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
     <new-process v-if="isShowNewModal"
                  v-model:visible="isShowNewModal"
                  @completed="getList" />
@@ -124,6 +163,9 @@
     del,
     importData,
     downloadTemplate,
+    getBindDevices,
+    bindDevices,
+    unbindDevice,
   } from "@/api/productionManagement/productionProcess.js";
   import {
     listPage as listProcessParamPage,
@@ -131,6 +173,7 @@
     addProductProcessParameter,
   } from "@/api/productionManagement/productProcessParameter.js";
   import { listPage as listProductParamPage } from "@/api/productionManagement/productionRecords.js";
+  import { getLedgerPage } from "@/api/equipmentManagement/ledger.js";
   import { getToken } from "@/utils/auth";
 
   const data = reactive({
@@ -177,13 +220,20 @@
       label: "鎿嶄綔",
       align: "center",
       fixed: "right",
-      width: 280,
+      width: 350,
       operation: [
         {
           name: "鏌ョ湅",
           type: "text",
           clickFun: row => {
             showProcessParamModal(row);
+          },
+        },
+        {
+          name: "鏌ョ湅璁惧",
+          type: "text",
+          clickFun: row => {
+            showDeviceModal(row);
           },
         },
         {
@@ -240,6 +290,40 @@
       formatData: v => (v === "1" || v === 1 ? "鏄�" : "鍚�"),
     },
   ]);
+
+  // 璁惧鍒楄〃鍒楅厤缃�
+  const deviceColumns = ref([
+    { label: "璁惧鍚嶇О", prop: "deviceName" },
+    { label: "瑙勬牸鍨嬪彿", prop: "deviceModel" },
+    { label: "璁惧鍝佺墝", prop: "deviceBrand" },
+    { label: "璁惧绫诲瀷", prop: "type" },
+    { label: "渚涘簲鍟�", prop: "supplierName" },
+    {
+      dataType: "action",
+      label: "鎿嶄綔",
+      align: "center",
+      width: 100,
+      operation: [
+        {
+          name: "鍒犻櫎",
+          type: "text",
+          typeAttrs: { danger: true },
+          clickFun: row => {
+            handleUnbindDevice(row);
+          },
+        },
+      ],
+    },
+  ]);
+
+  // 鍙�夎澶囧垪琛ㄥ垪閰嶇疆
+  const selectDeviceColumns = ref([
+    { label: "璁惧鍚嶇О", prop: "deviceName" },
+    { label: "瑙勬牸鍨嬪彿", prop: "deviceModel" },
+    { label: "璁惧鍝佺墝", prop: "deviceBrand" },
+    { label: "璁惧绫诲瀷", prop: "type" },
+    { label: "渚涘簲鍟�", prop: "supplierName" },
+  ]);
   const tableData = ref([]);
   const selectedRows = ref([]);
   const tableLoading = ref(false);
@@ -270,6 +354,23 @@
   const productParamTableData = ref([]);
   const processParamSelectedRows = ref([]);
   const productParamSelectedRows = ref([]);
+
+  // 璁惧鐩稿叧鍙橀噺
+  const isShowDeviceModal = ref(false);
+  const isShowSelectDeviceModal = ref(false);
+  const deviceTableData = ref([]);
+  const selectDeviceTableData = ref([]);
+  const selectedDeviceRows = ref([]);
+  const devicePage = reactive({
+    current: 1,
+    size: 100,
+    total: 0,
+  });
+  const selectDevicePage = reactive({
+    current: 1,
+    size: 100,
+    total: 0,
+  });
   const { proxy } = getCurrentInstance();
 
   // 瀵煎叆鐩稿叧閰嶇疆
@@ -421,6 +522,107 @@
         .catch(() => {});
   };
 
+  // 鏌ョ湅璁惧寮规
+  const showDeviceModal = row => {
+    currentProcess.value = row;
+    isShowDeviceModal.value = true;
+    devicePage.current = 1;
+    getDeviceList();
+  };
+
+  // 鑾峰彇宸茬粦瀹氱殑璁惧鍒楄〃
+  const getDeviceList = () => {
+    if (!currentProcess.value) return;
+    getBindDevices(currentProcess.value.id)
+      .then(res => {
+        deviceTableData.value = res.data || [];
+        devicePage.total = res.data?.length || 0;
+      })
+      .catch(() => {});
+  };
+
+  // 璁惧鍒楄〃鍒嗛〉
+  const devicePagination = obj => {
+    devicePage.current = obj.page;
+    devicePage.size = obj.limit;
+    getDeviceList();
+  };
+
+  // 瑙g粦璁惧
+  const handleUnbindDevice = row => {
+    if (!currentProcess.value) return;
+    proxy.$modal.confirm("鏄惁纭瑙g粦璇ヨ澶囷紵")
+      .then(() => {
+        return unbindDevice(currentProcess.value.id, row.id);
+      })
+      .then(() => {
+        proxy.$modal.msgSuccess("瑙g粦鎴愬姛");
+        getDeviceList();
+      })
+      .catch(() => {});
+  };
+
+  // 鎵撳紑娣诲姞璁惧寮规
+  const showAddDeviceModal = () => {
+    isShowSelectDeviceModal.value = true;
+    selectDevicePage.current = 1;
+    selectedDeviceRows.value = [];
+    getSelectDeviceList();
+  };
+
+  // 鑾峰彇鍙�夎澶囧垪琛�
+  const getSelectDeviceList = () => {
+    if (!currentProcess.value) return;
+    // 鍏堣幏鍙栧凡缁戝畾鐨勮澶嘔D
+    getBindDevices(currentProcess.value.id)
+      .then(res => {
+        const boundDeviceIds = new Set(
+          (res.data || []).map(item => item.id).filter(id => !!id)
+        );
+        // 鑾峰彇璁惧鍙拌处鍒嗛〉鍒楄〃
+        return getLedgerPage(selectDevicePage).then(deviceRes => {
+          const allDevices = deviceRes.data?.records || [];
+          // 杩囨护鎺夊凡缁戝畾鐨勮澶囷紝骞舵爣璁颁负disabled
+          selectDeviceTableData.value = allDevices.map(item => ({
+            ...item,
+            disabled: boundDeviceIds.has(item.id),
+          }));
+          selectDevicePage.total = deviceRes.data?.total || 0;
+        });
+      })
+      .catch(() => {});
+  };
+
+  // 閫夋嫨璁惧鍙樺寲
+  const handleSelectDeviceChange = selection => {
+    selectedDeviceRows.value = selection;
+  };
+
+  // 閫夋嫨璁惧鍒嗛〉
+  const selectDevicePagination = obj => {
+    selectDevicePage.current = obj.page;
+    selectDevicePage.size = obj.limit;
+    getSelectDeviceList();
+  };
+
+  // 缁戝畾璁惧
+  const handleBindDevices = () => {
+    if (!currentProcess.value) return;
+    const selectedList = selectedDeviceRows.value || [];
+    if (!selectedList.length) {
+      proxy.$modal.msgWarning("璇烽�夋嫨瑕佺粦瀹氱殑璁惧");
+      return;
+    }
+    const deviceIds = selectedList.map(item => item.id);
+    bindDevices(currentProcess.value.id, deviceIds)
+      .then(() => {
+        proxy.$modal.msgSuccess("缁戝畾鎴愬姛");
+        isShowSelectDeviceModal.value = false;
+        getDeviceList();
+      })
+      .catch(() => {});
+  };
+
   // 鍒犻櫎
   function handleDelete() {
     const no = selectedRows.value.map(item => item.no);

--
Gitblit v1.9.3