From 8ed10ff020d5cdbc5daf7b56263b3298739c389c Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期四, 15 一月 2026 14:05:27 +0800
Subject: [PATCH] feat(inventory): 添加生产出入库功能模块

---
 src/views/productionManagement/processRoute/processRouteItem/index.vue |  311 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 311 insertions(+), 0 deletions(-)

diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
new file mode 100644
index 0000000..7e32396
--- /dev/null
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -0,0 +1,311 @@
+<template>
+  <div class="app-container">
+    <PageHeader content="宸ヨ壓璺嚎椤圭洰">
+      <template #right-button>
+        <el-button type="primary" @click="handleAdd">鏂板</el-button>
+      </template>
+    </PageHeader>
+    
+    <el-table
+        v-loading="tableLoading"
+        border
+        :data="tableData"
+        :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+        row-key="id"
+        tooltip-effect="dark"
+        class="lims-table"
+    >
+      <el-table-column align="center" label="搴忓彿" width="60" type="index" />
+      <el-table-column label="宸ュ簭鍚嶇О" prop="processId" width="200">
+        <template #default="scope">
+          {{ getProcessName(scope.row.processId) || '-' }}
+        </template>
+      </el-table-column>
+      <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="160" />
+      <el-table-column label="瑙勬牸鍚嶇О" prop="model" min-width="140" />
+      <el-table-column label="鍗曚綅" prop="unit" width="100" />
+      <el-table-column label="鎿嶄綔" align="center" fixed="right" width="150">
+        <template #default="scope">
+          <el-button type="primary" link size="small" @click="handleEdit(scope.row)">缂栬緫</el-button>
+          <el-button type="danger" link size="small" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 鏂板/缂栬緫寮圭獥 -->
+    <el-dialog
+        v-model="dialogVisible"
+        :title="operationType === 'add' ? '鏂板宸ヨ壓璺嚎椤圭洰' : '缂栬緫宸ヨ壓璺嚎椤圭洰'"
+        width="500px"
+        @close="closeDialog"
+    >
+      <el-form
+          ref="formRef"
+          :model="form"
+          :rules="rules"
+          label-width="120px"
+      >
+        <el-form-item label="宸ュ簭" prop="processId">
+          <el-select
+              v-model="form.processId"
+              placeholder="璇烽�夋嫨宸ュ簭"
+              clearable
+              style="width: 100%"
+          >
+            <el-option
+                v-for="process in processOptions"
+                :key="process.id"
+                :label="process.name"
+                :value="process.id"
+            />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="浜у搧鍚嶇О" prop="productModelId">
+          <el-button type="primary" @click="showProductSelectDialog = true">
+            {{ form.productName && form.model 
+              ? `${form.productName} - ${form.model}` 
+              : '閫夋嫨浜у搧' }}
+          </el-button>
+        </el-form-item>
+
+        <el-form-item label="鍗曚綅" prop="unit">
+          <el-input 
+              v-model="form.unit" 
+              :placeholder="form.productModelId ? '鏍规嵁閫夋嫨鐨勪骇鍝佽嚜鍔ㄥ甫鍑�' : '璇峰厛閫夋嫨浜у搧'" 
+              clearable 
+              :disabled="true" 
+          />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <el-button @click="closeDialog">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 浜у搧閫夋嫨瀵硅瘽妗� -->
+    <ProductSelectDialog
+        v-model="showProductSelectDialog"
+        @confirm="handleProductSelect"
+        single
+    />
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, getCurrentInstance, onMounted } from "vue";
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+import { findProcessRouteItemList, addOrUpdateProcessRouteItem } from "@/api/productionManagement/processRouteItem.js";
+import { processList } from "@/api/productionManagement/productionProcess.js";
+import { useRoute } from 'vue-router'
+import { ElMessageBox } from 'element-plus'
+
+const route = useRoute()
+const { proxy } = getCurrentInstance() || {};
+
+const routeId = computed(() => route.query.id);
+
+const tableLoading = ref(false);
+const tableData = ref([]);
+const dialogVisible = ref(false);
+const operationType = ref('add'); // add | edit
+const formRef = ref(null);
+const submitLoading = ref(false);
+
+const processOptions = ref([]);
+const showProductSelectDialog = ref(false);
+
+const form = ref({
+  id: undefined,
+  routeId: routeId.value,
+  processId: undefined,
+  productModelId: undefined,
+  productName: "",
+  model: "",
+  unit: "",
+});
+
+const rules = {
+  processId: [{ required: true, message: '璇烽�夋嫨宸ュ簭', trigger: 'change' }],
+  productModelId: [{ required: true, message: '璇烽�夋嫨浜у搧', trigger: 'change' }],
+};
+
+// 鏍规嵁宸ュ簭ID鑾峰彇宸ュ簭鍚嶇О
+const getProcessName = (processId) => {
+  if (!processId) return '';
+  const process = processOptions.value.find(p => p.id === processId);
+  return process ? process.name : '';
+};
+
+// 鑾峰彇鍒楄〃
+const getList = () => {
+  tableLoading.value = true;
+  findProcessRouteItemList({ routeId: routeId.value })
+    .then(res => {
+      tableData.value = res.data || [];
+      tableLoading.value = false;
+    })
+    .catch(err => {
+      tableLoading.value = false;
+      console.error("鑾峰彇鍒楄〃澶辫触锛�", err);
+      proxy?.$modal?.msgError("鑾峰彇鍒楄〃澶辫触");
+    });
+};
+
+// 鑾峰彇宸ュ簭鍒楄〃
+const getProcessList = () => {
+  processList({})
+    .then(res => {
+      processOptions.value = res.data || [];
+    })
+    .catch(err => {
+      console.error("鑾峰彇宸ュ簭澶辫触锛�", err);
+    });
+};
+
+// 鏂板
+const handleAdd = () => {
+  operationType.value = 'add';
+  resetForm();
+  dialogVisible.value = true;
+};
+
+// 缂栬緫
+const handleEdit = (row) => {
+  operationType.value = 'edit';
+  form.value = {
+    id: row.id,
+    routeId: routeId.value,
+    processId: row.processId,
+    productModelId: row.productModelId,
+    productName: row.productName || "",
+    model: row.model || "",
+    unit: row.unit || "",
+  };
+  dialogVisible.value = true;
+};
+
+// 鍒犻櫎
+const handleDelete = (row) => {
+  ElMessageBox.confirm('纭鍒犻櫎璇ュ伐鑹鸿矾绾块」鐩紵', '鎻愮ず', {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  })
+    .then(() => {
+      // 璋冪敤鍒犻櫎鎺ュ彛锛屼紶鍗曚釜瀵硅薄锛堝寘鍚玦d锛�
+      addOrUpdateProcessRouteItem({
+        id: row.id,
+        routeId: routeId.value,
+      })
+        .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.model = product.model;
+    form.value.unit = product.unit || "";
+    showProductSelectDialog.value = false;
+    // 瑙﹀彂琛ㄥ崟楠岃瘉
+    formRef.value?.validateField('productModelId');
+  }
+};
+
+// 鎻愪氦
+const handleSubmit = () => {
+  formRef.value.validate((valid) => {
+    if (valid) {
+      submitLoading.value = true;
+      
+      // 鏋勫缓鎻愪氦鏁版嵁瀵硅薄锛堝崟涓璞″舰寮忥級
+      const submitData = {
+        routeId: routeId.value,
+        processId: form.value.processId,
+        productModelId: form.value.productModelId,
+      };
+
+      if (operationType.value === 'add') {
+        // 鏂板锛氫紶鍗曚釜瀵硅薄
+        addOrUpdateProcessRouteItem(submitData)
+          .then(() => {
+            proxy?.$modal?.msgSuccess('鏂板鎴愬姛');
+            closeDialog();
+            getList();
+          })
+          .catch(() => {
+            proxy?.$modal?.msgError('鏂板澶辫触');
+          })
+          .finally(() => {
+            submitLoading.value = false;
+          });
+      } else {
+        // 缂栬緫锛氫紶鍗曚釜瀵硅薄锛屽寘鍚玦d
+        addOrUpdateProcessRouteItem({
+          ...submitData,
+          id: form.value.id,
+        })
+          .then(() => {
+            proxy?.$modal?.msgSuccess('淇敼鎴愬姛');
+            closeDialog();
+            getList();
+          })
+          .catch(() => {
+            proxy?.$modal?.msgError('淇敼澶辫触');
+          })
+          .finally(() => {
+            submitLoading.value = false;
+          });
+      }
+    }
+  });
+};
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+  form.value = {
+    id: undefined,
+    routeId: routeId.value,
+    processId: undefined,
+    productModelId: undefined,
+    productName: "",
+    model: "",
+    unit: "",
+  };
+  formRef.value?.resetFields();
+};
+
+// 鍏抽棴寮圭獥
+const closeDialog = () => {
+  dialogVisible.value = false;
+  resetForm();
+};
+
+onMounted(() => {
+  getList();
+  getProcessList();
+});
+</script>
+
+<style scoped>
+:deep(.el-table__row) {
+  transition: background-color 0.2s;
+}
+
+:deep(.el-table__row:hover) {
+  background-color: #f9fafc !important;
+}
+</style>

--
Gitblit v1.9.3