From 53719f76ffb7a71db70c8b71bb5dd975904fbc83 Mon Sep 17 00:00:00 2001
From: z8018 <1282578289@qq.com>
Date: 星期三, 17 十二月 2025 21:33:49 +0800
Subject: [PATCH] 整箱出库

---
 项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db |    0 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutboundController.cs             |   21 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db      |    0 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs                       |    4 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundQueryService.cs                          |   20 
 项目代码/WIDESEA_WMSClient/src/api/http.js                                                                  |    4 
 项目代码/WIDESEA_WMSClient/src/views/outbound/out copyPicking.vue                                           |  558 ++++++++++++++++++++++++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_DTO/CalcOut/OutboundCompleteRequestDTO.cs                        |   23 +
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundService.cs                             |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs                               |  326 ++++++++++++++
 项目代码/WIDESEA_WMSClient/src/views/outbound/outPicking.vue                                                |  369 ++++++++++++++-
 项目代码/WIDESEA_WMSClient/src/views/Index.vue                                                              |   22 
 12 files changed, 1,296 insertions(+), 53 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/api/http.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/api/http.js"
index f61383c..02caf1c 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/api/http.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/api/http.js"
@@ -13,8 +13,8 @@
 let loadingInstance;
 let loadingStatus = false;
 if (process.env.NODE_ENV == 'development') {
-    axios.defaults.baseURL = 'http://127.0.0.1:9291/';
-    // axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
+    // axios.defaults.baseURL = 'http://127.0.0.1:9291/';
+    axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
 }
 else if (process.env.NODE_ENV == 'debug') {
     axios.defaults.baseURL = 'http://127.0.0.1:8098/';
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/Index.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/Index.vue"
index 7084e70..eaa6fba 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/Index.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/Index.vue"
@@ -333,20 +333,20 @@
     const createSocket = (url) => {
       // 鍒涘缓WebSocket杩炴帴
       //"ws://127.0.0.1:9295/admin"
-      client = new WebSocket(url);
+      // client = new WebSocket(url);
 
-      client.onopen = function () {
-        client.onmessage = handleMessage;
-        store.commit("setWebsocket", client);
-        console.log("WebSocket 杩炴帴鎴愬姛");
-      };
+      // client.onopen = function () {
+      //   client.onmessage = handleMessage;
+      //   store.commit("setWebsocket", client);
+      //   console.log("WebSocket 杩炴帴鎴愬姛");
+      // };
 
-      client.onclose = function () {
-        console.log("WebSocket 杩炴帴鍏抽棴");
-        setTimeout(createSocket, 10000);
-      };
+      // client.onclose = function () {
+      //   console.log("WebSocket 杩炴帴鍏抽棴");
+      //   setTimeout(createSocket, 10000);
+      // };
 
-      client.onerror = function () {};
+      // client.onerror = function () {};
     };
 
     const changeTheme = (name) => {
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/out copyPicking.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/out copyPicking.vue"
index 8a0384f..955300d 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/out copyPicking.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/out copyPicking.vue"
@@ -21,7 +21,13 @@
             <div class="scan-section">
                 <el-alert title="璇蜂娇鐢ㄦ壂鐮佹灙鎵弿锛屾敮鎸佸洖杞﹁嚜鍔ㄧ‘璁�" type="info" :closable="false" show-icon class="scan-alert">
                     <template #default>
-                        <span>1. 璇峰厛鎵弿鎵樼洏鐮� 鈫� 2. 鍐嶆壂鎻忕墿鏂欐潯鐮�</span>
+                        <div>
+                            <div>1. 璇峰厛鎵弿鎵樼洏鐮� 鈫� 2. 鍐嶆壂鎻忕墿鏂欐爣绛剧爜</div>
+                            <div style="margin-top: 8px; font-size: 13px; color: #666;">
+                                <i class="el-icon-info" style="color: #409EFF;"></i>
+                                鏀寔鎵墭鐩樼爜鏁寸鍑哄簱锛氭壂鎻忔墭鐩樼爜鍚庡彲鐩存帴杩涜鏁寸鐗╂枡鎷i�夛紝鏃犻渶鍐嶆壂鎻忕墿鏂欐爣绛剧爜銆�
+                            </div>
+                        </div>
                     </template>
                 </el-alert>
 
@@ -71,6 +77,41 @@
                         </el-col>
                     </el-row>
                 </el-form>
+
+                <!-- 鍒嗘嫞缁熻淇℃伅 -->
+                <div class="picking-stats" v-if="scanForm.palletCode && unpickedData.length > 0">
+                    <el-divider content-position="left">
+                        <span style="color: #409EFF; font-size: 14px;">
+                            <i class="el-icon-data-analysis"></i> 鎵樼洏鍒嗘嫞缁熻
+                        </span>
+                    </el-divider>
+                    <div class="stats-container">
+                        <div class="stat-item">
+                            <el-tag type="primary" size="medium" effect="dark">
+                                <i class="el-icon-s-order"></i>
+                                鍒嗘嫞鎬绘暟锛�<b>{{ calculateTotalAssignQuantity() }}</b>
+                            </el-tag>
+                        </div>
+                        <div class="stat-item">
+                            <el-tag type="success" size="medium" effect="dark">
+                                <i class="el-icon-circle-check"></i>
+                                宸插垎鎷o細<b>{{ calculateTotalSortedQuantity() }}</b>
+                            </el-tag>
+                        </div>
+                        <div class="stat-item">
+                            <el-tag type="warning" size="medium" effect="dark">
+                                <i class="el-icon-time"></i>
+                                鏈垎鎷o細<b>{{ calculateTotalUnsortedQuantity() }}</b>
+                            </el-tag>
+                        </div>
+                        <div class="stat-item">
+                            <el-tag type="success" size="medium" effect="dark">
+                                <i class="el-icon-box"></i>
+                                鏄惁鏁村嚭锛歿{ hasWholeOut() ? '鏄�' : '鍚�' }}
+                            </el-tag>
+                        </div>
+                    </div>
+                </div>
             </div>
         </el-card>
 
@@ -198,6 +239,53 @@
                     </el-card>
                 </el-col>
             </el-row>
+
+            <!-- 鎵樼洏鐗╂枡搴撳瓨淇℃伅 -->
+            <!-- <div class="pallet-inventory" v-if="scanForm.palletCode && unpickedData.length > 0">
+                <el-divider content-position="left">
+                    <span style="color: #67C23A; font-size: 14px;">
+                        <i class="el-icon-goods"></i> 鎵樼洏鐗╂枡搴撳瓨淇℃伅
+                    </span>
+                </el-divider>
+                <div class="inventory-container">
+                    <el-table :data="unpickedData" size="small" :show-header="true" :border="true" stripe
+                        highlight-current-row max-height="200" class="inventory-table">
+                        <el-table-column type="index" label="搴忓彿" width="50" align="center" />
+                        <el-table-column prop="materielCode" label="鐗╂枡缂栫爜" width="100" show-overflow-tooltip />
+                        <el-table-column prop="materielName" label="鐗╂枡鍚嶇О" width="120" show-overflow-tooltip />
+                        <el-table-column prop="batchNo" label="鎵规鍙�" width="90" />
+                        <el-table-column label="褰撳墠搴撳瓨" width="80" align="right">
+                            <template #default="scope">
+                                <el-text type="primary" tag="b">{{ scope.row.currentStock || 0 }}</el-text>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="鍒嗘嫞鏁伴噺" width="80" align="right">
+                            <template #default="scope">
+                                <el-text type="warning">{{ scope.row.assignQuantity }}</el-text>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="宸插垎鎷�" width="70" align="right">
+                            <template #default="scope">
+                                <el-text type="success">{{ scope.row.sortedQuantity || 0 }}</el-text>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="鍓╀綑搴撳瓨" width="80" align="right">
+                            <template #default="scope">
+                                <el-text type="info">{{ calculateRemainingStock(scope.row) }}</el-text>
+                            </template>
+                        </el-table-column>
+                        <el-table-column prop="unit" label="鍗曚綅" width="100" align="center" />
+                        <el-table-column prop="locationCode" label="搴撲綅" width="150" />
+                        <el-table-column label="鐘舵��" width="80" align="center">
+                            <template #default="scope">
+                                <el-tag :type="getStockStatusType(scope.row)" size="mini">
+                                    {{ getStockStatusText(scope.row) }}
+                                </el-tag>
+                            </template>
+                        </el-table-column>
+                    </el-table>
+                </div>
+            </div> -->
         </div>
 
         <print-view ref="printView" @parentcall="parentcall"></print-view>
@@ -212,6 +300,81 @@
                     <el-button @click="confirmDialogVisible = false">鍙栨秷</el-button>
                     <el-button type="primary" @click="executeConfirm" :loading="executeLoading">
                         纭畾
+                    </el-button>
+                </span>
+            </template>
+        </el-dialog>
+
+        <!-- 鏁村嚭纭瀵硅瘽妗� -->
+        <el-dialog v-model="wholeOutDialogVisible" title="鏁村嚭鎿嶄綔纭" width="500px" :before-close="handleWholeOutDialogClose" custom-class="whole-out-dialog">
+            <div class="whole-out-content" v-if="wholeOutInfo">
+                <!-- 璀﹀憡鎻愮ず -->
+                <el-alert title="璇ユ墭鐩樺寘鍚渶瑕佹暣鍑虹殑鐗╂枡" type="warning" :closable="false" show-icon class="whole-out-alert">
+                    <template #default>
+                        <div>鏁村嚭鎿嶄綔灏嗕竴娆℃�ф嫞閫夎鐗╂枡鐨勬墍鏈夊簱瀛橈紝璇风‘璁や俊鎭棤璇悗鎵ц</div>
+                    </template>
+                </el-alert>
+
+                <!-- 鎵樼洏淇℃伅 -->
+                <div class="info-section">
+                    <h4 class="section-title">
+                        <i class="el-icon-box"></i>
+                        鎵樼洏淇℃伅
+                    </h4>
+                    <div class="info-grid">
+                        <div class="info-item">
+                            <label>鎵樼洏鐮侊細</label>
+                            <span class="info-value">{{ wholeOutInfo.palletCode }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>搴撲綅锛�</label>
+                            <span class="info-value">{{ wholeOutInfo.locationCode || '鏈寚瀹�' }}</span>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 鏁村嚭鐗╂枡璇︽儏 -->
+                <div class="info-section">
+                    <h4 class="section-title">
+                        <i class="el-icon-s-grid"></i>
+                        鏁村嚭鐗╂枡璇︽儏
+                    </h4>
+                    <div class="info-grid">
+                        <div class="info-item">
+                            <label>鐗╂枡缂栫爜锛�</label>
+                            <span class="info-value">{{ wholeOutInfo.materielCode }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>鐗╂枡鍚嶇О锛�</label>
+                            <span class="info-value">{{ wholeOutInfo.materielName }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>鎵规鍙凤細</label>
+                            <span class="info-value">{{ wholeOutInfo.batchNo }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>鏁村嚭鏁伴噺锛�</label>
+                            <span class="info-value highlight">{{ wholeOutInfo.assignQuantity }} {{ wholeOutInfo.unit }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>褰撳墠搴撳瓨锛�</label>
+                            <span class="info-value">{{ wholeOutInfo.currentStock || wholeOutInfo.originalQuantity }} {{ wholeOutInfo.unit }}</span>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 鎿嶄綔鎻愮ず -->
+                <div class="operation-tip">
+                    <i class="el-icon-info"></i>
+                    <span>纭鎵ц鏁村嚭鎿嶄綔鍚楋紵姝ゆ搷浣滃皢涓�娆℃�ф嫞閫夎鐗╂枡鐨勬墍鏈夊簱瀛樸��</span>
+                </div>
+            </div>
+            <template #footer>
+                <span class="dialog-footer">
+                    <el-button @click="wholeOutDialogVisible = false" size="medium">鍙栨秷</el-button>
+                    <el-button type="warning" @click="executeWholeOut" :loading="executeLoading" size="medium">
+                        <i class="el-icon-check"></i>
+                        纭鏁村嚭
                     </el-button>
                 </span>
             </template>
@@ -253,7 +416,10 @@
             confirmDialogVisible: false,
             confirmMessage: '',
             currentAction: null,
-            executeLoading: false
+            executeLoading: false,
+            matMixed: true,
+            wholeOutDialogVisible: false,
+            wholeOutInfo: null
         }
     },
     computed: {
@@ -300,8 +466,9 @@
             try {
                 this.http.post(`/api/Outbound/QueryPickingTasks?orderNo=${this.orderNo}&palletCode=${this.scanForm.palletCode}`, {}).then(response => {
                     if (response.status) {
-                        if (response.data.length > 0) {
-                            this.unpickedData = response.data
+                        if (response.data.outStockLockInfos.length > 0) {
+                            this.unpickedData = response.data.outStockLockInfos;
+                            this.matMixed = response.data.isMatMixed;
                             this.calculateUnpickedStats()
 
                             // 鑷姩鑱氱劍鍒扮墿鏂欐潯鐮佽緭鍏ユ
@@ -384,7 +551,12 @@
                 // this.$message.success(`鎵樼洏鐮�: ${this.scanForm.palletCode}`)
                 this.loadPalletData()
 
-
+                // 妫�鏌ユ槸鍚﹂渶瑕佹暣鍑虹‘璁�
+                this.$nextTick(() => {
+                    if (this.hasWholeOut() && this.matMixed) {
+                        this.showWholeOutConfirm()
+                    }
+                })
             }
         },
 
@@ -504,6 +676,69 @@
             }
         },
 
+        // 鏁村嚭纭鐩稿叧鏂规硶
+        showWholeOutConfirm() {
+            // 鑾峰彇闇�瑕佹暣鍑虹殑鐗╂枡淇℃伅
+            const wholeOutItem = this.unpickedData.find(item => item.assignQuantity === item.originalQuantity);
+            if (wholeOutItem) {
+                this.wholeOutInfo = {
+                    palletCode: this.scanForm.palletCode,
+                    locationCode: wholeOutItem.locationCode,
+                    materielCode: wholeOutItem.materielCode,
+                    materielName: wholeOutItem.materielName,
+                    batchNo: wholeOutItem.batchNo,
+                    assignQuantity: wholeOutItem.assignQuantity,
+                    currentStock: wholeOutItem.currentStock,
+                    originalQuantity: wholeOutItem.originalQuantity,
+                    unit: wholeOutItem.unit
+                };
+                this.wholeOutDialogVisible = true;
+            }
+        },
+
+        handleWholeOutDialogClose() {
+            if (!this.executeLoading) {
+                this.wholeOutDialogVisible = false;
+                this.wholeOutInfo = null;
+            }
+        },
+
+        executeWholeOut() {
+            if (!this.wholeOutInfo) {
+                this.$message.error('鏁村嚭淇℃伅鏃犳晥');
+                return;
+            }
+
+            this.executeLoading = true;
+
+            try {
+                // 璋冪敤鏁村嚭鎺ュ彛锛岃繖閲屼娇鐢ㄧ墿鏂欑紪鐮佷綔涓烘潯鐮�
+                this.http.post('/api/Outbound/CompleteOutboundWithBarcode', {
+                    orderNo: this.orderNo,
+                    palletCode: this.scanForm.palletCode,
+                    barcode: this.wholeOutInfo.materielCode, // 浣跨敤鐗╂枡缂栫爜杩涜鏁村嚭
+                    operator: this.getUserName()
+                }).then(response => {
+                    if (response.status) {
+                        if (response.data.scannedDetail.isUnpacked && response.data.scannedDetail.materialCodes.length > 0) {
+                            this.$refs.printView.open(response.data.scannedDetail.materialCodes);
+                        }
+                        this.$message.success('鏁村嚭鎿嶄綔鎴愬姛');
+                        this.wholeOutDialogVisible = false;
+                        this.wholeOutInfo = null;
+                        this.loadPalletData();
+                    } else {
+                        this.$message.error(response.message || '鏁村嚭鎿嶄綔澶辫触');
+                    }
+                });
+            } catch (error) {
+                console.error('鏁村嚭鎿嶄綔澶辫触:', error);
+                this.$message.error('鏁村嚭鎿嶄綔澶辫触');
+            } finally {
+                this.executeLoading = false;
+            }
+        },
+
         quickPick(row) {
             this.scanForm.materialBarcode = row.materielCode
             this.handleConfirmPick()
@@ -587,6 +822,71 @@
             }
 
             return '鏈櫥褰曠敤鎴�'
+        },
+
+        // 璁$畻鍒嗘嫞鎬绘暟
+        calculateTotalAssignQuantity() {
+            return this.unpickedData.reduce((sum, item) => {
+                return sum + (item.assignQuantity || 0)
+            }, 0)
+        },
+
+        // 璁$畻宸插垎鎷f�绘暟
+        calculateTotalSortedQuantity() {
+            return this.unpickedData.reduce((sum, item) => {
+                return sum + (item.sortedQuantity || 0)
+            }, 0)
+        },
+
+        // 璁$畻鏈垎鎷f�绘暟
+        calculateTotalUnsortedQuantity() {
+            return this.unpickedData.reduce((sum, item) => {
+                const assignQty = item.assignQuantity || 0
+                const sortedQty = item.sortedQuantity || 0
+                return sum + Math.max(0, assignQty - sortedQty)
+            }, 0)
+        },
+
+        // 妫�鏌ユ槸鍚﹀寘鍚暣鍑�
+        hasWholeOut() {
+            return this.unpickedData.some(item => item.assignQuantity === item.originalQuantity) && this.matMixed;
+        },
+
+        // 璁$畻鍓╀綑搴撳瓨
+        calculateRemainingStock(row) {
+            const currentStock = row.currentStock || 0
+            const assignQty = row.assignQuantity || 0
+            return Math.max(0, currentStock - assignQty)
+        },
+
+        // 鑾峰彇搴撳瓨鐘舵�佺被鍨�
+        getStockStatusType(row) {
+            const currentStock = row.currentStock || 0
+            const assignQty = row.assignQuantity || 0
+            const sortedQty = row.sortedQuantity || 0
+
+            if (sortedQty >= assignQty) {
+                return 'success' // 宸插畬鎴�
+            } else if (currentStock < assignQty) {
+                return 'danger' // 搴撳瓨涓嶈冻
+            } else {
+                return 'warning' // 杩涜涓�
+            }
+        },
+
+        // 鑾峰彇搴撳瓨鐘舵�佹枃鏈�
+        getStockStatusText(row) {
+            const currentStock = row.currentStock || 0
+            const assignQty = row.assignQuantity || 0
+            const sortedQty = row.sortedQuantity || 0
+
+            if (sortedQty >= assignQty) {
+                return '宸插畬鎴�'
+            } else if (currentStock < assignQty) {
+                return '搴撳瓨涓嶈冻'
+            } else {
+                return '鍒嗘嫞涓�'
+            }
         },
 
         getStatusType(status) {
@@ -802,4 +1102,252 @@
 ::v-deep .el-descriptions__content {
     color: #606266;
 }
+
+/* 琛ㄦ牸澧炲己鏍峰紡 */
+::v-deep .el-table th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #303133;
+}
+
+::v-deep .el-table .el-text {
+    font-weight: 500;
+}
+
+/* 鏍囩鏍峰紡澧炲己 */
+::v-deep .el-tag--small {
+    font-weight: 500;
+}
+
+/* 鎻愮ず淇℃伅鏍峰紡澧炲己 */
+.scan-alert ::v-deep .el-alert__content {
+    width: 100%;
+}
+
+.scan-alert ::v-deep .el-alert__description {
+    margin-top: 8px;
+}
+
+/* 鍒嗘嫞缁熻淇℃伅鏍峰紡 */
+.picking-stats {
+    margin-top: 20px;
+    padding: 0 10px;
+}
+
+.stats-container {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 12px;
+    align-items: center;
+}
+
+.stat-item {
+    display: inline-flex;
+    align-items: center;
+}
+
+.stat-item .el-tag {
+    display: flex;
+    align-items: center;
+    padding: 6px 12px;
+    font-size: 13px;
+    border-radius: 20px;
+}
+
+.stat-item .el-tag i {
+    margin-right: 6px;
+    font-size: 14px;
+}
+
+.stat-item b {
+    margin-left: 4px;
+    font-size: 14px;
+}
+
+/* 鍒嗗壊绾挎牱寮� */
+::v-deep .el-divider__text {
+    background-color: #f5f5f5;
+    padding: 0 20px;
+}
+
+/* 鎵樼洏搴撳瓨淇℃伅鏍峰紡 */
+.pallet-inventory {
+    margin-top: 20px;
+    padding: 0 10px;
+}
+
+.inventory-container {
+    margin-top: 10px;
+}
+
+.inventory-table {
+    width: 100%;
+}
+
+.inventory-table ::v-deep .el-table__header {
+    background-color: #f0f9ff;
+}
+
+.inventory-table ::v-deep .el-table__header th {
+    background-color: #e1f3ff;
+    color: #1f2937;
+    font-weight: 600;
+    font-size: 12px;
+    padding: 8px 0;
+}
+
+.inventory-table ::v-deep .el-table__body td {
+    padding: 6px 0;
+    font-size: 12px;
+}
+
+.inventory-table ::v-deep .el-table__row {
+    cursor: pointer;
+}
+
+.inventory-table ::v-deep .el-table__row:hover {
+    background-color: #f0f9ff;
+}
+
+/* 搴撳瓨琛ㄦ牸涓殑鏍囩鏍峰紡 */
+.inventory-table ::v-deep .el-tag--mini {
+    font-size: 11px;
+    padding: 1px 6px;
+    height: 18px;
+    line-height: 16px;
+}
+
+/* 鏁村嚭纭寮圭獥鏍峰紡 */
+::v-deep .whole-out-dialog {
+    border-radius: 8px;
+}
+
+::v-deep .whole-out-dialog .el-dialog__header {
+    background: linear-gradient(135deg, #E6A23C 0%, #d9971a 100%);
+    color: white;
+    padding: 15px 20px;
+    border-radius: 8px 8px 0 0;
+}
+
+::v-deep .whole-out-dialog .el-dialog__title {
+    color: white;
+    font-weight: bold;
+    font-size: 16px;
+}
+
+::v-deep .whole-out-dialog .el-dialog__headerbtn .el-dialog__close {
+    color: white;
+    font-size: 18px;
+}
+
+.whole-out-content {
+    padding: 0 10px;
+}
+
+.whole-out-alert {
+    margin-bottom: 20px;
+}
+
+.whole-out-alert ::v-deep .el-alert__description {
+    margin-top: 5px;
+    font-size: 14px;
+    color: #666;
+}
+
+.info-section {
+    margin-bottom: 20px;
+}
+
+.section-title {
+    color: #303133;
+    font-size: 15px;
+    font-weight: bold;
+    margin-bottom: 10px;
+    padding-bottom: 5px;
+    border-bottom: 2px solid #E6A23C;
+    display: flex;
+    align-items: center;
+}
+
+.section-title i {
+    margin-right: 8px;
+    color: #E6A23C;
+    font-size: 16px;
+}
+
+.info-grid {
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    gap: 12px;
+}
+
+.info-item {
+    display: flex;
+    align-items: center;
+    padding: 8px 0;
+    border-bottom: 1px solid #f0f0f0;
+}
+
+.info-item label {
+    font-weight: 500;
+    color: #606266;
+    min-width: 80px;
+    font-size: 14px;
+}
+
+.info-item .info-value {
+    color: #303133;
+    font-size: 14px;
+    flex: 1;
+}
+
+.info-item .info-value.highlight {
+    color: #E6A23C;
+    font-weight: bold;
+    font-size: 15px;
+}
+
+.operation-tip {
+    background-color: #fff7e6;
+    border: 1px solid #ffd591;
+    border-radius: 6px;
+    padding: 12px 15px;
+    margin-top: 20px;
+    display: flex;
+    align-items: center;
+}
+
+.operation-tip i {
+    color: #E6A23C;
+    margin-right: 8px;
+    font-size: 16px;
+    flex-shrink: 0;
+}
+
+.operation-tip span {
+    color: #606266;
+    font-size: 14px;
+    line-height: 1.5;
+}
+
+/* 鍝嶅簲寮忚皟鏁� */
+@media (max-width: 768px) {
+    .info-grid {
+        grid-template-columns: 1fr;
+        gap: 8px;
+    }
+
+    .info-item {
+        padding: 6px 0;
+    }
+
+    .info-item label {
+        min-width: 70px;
+        font-size: 13px;
+    }
+
+    .info-item .info-value {
+        font-size: 13px;
+    }
+}
 </style>
\ No newline at end of file
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
index 16b62c5..0fa082e 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
@@ -1,5 +1,6 @@
 <template>
-    <div class="picking-container">
+    <div class="picking-container" v-loading="globalLoading" element-loading-text="澶勭悊涓�..."
+        element-loading-background="rgba(255, 255, 255, 0.8)">
         <!-- 椤堕儴璁㈠崟淇℃伅 -->
         <el-card class="order-info-card" shadow="never">
             <div class="order-header">
@@ -105,7 +106,7 @@
                             </el-tag>
                         </div>
                         <div class="stat-item">
-                            <el-tag type="success" size="medium" effect="dark">
+                            <el-tag :type="hasWholeOut() ? 'success' : 'warning'" size="medium" effect="dark">
                                 <i class="el-icon-box"></i>
                                 鏄惁鏁村嚭锛歿{ hasWholeOut() ? '鏄�' : '鍚�' }}
                             </el-tag>
@@ -304,6 +305,84 @@
                 </span>
             </template>
         </el-dialog>
+
+        <!-- 鏁村嚭纭瀵硅瘽妗� -->
+        <el-dialog v-model="wholeOutDialogVisible" title="鏁村嚭鎿嶄綔纭" width="500px"
+            :before-close="handleWholeOutDialogClose" custom-class="whole-out-dialog" style="margin-right: 0px;">
+            <div class="whole-out-content" v-if="wholeOutInfo">
+                <!-- 璀﹀憡鎻愮ず -->
+                <el-alert title="璇ユ墭鐩樺寘鍚渶瑕佹暣鍑虹殑鐗╂枡" type="warning" :closable="false" show-icon class="whole-out-alert">
+                    <template #default>
+                        <div>鏁村嚭鎿嶄綔灏嗕竴娆℃�ф嫞閫夎鐗╂枡鐨勬墍鏈夊簱瀛橈紝璇风‘璁や俊鎭棤璇悗鎵ц</div>
+                    </template>
+                </el-alert>
+
+                <!-- 鎵樼洏淇℃伅 -->
+                <div class="info-section">
+                    <h4 class="section-title">
+                        <i class="el-icon-box"></i>
+                        鎵樼洏淇℃伅
+                    </h4>
+                    <div class="info-grid">
+                        <div class="info-item">
+                            <label>鎵樼洏鐮侊細</label>
+                            <span class="info-value">{{ wholeOutInfo.palletCode }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>搴撲綅锛�</label>
+                            <span class="info-value">{{ wholeOutInfo.locationCode || '鏈寚瀹�' }}</span>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 鏁村嚭鐗╂枡璇︽儏 -->
+                <div class="info-section">
+                    <h4 class="section-title">
+                        <i class="el-icon-s-grid"></i>
+                        鏁村嚭鐗╂枡璇︽儏
+                    </h4>
+                    <div class="info-grid">
+                        <div class="info-item">
+                            <label>鐗╂枡缂栫爜锛�</label>
+                            <span class="info-value">{{ wholeOutInfo.materielCode }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>鐗╂枡鍚嶇О锛�</label>
+                            <span class="info-value">{{ wholeOutInfo.materielName }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>鎵规鍙凤細</label>
+                            <span class="info-value">{{ wholeOutInfo.batchNo }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>鏁村嚭鏁伴噺锛�</label>
+                            <span class="info-value highlight">{{ wholeOutInfo.assignQuantity }} {{ wholeOutInfo.unit
+                            }}</span>
+                        </div>
+                        <div class="info-item">
+                            <label>褰撳墠搴撳瓨锛�</label>
+                            <span class="info-value">{{ wholeOutInfo.currentStock || wholeOutInfo.originalQuantity }} {{
+                                wholeOutInfo.unit }}</span>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 鎿嶄綔鎻愮ず -->
+                <div class="operation-tip">
+                    <i class="el-icon-info"></i>
+                    <span>纭鎵ц鏁村嚭鎿嶄綔鍚楋紵姝ゆ搷浣滃皢涓�娆℃�ф嫞閫夎鐗╂枡鐨勬墍鏈夊簱瀛樸��</span>
+                </div>
+            </div>
+            <template #footer>
+                <span class="dialog-footer">
+                    <el-button @click="wholeOutDialogVisible = false" size="medium">鍙栨秷</el-button>
+                    <el-button type="warning" @click="executeWholeOut" :loading="executeLoading" size="medium">
+                        <i class="el-icon-check"></i>
+                        纭鏁村嚭
+                    </el-button>
+                </span>
+            </template>
+        </el-dialog>
     </div>
 </template>
 
@@ -342,7 +421,10 @@
             confirmMessage: '',
             currentAction: null,
             executeLoading: false,
-            matMixed: true
+            matMixed: true,
+            wholeOutDialogVisible: false,
+            wholeOutInfo: null,
+            globalLoading: false
         }
     },
     computed: {
@@ -370,30 +452,40 @@
             })
         },
 
-        loadPalletData() {
+        async loadPalletData() {
             if (!this.scanForm.palletCode) {
                 this.unpickedData = []
                 return
             }
 
             try {
-                this.loadUnpickedData();
-                this.loadPickedData();
+                this.globalLoading = true
+                await Promise.all([
+                    this.loadUnpickedData(),
+                    this.loadPickedData()
+                ]);
 
             } catch (error) {
                 console.error('鍔犺浇鎵樼洏鏁版嵁澶辫触:', error)
                 this.unpickedData = []
+            } finally {
+                this.globalLoading = false
             }
         },
         loadUnpickedData() {
-            try {
+            return new Promise((resolve, reject) => {
                 this.http.post(`/api/Outbound/QueryPickingTasks?orderNo=${this.orderNo}&palletCode=${this.scanForm.palletCode}`, {}).then(response => {
                     if (response.status) {
                         if (response.data.outStockLockInfos.length > 0) {
                             this.unpickedData = response.data.outStockLockInfos;
                             this.matMixed = response.data.isMatMixed;
                             this.calculateUnpickedStats()
-
+                            // 妫�鏌ユ槸鍚﹂渶瑕佹暣鍑虹‘璁�
+                            this.$nextTick(() => {
+                                if (this.hasWholeOut()) {
+                                    this.showWholeOutConfirm()
+                                }
+                            })
                             // 鑷姩鑱氱劍鍒扮墿鏂欐潯鐮佽緭鍏ユ
                             this.$nextTick(() => {
                                 if (this.$refs.materialInput) {
@@ -404,20 +496,21 @@
                             this.$message.warning('璇ユ墭鐩樻棤鏈嫞閫変换鍔�')
                             this.unpickedData = []
                         }
+                        resolve()
                     } else {
                         this.$message.error(response.message || '鑾峰彇鎵樼洏鏁版嵁澶辫触')
                         this.unpickedData = []
+                        reject(response.message || '鑾峰彇鎵樼洏鏁版嵁澶辫触')
                     }
-                }
-                )
-
-            } catch (error) {
-                console.error('鍔犺浇鏈嫞閫夋暟鎹け璐�:', error)
-            }
+                }).catch(error => {
+                    console.error('鍔犺浇鏈嫞閫夋暟鎹け璐�:', error)
+                    reject(error)
+                })
+            })
         },
 
         loadPickedData() {
-            try {
+            return new Promise((resolve, reject) => {
                 this.http.post(`/api/Outbound/QueryPickedList?orderNo=${this.orderNo}&palletCode=${this.scanForm.palletCode}`, {}).then(response => {
                     if (response.status) {
                         if (response.data.length > 0) {
@@ -426,16 +519,17 @@
                         } else {
                             this.pickedData = []
                         }
+                        resolve()
                     } else {
                         this.$message.error(response.message || '鑾峰彇鎵樼洏鏁版嵁澶辫触')
                         this.pickedData = []
+                        reject(response.message || '鑾峰彇鎵樼洏鏁版嵁澶辫触')
                     }
-                }
-                )
-
-            } catch (error) {
-                console.error('鍔犺浇宸叉嫞閫夋暟鎹け璐�:', error)
-            }
+                }).catch(error => {
+                    console.error('鍔犺浇宸叉嫞閫夋暟鎹け璐�:', error)
+                    reject(error)
+                })
+            })
         },
 
         // 璁$畻鏈嫞閫�
@@ -473,8 +567,6 @@
             if (this.scanForm.palletCode) {
                 // this.$message.success(`鎵樼洏鐮�: ${this.scanForm.palletCode}`)
                 this.loadPalletData()
-
-
             }
         },
 
@@ -501,6 +593,7 @@
             }
 
             this.confirmLoading = true
+            this.globalLoading = true
 
             try {
                 this.http.post('/api/Outbound/CompleteOutboundWithBarcode', {
@@ -527,6 +620,7 @@
                 this.$message.error('鎷i�夌‘璁ゅけ璐�')
             } finally {
                 this.confirmLoading = false
+                this.globalLoading = false
             }
         },
 
@@ -554,6 +648,7 @@
 
         executeConfirm() {
             this.executeLoading = true
+            this.globalLoading = true
 
             try {
                 let apiUrl = ''
@@ -585,12 +680,75 @@
                 this.$message.error('鎿嶄綔澶辫触')
             } finally {
                 this.executeLoading = false
+                this.globalLoading = false
             }
         },
 
         handleDialogClose() {
             if (!this.executeLoading) {
                 this.confirmDialogVisible = false
+            }
+        },
+
+        // 鏁村嚭纭鐩稿叧鏂规硶
+        showWholeOutConfirm() {
+            // 鑾峰彇闇�瑕佹暣鍑虹殑鐗╂枡淇℃伅
+            const wholeOutItem = this.unpickedData.find(item => item.assignQuantity === item.originalQuantity);
+            console.log('wholeOutItem:', wholeOutItem);
+            if (wholeOutItem) {
+                this.wholeOutInfo = {
+                    palletCode: this.scanForm.palletCode,
+                    locationCode: wholeOutItem.locationCode,
+                    materielCode: wholeOutItem.materielCode,
+                    materielName: wholeOutItem.materielName,
+                    batchNo: wholeOutItem.batchNo,
+                    assignQuantity: wholeOutItem.assignQuantity,
+                    currentStock: wholeOutItem.currentStock,
+                    originalQuantity: wholeOutItem.originalQuantity,
+                    unit: wholeOutItem.unit
+                };
+                this.wholeOutDialogVisible = true;
+            }
+        },
+
+        handleWholeOutDialogClose() {
+            if (!this.executeLoading) {
+                this.wholeOutDialogVisible = false;
+                this.wholeOutInfo = null;
+            }
+        },
+
+        executeWholeOut() {
+            if (!this.wholeOutInfo) {
+                this.$message.error('鏁村嚭淇℃伅鏃犳晥');
+                return;
+            }
+
+            this.executeLoading = true;
+            this.globalLoading = true;
+
+            try {
+                // 璋冪敤鏁村嚭鎺ュ彛锛岃繖閲屼娇鐢ㄧ墿鏂欑紪鐮佷綔涓烘潯鐮�
+                this.http.post('/api/Outbound/CompleteOutboundWithPallet', {
+                    orderNo: this.orderNo,
+                    palletCode: this.scanForm.palletCode,
+                    operator: this.getUserName()
+                }).then(response => {
+                    if (response.status) {
+                        this.$message.success('鏁村嚭鎿嶄綔鎴愬姛');
+                        this.wholeOutDialogVisible = false;
+                        this.wholeOutInfo = null;
+                        this.loadPalletData();
+                    } else {
+                        this.$message.error(response.message || '鏁村嚭鎿嶄綔澶辫触');
+                    }
+                });
+            } catch (error) {
+                console.error('鏁村嚭鎿嶄綔澶辫触:', error);
+                this.$message.error('鏁村嚭鎿嶄綔澶辫触');
+            } finally {
+                this.executeLoading = false;
+                this.globalLoading = false;
             }
         },
 
@@ -636,7 +794,9 @@
         },
 
         refreshPickedTable() {
-            this.loadPickedData()
+            this.loadPickedData().catch(error => {
+                console.error('鍒锋柊宸叉嫞閫夊垪琛ㄥけ璐�:', error)
+            })
         },
 
         resetMaterialBarcode() {
@@ -704,7 +864,8 @@
 
         // 妫�鏌ユ槸鍚﹀寘鍚暣鍑�
         hasWholeOut() {
-            return this.unpickedData.some(item => item.assignQuantity === item.originalQuantity) && this.matMixed;
+            console.log('妫�鏌ユ暣鍑虹姸鎬�:', this.unpickedData.some(item => item.assignQuantity === item.originalQuantity));
+            return this.unpickedData.some(item => item.assignQuantity === item.originalQuantity) && !this.matMixed;
         },
 
         // 璁$畻鍓╀綑搴撳瓨
@@ -758,11 +919,19 @@
 }
 </script>
 
+<style>
+.el-dialog__header {
+    margin: 0;
+}
+</style>
+
 <style scoped>
 .picking-container {
     padding: 20px;
     background-color: #f5f5f5;
     min-height: 100vh;
+    position: relative;
+    overflow: hidden;
 }
 
 /* 璁㈠崟淇℃伅鍗$墖 */
@@ -1071,4 +1240,154 @@
     height: 18px;
     line-height: 16px;
 }
+
+/* 鏁村嚭纭寮圭獥鏍峰紡 */
+::v-deep .whole-out-dialog {
+    border-radius: 8px;
+}
+
+::v-deep .whole-out-dialog .el-dialog__header {
+    background: linear-gradient(135deg, #E6A23C 0%, #d9971a 100%);
+    color: white;
+    padding: 15px 20px;
+    border-radius: 8px 8px 0 0;
+}
+
+::v-deep .whole-out-dialog .el-dialog__title {
+    color: white;
+    font-weight: bold;
+    font-size: 16px;
+}
+
+::v-deep .whole-out-dialog .el-dialog__headerbtn .el-dialog__close {
+    color: white;
+    font-size: 18px;
+}
+
+.whole-out-content {
+    padding: 0 10px;
+}
+
+.whole-out-alert {
+    margin-bottom: 20px;
+}
+
+.whole-out-alert ::v-deep .el-alert__description {
+    margin-top: 5px;
+    font-size: 14px;
+    color: #666;
+}
+
+.info-section {
+    margin-bottom: 20px;
+}
+
+.section-title {
+    color: #303133;
+    font-size: 15px;
+    font-weight: bold;
+    margin-bottom: 10px;
+    padding-bottom: 5px;
+    border-bottom: 2px solid #E6A23C;
+    display: flex;
+    align-items: center;
+}
+
+.section-title i {
+    margin-right: 8px;
+    color: #E6A23C;
+    font-size: 16px;
+}
+
+.info-grid {
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    gap: 12px;
+}
+
+.info-item {
+    display: flex;
+    align-items: center;
+    padding: 8px 0;
+    border-bottom: 1px solid #f0f0f0;
+}
+
+.info-item label {
+    font-weight: 500;
+    color: #606266;
+    min-width: 80px;
+    font-size: 14px;
+}
+
+.info-item .info-value {
+    color: #303133;
+    font-size: 14px;
+    flex: 1;
+}
+
+.info-item .info-value.highlight {
+    color: #E6A23C;
+    font-weight: bold;
+    font-size: 15px;
+}
+
+.operation-tip {
+    background-color: #fff7e6;
+    border: 1px solid #ffd591;
+    border-radius: 6px;
+    padding: 12px 15px;
+    margin-top: 20px;
+    display: flex;
+    align-items: center;
+}
+
+.operation-tip i {
+    color: #E6A23C;
+    margin-right: 8px;
+    font-size: 16px;
+    flex-shrink: 0;
+}
+
+.operation-tip span {
+    color: #606266;
+    font-size: 14px;
+    line-height: 1.5;
+}
+
+/* 鍝嶅簲寮忚皟鏁� */
+@media (max-width: 768px) {
+    .info-grid {
+        grid-template-columns: 1fr;
+        gap: 8px;
+    }
+
+    .info-item {
+        padding: 6px 0;
+    }
+
+    .info-item label {
+        min-width: 70px;
+        font-size: 13px;
+    }
+
+    .info-item .info-value {
+        font-size: 13px;
+    }
+}
+
+/* Element Plus Loading 閬僵灞傛牱寮忎慨澶� */
+::v-deep .el-loading-mask {
+    background-color: rgba(255, 255, 255, 0.8);
+    z-index: 2000;
+}
+
+::v-deep .el-loading-spinner {
+    z-index: 2001;
+}
+
+::v-deep .el-loading-text {
+    color: #409EFF;
+    font-weight: bold;
+    font-size: 14px;
+}
 </style>
\ No newline at end of file
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db"
index 411f3cf..564919e 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db"
Binary files differ
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db"
index 4e7627a..339483f 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db"
Binary files differ
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_DTO/CalcOut/OutboundCompleteRequestDTO.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_DTO/CalcOut/OutboundCompleteRequestDTO.cs"
index 734cef1..f60b34f 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_DTO/CalcOut/OutboundCompleteRequestDTO.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_DTO/CalcOut/OutboundCompleteRequestDTO.cs"
@@ -35,4 +35,27 @@
         /// </summary>
         public string Operator { get; set; }
     }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public class OutboundCompletePalletRequestDTO
+    {
+        /// <summary>
+        /// 鍑哄簱鍗曠紪鍙�
+        /// </summary>
+        [Required(ErrorMessage = "鍑哄簱鍗曠紪鍙蜂笉鑳戒负绌�")]
+        public string OrderNo { get; set; }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        [Required(ErrorMessage = "鎵樼洏鍙蜂笉鑳戒负绌�")]
+        public string PalletCode { get; set; }
+
+        /// <summary>
+        /// 鎿嶄綔鑰�
+        /// </summary>
+        public string Operator { get; set; }
+    }
 }
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundService.cs"
index 42c2637..d262388 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundService.cs"
@@ -30,6 +30,8 @@
         /// <returns>鍑哄簱瀹屾垚鍝嶅簲</returns>
         WebResponseContent CompleteOutboundWithBarcode(OutboundCompleteRequestDTO request);
 
+        WebResponseContent CompleteOutboundWithPallet(OutboundCompletePalletRequestDTO request);
+
         WebResponseContent QueryPickingTasks(string palletCode, string orderNo);
 
         WebResponseContent QueryPickedList(string orderNo, string palletCode);
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs"
index e583f96..a24c5a0 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs"
@@ -153,7 +153,7 @@
         public async Task<List<Dt_OutStockLockInfo>> GetByOrderDetailId(int orderDetailId)
         {
             return await Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(x => x.OrderDetailId == orderDetailId)
+                .Where(x => x.OrderDetailIds.Contains(orderDetailId.ToString()))
                 .OrderBy(x => x.Id)
                 .ToListAsync();
         }
@@ -255,7 +255,7 @@
 
         public List<Dt_OutStockLockInfo> GetByOrderDetailId(int orderDetailId, OutLockStockStatusEnum? outStockStatus)
         {
-            return BaseDal.QueryData(x => x.OrderDetailId == orderDetailId );
+            return BaseDal.QueryData(x => x.OrderDetailIds.Contains(orderDetailId.ToString()));
         }
 
     }
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundQueryService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundQueryService.cs"
index 956e03f..bd83f1b 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundQueryService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundQueryService.cs"
@@ -19,15 +19,19 @@
             try
             {
                 Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).Includes(x => x.Details).First();
-
-                bool isMatMixed = stockInfo.Details.GroupBy(x => new
+                bool isMatMixed = false;
+                if (stockInfo != null)
                 {
-                    x.MaterielCode,
-                    x.MaterielName,
-                    x.BatchNo,
-                    x.SupplyCode,
-                    x.WarehouseCode
-                }).Count() > 1;
+                    isMatMixed = stockInfo.Details.GroupBy(x => new
+                    {
+                        x.MaterielCode,
+                        x.MaterielName,
+                        x.BatchNo,
+                        x.SupplyCode,
+                        x.WarehouseCode
+                    }).Count() > 1;
+                }
+
 
                 List<Dt_OutStockLockInfo> outStockLockInfos = _outboundLockInfoRepository.QueryData(x => x.PalletCode == palletCode && x.OrderNo == orderNo);
                 return WebResponseContent.Instance.OK(data: new { outStockLockInfos, stockInfo, isMatMixed });
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs"
index 6c5a0ce..bbea89b 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs"
@@ -813,6 +813,332 @@
         }
         #endregion
 
+
+
+        public WebResponseContent CompleteOutboundWithPallet(OutboundCompletePalletRequestDTO request)
+        {
+            WebResponseContent content = WebResponseContent.Instance;
+
+            OutboundCompleteResponseDTO response = new();
+            try
+            {
+                // 1. 鏍规嵁鎵樼洏鍙锋煡鎵惧簱瀛樹俊鎭�
+                Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == request.PalletCode).Includes(x => x.Details).First();
+                if (stockInfo == null)
+                {
+                    response.Success = false;
+                    response.Message = $"鎵樼洏鍙� {request.PalletCode} 瀵瑰簲鐨勫簱瀛樹笉瀛樺湪";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                if (!stockInfo.Details.Any())
+                {
+                    response.Success = false;
+                    response.Message = $"鎵樼洏 {request.PalletCode} 瀵瑰簲鐨勫簱瀛樻槑缁嗕笉瀛樺湪";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                bool isMatMixed = stockInfo.Details.GroupBy(x => new
+                {
+                    x.MaterielCode,
+                    x.MaterielName,
+                    x.BatchNo,
+                    x.SupplyCode,
+                    x.WarehouseCode
+                }).Count() > 1;
+
+                if (isMatMixed)
+                {
+                    response.Success = false;
+                    response.Message = $"娣锋枡鎵樼洏 {request.PalletCode} 涓嶈兘鏁寸鍑哄簱";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                // 2. 鏌ユ壘鍑哄簱鍗曚俊鎭�
+                Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(o => o.OrderNo == request.OrderNo);
+                if (outboundOrder == null)
+                {
+                    response.Success = false;
+                    response.Message = $"鍑哄簱鍗� {request.OrderNo} 涓嶅瓨鍦�";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                Dt_StockInfoDetail stockInfoDetail = stockInfo.Details.First();
+
+                // 3. 鏌ユ壘閿佸畾璁板綍
+                Dt_OutStockLockInfo lockInfo = _outboundLockInfoRepository.QueryFirst(x =>
+                    x.OrderNo == request.OrderNo &&
+                    x.StockId == stockInfo.Id &&
+                    x.MaterielCode == stockInfoDetail.MaterielCode &&
+                    x.PalletCode == stockInfo.PalletCode);
+
+                if (lockInfo == null || lockInfo.AssignQuantity <= 0)
+                {
+                    response.Success = false;
+                    response.Message = $"璇ュ簱瀛樻病鏈夊垎閰嶅嚭搴撻噺锛屾墭鐩樺彿锛歿request.PalletCode}";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                // 鎵惧嚭宸插垎閰嶇殑璁㈠崟鏄庣粏Id
+                List<int> detailIds = new List<int>();
+                string[] ids = lockInfo.OrderDetailIds.Split(",");
+                foreach (string id in ids)
+                {
+                    if (int.TryParse(id, out int detailId))
+                    {
+                        detailIds.Add(detailId);
+                    }
+                }
+                // 4. 鏌ユ壘鍑哄簱鍗曟槑缁嗕俊鎭�
+                List<Dt_OutboundOrderDetail> outboundOrderDetails = FindMatchingOutboundDetails(outboundOrder.Id, stockInfoDetail, detailIds);
+                if (!outboundOrderDetails.Any())
+                {
+                    response.Success = false;
+                    response.Message = $"鏈壘鍒板尮閰嶇殑鍑哄簱鍗曟槑缁嗭紝鐗╂枡锛歿stockInfoDetail.MaterielCode}锛屾壒娆★細{stockInfoDetail.BatchNo}";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                decimal totalStockQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
+
+                // 5. 璁$畻瀹為檯鍑哄簱閲�
+                decimal actualOutboundQuantity = CalculateActualOutboundQuantity(stockInfo.Details, outboundOrderDetails, lockInfo);// 闇�鍑哄簱閲�
+
+                if (actualOutboundQuantity <= 0)
+                {
+                    decimal totalAllocatedQuantity = lockInfo.AllocatedQuantity;
+                    decimal availableOutboundQuantity = lockInfo.AssignQuantity - totalAllocatedQuantity;
+                    decimal detailRemainingQuantity = outboundOrderDetails.Sum(x => x.OrderQuantity - x.OverOutQuantity - x.MoveQty);
+
+                    response.Success = false;
+                    response.Message = $"鏃犳硶鍑哄簱锛屾墭鐩樺彿锛歿request.PalletCode}锛屽簱瀛橀噺锛歿totalStockQuantity}锛屽凡鍑哄簱锛歿totalAllocatedQuantity}锛屽垎閰嶉噺锛歿lockInfo.AssignQuantity}锛屾槑缁嗗墿浣欙細{detailRemainingQuantity}";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                if (lockInfo.AssignQuantity != totalStockQuantity)
+                {
+                    response.Success = false;
+                    response.Message = $"鏃犳硶鍑哄簱锛屾墭鐩樺彿锛歿request.PalletCode}锛屽簱瀛橀噺锛歿totalStockQuantity}锛屽垎閰嶉噺锛歿lockInfo.AssignQuantity}";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                // 6. 寮�鍚簨鍔�
+                _unitOfWorkManage.BeginTran();
+                try
+                {
+                    // 鏁寸鍑哄簱鏃犻渶鎷嗗寘
+                    PerformFullOutboundOperation(stockInfo, request, lockInfo.TaskNum.GetValueOrDefault());
+
+
+                    decimal allocatedQuantity = actualOutboundQuantity;
+                    List<Dt_OutboundOrderDetail> updateDetails = new();
+                    foreach (var item in outboundOrderDetails)
+                    {
+                        if (allocatedQuantity <= 0) break;
+
+
+                        //if (item.OrderQuantity - item.MoveQty - item.OverOutQuantity >= allocatedQuantity)
+                        //{
+                        //    item.OverOutQuantity += allocatedQuantity;
+                        //    allocatedQuantity = 0;
+                        //}
+                        //else
+                        //{
+                        //    allocatedQuantity -= (item.OrderQuantity - item.MoveQty - item.OverOutQuantity);
+                        //    item.OverOutQuantity = item.OrderQuantity - item.MoveQty;
+                        //}
+                        List<Barcodes> barcodesList = new List<Barcodes>();
+                        List<Dt_StockInfoDetail> stockInfoDetails = stockInfo.Details.Where((x => x.StockQuantity > x.OutboundQuantity)).ToList();
+                        foreach (var stockDetail in stockInfoDetails)
+                        {
+                            if (item.LockQuantity - item.OverOutQuantity >= stockDetail.StockQuantity - stockInfoDetail.OutboundQuantity)
+                            {
+                                Barcodes barcodes = new Barcodes
+                                {
+                                    Barcode = stockDetail.Barcode,
+                                    Qty = stockDetail.StockQuantity - stockInfoDetail.OutboundQuantity,
+                                    SupplyCode = stockDetail?.SupplyCode ?? "",
+                                    BatchNo = stockDetail?.BatchNo ?? "",
+                                    Unit = stockDetail?.Unit ?? ""
+                                };
+
+                                stockDetail.StockQuantity = stockInfoDetail.OutboundQuantity;
+                                barcodesList.Add(barcodes);
+                            }
+                            else
+                            {
+                                Barcodes barcodes = new Barcodes
+                                {
+                                    Barcode = stockDetail.Barcode,
+                                    Qty = item.LockQuantity - item.OverOutQuantity,
+                                    SupplyCode = stockDetail?.SupplyCode ?? "",
+                                    BatchNo = stockDetail?.BatchNo ?? "",
+                                    Unit = stockDetail?.Unit ?? ""
+                                };
+                                stockInfoDetail.OutboundQuantity += item.LockQuantity - item.OverOutQuantity;
+                                barcodesList.Add(barcodes);
+                            }
+                        }
+
+                        decimal barcodeQuantity = allocatedQuantity;
+
+                        if (item.LockQuantity - item.OverOutQuantity >= allocatedQuantity)
+                        {
+                            item.OverOutQuantity += allocatedQuantity;
+                            item.CurrentDeliveryQty += allocatedQuantity;
+                            allocatedQuantity = 0;
+                        }
+                        else
+                        {
+                            barcodeQuantity = item.LockQuantity - item.OverOutQuantity;
+                            allocatedQuantity -= (item.LockQuantity - item.OverOutQuantity);
+                            item.OverOutQuantity = item.LockQuantity;
+                            item.CurrentDeliveryQty = item.LockQuantity;
+                        }
+
+                        updateDetails.Add(item);
+
+
+                        if (!string.IsNullOrEmpty(item.ReturnJsonData))
+                        {
+                            barcodesList.AddRange(JsonConvert.DeserializeObject<List<Barcodes>>(item.ReturnJsonData) ?? new List<Barcodes>());
+                        }
+
+                        JsonSerializerSettings settings = new JsonSerializerSettings
+                        {
+                            ContractResolver = new CamelCasePropertyNamesContractResolver()
+                        };
+                        item.ReturnJsonData = JsonConvert.SerializeObject(barcodesList, settings);
+                    }
+
+                    lockInfo.SortedQuantity = lockInfo.SortedQuantity + actualOutboundQuantity;
+
+                    if (lockInfo.SortedQuantity == lockInfo.AssignQuantity)
+                    {
+                        _outboundLockInfoRepository.DeleteAndMoveIntoHty(lockInfo, WIDESEA_Core.Enums.OperateTypeEnum.鑷姩瀹屾垚);
+                    }
+                    else
+                    {
+                        // 鏇存柊閿佸畾璁板綍
+                        _outboundLockInfoRepository.UpdateData(lockInfo);
+                    }
+
+                    // 鏇存柊鍑哄簱鍗曟槑缁嗙殑宸插嚭搴撴暟閲�
+                    _detailRepository.UpdateData(updateDetails);
+
+                    // 鏇存柊閿佸畾璁板綍鐨勭疮璁″凡鍑哄簱鏁伴噺锛堥渶瑕佹洿鏂拌鎵樼洏璇ョ墿鏂欑殑鎵�鏈夌浉鍏宠褰曪級
+                    //UpdateLockInfoAllocatedQuantity(stockInfo.Id, stockDetail.MaterielCode, stockDetail.BatchNo, actualOutboundQuantity);
+
+                    // 鎻愪氦浜嬪姟
+                    _unitOfWorkManage.CommitTran();
+
+                    response.Success = true;
+                    response.Message = "鍑哄簱瀹屾垚";
+                    response.UpdatedDetails = updateDetails;
+
+                    // 妫�鏌ュ嚭搴撳崟鏄惁瀹屾垚
+                    if (CheckOutboundOrderCompleted(request.OrderNo))
+                    {
+                        UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt());
+
+
+                        //todo: 鍥炰紶MES
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _unitOfWorkManage.RollbackTran();
+                    response.Success = false;
+                    response.Message = $"鍑哄簱澶勭悊澶辫触锛歿ex.Message}";
+                    return WebResponseContent.Instance.Error(ex.Message);
+                }
+
+                content = WebResponseContent.Instance.OK(data: response);
+            }
+            catch (Exception ex)
+            {
+                content = WebResponseContent.Instance.Error("澶勭悊鍑哄簱瀹屾垚澶辫触锛�" + ex.Message);
+            }
+            return content;
+        }
+
+        /// <summary>
+        /// 璁$畻瀹為檯鍑哄簱鏁伴噺
+        /// </summary>
+        private decimal CalculateActualOutboundQuantity(List<Dt_StockInfoDetail> stockDetails, List<Dt_OutboundOrderDetail> outboundDetails, Dt_OutStockLockInfo lockInfo)
+        {
+            decimal availableOutboundQuantity = lockInfo.AssignQuantity;
+            decimal detailRemainingQuantity = outboundDetails.Sum(x => x.OrderQuantity - x.OverOutQuantity - x.MoveQty);//outboundDetail.OrderQuantity - outboundDetail.OverOutQuantity;
+
+            return Math.Min(
+                Math.Min(availableOutboundQuantity, detailRemainingQuantity),
+                stockDetails.Sum(x => x.StockQuantity));
+        }
+
+        /// <summary>
+        /// 鎵ц瀹屾暣鍑哄簱鎿嶄綔锛堜笉鎷嗗寘锛�
+        /// </summary>
+        private void PerformFullOutboundOperation(Dt_StockInfo stockInfo, OutboundCompletePalletRequestDTO request, int taskNum)
+        {
+            List<Dt_StockInfoDetail_Hty> historyRecords = new List<Dt_StockInfoDetail_Hty>();
+            List<Dt_StockQuantityChangeRecord> changeRecords = new List<Dt_StockQuantityChangeRecord>();
+            foreach (var item in stockInfo.Details)
+            {
+                // 淇濆瓨搴撳瓨鏄庣粏鍒板巻鍙茶褰�
+                Dt_StockInfoDetail_Hty historyRecord = new Dt_StockInfoDetail_Hty
+                {
+                    SourceId = item.Id,
+                    OperateType = "鍑哄簱瀹屾垚",
+                    InsertTime = DateTime.Now,
+                    StockId = item.StockId,
+                    MaterielCode = item.MaterielCode,
+                    MaterielName = item.MaterielName,
+                    OrderNo = item.OrderNo,
+                    BatchNo = item.BatchNo,
+                    ProductionDate = item.ProductionDate,
+                    EffectiveDate = item.EffectiveDate,
+                    SerialNumber = item.SerialNumber,
+                    StockQuantity = item.StockQuantity,
+                    OutboundQuantity = item.StockQuantity,
+                    Status = item.Status,
+                    Unit = item.Unit,
+                    InboundOrderRowNo = item.InboundOrderRowNo,
+                    SupplyCode = item.SupplyCode,
+                    FactoryArea = item.FactoryArea,
+                    WarehouseCode = item.WarehouseCode,
+                    Barcode = item.Barcode,
+                    Remark = $"鏁寸鍑哄簱瀹屾垚鍒犻櫎锛屾潯鐮侊細{request.PalletCode}锛屽師鏁伴噺锛歿item.StockQuantity}锛屽嚭搴撴暟閲忥細{item.StockQuantity}锛屾搷浣滆�咃細{request.Operator}"
+                };
+                historyRecords.Add(historyRecord);
+
+                // 璁板綍搴撳瓨鍙樺姩
+                Dt_StockQuantityChangeRecord changeRecord = new Dt_StockQuantityChangeRecord
+                {
+                    StockDetailId = item.Id,
+                    PalleCode = stockInfo.PalletCode,
+                    MaterielCode = item.MaterielCode,
+                    MaterielName = item.MaterielName,
+                    BatchNo = item.BatchNo,
+                    OriginalSerilNumber = item.Barcode,
+                    NewSerilNumber = "",
+                    OrderNo = request.OrderNo,
+                    TaskNum = taskNum,
+                    ChangeType = (int)StockChangeTypeEnum.Outbound,
+                    ChangeQuantity = -item.StockQuantity,
+                    BeforeQuantity = item.StockQuantity,
+                    AfterQuantity = 0,
+                    SupplyCode = item.SupplyCode,
+                    WarehouseCode = item.WarehouseCode,
+                    Remark = $"鏁寸鍑哄簱瀹屾垚鍒犻櫎搴撳瓨鏄庣粏锛屾潯鐮侊細{request.PalletCode}锛屽嚭搴撴暟閲忥細{item.StockQuantity}锛屾搷浣滆�咃細{request.Operator}"
+                };
+                changeRecords.Add(changeRecord);
+            }
+            _stockDetailHistoryRepository.AddData(historyRecords);
+
+            // 鍒犻櫎搴撳瓨鏄庣粏璁板綍
+            _stockDetailRepository.DeleteData(stockInfo.Details);
+            _stockChangeRepository.AddData(changeRecords);
+        }
+
         #region 鎷i��
         /// <summary>
         /// 鍑哄簱瀹屾垚澶勭悊锛堟壂鎻忔潯鐮佹墸鍑忓簱瀛橈級
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutboundController.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutboundController.cs"
index 8535a25..152fb90 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutboundController.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutboundController.cs"
@@ -63,6 +63,27 @@
             }
         }
 
+        [HttpPost, Route("CompleteOutboundWithPallet"), AllowAnonymous]
+        public WebResponseContent CompleteOutboundWithPallet([FromBody] OutboundCompletePalletRequestDTO request)
+        {
+            try
+            {
+                lock (lockObj)
+                {
+                    if (!ModelState.IsValid)
+                        return WebResponseContent.Instance.Error(string.Join("; ", ModelState.Values
+                            .SelectMany(v => v.Errors)
+                            .Select(e => e.ErrorMessage)));
+
+                    return _outboundService.CompleteOutboundWithPallet(request);
+                }
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error($"鏁寸鍑哄簱鎿嶄綔澶辫触: {ex.Message}");
+            }
+        }
+
         [HttpPost, Route("QueryPickingTasks"), AllowAnonymous]
         public WebResponseContent QueryPickingTasks(string palletCode, string orderNo)
         {

--
Gitblit v1.9.3