ÏîÄ¿´úÂë/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/'; ÏîÄ¿´úÂë/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) => { ÏîÄ¿´úÂë/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> æ¯ææ«æçç æ´ç®±åºåºï¼æ«ææçç åå¯ç´æ¥è¿è¡æ´ç®±ç©ææ£éï¼æ éåæ«æç©ææ ç¾ç ã </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> 已忣ï¼<b>{{ calculateTotalSortedQuantity() }}</b> </el-tag> </div> <div class="stat-item"> <el-tag type="warning" size="medium" effect="dark"> <i class="el-icon-time"></i> æªåæ£ï¼<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) }, // 计ç®å·²åæ£æ»æ° calculateTotalSortedQuantity() { return this.unpickedData.reduce((sum, item) => { return sum + (item.sortedQuantity || 0) }, 0) }, // è®¡ç®æªåæ£æ»æ° 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> ÏîÄ¿´úÂë/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('æ£é确认失败') } 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> ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.dbBinary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.dbBinary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/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; } } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/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); ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/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())); } } ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/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 }); ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/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 æ£é /// <summary> /// åºåºå®æå¤çï¼æ«ææ¡ç æ£ååºåï¼ ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/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) {