From cdf8190c92a536dabdbd3dfd6758cf67320ff6df Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期五, 16 一月 2026 17:47:21 +0800
Subject: [PATCH] Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New

---
 src/views/productionManagement/productStructure/index.vue |  301 ++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 264 insertions(+), 37 deletions(-)

diff --git a/src/views/productionManagement/productStructure/index.vue b/src/views/productionManagement/productStructure/index.vue
index e32ff8d..d8ce689 100644
--- a/src/views/productionManagement/productStructure/index.vue
+++ b/src/views/productionManagement/productStructure/index.vue
@@ -1,5 +1,9 @@
 <template>
   <div class="app-container">
+    <div style="text-align: right; margin-bottom: 10px;">
+      <el-button type="primary" @click="handleAdd">鏂板</el-button>
+      <el-button type="danger" plain @click="handleBatchDelete" :disabled="selectedRows.length === 0">鍒犻櫎</el-button>
+    </div>
     <PIMTable
         rowKey="id"
         :column="tableColumn"
@@ -14,100 +18,323 @@
         <el-button
             type="primary"
             text
-            @click="showDetail(row.id)">{{ row.productName }}
+            @click="showDetail(row)">{{ row.bomNo }}
         </el-button>
       </template>
     </PIMTable>
     <StructureEdit v-if="showEdit" v-model:show-model="showEdit" :record="currentRow"/>
+    
+    <!-- 鏂板/缂栬緫寮圭獥 -->
+    <el-dialog
+        v-model="dialogVisible"
+        :title="operationType === 'add' ? '鏂板BOM' : '缂栬緫BOM'"
+        width="600px"
+        @close="closeDialog"
+    >
+      <el-form
+          ref="formRef"
+          :model="form"
+          :rules="rules"
+          label-width="120px"
+      >
+        <el-form-item label="浜у搧鍚嶇О" prop="productModelId">
+          <el-button type="primary" @click="showProductSelectDialog = true">
+            {{ form.productName || '閫夋嫨浜у搧' }}
+          </el-button>
+        </el-form-item>
+        <el-form-item label="鐗堟湰鍙�" prop="version">
+          <el-input v-model="form.version" placeholder="璇疯緭鍏ョ増鏈彿" clearable />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input
+              v-model="form.remark"
+              type="textarea"
+              :rows="3"
+              placeholder="璇疯緭鍏ュ娉�"
+              clearable
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="closeDialog">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSubmit">纭畾</el-button>
+      </template>
+    </el-dialog>
+    
+    <!-- 浜у搧閫夋嫨寮圭獥 -->
+    <ProductSelectDialog
+        v-model="showProductSelectDialog"
+        @confirm="handleProductSelect"
+        single
+    />
   </div>
 </template>
 
 <script setup>
-import {ref} from "vue";
-import {productModelList} from "@/api/basicData/productModel.js";
+import { ref, reactive, toRefs, onMounted, getCurrentInstance, defineAsyncComponent } from "vue";
+import { listPage, add, update, batchDelete } from "@/api/productionManagement/productBom.js";
 import { useRouter } from 'vue-router'
+import { ElMessageBox } from 'element-plus'
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
 
 const router = useRouter()
+const { proxy } = getCurrentInstance()
 const StructureEdit = defineAsyncComponent(() => import('@/views/productionManagement/productStructure/StructureEdit.vue'))
 
 const tableColumn = ref([
   {
-    label: "浜у搧缂栫爜",
-    prop: "productCode",
-    slot: "detail"
+    label: "BOM缂栧彿",
+    prop: "bomNo",
+    dataType: 'slot',
+    slot: "detail",
+    minWidth: 140
   },
   {
     label: "浜у搧鍚嶇О",
     prop: "productName",
-    dataType: 'slot',
-    slot: "detail"
+    
+    minWidth: 160
   },
   {
     label: "瑙勬牸鍨嬪彿",
-    prop: "model",
+    prop: "productModelName",
+    minWidth: 140
   },
   {
-    label: "鍗曚綅",
-    prop: "unit",
+    label: "鐗堟湰鍙�",
+    prop: "version",
+    width: 100
+  },
+  {
+    label: "澶囨敞",
+    prop: "remark",
+    minWidth: 160
+  },
+  {
+    dataType: "action",
+    label: "鎿嶄綔",
+    align: "center",
+    fixed: "right",
+    width: 150,
+    operation: [
+      {
+        name: "缂栬緫",
+        type: "text",
+        clickFun: (row) => {
+          handleEdit(row)
+        }
+      },
+      {
+        name: "鍒犻櫎",
+        type: "danger",
+        link: true,
+        clickFun: (row) => {
+          handleDelete(row)
+        }
+      }
+    ]
   }
 ]);
+
 const tableData = ref([]);
 const tableLoading = ref(false);
 const showEdit = ref(false);
 const selectedRows = ref([]);
 const currentRow = ref({});
+const dialogVisible = ref(false);
+const operationType = ref('add'); // add | edit
+const formRef = ref(null);
+const showProductSelectDialog = ref(false);
+
 const page = reactive({
   current: 1,
   size: 10,
   total: 0,
 });
+
 const data = reactive({
   form: {
+    id: undefined,
     productName: "",
+    productModelName: "",
+    productModelId: "",
+    remark: "",
+    version: ""
   },
   rules: {
-    productName: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
-  },
-  modelForm: {
-    otherModel: '',
-    model: "",
-    unit: "",
-    speculativeTradingName: [],
-  },
+    productModelId: [{ required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" }],
+    version: [{ required: true, message: "璇疯緭鍏ョ増鏈彿", trigger: "blur" }]
+  }
 });
-const {form, rules} = toRefs(data);
+
+const { form, rules } = toRefs(data);
+
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
   selectedRows.value = selection;
 };
 
-// 鏌ヨ瑙勬牸鍨嬪彿
+// 鍒嗛〉
 const pagination = (obj) => {
   page.current = obj.page;
   page.size = obj.limit;
-  getModelList();
+  getList();
 };
 
-const showDetail = (id) => {
+// 鏌ヨ鍒楄〃
+const getList = () => {
+  tableLoading.value = true;
+  listPage({
+    current: page.current,
+    size: page.size,
+  })
+    .then((res) => {
+      const records = res?.data?.records || [];
+      tableData.value = records;
+      page.total = res?.data?.total || 0;
+    })
+    .catch((err) => {
+      console.error("鑾峰彇鍒楄〃澶辫触锛�", err);
+    })
+    .finally(() => {
+      tableLoading.value = false;
+    });
+};
+
+// 鏂板
+const handleAdd = () => {
+  operationType.value = 'add';
+  Object.assign(form.value, {
+    id: undefined,
+    productName: "",
+    productModelName: "",
+    productModelId: "",
+    remark: "",
+    version: ""
+  });
+  dialogVisible.value = true;
+};
+
+// 缂栬緫
+const handleEdit = (row) => {
+  operationType.value = 'edit';
+  Object.assign(form.value, {
+    id: row.id,
+    productName: row.productName || "",
+    productModelName: row.productModelName || "",
+    productModelId: row.productModelId || "",
+    remark: row.remark || "",
+    version: row.version || ""
+  });
+  dialogVisible.value = true;
+};
+
+// 鍒犻櫎锛堝崟鏉★級
+const handleDelete = (row) => {
+  ElMessageBox.confirm('纭鍒犻櫎璇OM锛�', '鎻愮ず', {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  })
+    .then(() => {
+      batchDelete([row.id])
+        .then(() => {
+          proxy.$modal.msgSuccess('鍒犻櫎鎴愬姛');
+          getList();
+        })
+        .catch(() => {
+          proxy.$modal.msgError('鍒犻櫎澶辫触');
+        });
+    })
+    .catch(() => {});
+};
+
+// 鎵归噺鍒犻櫎
+const handleBatchDelete = () => {
+  if (!selectedRows.value.length) {
+    proxy.$modal.msgWarning('璇烽�夋嫨鏁版嵁');
+    return;
+  }
+  const ids = selectedRows.value.map(item => item.id);
+  ElMessageBox.confirm('閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�', '鍒犻櫎鎻愮ず', {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  })
+    .then(() => {
+      batchDelete(ids)
+        .then(() => {
+          proxy.$modal.msgSuccess('鍒犻櫎鎴愬姛');
+          getList();
+        })
+        .catch(() => {
+          proxy.$modal.msgError('鍒犻櫎澶辫触');
+        });
+    })
+    .catch(() => {});
+};
+
+// 浜у搧閫夋嫨
+const handleProductSelect = (products) => {
+  if (products && products.length > 0) {
+    const product = products[0];
+    form.value.productModelId = product.id;
+    form.value.productName = product.productName;
+    form.value.productModelName = product.model;
+  }
+  showProductSelectDialog.value = false;
+};
+
+// 鎻愪氦琛ㄥ崟
+const handleSubmit = () => {
+  formRef.value.validate((valid) => {
+    if (valid) {
+      const payload = { ...form.value };
+      if (operationType.value === 'add') {
+        add(payload)
+          .then(() => {
+            proxy.$modal.msgSuccess('鏂板鎴愬姛');
+            closeDialog();
+            getList();
+          })
+          .catch(() => {
+            proxy.$modal.msgError('鏂板澶辫触');
+          });
+      } else {
+        update(payload)
+          .then(() => {
+            proxy.$modal.msgSuccess('淇敼鎴愬姛');
+            closeDialog();
+            getList();
+          })
+          .catch(() => {
+            proxy.$modal.msgError('淇敼澶辫触');
+          });
+      }
+    }
+  });
+};
+
+// 鍏抽棴寮圭獥
+const closeDialog = () => {
+  dialogVisible.value = false;
+  formRef.value?.resetFields();
+};
+
+// 鏌ョ湅璇︽儏
+const showDetail = (row) => {
   router.push({
     path: '/productionManagement/productStructureDetail',
     query: {
-      id: id
+      id: row.id,
+      bomNo: row.bomNo || '',
+      productName: row.productName || '',
+      productModelName: row.productModelName || ''
     }
-  })
-}
-const getModelList = () => {
-  tableLoading.value = true;
-  productModelList({
-    current: page.current,
-    size: page.size,
-  }).then((res) => {
-    tableData.value = res.records;
-    page.total = res.total;
-    tableLoading.value = false;
   });
 };
+
 onMounted(() => {
-  getModelList();
-})
+  getList();
+});
 </script>

--
Gitblit v1.9.3