From d1df8e56fd794ec9a71a2fbd6aadbab72d1e0815 Mon Sep 17 00:00:00 2001
From: 647556386 <647556386@qq.com>
Date: 星期五, 19 十二月 2025 14:51:46 +0800
Subject: [PATCH] 1

---
 项目代码/WIDESEA_WMSClient/src/views/outbound/outPicking.vue |  831 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 765 insertions(+), 66 deletions(-)

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 5bbee91..75de823 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,7 @@
 <template>
-    <div class="picking-container">
+    <div class="picking-container" v-loading="globalLoading" element-loading-text="澶勭悊涓�..."
+        element-loading-background="rgba(255, 255, 255, 0.8)" element-loading-spinner="el-icon-loading"
+        element-loading-custom-class="custom-loading">
         <!-- 椤堕儴璁㈠崟淇℃伅 -->
         <el-card class="order-info-card" shadow="never">
             <div class="order-header">
@@ -8,8 +10,11 @@
                     <span class="order-label">璁㈠崟鍙凤細</span>
                     <span class="order-value">{{ orderNo }}</span>
                 </div>
-                <div class="order-status" v-if="orderInfo">
-                    <el-tag :type="getStatusType(orderInfo.status)" size="medium">
+                <div class="order-status">
+                    <!-- 娴嬭瘯鎸夐挳 -->
+
+                    <el-tag v-if="orderInfo" :type="getStatusType(orderInfo.orderStatus)" size="medium"
+                        style="margin-left: 10px;">
                         {{ orderInfo.statusName || '杩涜涓�' }}
                     </el-tag>
                 </div>
@@ -21,7 +26,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 +82,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="hasWholeOut() ? 'success' : 'warning'" size="medium" effect="dark">
+                                <i class="el-icon-box"></i>
+                                鏄惁鏁村嚭锛歿{ hasWholeOut() ? '鏄�' : '鍚�' }}
+                            </el-tag>
+                        </div>
+                    </div>
+                </div>
             </div>
         </el-card>
 
@@ -198,7 +244,56 @@
                     </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>
 
         <!-- 纭瀵硅瘽妗� -->
         <el-dialog v-model="confirmDialogVisible" title="鎿嶄綔纭" width="400px" :before-close="handleDialogClose">
@@ -214,11 +309,95 @@
                 </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>
 
 <script>
+
+import printView from "@/extension/outbound/extend/printView.vue"
+import { stationManager, STATION_STORAGE_KEY } from "@/../src/uitils/stationManager";
+import { ElLoading } from 'element-plus'
+
 export default {
+    components: { printView },
     name: 'OutPicking',
     data() {
         return {
@@ -248,7 +427,12 @@
             confirmDialogVisible: false,
             confirmMessage: '',
             currentAction: null,
-            executeLoading: false
+            executeLoading: false,
+            matMixed: true,
+            wholeOutDialogVisible: false,
+            wholeOutInfo: null,
+            globalLoading: false,
+            loadingInstance: null
         }
     },
     computed: {
@@ -268,6 +452,10 @@
                 this.$router.back()
                 return
             }
+
+            // 鍔犺浇璁㈠崟淇℃伅
+            this.loadOrderInfo()
+
             // 鑷姩鑱氱劍鍒版墭鐩樼爜杈撳叆妗�
             this.$nextTick(() => {
                 if (this.$refs.palletInput) {
@@ -275,30 +463,55 @@
                 }
             })
         },
+        async loadOrderInfo() {
+            try {
+                this.showFullScreenLoading()
+                const response = await this.http.get(`/api/Outbound/GetOrderInfo?orderNo=${this.orderNo}`)
+                if (response.status) {
+                    this.orderInfo = response.data
+                } else {
+                }
+            }
+            catch (error) {
 
-        loadPalletData() {
+            } finally {
+                this.hideFullScreenLoading()
+            }
+        },
+
+        async loadPalletData() {
             if (!this.scanForm.palletCode) {
                 this.unpickedData = []
                 return
             }
 
             try {
-                this.loadUnpickedData();
-                this.loadPickedData();
+                this.showFullScreenLoading()
+                await Promise.all([
+                    this.loadUnpickedData(),
+                    this.loadPickedData()
+                ]);
 
             } catch (error) {
-                console.error('鍔犺浇鎵樼洏鏁版嵁澶辫触:', error)
                 this.unpickedData = []
+            } finally {
+                this.hideFullScreenLoading()
             }
         },
         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.length > 0) {
-                            this.unpickedData = response.data
+                        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) {
@@ -306,42 +519,43 @@
                                 }
                             })
                         } else {
-                            this.$message.warning('璇ユ墭鐩樻棤鏈嫞閫変换鍔�')
+                            if (flag) {
+                                this.$message.warning('璇ユ墭鐩樻棤鏈嫞閫変换鍔�')
+                            }
                             this.unpickedData = []
                         }
+                        resolve()
                     } else {
                         this.$message.error(response.message || '鑾峰彇鎵樼洏鏁版嵁澶辫触')
                         this.unpickedData = []
+                        reject(response.message || '鑾峰彇鎵樼洏鏁版嵁澶辫触')
                     }
-                }
-                )
-
-            } catch (error) {
-                console.error('鍔犺浇鏈嫞閫夋暟鎹け璐�:', error)
-            }
+                }).catch(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) {
                             this.pickedData = response.data
                             this.calculatePickedStats()
                         } else {
-                            this.$message.warning('璇ユ墭鐩樻棤鏈嫞閫変换鍔�')
-                            this.unpickedData = []
+                            this.pickedData = []
                         }
+                        resolve()
                     } else {
                         this.$message.error(response.message || '鑾峰彇鎵樼洏鏁版嵁澶辫触')
-                        this.unpickedData = []
+                        this.pickedData = []
+                        reject(response.message || '鑾峰彇鎵樼洏鏁版嵁澶辫触')
                     }
-                }
-                )
-
-            } catch (error) {
-                console.error('鍔犺浇宸叉嫞閫夋暟鎹け璐�:', error)
-            }
+                }).catch(error => {
+                    reject(error)
+                })
+            })
         },
 
         // 璁$畻鏈嫞閫�
@@ -375,12 +589,11 @@
             this.pickedTotal = this.pickedCount
         },
 
-        handlePalletScan() {
+        handlePalletScan(flag = true) {
             if (this.scanForm.palletCode) {
                 // this.$message.success(`鎵樼洏鐮�: ${this.scanForm.palletCode}`)
-                this.loadPalletData()
-
-
+                this.loadPalletData(flag)
+            } else {
             }
         },
 
@@ -400,36 +613,39 @@
             this.handleConfirmPick()
         },
 
-        handleConfirmPick() {
+        async handleConfirmPick() {
             if (!this.scanForm.palletCode || !this.scanForm.materialBarcode) {
                 this.$message.warning('璇峰厛鎵弿鎵樼洏鐮佸拰鐗╂枡鏉$爜')
                 return
             }
 
             this.confirmLoading = true
+            this.showFullScreenLoading()
 
             try {
-                this.http.post('/api/Outbound/CompleteOutboundWithBarcode', {
+                const response = await this.http.post('/api/Outbound/CompleteOutboundWithBarcode', {
                     orderNo: this.orderNo,
                     palletCode: this.scanForm.palletCode,
                     barcode: this.scanForm.materialBarcode,
                     operator: this.getUserName()
-                }).then(response => {
-                    if (response.status) {
-                        this.$message.success('鎷i�夌‘璁ゆ垚鍔�')
-                        this.resetMaterialBarcode()
-                        // this.loadUnpickedData()
-                        // this.loadPickedData()
-                        this.loadPalletData()
-                    } else {
-                        this.$message.error(response.message || '鎷i�夌‘璁ゅけ璐�')
-                    }
                 })
+                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('鎷i�夌‘璁ゆ垚鍔�')
+                    this.resetMaterialBarcode()
+                    // this.loadUnpickedData()
+                    // this.loadPickedData()
+                    await this.loadPalletData(false)
+                } else {
+                    this.$message.error(response.message || '鎷i�夌‘璁ゅけ璐�')
+                }
             } catch (error) {
-                console.error('鎷i�夌‘璁ゅけ璐�:', error)
                 this.$message.error('鎷i�夌‘璁ゅけ璐�')
             } finally {
                 this.confirmLoading = false
+                this.hideFullScreenLoading()
             }
         },
 
@@ -455,45 +671,104 @@
             this.confirmDialogVisible = true
         },
 
-        executeConfirm() {
+        async executeConfirm() {
             this.executeLoading = true
+            this.showFullScreenLoading()
 
             try {
                 let apiUrl = ''
                 let params = {
                     orderNo: this.orderNo,
-                    palletCode: this.scanForm.palletCode
+                    palletCode: this.scanForm.palletCode,
+                    station: stationManager.getStation()
                 }
-
                 if (this.currentAction === 'emptyBox') {
                     apiUrl = '/api/Outbound/EmptyBox'
                 } else if (this.currentAction === 'returnToWarehouse') {
                     apiUrl = '/api/Outbound/ReturnToWarehouse'
                 }
 
-                this.http.post(apiUrl, params).then(response => {
+                const response = await this.http.post(apiUrl, params)
 
-                    if (response.status) {
-                        this.$message.success('鎿嶄綔鎴愬姛')
-                        this.confirmDialogVisible = false
-                        this.resetForm()
-                        // this.loadUnpickedData()
-                        // this.loadPickedData()
-                    } else {
-                        this.$message.error(response.message || '鎿嶄綔澶辫触')
-                    }
-                })
+                if (response.status) {
+                    this.$message.success('鎿嶄綔鎴愬姛')
+                    this.confirmDialogVisible = false
+                    this.resetForm()
+                    // this.loadUnpickedData()
+                    // this.loadPickedData()
+                } else {
+                    this.$message.error(response.message || '鎿嶄綔澶辫触')
+                }
             } catch (error) {
-                console.error('鎿嶄綔澶辫触:', error)
                 this.$message.error('鎿嶄綔澶辫触')
             } finally {
                 this.executeLoading = false
+                this.hideFullScreenLoading()
             }
         },
 
         handleDialogClose() {
             if (!this.executeLoading) {
                 this.confirmDialogVisible = false
+            }
+        },
+
+        // 鏁村嚭纭鐩稿叧鏂规硶
+        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;
+            }
+        },
+
+        async executeWholeOut() {
+            if (!this.wholeOutInfo) {
+                this.$message.error('鏁村嚭淇℃伅鏃犳晥');
+                return;
+            }
+
+            this.executeLoading = true;
+            this.showFullScreenLoading();
+
+            try {
+                // 璋冪敤鏁村嚭鎺ュ彛锛岃繖閲屼娇鐢ㄧ墿鏂欑紪鐮佷綔涓烘潯鐮�
+                const response = await this.http.post('/api/Outbound/CompleteOutboundWithPallet', {
+                    orderNo: this.orderNo,
+                    palletCode: this.scanForm.palletCode,
+                    operator: this.getUserName()
+                });
+                if (response.status) {
+                    this.$message.success('鏁村嚭鎿嶄綔鎴愬姛');
+                    this.wholeOutDialogVisible = false;
+                    this.wholeOutInfo = null;
+                    await this.loadPalletData();
+                } else {
+                    this.$message.error(response.message || '鏁村嚭鎿嶄綔澶辫触');
+                }
+            } catch (error) {
+                this.$message.error('鏁村嚭鎿嶄綔澶辫触');
+            } finally {
+                this.executeLoading = false;
+                this.hideFullScreenLoading();
             }
         },
 
@@ -521,7 +796,6 @@
                 })
             } catch (error) {
                 if (error !== 'cancel') {
-                    console.error('鎾ら攢澶辫触:', error)
                     this.$message.error('鎾ら攢澶辫触')
                 }
             }
@@ -539,7 +813,9 @@
         },
 
         refreshPickedTable() {
-            this.loadPickedData()
+            this.loadPickedData().catch(error => {
+                console.error('鍒锋柊宸叉嫞閫夊垪琛ㄥけ璐�:', error)
+            })
         },
 
         resetMaterialBarcode() {
@@ -576,31 +852,137 @@
                     return user.userName || user.username || '鏈櫥褰曠敤鎴�'
                 }
             } catch (error) {
-                console.error('鑾峰彇鐢ㄦ埛淇℃伅澶辫触:', error)
             }
 
             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) {
             const statusMap = {
                 0: 'info',    // 寰呭鐞�
-                10: 'warning', // 杩涜涓�
+                1: 'warning', // 杩涜涓�
                 20: 'primary', // 鎷i�変腑
                 30: 'success', // 宸插畬鎴�
                 40: 'danger'   // 寮傚父
             }
             return statusMap[status] || 'info'
+        },
+
+        // 鏄剧ず鍏ㄥ睆閬僵灞�
+        showFullScreenLoading() {
+            if (this.loadingInstance) {
+                this.loadingInstance.close()
+            }
+            this.loadingInstance = ElLoading.service({
+                lock: true,
+                text: '澶勭悊涓�...',
+                background: 'rgba(0, 0, 0, 0.7)',
+                customClass: 'custom-full-loading'
+            })
+        },
+
+        // 闅愯棌鍏ㄥ睆閬僵灞�
+        hideFullScreenLoading() {
+            if (this.loadingInstance) {
+                this.loadingInstance.close()
+                this.loadingInstance = null
+            } else {
+            }
+        },
+
+        // 娴嬭瘯閬僵灞傛樉绀�
+        testLoading() {
+            // 娴嬭瘯涓ょ鏂瑰紡
+            this.globalLoading = true
+            // 鍚屾椂涔熸祴璇曞叏灞弆oading
+            this.showFullScreenLoading()
+            setTimeout(() => {
+                this.globalLoading = false
+                this.hideFullScreenLoading()
+            }, 3000)
         }
     }
 }
 </script>
+
+<style>
+.el-dialog__header {
+    margin: 0;
+}
+</style>
 
 <style scoped>
 .picking-container {
     padding: 20px;
     background-color: #f5f5f5;
     min-height: 100vh;
+    position: relative;
+    overflow: hidden;
 }
 
 /* 璁㈠崟淇℃伅鍗$墖 */
@@ -795,4 +1177,321 @@
 ::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;
+    }
+}
+
+/* Element Plus Loading 閬僵灞傛牱寮忎慨澶� */
+::v-deep .custom-loading {
+    background-color: rgba(0, 0, 0, 0.7) !important;
+    z-index: 9999 !important;
+}
+
+::v-deep .custom-loading .el-loading-mask {
+    background-color: rgba(0, 0, 0, 0.7) !important;
+}
+
+::v-deep .custom-loading .el-loading-spinner {
+    z-index: 10000 !important;
+}
+
+::v-deep .custom-loading .el-loading-text {
+    color: #ffffff !important;
+    font-weight: bold !important;
+    font-size: 16px !important;
+}
+
+/* 鍏ㄥ眬 Loading 鏍峰紡 */
+::v-deep .el-loading-mask {
+    background-color: rgba(0, 0, 0, 0.7) !important;
+    z-index: 9999 !important;
+}
+
+::v-deep .el-loading-spinner {
+    z-index: 10000 !important;
+}
+
+::v-deep .el-loading-text {
+    color: #ffffff !important;
+    font-weight: bold !important;
+}
+
+/* 鍏ㄥ睆Loading鑷畾涔夋牱寮� */
+::v-deep .custom-full-loading {
+    z-index: 999999 !important;
+}
+
+::v-deep .custom-full-loading .el-loading-mask {
+    z-index: 999999 !important;
+}
+
+::v-deep .custom-full-loading .el-loading-spinner {
+    z-index: 1000000 !important;
+}
+
+::v-deep .custom-full-loading .el-loading-text {
+    color: #ffffff !important;
+    font-weight: bold !important;
+    font-size: 18px !important;
+}
+
+/* 纭繚瀵硅瘽妗嗕笉浼氶伄鐩杔oading */
+::v-deep .el-dialog {
+    z-index: 2000 !important;
+}
+
+::v-deep .el-dialog__wrapper {
+    z-index: 2000 !important;
+}
+
+/* 纭繚瀹瑰櫒鐩稿瀹氫綅 */
+.picking-container {
+    position: relative !important;
+    min-height: 100vh;
+}
 </style>
\ No newline at end of file

--
Gitblit v1.9.3