From 01a0dbc37d2df7557f6bab27a8f3f78970b8251e Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 01 四月 2026 17:39:03 +0800
Subject: [PATCH] 军泰伟业 1.军泰伟业-库存管理增加库位 2.军泰伟业-生产入库要审核,加个入库审核菜单,入库数量,库位,通过不通过

---
 src/views/inventoryManagement/dispatchLog/Record.vue                              |    5 
 src/views/inventoryManagement/stockManagement/New.vue                             |   21 ++
 src/views/salesManagement/deliveryLedger/index.vue                                |   35 +++
 src/api/collaborativeApproval/approvalProcess.js                                  |   18 +
 src/views/collaborativeApproval/approvalProcess/components/purchaseInboundDia.vue |  148 ++++++++++++++
 src/api/inventoryManagement/stockInRecord.js                                      |   11 +
 src/views/productionManagement/productionOrder/index.vue                          |   35 +++
 src/views/collaborativeApproval/approvalProcess/index.vue                         |   19 +
 src/views/inventoryManagement/inboundApproval/index.vue                           |  256 +++++++++++++++++++++++++
 src/views/inventoryManagement/stockManagement/Qualified.vue                       |    1 
 src/views/inventoryManagement/receiptManagement/Record.vue                        |    5 
 11 files changed, 544 insertions(+), 10 deletions(-)

diff --git a/src/api/collaborativeApproval/approvalProcess.js b/src/api/collaborativeApproval/approvalProcess.js
index 415bed8..a942c88 100644
--- a/src/api/collaborativeApproval/approvalProcess.js
+++ b/src/api/collaborativeApproval/approvalProcess.js
@@ -8,6 +8,7 @@
         params: query,
     })
 }
+
 export function getDept(query) {
     return request({
         url: '/approveProcess/getDept',
@@ -15,6 +16,7 @@
         params: query,
     })
 }
+
 export function approveProcessGetInfo(query) {
     return request({
         url: '/approveProcess/get',
@@ -22,6 +24,7 @@
         params: query,
     })
 }
+
 // 鏂板瀹℃壒娴佺▼
 export function approveProcessAdd(query) {
     return request({
@@ -30,6 +33,7 @@
         data: query,
     })
 }
+
 // 淇敼瀹℃壒娴佺▼
 export function approveProcessUpdate(query) {
     return request({
@@ -38,6 +42,7 @@
         data: query,
     })
 }
+
 // 鎻愪氦瀹℃壒
 export function updateApproveNode(query) {
     return request({
@@ -46,6 +51,16 @@
         data: query,
     })
 }
+
+// 閲囪喘鍏ュ簱
+export function purchaseApprove(query) {
+    return request({
+        url: '/approveNode/purchaseApprove',
+        method: 'post',
+        data: query,
+    })
+}
+
 // 鍒犻櫎瀹℃壒娴佺▼
 export function approveProcessDelete(query) {
     return request({
@@ -54,10 +69,11 @@
         data: query,
     })
 }
+
 // 鏌ヨ瀹℃壒娴佺▼
 export function approveProcessDetails(query) {
     return request({
         url: '/approveNode/details/' + query,
         method: 'get',
     })
-}
\ No newline at end of file
+}
diff --git a/src/api/inventoryManagement/stockInRecord.js b/src/api/inventoryManagement/stockInRecord.js
index 1746bfe..f5ca6e6 100644
--- a/src/api/inventoryManagement/stockInRecord.js
+++ b/src/api/inventoryManagement/stockInRecord.js
@@ -18,10 +18,19 @@
     });
 };
 
+// 鍏ュ簱瀹℃牳
+export const productionApprove = (data) => {
+    return request({
+        url: "/stockInRecord/productionApprove",
+        method: "post",
+        data,
+    });
+};
+
 export const batchDeleteStockInRecords = (ids) => {
     return request({
         url: "/stockInRecord",
         method: "delete",
         data: ids,
     });
-};
\ No newline at end of file
+};
diff --git a/src/views/collaborativeApproval/approvalProcess/components/purchaseInboundDia.vue b/src/views/collaborativeApproval/approvalProcess/components/purchaseInboundDia.vue
new file mode 100644
index 0000000..5ed0bdc
--- /dev/null
+++ b/src/views/collaborativeApproval/approvalProcess/components/purchaseInboundDia.vue
@@ -0,0 +1,148 @@
+<template>
+  <div>
+    <el-dialog
+      v-model="dialogVisible"
+      title="閲囪喘鍏ュ簱"
+      width="900px"
+      @close="closeDialog"
+    >
+      <el-skeleton :loading="loading" animated>
+        <template #template>
+          <el-skeleton-item variant="h3" style="width: 30%" />
+          <el-skeleton-item variant="text" style="width: 100%" />
+          <el-skeleton-item variant="text" style="width: 100%" />
+        </template>
+        <template #default>
+          <el-empty
+            v-if="!currentPurchase || !currentPurchase.purchaseContractNumber"
+            description="鏈煡璇㈠埌閲囪喘鍗曟嵁"
+          />
+          <template v-else>
+            <el-descriptions :column="2" border>
+              <el-descriptions-item label="閲囪喘鍚堝悓鍙�">{{ currentPurchase.purchaseContractNumber }}</el-descriptions-item>
+              <el-descriptions-item label="渚涘簲鍟�">{{ currentPurchase.supplierName }}</el-descriptions-item>
+              <el-descriptions-item label="椤圭洰鍚嶇О">{{ currentPurchase.projectName }}</el-descriptions-item>
+              <el-descriptions-item label="閿�鍞悎鍚屽彿">{{ currentPurchase.salesContractNo }}</el-descriptions-item>
+              <el-descriptions-item label="绛捐鏃ユ湡">{{ currentPurchase.executionDate }}</el-descriptions-item>
+              <el-descriptions-item label="褰曞叆鏃ユ湡">{{ currentPurchase.entryDate }}</el-descriptions-item>
+            </el-descriptions>
+
+            <div style="margin-top: 20px;">
+              <h4>浜у搧鏄庣粏</h4>
+              <el-table :data="currentPurchase.productData || []" border style="width: 100%">
+                <el-table-column prop="productCategory" label="浜у搧鍚嶇О" />
+                <el-table-column prop="specificationModel" label="鍥剧焊缂栧彿" />
+                <el-table-column prop="unit" label="鍗曚綅" />
+                <el-table-column prop="quantity" label="鏁伴噺" />
+                <el-table-column label="搴撲綅" min-width="180">
+                  <template #default="scope">
+                    <el-input
+                      v-model="scope.row.stockLocation"
+                      placeholder="璇峰~鍐欏簱浣�"
+                      clearable
+                    />
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </template>
+        </template>
+      </el-skeleton>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="handleInbound">纭鍏ュ簱</el-button>
+          <el-button @click="closeDialog">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { getCurrentInstance, ref } from "vue";
+import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js";
+import { purchaseApprove } from "@/api/collaborativeApproval/approvalProcess.js";
+
+const emit = defineEmits(["close"]);
+const { proxy } = getCurrentInstance();
+
+const dialogVisible = ref(false);
+const loading = ref(false);
+const currentPurchase = ref({});
+
+const openDialog = (type, row) => {
+  if (type !== "inbound") {
+    return;
+  }
+
+  dialogVisible.value = true;
+  loading.value = true;
+  currentPurchase.value = {};
+
+  const purchaseContractNumber = row?.approveReason;
+  if (!purchaseContractNumber) {
+    loading.value = false;
+    proxy.$modal.msgError("鏈壘鍒伴噰璐悎鍚屽彿");
+    return;
+  }
+
+  getPurchaseByCode({ purchaseContractNumber })
+    .then((res) => {
+      currentPurchase.value = {
+        ...res,
+        productData: (res?.productData || []).map((item) => ({
+          ...item,
+          stockLocation: item.stockLocation || "",
+        })),
+      };
+    })
+    .catch((err) => {
+      console.error("鍔犺浇閲囪喘淇℃伅澶辫触:", err);
+      proxy.$modal.msgError("鍔犺浇閲囪喘淇℃伅澶辫触");
+    })
+    .finally(() => {
+      loading.value = false;
+    });
+};
+
+const closeDialog = () => {
+  dialogVisible.value = false;
+  loading.value = false;
+  currentPurchase.value = {};
+  emit("close");
+};
+
+const handleInbound = () => {
+  const productData = currentPurchase.value?.productData || [];
+  if (productData.length === 0) {
+    proxy.$modal.msgError("鏈壘鍒伴噰璐槑缁�");
+    return;
+  }
+
+  const emptyRow = productData.find((item) => !item.stockLocation || !String(item.stockLocation).trim());
+  if (emptyRow) {
+    proxy.$modal.msgError(`璇峰厛濉啓浜у搧銆�${emptyRow.productCategory || emptyRow.specificationModel || "鏈煡"}銆戠殑搴撲綅`);
+    return;
+  }
+
+  const payload = productData.map((item) => ({
+    ...item,
+    stockLocation: String(item.stockLocation).trim(),
+  }));
+
+  purchaseApprove(payload)
+    .then(() => {
+      proxy.$modal.msgSuccess("鍏ュ簱鎴愬姛");
+      closeDialog();
+    })
+    .catch((err) => {
+      console.error("鍏ュ簱澶辫触:", err);
+      proxy.$modal.msgError("鍏ュ簱澶辫触");
+    });
+};
+
+defineExpose({
+  openDialog,
+});
+</script>
diff --git a/src/views/collaborativeApproval/approvalProcess/index.vue b/src/views/collaborativeApproval/approvalProcess/index.vue
index 65941e1..75044f3 100644
--- a/src/views/collaborativeApproval/approvalProcess/index.vue
+++ b/src/views/collaborativeApproval/approvalProcess/index.vue
@@ -6,7 +6,7 @@
       <el-tab-pane label="璇峰亣绠$悊" name="2"></el-tab-pane>
       <el-tab-pane label="鍑哄樊绠$悊" name="3"></el-tab-pane>
       <el-tab-pane label="鎶ラ攢绠$悊" name="4"></el-tab-pane>
-      <el-tab-pane label="閲囪喘瀹℃壒" name="5"></el-tab-pane>
+      <el-tab-pane label="閲囪喘鍏ュ簱瀹℃壒" name="5"></el-tab-pane>
       <el-tab-pane label="鎶ヤ环瀹℃壒" name="6"></el-tab-pane>
       <el-tab-pane label="鍙戣揣瀹℃壒" name="7"></el-tab-pane>
     </el-tabs>
@@ -64,6 +64,7 @@
     </div>
     <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="currentApproveType"></info-form-dia>
     <approval-dia ref="approvalDia" @close="handleQuery" :approveType="currentApproveType"></approval-dia>
+    <purchase-inbound-dia ref="purchaseInboundDia" @close="handleQuery" :approveType="currentApproveType"></purchase-inbound-dia>
     <FileList ref="fileListRef" />
   </div>
 </template>
@@ -76,6 +77,7 @@
 import { useRoute } from 'vue-router';
 import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue";
 import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue";
+import PurchaseInboundDia from "@/views/collaborativeApproval/approvalProcess/components/purchaseInboundDia.vue";
 import {approveProcessDelete, approveProcessListPage} from "@/api/collaborativeApproval/approvalProcess.js";
 import useUserStore from "@/store/modules/user";
 
@@ -231,6 +233,14 @@
         },
         disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || row.approveUserCurrentId !== userStore.id
       },
+      ...(isPurchaseType ? [{
+        name: "鍏ュ簱",
+        type: "text",
+        clickFun: (row) => {
+          openPurchaseInboundDia(row);
+        },
+        disabled: (row) => row.approveStatus != 2
+      }] : []),
       {
         name: "璇︽儏",
         type: "text",
@@ -260,6 +270,7 @@
 });
 const infoFormDia = ref()
 const approvalDia = ref()
+const purchaseInboundDia = ref()
 const { proxy } = getCurrentInstance()
 
 // 鏌ヨ鍒楄〃
@@ -333,6 +344,12 @@
   })
 };
 
+const openPurchaseInboundDia = (row) => {
+  nextTick(() => {
+    purchaseInboundDia.value?.openDialog('inbound', row)
+  })
+};
+
 // 鍒犻櫎
 const handleDelete = () => {
   let ids = [];
diff --git a/src/views/inventoryManagement/dispatchLog/Record.vue b/src/views/inventoryManagement/dispatchLog/Record.vue
index 1acc0a3..484ddfe 100644
--- a/src/views/inventoryManagement/dispatchLog/Record.vue
+++ b/src/views/inventoryManagement/dispatchLog/Record.vue
@@ -85,6 +85,11 @@
 					prop="stockOutNum"
 					show-overflow-tooltip
 				/>
+				<el-table-column
+					label="搴撲綅"
+					prop="stockLocation"
+					show-overflow-tooltip
+				/>
 				<el-table-column label="璐ㄦ鐘舵��"
                          prop="type"
                          show-overflow-tooltip
diff --git a/src/views/inventoryManagement/inboundApproval/index.vue b/src/views/inventoryManagement/inboundApproval/index.vue
new file mode 100644
index 0000000..275f0ad
--- /dev/null
+++ b/src/views/inventoryManagement/inboundApproval/index.vue
@@ -0,0 +1,256 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title ml10">浜у搧鍚嶇О锛�</span>
+        <el-input
+          v-model="searchForm.productName"
+          style="width: 240px"
+          placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+          clearable
+          @change="handleQuery"
+        />
+        <span class="search_title ml10">鍥剧焊缂栧彿锛�</span>
+        <el-input
+          v-model="searchForm.model"
+          style="width: 240px"
+          placeholder="璇疯緭鍏ュ浘绾哥紪鍙�"
+          clearable
+          @change="handleQuery"
+        />
+        <el-button type="primary" style="margin-left: 10px" @click="handleQuery">鎼滅储</el-button>
+        <el-button @click="handleReset">閲嶇疆</el-button>
+      </div>
+    </div>
+
+    <div class="table_list">
+      <el-table :data="tableData" border v-loading="tableLoading" style="width: 100%" height="calc(100vh - 18.5em)">
+        <el-table-column align="center" type="index" label="搴忓彿" width="60" />
+        <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="160" show-overflow-tooltip />
+        <el-table-column prop="model" label="鍥剧焊缂栧彿" min-width="160" show-overflow-tooltip />
+        <el-table-column prop="waitAuditNum" label="寰呭鏍告暟閲�" min-width="120" align="center" />
+        <el-table-column prop="stockLocation" label="搴撲綅" min-width="180" show-overflow-tooltip />
+        <el-table-column prop="status" label="瀹℃牳鐘舵��" min-width="120" align="center">
+          <template #default="scope">
+            <el-tag v-if="scope.row.status === 1 || scope.row.status === '1'" type="warning">寰呭鏍�</el-tag>
+            <el-tag v-else-if="scope.row.status === 2 || scope.row.status === '2'" type="success">宸插叆搴�</el-tag>
+            <el-tag v-else type="info">{{ scope.row.status }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鎿嶄綔" min-width="120" align="center" fixed="right">
+          <template #default="scope">
+            <el-button
+              link
+              type="primary"
+              size="small"
+              :disabled="!(scope.row.status === 1 || scope.row.status === '1')"
+              @click="openAuditDialog(scope.row)"
+            >
+              瀹℃牳
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <el-dialog v-model="auditDialogVisible" title="鍏ュ簱瀹℃牳" width="620px" @close="closeAuditDialog">
+      <el-form :model="auditForm" label-width="120px" label-position="top" ref="auditFormRef">
+        <el-form-item
+          label="瀹℃牳缁撴灉"
+          prop="result"
+          :rules="[{ required: true, message: '璇烽�夋嫨瀹℃牳缁撴灉', trigger: 'change' }]"
+        >
+          <el-radio-group v-model="auditForm.result">
+            <el-radio value="approved">閫氳繃</el-radio>
+            <el-radio value="rejected">涓嶉�氳繃</el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+        <el-form-item
+          v-if="auditForm.result === 'rejected'"
+          label="瀹為檯鍏ュ簱鏁伴噺"
+          prop="actualStockInNum"
+          :rules="[{ required: true, message: '璇疯緭鍏ュ疄闄呭叆搴撴暟閲�', trigger: 'blur' }]"
+        >
+          <el-input-number
+            v-model="auditForm.actualStockInNum"
+            :min="0"
+            :precision="0"
+            controls-position="right"
+            style="width: 100%;"
+          />
+        </el-form-item>
+
+        <el-form-item
+          v-if="auditForm.result === 'approved' || auditForm.result === 'rejected'"
+          label="搴撲綅"
+          prop="stockLocation"
+          :rules="[{ required: true, message: '璇疯緭鍏ュ簱浣�', trigger: 'blur' }]"
+        >
+          <el-input v-model="auditForm.stockLocation" placeholder="璇疯緭鍏ュ簱浣�" clearable />
+        </el-form-item>
+
+        <el-form-item
+          v-if="auditForm.result === 'rejected'"
+          label="涓嶉�氳繃鍘熷洜"
+          prop="reason"
+          :rules="[{ required: true, message: '璇疯緭鍏ヤ笉閫氳繃鍘熷洜', trigger: 'blur' }]"
+        >
+          <el-input
+            v-model="auditForm.reason"
+            type="textarea"
+            :rows="3"
+            placeholder="璇疯緭鍏ヤ笉閫氳繃鍘熷洜"
+            clearable
+          />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitAudit">纭</el-button>
+          <el-button @click="closeAuditDialog">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, toRefs, getCurrentInstance, nextTick, onMounted } from "vue";
+import { getStockInRecordListPage, productionApprove } from "@/api/inventoryManagement/stockInRecord.js";
+
+const { proxy } = getCurrentInstance();
+
+const tableLoading = ref(false);
+const tableData = ref([]);
+
+const data = reactive({
+  searchForm: {
+    productName: "",
+    model: "",
+  },
+});
+const { searchForm } = toRefs(data);
+
+const auditDialogVisible = ref(false);
+const auditRow = ref(null);
+const auditFormRef = ref(null);
+const auditForm = reactive({
+  result: "",
+  stockLocation: "",
+  actualStockInNum: null,
+  reason: "",
+});
+
+const handleQuery = () => {
+  tableLoading.value = true;
+  const params = {
+    current: 1,
+    size: 10,
+    productType: 1,
+    status: 1,
+    productName: searchForm.value.productName,
+    model: searchForm.value.model,
+  };
+
+  getStockInRecordListPage(params)
+    .then((res) => {
+      tableData.value = res?.data?.records || res?.data || [];
+    })
+    .catch((err) => {
+      console.error("鍔犺浇鍏ュ簱瀹℃牳鍒楄〃澶辫触:", err);
+      tableData.value = [];
+      proxy.$modal.msgError("鍔犺浇鍏ュ簱瀹℃牳鍒楄〃澶辫触");
+    })
+    .finally(() => {
+      tableLoading.value = false;
+    });
+};
+
+const handleReset = () => {
+  searchForm.value.productName = "";
+  searchForm.value.model = "";
+  handleQuery();
+};
+
+const openAuditDialog = (row) => {
+  auditRow.value = row;
+  auditForm.result = "";
+  auditForm.stockLocation = row.stockLocation || "";
+  auditForm.actualStockInNum = row.waitAuditNum ?? null;
+  auditForm.reason = "";
+  auditDialogVisible.value = true;
+  nextTick(() => {
+    auditFormRef.value?.clearValidate?.();
+  });
+};
+
+const closeAuditDialog = () => {
+  auditDialogVisible.value = false;
+  auditRow.value = null;
+  auditForm.result = "";
+  auditForm.stockLocation = "";
+  auditForm.actualStockInNum = null;
+  auditForm.reason = "";
+};
+
+const submitAudit = () => {
+  auditFormRef.value?.validate((valid) => {
+    if (!valid || !auditRow.value) {
+      return;
+    }
+
+    if (auditForm.result === "rejected") {
+      if (auditForm.actualStockInNum === null || auditForm.actualStockInNum === "" || Number(auditForm.actualStockInNum) < 0) {
+        proxy.$modal.msgError("璇疯緭鍏ュ疄闄呭叆搴撴暟閲�");
+        return;
+      }
+      if (Number(auditForm.actualStockInNum) > Number(auditRow.value.waitAuditNum ?? 0)) {
+        proxy.$modal.msgError("瀹為檯鍏ュ簱鏁伴噺涓嶈兘澶т簬寰呭鏍告暟閲�");
+        return;
+      }
+      if (!auditForm.reason || !String(auditForm.reason).trim()) {
+        proxy.$modal.msgError("璇疯緭鍏ヤ笉閫氳繃鍘熷洜");
+        return;
+      }
+    }
+
+    if (!auditForm.stockLocation || !String(auditForm.stockLocation).trim()) {
+      proxy.$modal.msgError("璇疯緭鍏ュ簱浣�");
+      return;
+    }
+
+    const payload = {
+      id: auditRow.value.id,
+      status: auditForm.result === "approved" ? 2 : 1,
+      actualStockInNum: auditForm.result === "approved"
+        ? Number(auditRow.value.waitAuditNum)
+        : Number(auditForm.actualStockInNum),
+      stockLocation: String(auditForm.stockLocation || "").trim(),
+      reason: auditForm.result === "rejected" ? String(auditForm.reason).trim() : "",
+      recordId: auditForm.result === "rejected" ? (auditRow.value.recordId ?? auditRow.value.id) : undefined,
+    };
+
+    productionApprove(payload)
+      .then(() => {
+        auditRow.value.status = payload.status;
+        auditRow.value.stockLocation = payload.stockLocation;
+        if (auditForm.result === "rejected") {
+          auditRow.value.waitAuditNum = payload.actualStockInNum;
+          auditRow.value.reason = payload.reason;
+        }
+        proxy.$modal.msgSuccess("瀹℃牳鎻愪氦鎴愬姛");
+        closeAuditDialog();
+        handleQuery();
+      })
+      .catch(() => {
+        proxy.$modal.msgError("瀹℃牳鎻愪氦澶辫触");
+      });
+  });
+};
+
+onMounted(() => {
+  handleQuery();
+});
+</script>
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index b85e79b..9b72c61 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -93,7 +93,7 @@
           </template>
         </el-table-column>
         <el-table-column label="搴撲綅"
-                         prop="locationName"
+                         prop="stockLocation"
                          show-overflow-tooltip/>
         <el-table-column label="鍏ュ簱浜�"
                          prop="createBy"
@@ -195,6 +195,9 @@
 const getList = () => {
   tableLoading.value = true;
   const params = {...page, productType: props.type};
+  if (props.type === 1) {
+    params.status = 2;
+  }
   params.timeStr = searchForm.value.timeStr;
   params.productName = searchForm.value.productName;
   params.recordType = searchForm.value.recordType;
diff --git a/src/views/inventoryManagement/stockManagement/New.vue b/src/views/inventoryManagement/stockManagement/New.vue
index 8640d83..2266a6a 100644
--- a/src/views/inventoryManagement/stockManagement/New.vue
+++ b/src/views/inventoryManagement/stockManagement/New.vue
@@ -45,6 +45,20 @@
         </el-form-item>
 
         <el-form-item
+            label="搴撲綅"
+            prop="stockLocation"
+            :rules="[
+                {
+                required: true,
+                message: '璇疯緭鍏ュ簱浣�',
+                trigger: 'blur',
+              }
+            ]"
+        >
+          <el-input v-model="formState.stockLocation" placeholder="璇疯緭鍏ュ簱浣�" />
+        </el-form-item>
+
+        <el-form-item
             v-if="type === 'qualified'"
             label="搴撳瓨棰勮鏁伴噺"
             prop="warnNum"
@@ -102,6 +116,7 @@
   productModelName: "",
   unit: "",
   qualitity: 0,
+  stockLocation: "",
   warnNum: 0,
   remark: '',
 });
@@ -126,7 +141,11 @@
     productModelId: undefined,
     productName: "",
     productModelName: "",
-    description: '',
+    unit: "",
+    qualitity: 0,
+    stockLocation: "",
+    warnNum: 0,
+    remark: '',
   };
   isShow.value = false;
 };
diff --git a/src/views/inventoryManagement/stockManagement/Qualified.vue b/src/views/inventoryManagement/stockManagement/Qualified.vue
index 97e38a7..ed1ad1d 100644
--- a/src/views/inventoryManagement/stockManagement/Qualified.vue
+++ b/src/views/inventoryManagement/stockManagement/Qualified.vue
@@ -35,6 +35,7 @@
         <el-table-column label="鍥剧焊缂栧彿" prop="model" show-overflow-tooltip />
         <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
         <el-table-column label="搴撳瓨鏁伴噺" prop="qualitity" show-overflow-tooltip />
+        <el-table-column label="搴撲綅" prop="stockLocation" show-overflow-tooltip />
         <el-table-column label="璐ㄦ鐘舵��"
                          show-overflow-tooltip
                          width="100">
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 7984915..ca0172f 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -116,6 +116,15 @@
             />
           </template>
         </el-table-column>
+        <el-table-column label="搴撲綅" min-width="180" align="center" prop="stockLocation">
+          <template #default="{ row }">
+            <el-input
+              v-model="row.stockLocation"
+              placeholder="璇疯緭鍏ュ簱浣�"
+              clearable
+            />
+          </template>
+        </el-table-column>
       </el-table>
       <div class="picking-footer-info">
         <span>宸查�� {{ inputSelectedRows.length }} 鏉�</span>
@@ -132,7 +141,7 @@
     <!-- 棰嗘枡寮规 -->
     <el-dialog v-model="pickingDialogVisible"
                title="宸ュ崟棰嗘枡"
-               width="1200px"
+               width="70%"
                :close-on-click-modal="false">
 
       <el-table
@@ -162,6 +171,15 @@
               size="small" 
               style="width: 160px"
               @change="(val) => handlePickingQuantityChange(val, row)"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column label="搴撲綅" min-width="180" align="center" prop="stockLocation">
+          <template #default="{ row }">
+            <el-input
+              v-model="row.stockLocation"
+              placeholder="璇疯緭鍏ュ簱浣�"
+              clearable
             />
           </template>
         </el-table-column>
@@ -737,6 +755,7 @@
         inputTableData.value = res.data.records.map(item => ({
           ...item,
           currentReturnQuantity: 0,
+          stockLocation: item.stockLocation || "",
         }));
         inputPage.total = res.data.total;
       })
@@ -759,6 +778,7 @@
       pickingTableData.value = materials.map(item => ({
         ...item,
         quantity: 0,
+        stockLocation: item.stockLocation || "",
         unpickedQuantity: (item.demandedQuantity || 0) - (item.completedQuantity || 0),
       }));
     } catch (e) {
@@ -796,6 +816,10 @@
         proxy.$modal.msgWarning(`${row.productName} 鐨勯鏂欐暟閲忓繀椤诲ぇ浜�0`);
         return;
       }
+      if (!row.stockLocation || !String(row.stockLocation).trim()) {
+        proxy.$modal.msgWarning(`${row.productName} 鐨勫簱浣嶄笉鑳戒负绌篳);
+        return;
+      }
     }
     
     // 鎻愪氦棰嗘枡鏁版嵁
@@ -805,6 +829,7 @@
         productStructureRecordId: row.id,
         productModelId: row.productModelId,
         quantity: row.quantity,
+        stockLocation: String(row.stockLocation).trim(),
       }));
       await pickMaterial(pickData);
       proxy.$modal.msgSuccess("棰嗘枡鎴愬姛");
@@ -851,10 +876,18 @@
       proxy.$modal.msgWarning("璇峰~鍐欐湰娆¢��鏂欐暟閲�");
       return;
     }
+    const invalidLocationRows = inputSelectedRows.value.filter(
+      row => !row.stockLocation || !String(row.stockLocation).trim()
+    );
+    if (invalidLocationRows.length > 0) {
+      proxy.$modal.msgWarning("璇峰~鍐欏簱浣�");
+      return;
+    }
 
     const returnData = inputSelectedRows.value.map(row => ({
       ...row,
       returnQuantity: row.currentReturnQuantity,
+      stockLocation: String(row.stockLocation).trim(),
     }));
 
     try {
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index 4fefc20..ae655fa 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -29,6 +29,8 @@
         <el-table-column align="center" label="搴忓彿" type="index" width="60" />
         <el-table-column label="閿�鍞鍗�" prop="salesContractNo" show-overflow-tooltip />
         <el-table-column label="鍙戣揣璁㈠崟鍙�" prop="shippingNo" show-overflow-tooltip />
+        <el-table-column label="浜у搧鍚嶇О" prop="productCategory" show-overflow-tooltip />
+        <el-table-column label="鍥剧焊缂栧彿" prop="specificationModel" show-overflow-tooltip />
         <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip />
         <el-table-column label="鍙戣揣杩涘害" align="center" width="150">
           <template #default="scope">
@@ -105,6 +107,14 @@
                 <div class="info-item">
                   <span class="label">鍙戣揣璁㈠崟鍙�</span>
                   <span class="value">{{ currentShippingOrder.shippingNo || '--' }}</span>
+                </div>
+                <div class="info-item">
+                  <span class="label">浜у搧鍚嶇О</span>
+                  <span class="value">{{ currentShippingOrder.productCategory || '--' }}</span>
+                </div>
+                <div class="info-item">
+                  <span class="label">鍥剧焊缂栧彿</span>
+                  <span class="value">{{ currentShippingOrder.specificationModel || '--' }}</span>
                 </div>
                 <el-divider />
                 <div class="quantity-summary">
@@ -203,6 +213,10 @@
                           />
                         </div>
                       </div>
+											<div class="info-row">
+												<span class="info-label">搴撲綅</span>
+												<span class="info-value">{{ record.stockLocation || '--' }}</span>
+											</div>
                       <div class="record-actions" v-if="canRevokeShipping(record)">
                         <el-button 
                           type="danger" 
@@ -260,11 +274,18 @@
         </el-row>
         <el-row :gutter="20">
           <el-col :span="24">
+            <el-form-item label="搴撲綅" prop="stockLocation">
+							<el-input v-model="shippingForm.stockLocation" placeholder="璇疯緭鍏ュ簱浣�" clearable/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="24">
             <el-form-item label="鍙戣揣鏃ユ湡" prop="shippingDate">
-              <el-date-picker 
-                v-model="shippingForm.shippingDate" 
-                value-format="YYYY-MM-DD HH:mm:ss" 
-                type="datetime" 
+              <el-date-picker
+                v-model="shippingForm.shippingDate"
+                value-format="YYYY-MM-DD HH:mm:ss"
+                type="datetime"
                 placeholder="璇烽�夋嫨"
                 style="width: 100%"
               />
@@ -373,9 +394,11 @@
   shippingCarNumber: "",
   expressCompany: "",
   expressNumber: "",
+	stockLocation: "",
 });
 const shippingRules = {
   shippingNum: [{ required: true, message: "璇疯緭鍏ュ彂璐ф暟閲�", trigger: "blur" }],
+	stockLocation: [{ required: true, message: "璇疯緭鍏ュ簱浣�", trigger: "blur" }],
   type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
   shippingDate: [{ required: true, message: "璇烽�夋嫨鍙戣揣鏃ユ湡", trigger: "change" }],
   shippingCarNumber: [
@@ -474,6 +497,7 @@
     shippingCarNumber: "",
     expressCompany: "",
     expressNumber: "",
+		stockLocation: "",
   };
   shippingFileList.value = [];
   
@@ -509,6 +533,7 @@
     shippingCarNumber: "",
     expressCompany: "",
     expressNumber: "",
+		stockLocation: "",
   };
   shippingFileList.value = [];
 };
@@ -523,6 +548,7 @@
     shippingCarNumber: "",
     expressCompany: "",
     expressNumber: "",
+		stockLocation: "",
   };
   shippingFileList.value = [];
 };
@@ -581,6 +607,7 @@
         shippingNum: shippingForm.value.shippingNum,
         type: shippingForm.value.type,
         shippingDate: shippingForm.value.shippingDate,
+				stockLocation: shippingForm.value.stockLocation,
         shippingCarNumber: shippingForm.value.type === "璐ц溅" ? shippingForm.value.shippingCarNumber : "",
         expressCompany: shippingForm.value.type === "蹇��" ? shippingForm.value.expressCompany : "",
         expressNumber: shippingForm.value.type === "蹇��" ? shippingForm.value.expressNumber : "",

--
Gitblit v1.9.3