From ca3e4977395bc02c5d147dffdff7381333fdfbca Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期四, 09 四月 2026 14:39:37 +0800
Subject: [PATCH] 空箱跨区域移库
---
项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue | 185 ++++++++++++++++++++++++++++++++++++++--------
1 files changed, 152 insertions(+), 33 deletions(-)
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue"
index d19a48e..9d2333c 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/NoStockOut.vue"
@@ -8,6 +8,14 @@
title="铏氭嫙鍑哄叆搴�"
class="custom-vol-box"
>
+ <!-- 鎻愪氦閬僵灞傦細瑕嗙洊鏁翠釜寮圭獥鍐呭鍖哄煙 -->
+ <div class="submit-mask" v-show="submitLoading">
+ <div class="mask-content">
+ <el-loading-spinner class="loading-icon" />
+ <span class="loading-text">姝e湪鎻愪氦鍑哄簱锛岃绋嶅��...</span>
+ </div>
+ </div>
+
<div>
<!-- 鍗曟嵁杈撳叆鍖哄煙锛堟敮鎸佹壂鐮侊級 -->
<el-form
@@ -25,8 +33,11 @@
@input="handleOutboundInput"
@keyup.enter="validateOutboundOrder"
ref="outboundInputRef"
- :disabled="loading"
+ :disabled="loading || submitLoading || isOutboundVerified"
></el-input>
+ <!-- 鏂板锛氶獙璇佺姸鎬佹彁绀� -->
+ <span v-if="isOutboundVerified" class="verified-tag">鉁� 宸查獙璇�</span>
+ <span v-else-if="loading" class="loading-tag">鉁� 楠岃瘉涓�...</span>
</el-form-item>
<el-form-item label="閲囪喘鍗曟嵁:" name="purchaseOrderNo">
<el-input
@@ -37,6 +48,7 @@
@input="handlePurchaseInput"
readonly
ref="purchaseInputRef"
+ :disabled="submitLoading"
></el-input>
</el-form-item>
</el-form>
@@ -53,7 +65,6 @@
label="鎵弿鏉$爜:"
style="width: 80%"
name="barcode"
- :rules="[{ required: true, message: '璇锋壂鎻忔垨杈撳叆鏉$爜', trigger: 'blur' }]"
>
<el-input
ref="barcodeInputRef"
@@ -62,7 +73,7 @@
@keydown.enter="debouncedHandleScan"
autofocus
class="custom-input"
- :disabled="!orderForm.outboundOrderNo || loading"
+ :disabled="!isOutboundVerified || loading || submitLoading"
></el-input>
</el-form-item>
<el-form-item>
@@ -71,7 +82,7 @@
size="small"
@click="handleScan"
class="custom-button"
- :disabled="!orderForm.outboundOrderNo || loading"
+ :disabled="!isOutboundVerified || loading || submitLoading"
>
<Search /> 纭鎵弿
</el-button>
@@ -123,12 +134,13 @@
@click="removeItem(index, item.barcode)"
icon="Delete"
circle
- :disabled="loading"
+ :disabled="loading || submitLoading"
></el-button>
</div>
</transition-group>
<div class="empty-tip" v-if="scannedBarcodes.length === 0">
- <span>鏆傛棤鎵弿璁板綍锛岃鍏堣緭鍏ュ嚭搴撳崟鎹悗鎵弿鏉$爜</span>
+ <span v-if="isOutboundVerified">鏆傛棤鎵弿璁板綍锛岃鎵弿鏉$爜</span>
+ <span v-else>璇峰厛杈撳叆骞堕獙璇佹湁鏁堢殑鍑哄簱鍗曟嵁鍙�</span>
</div>
</el-scrollbar>
</div>
@@ -142,7 +154,7 @@
type="primary"
size="small"
@click="submit"
- :disabled="scannedBarcodes.length === 0 || !orderForm.outboundOrderNo || loading"
+ :disabled="scannedBarcodes.length === 0 || !isOutboundVerified || loading || submitLoading"
class="submit-btn"
>
<Check /> 鎻愪氦鍑哄簱
@@ -156,7 +168,7 @@
showDetailBox = false;
}"
class="cancel-btn"
- :disabled="loading"
+ :disabled="loading || submitLoading"
>
鍙栨秷
</el-button>
@@ -185,12 +197,31 @@
});
const scannedBarcodes = ref([]);
const loading = ref(false);
+// 鏂板锛氭彁浜や笓灞瀕oading鐘舵�侊紝鎺у埗閬僵灞傛樉绀�
+const submitLoading = ref(false);
+// 鏍稿績鏂板锛氬嚭搴撳崟楠岃瘉鐘舵�佹爣璇�
+const isOutboundVerified = ref(false);
// 妯℃澘寮曠敤
const formRef = ref(null);
const barcodeInputRef = ref(null);
const outboundInputRef = ref(null);
const purchaseInputRef = ref(null);
+
+const successAudioSrc = require('@/assets/audio/success.mp3');
+const errorAudioSrc = require('@/assets/audio/error.mp3');
+
+// ========== 浠呮柊澧烇細闊抽鎾斁鍑芥暟锛堟棤鍏朵粬浠g爜鏀瑰姩锛� ==========
+const playAudio = (audioSrc, volume = 0.8) => {
+ try {
+ const audio = new Audio(audioSrc);
+ audio.volume = volume;
+ audio.play().catch(() => {});
+ } catch (e) {}
+};
+const playSuccess = () => playAudio(successAudioSrc);
+const playError = () => playAudio(errorAudioSrc);
+// ========== 闊抽鍑芥暟缁撴潫 ==========
// 缁勪欢鎸傝浇鏃惰仛鐒﹀埌鍑哄簱鍗曡緭鍏ユ
onMounted(() => {
@@ -217,6 +248,8 @@
formData.barcode = "";
orderForm.outboundOrderNo = "";
orderForm.purchaseOrderNo = "";
+ submitLoading.value = false; // 鎵撳紑寮圭獥鏃堕噸缃彁浜oading
+ isOutboundVerified.value = false; // 鎵撳紑寮圭獥鏃堕噸缃嚭搴撳崟楠岃瘉鐘舵��
nextTick(() => {
outboundInputRef.value?.focus(); // 鎵撳紑寮圭獥浠嶈仛鐒﹀嚭搴撳崟杈撳叆妗�
});
@@ -224,11 +257,12 @@
/**
* 楠岃瘉鍑哄簱鍗曟嵁鍙风殑鏈夋晥鎬�
- * 鏍稿績淇敼锛氶獙璇佹垚鍔熷悗鐩存帴鑱氱劍鏉$爜鎵弿妗嗭紝澶辫触鍒欒仛鐒﹀洖鍑哄簱鍗曡緭鍏ユ
+ * 鏍稿績淇敼锛氶獙璇佹垚鍔熷悗鏍囪isOutboundVerified涓簍rue锛屽け璐ュ垯閲嶇疆涓篺alse
*/
const validateOutboundOrder = async () => {
const outboundOrderNo = orderForm.outboundOrderNo.trim();
if (!outboundOrderNo) {
+ ElMessage.warning("璇疯緭鍏ュ嚭搴撳崟鎹彿");
return;
}
@@ -240,8 +274,9 @@
);
if (res.status !== true) {
- // 楠岃瘉澶辫触锛氭竻绌鸿緭鍏ユ锛屾彁绀洪敊璇紝鑱氱劍鍥炲嚭搴撳崟杈撳叆妗�
+ // 楠岃瘉澶辫触锛氭竻绌鸿緭鍏ユ锛屾彁绀洪敊璇紝閲嶇疆楠岃瘉鐘舵�侊紝鑱氱劍鍥炲嚭搴撳崟杈撳叆妗�
orderForm.outboundOrderNo = "";
+ isOutboundVerified.value = false;
ElMessage.error(res.message || "鍑哄簱鍗曟嵁鍙烽獙璇佸け璐ワ紝璇锋鏌ュ崟鎹彿鏄惁姝g‘");
nextTick(() => {
outboundInputRef.value?.focus(); // 澶辫触鑱氱劍鍑哄簱鍗曡緭鍏ユ
@@ -249,14 +284,16 @@
return;
}
- // 楠岃瘉鎴愬姛锛氭彁绀虹敤鎴凤紝鐩存帴鑱氱劍鏉$爜鎵弿妗嗭紙鏍稿績淇敼锛�
+ // 楠岃瘉鎴愬姛锛氭爣璁伴獙璇佺姸鎬佷负true锛屾彁绀虹敤鎴凤紝鑱氱劍鏉$爜鎵弿妗�
+ isOutboundVerified.value = true;
ElMessage.success("鍑哄簱鍗曟嵁鍙烽獙璇侀�氳繃");
nextTick(() => {
barcodeInputRef.value?.focus(); // 鎴愬姛鐩存帴璺宠浆鍒版潯鐮佹壂鎻忔
});
} catch (error) {
- // 鎺ュ彛寮傚父锛氭竻绌鸿緭鍏ユ锛屾彁绀洪敊璇紝鑱氱劍鍥炲嚭搴撳崟杈撳叆妗�
+ // 鎺ュ彛寮傚父锛氭竻绌鸿緭鍏ユ锛屾彁绀洪敊璇紝閲嶇疆楠岃瘉鐘舵�侊紝鑱氱劍鍥炲嚭搴撳崟杈撳叆妗�
orderForm.outboundOrderNo = "";
+ isOutboundVerified.value = false;
ElMessage.error(`鍑哄簱鍗曟嵁鍙烽獙璇佸紓甯革細${error.message || "缃戠粶閿欒锛岃閲嶈瘯"}`);
nextTick(() => {
outboundInputRef.value?.focus(); // 寮傚父鑱氱劍鍑哄簱鍗曡緭鍏ユ
@@ -268,8 +305,9 @@
// 鍑哄簱鍗曡緭鍏ュ鐞�
const handleOutboundInput = (value) => {
+ // 鏍稿績淇敼锛氳緭鍏ユ椂鑷姩閲嶇疆楠岃瘉鐘舵�侊紙闃叉鎵嬪姩淇敼宸查獙璇佺殑鍑哄簱鍗曞彿锛�
if (value && value.trim()) {
- // 鍙繚鐣欏嚭搴撳崟鍙锋牸寮忛獙璇侀�昏緫
+ isOutboundVerified.value = false;
}
};
@@ -282,10 +320,13 @@
// 鑱氱劍鏉$爜杈撳叆妗嗭紙澶嶇敤鍑芥暟锛�
const focusBarcodeInputDirectly = () => {
- if (orderForm.outboundOrderNo.trim()) {
+ if (isOutboundVerified.value) {
barcodeInputRef.value?.focus();
} else {
- ElMessage.warning("璇峰厛杈撳叆鏈夋晥鐨勫嚭搴撳崟鎹彿");
+ ElMessage.warning("璇峰厛杈撳叆骞堕獙璇佹湁鏁堢殑鍑哄簱鍗曟嵁鍙�");
+ nextTick(() => {
+ outboundInputRef.value?.focus();
+ });
}
};
@@ -311,6 +352,16 @@
// 鎵弿鏉$爜鏍稿績閫昏緫
const handleScan = async () => {
+ // 鏍稿績鏂板锛氬墠缃牎楠岋紝纭繚鍑哄簱鍗曞凡楠岃瘉
+ if (!isOutboundVerified.value) {
+ ElMessage.warning("璇峰厛楠岃瘉鏈夋晥鐨勫嚭搴撳崟鎹彿鍚庡啀鎵弿鏉$爜");
+ playError(); // ========== 浠呮柊澧炶繖涓�琛� ==========
+ nextTick(() => {
+ outboundInputRef.value?.focus();
+ });
+ return;
+ }
+
if (!formRef.value) return;
await formRef.value.validateField('barcode');
@@ -321,6 +372,7 @@
const isDuplicate = scannedBarcodes.value.some(item => item.barcode === barcode);
if (isDuplicate) {
ElMessage.warning(`鏉$爜銆�${barcode}銆戝凡瀛樺湪锛屾棤闇�閲嶅鎵弿`);
+ playError(); // ========== 浠呮柊澧炶繖涓�琛� ==========
formData.barcode = "";
nextTick(() => barcodeInputRef.value?.focus()); // 鍘婚噸鍚庝粛鑱氱劍鏉$爜妗�
return;
@@ -330,13 +382,18 @@
loading.value = true;
// 姝ラ1锛氭煡璇㈤噰璐崟鍙�
- const purchaseOrderNo = await getPurchaseOrderByBarcode(barcode);
- if (purchaseOrderNo) {
- orderForm.purchaseOrderNo = purchaseOrderNo;
- } else {
- ElMessage.info("鏈煡璇㈠埌璇ユ潯鐮佸搴旂殑閲囪喘鍗曞彿锛岀户缁獙璇佹潯鐮佹湁鏁堟��");
- formData.barcode = ""; // 鏂板锛氶獙璇佸け璐ユ椂娓呯┖杈撳叆妗�
- nextTick(() => barcodeInputRef.value?.focus()); // 鏂板锛氳仛鐒︽潯鐮佽緭鍏ユ
+ let purchaseOrderNo = '';
+ try {
+ purchaseOrderNo = await getPurchaseOrderByBarcode(barcode);
+ if (purchaseOrderNo) {
+ orderForm.purchaseOrderNo = purchaseOrderNo;
+ } else {
+ ElMessage.info("鏈煡璇㈠埌璇ユ潯鐮佸搴旂殑閲囪喘鍗曞彿锛岀户缁獙璇佹潯鐮佹湁鏁堟��");
+ playError(); // ========== 浠呮柊澧炶繖涓�琛� ==========
+ }
+ } catch (error) {
+ ElMessage.info("鏈煡璇㈠埌璇ユ潯鐮佸搴旂殑閲囪喘鍗曞彿锛岀户缁獙璇佹潯鐮佹湁鏁堟�э細" + error.message);
+ playError(); // ========== 浠呮柊澧炶繖涓�琛� ==========
}
// 姝ラ2锛氶獙璇佹潯鐮佸苟鑾峰彇鐗╂枡淇℃伅
@@ -349,8 +406,9 @@
if (validateRes.status === true) {
if (!Array.isArray(validateRes.data) || validateRes.data.length === 0) {
ElMessage.warning("璇ユ潯鐮侀獙璇佹垚鍔燂紝浣嗘湭杩斿洖鐗╂枡淇℃伅");
- formData.barcode = ""; // 鏂板锛氭棤鐗╂枡淇℃伅鏃朵篃娓呯┖杈撳叆妗�
- nextTick(() => barcodeInputRef.value?.focus()); // 鏂板锛氳仛鐒︽潯鐮佹
+ playError(); // ========== 浠呮柊澧炶繖涓�琛� ==========
+ formData.barcode = "";
+ nextTick(() => barcodeInputRef.value?.focus());
} else {
const newItems = validateRes.data.map(item => ({
barcode: item.barcode || '',
@@ -363,17 +421,19 @@
}));
scannedBarcodes.value.push(...newItems);
ElMessage.success(`鎵弿鎴愬姛锛屾柊澧� ${newItems.length} 鏉$墿鏂欎俊鎭紝绱 ${scannedBarcodes.value.length} 鏉);
+ playSuccess(); // ========== 浠呮柊澧炶繖涓�琛� ==========
formData.barcode = "";
}
} else {
- ElMessage.error("鎵弿澶辫触锛�" + (validateRes.message || '鏉$爜楠岃瘉澶辫触'));
- formData.barcode = ""; // 鏂板锛氶獙璇佸け璐ユ椂娓呯┖杈撳叆妗�
- nextTick(() => barcodeInputRef.value?.focus()); // 鏂板锛氳仛鐒︽潯鐮佽緭鍏ユ
+
+ playError(); // ========== 浠呮柊澧炶繖涓�琛� ==========
+ formData.barcode = "";
+ nextTick(() => barcodeInputRef.value?.focus());
}
} catch (error) {
ElMessage.error(error.message);
- formData.barcode = ""; // 淇濈暀锛氭帴鍙e紓甯告椂娓呯┖
- // 鏂板锛氬紓甯告椂涔熷己鍒惰仛鐒︽潯鐮佹
+ playError(); // ========== 浠呮柊澧炶繖涓�琛� ==========
+ formData.barcode = "";
nextTick(() => barcodeInputRef.value?.focus());
} finally {
loading.value = false;
@@ -425,9 +485,18 @@
// 鎻愪氦鍑哄簱
const submit = async () => {
+ // 鏍稿績鏂板锛氬墠缃牎楠屽嚭搴撳崟楠岃瘉鐘舵��
+ if (!isOutboundVerified.value) {
+ ElMessage.warning("鍑哄簱鍗曟嵁鍙锋湭楠岃瘉锛屾棤娉曟彁浜�");
+ nextTick(() => {
+ outboundInputRef.value?.focus();
+ });
+ return;
+ }
+
if (scannedBarcodes.value.length === 0) {
ElMessage.warning("璇峰厛鎵弿鑷冲皯涓�鏉℃潯鐮�");
- nextTick(() => barcodeInputRef.value?.focus()); // 鎻愪氦澶辫触鑱氱劍鏉$爜妗�
+ nextTick(() => barcodeInputRef.value?.focus());
return;
}
@@ -435,7 +504,8 @@
const purchaseOrderNos = [...new Set(scannedBarcodes.value.map(item => item.purchaseOrderNo).filter(Boolean))];
try {
- loading.value = true;
+ // 寮�鍚彁浜oading锛屾樉绀洪伄缃╁眰
+ submitLoading.value = true;
const res = await http.post("/api/OutboundPicking/NoStockOutSubmit", {
OutOderSubmit: orderForm.outboundOrderNo,
InOderSubmit: purchaseOrderNos.join(',') || '',
@@ -447,14 +517,17 @@
showDetailBox.value = false;
scannedBarcodes.value = [];
orderForm.purchaseOrderNo = "";
+ isOutboundVerified.value = false; // 鎻愪氦鎴愬姛鍚庨噸缃獙璇佺姸鎬�
} else {
ElMessage.error("鍑哄簱鎻愪氦澶辫触锛�" + (res.message || '鎻愪氦澶辫触'));
- nextTick(() => barcodeInputRef.value?.focus()); // 鎻愪氦澶辫触鑱氱劍鏉$爜妗�
+ nextTick(() => barcodeInputRef.value?.focus());
}
} catch (error) {
ElMessage.error("鍑哄簱鎻愪氦寮傚父锛�" + error.message);
- nextTick(() => barcodeInputRef.value?.focus()); // 寮傚父鑱氱劍鏉$爜妗�
+ nextTick(() => barcodeInputRef.value?.focus());
} finally {
+ // 鍏抽棴鎻愪氦loading锛岄殣钘忛伄缃╁眰
+ submitLoading.value = false;
loading.value = false;
}
};
@@ -483,6 +556,52 @@
transition: transform 1s ease;
}
+/* 鏂板锛氭彁浜ら伄缃╁眰鏍峰紡 */
+.submit-mask {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(255, 255, 255, 0.85);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 100;
+ border-radius: inherit;
+}
+.mask-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 12px;
+ color: #409eff;
+ font-size: 15px;
+}
+.loading-icon {
+ font-size: 24px;
+ animation: el-loading-circle 1.5s linear infinite;
+}
+
+/* 鏂板锛氶獙璇佺姸鎬佹爣绛炬牱寮� */
+.verified-tag {
+ color: #67c23a;
+ font-size: 12px;
+ margin-left: 8px;
+ font-weight: 500;
+}
+.loading-tag {
+ color: #409eff;
+ font-size: 12px;
+ margin-left: 8px;
+ font-weight: 500;
+ animation: spin 1s linear infinite;
+}
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
.scan-list {
width: 100%;
}
--
Gitblit v1.9.3