From ca8dfc8a7dd8ba9b84d9a58c3c2a6d52a0c98a74 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 28 五月 2026 09:48:59 +0800
Subject: [PATCH] 中兴实强new 1.生产订单补料时如果库存不足可以提交采购申请单

---
 src/views/productionManagement/productionOrder/components/PurchaseRequestDialog.vue |  309 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 309 insertions(+), 0 deletions(-)

diff --git a/src/views/productionManagement/productionOrder/components/PurchaseRequestDialog.vue b/src/views/productionManagement/productionOrder/components/PurchaseRequestDialog.vue
new file mode 100644
index 0000000..88d2a28
--- /dev/null
+++ b/src/views/productionManagement/productionOrder/components/PurchaseRequestDialog.vue
@@ -0,0 +1,309 @@
+<template>
+  <div>
+    <el-dialog v-model="dialogVisible"
+               title="閲囪喘鐢宠锛堝簱瀛樹笉瓒筹級"
+               width="900px"
+               @close="handleClose">
+      <!-- 绠�鏄撻噰璐敵璇疯〃鍗� -->
+      <el-form :model="form" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="閿�鍞鍗曞彿" required>
+              <el-input v-model="form.salesContractNo" placeholder="璇疯緭鍏ラ攢鍞鍗曞彿" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鎶勯�佷汉" required>
+              <el-select v-model="form.ccUserId" placeholder="璇烽�夋嫨鎶勯�佷汉" style="width: 100%" filterable>
+                <el-option v-for="user in userOptions" :key="user.userId" :label="user.nickName" :value="user.userId" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+
+      <!-- 浜у搧琛ㄦ牸 -->
+      <div class="purchase-request-table">
+        <div class="table-toolbar">
+          <span class="table-title">閲囪喘浜у搧鏄庣粏</span>
+          <el-button type="primary" @click="handleAddRow">鏂板浜у搧</el-button>
+        </div>
+        <el-table :data="tableData" border style="width: 100%;" max-height="400">
+          <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+          <el-table-column label="浜у搧鍚嶇О" min-width="150">
+            <template #default="{ row }">
+              <el-button v-if="!row.productName" type="primary" link @click="openProductSelect(row)">
+                閫夋嫨浜у搧
+              </el-button>
+              <span v-else>{{ row.productName }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鍨嬪彿/瑙勬牸" min-width="150">
+            <template #default="{ row }">
+              {{ row.model || '-' }}
+            </template>
+          </el-table-column>
+          <el-table-column label="鍗曚綅" width="80" align="center">
+            <template #default="{ row }">
+              {{ row.unit || '-' }}
+            </template>
+          </el-table-column>
+          <el-table-column label="鏁伴噺" width="120">
+            <template #default="{ row }">
+              <el-input-number v-model="row.quantity" :min="1" :precision="0" :step="1" controls-position="right" style="width: 100%;" />
+            </template>
+          </el-table-column>
+          <el-table-column label="鎿嶄綔" width="80" align="center" fixed="right">
+            <template #default="{ $index }">
+              <el-button type="danger" link @click="handleDeleteRow($index)">鍒犻櫎</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button type="primary" :loading="saving" @click="handleSave">淇濆瓨鑽夌</el-button>
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <ProductSelectDialog v-model="productSelectVisible" @confirm="handleProductConfirm" single />
+  </div>
+</template>
+
+<script setup>
+import { computed, ref, watch, onMounted } from "vue";
+import { ElMessage } from "element-plus";
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+import { saveShortagePurchaseDraft } from "@/api/procurementManagement/procurementLedger.js";
+import { listUser } from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user.js";
+
+const userStore = useUserStore();
+
+const props = defineProps({
+  modelValue: { type: Boolean, default: false },
+  insufficientItems: { type: Array, default: () => [] },
+  orderRow: { type: Object, default: null },
+});
+const emit = defineEmits(["update:modelValue", "saved"]);
+
+const dialogVisible = computed({
+  get: () => props.modelValue,
+  set: (val) => emit("update:modelValue", val),
+});
+
+const productSelectVisible = ref(false);
+const saving = ref(false);
+const currentSelectRowIndex = ref(-1);
+const userOptions = ref([]);
+
+// 琛ㄥ崟鏁版嵁
+const form = ref({
+  salesContractNo: "",
+  ccUserId: null,
+  ccUserName: "",
+});
+
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([]);
+
+// 鑾峰彇鐢ㄦ埛鍒楄〃锛堟妱閫佷汉閫夋嫨锛�
+const getUserList = async () => {
+  try {
+    const res = await listUser({ pageSize: 1000 });
+    userOptions.value = res.rows || [];
+  } catch (error) {
+    console.error("鑾峰彇鐢ㄦ埛鍒楄〃澶辫触:", error);
+  }
+};
+
+onMounted(() => {
+  getUserList();
+});
+
+// 鐩戝惉瀵硅瘽妗嗘墦寮�锛屽垵濮嬪寲鏁版嵁
+watch(
+  () => dialogVisible.value,
+  (visible) => {
+    if (visible) {
+      initData();
+    }
+  }
+);
+
+// 鍒濆鍖栨暟鎹�
+const initData = () => {
+  // 浠庣敓浜ц鍗曚腑鑾峰彇閿�鍞鍗曞彿
+  form.value.salesContractNo = props.orderRow?.salesContractNo || "";
+  form.value.applicantId = userStore.id || "";
+  form.value.applicantName = userStore.name || "";
+  form.value.ccUserId = null;
+  form.value.ccUserName = "";
+
+  // 灏嗗簱瀛樹笉瓒崇殑浜у搧濉厖鍒拌〃鏍�
+  // 鍏煎棰嗘枡鍜岃ˉ鏂欑殑鏁版嵁缁撴瀯
+  tableData.value = props.insufficientItems.map((item) => ({
+    tempId: generateTempId(),
+    productModelId: item.materialModelId || item.productModelId,
+    productName: item.materialName || item.productName,
+    model: item.materialModel || item.model,
+    unit: item.unit,
+    quantity: Math.max(1, Math.ceil((item.demandedQuantity || 0) - (item.stockQuantity || 0))),
+  }));
+};
+
+// 鐢熸垚涓存椂ID
+let tempIdCounter = 0;
+const generateTempId = () => {
+  return `temp_${++tempIdCounter}_${Date.now()}`;
+};
+
+// 鍏抽棴瀵硅瘽妗�
+const handleClose = () => {
+  form.value = {
+    salesContractNo: "",
+    applicantId: "",
+    applicantName: "",
+    ccUserId: null,
+    ccUserName: "",
+  };
+  tableData.value = [];
+  currentSelectRowIndex.value = -1;
+};
+
+// 鏂板琛�
+const handleAddRow = () => {
+  tableData.value.push({
+    tempId: generateTempId(),
+    productModelId: null,
+    productName: "",
+    model: "",
+    unit: "",
+    quantity: 1,
+  });
+};
+
+// 鍒犻櫎琛�
+const handleDeleteRow = (index) => {
+  tableData.value.splice(index, 1);
+};
+
+// 鎵撳紑浜у搧閫夋嫨
+const openProductSelect = (row) => {
+  currentSelectRowIndex.value = tableData.value.findIndex(
+    (item) => item.tempId === row.tempId
+  );
+  productSelectVisible.value = true;
+};
+
+// 浜у搧閫夋嫨纭
+const handleProductConfirm = (products) => {
+  if (!products || products.length === 0) return;
+  const index = currentSelectRowIndex.value;
+  if (index < 0 || !tableData.value[index]) return;
+  const product = products[0];
+  const row = tableData.value[index];
+  row.productModelId = product.materialModelId || product.modelId || product.id;
+  row.productName = product.materialName || product.productName || product.name || "";
+  row.model = product.materialModel || product.model || "";
+  row.unit = product.unit || product.measureUnit || "";
+  currentSelectRowIndex.value = -1;
+  productSelectVisible.value = false;
+};
+
+// 楠岃瘉琛ㄥ崟
+const validateForm = () => {
+  if (!form.value.salesContractNo) {
+    ElMessage.warning("璇疯緭鍏ラ攢鍞鍗曞彿");
+    return false;
+  }
+  if (!form.value.ccUserId) {
+    ElMessage.warning("璇烽�夋嫨鎶勯�佷汉");
+    return false;
+  }
+  if (tableData.value.length === 0) {
+    ElMessage.warning("璇疯嚦灏戞坊鍔犱竴涓骇鍝�");
+    return false;
+  }
+  for (let i = 0; i < tableData.value.length; i++) {
+    const row = tableData.value[i];
+    if (!row.productName) {
+      ElMessage.warning(`绗�${i + 1}琛岃閫夋嫨浜у搧`);
+      return false;
+    }
+    if (!row.quantity || row.quantity <= 0) {
+      ElMessage.warning(`绗�${i + 1}琛屾暟閲忓繀椤诲ぇ浜�0`);
+      return false;
+    }
+  }
+  return true;
+};
+
+// 淇濆瓨鑽夌
+const handleSave = async () => {
+  if (!validateForm()) return;
+
+  // 鑾峰彇鎶勯�佷汉濮撳悕
+  const selectedUser = userOptions.value.find(u => u.userId === form.value.ccUserId);
+  form.value.ccUserName = selectedUser?.userName || "";
+
+  saving.value = true;
+  try {
+    // 鏋勫缓閲囪喘鑽夌鏁版嵁锛堟牴鎹仈璋冩枃妗� PurchaseLedgerDto 鏍煎紡锛�
+    const draftData = {
+      salesContractNo: form.value.salesContractNo,
+      ccUserId: form.value.ccUserId,
+      ccUserName: form.value.ccUserName,
+      // 浜у搧鏄庣粏鏁版嵁
+      productData: tableData.value.map((item) => ({
+        productModelId: item.productModelId,
+        productName: item.productName,
+        model: item.model,
+        unit: item.unit,
+        quantity: item.quantity,
+      })),
+    };
+
+    const res = await saveShortagePurchaseDraft(draftData);
+    if (res.code === 200) {
+      ElMessage.success("閲囪喘鑽夌淇濆瓨鎴愬姛锛屽凡閫氱煡鎶勯�佷汉琛ュ叏淇℃伅");
+      emit("saved", res.data); // 杩斿洖鑽夌ID
+      dialogVisible.value = false;
+    } else {
+      ElMessage.error(res.msg || "淇濆瓨澶辫触");
+    }
+  } catch (error) {
+    console.error("淇濆瓨閲囪喘鑽夌澶辫触:", error);
+    ElMessage.error("淇濆瓨澶辫触锛岃閲嶈瘯");
+  } finally {
+    saving.value = false;
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.purchase-request-table {
+  margin-top: 20px;
+
+  .table-toolbar {
+    margin-bottom: 10px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .table-title {
+      font-weight: bold;
+      font-size: 14px;
+    }
+  }
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: center;
+  gap: 10px;
+}
+</style>

--
Gitblit v1.9.3