diff --git a/src/views/modules/haianAutoWarehouse/haianPalletSpecialEdit.vue b/src/views/modules/haianAutoWarehouse/haianPalletSpecialEdit.vue index e3dfd60..4eefead 100644 --- a/src/views/modules/haianAutoWarehouse/haianPalletSpecialEdit.vue +++ b/src/views/modules/haianAutoWarehouse/haianPalletSpecialEdit.vue @@ -114,7 +114,7 @@ import { scanPalletForSpecialEdit, savePalletSpecialEdit, forceRemovePalletSpeci export default { name: 'haianPalletSpecialEdit', - data() { + data () { return { // 海安PDA的site只取登录用户工厂,扫描和保存都显式传给后端 - rqrq site: this.$store.state.user.site, @@ -127,6 +127,8 @@ export default { wcsOccupied: false, stationLoading: false, stationRequestSeq: 0, + // 扫码及重查请求版本:离开或重新扫码后,旧响应不得覆盖当前页面 - rqrq + scanRequestSeq: 0, areaOptions: [], stationOptions: [], form: { @@ -141,44 +143,56 @@ export default { }, computed: { // 扫描、保存和强制置空时锁整页;拉站点不锁整页,避免禁用其它字段 - rqrq - pageBusy() { + pageBusy () { return this.scanLoading || this.saveLoading || this.removeLoading }, // 立库区域所在位置用手输,其它区域用站点下拉。标记来自扫描结果里的stockArea - rqrq - isStockArea() { + isStockArea () { const area = (this.areaOptions || []).find(item => item && item.areaId === this.form.areaId) return !!(area && area.stockArea) } }, - mounted() { - this.$nextTick(() => { - if (this.$refs.palletInput) { - this.$refs.palletInput.focus() - } - }) - }, methods: { - handleBack() { + handleBack () { if (this.pageBusy) { return } + // 返回菜单前清空当前栈板和候选项,避免keep-alive再次进入时回显旧数据 - rqrq + this.resetPage(false) this.$router.back() }, - goHome() { + goHome () { if (this.pageBusy) { return } + // 返回首页前清理缓存表单,后续重新进入必须重新扫码 - rqrq + this.resetPage(false) this.$router.push({ path: '/' }) }, + // 统一重置扫码、表单、候选项与请求状态;递增序号使离开前的查询响应不能回填缓存页面 - rqrq + resetPage (needFocus = true) { + this.site = this.$store.state.user.site + this.scanRequestSeq += 1 + this.stationRequestSeq += 1 + this.palletCode = '' + this.clearScan() + this.scanLoading = false + this.saveLoading = false + this.removeLoading = false + this.stationLoading = false + if (needFocus) { + this.focusPalletInput() + } + }, // 区域下拉只显示名称,不展示A01这类编码 - rqrq - formatAreaLabel(area) { + formatAreaLabel (area) { if (!area || !area.areaDesc) { return '未命名区域' } return area.areaDesc }, // 换成立库时保留输入框里的位置,是否在货架可再选;换成其它区域时固定为否并清空位置,再拉该区域全部站点 - rqrq - handleAreaChange() { + handleAreaChange () { if (this.isStockArea) { this.stationOptions = [] this.form.batchWcsFlag = null @@ -190,7 +204,7 @@ export default { this.loadStations(false) }, // 扫描栈板:后端按wcs_location是否为空回显是否在货架 - rqrq - handlePalletScan() { + handlePalletScan () { if (this.pageBusy) { return } @@ -201,11 +215,16 @@ export default { return } this.site = this.$store.state.user.site + const requestSeq = this.scanRequestSeq + 1 + this.scanRequestSeq = requestSeq this.scanLoading = true scanPalletForSpecialEdit({ site: this.site, palletId: scannedCode }).then(({ data }) => { + if (this.scanRequestSeq !== requestSeq) { + return + } if (data && data.code === 0 && data.row) { this.applyScanResult(data.row, scannedCode) } else { @@ -214,15 +233,20 @@ export default { this.focusPalletInput() } }).catch(error => { + if (this.scanRequestSeq !== requestSeq) { + return + } this.clearScan() this.$message.error((error && error.message) || '栈板扫描失败') this.focusPalletInput() }).finally(() => { - this.scanLoading = false + if (this.scanRequestSeq === requestSeq) { + this.scanLoading = false + } }) }, // 把扫描结果写进表单;区域列表为空时仍保留当前区域编码,避免下拉空白 - rqrq - applyScanResult(row, scannedCode) { + applyScanResult (row, scannedCode) { // 货架占用由后端根据wcs_location生成,独立保存以免用户修改表单后误开放强制置空按钮 - rqrq this.wcsOccupied = row.onShelfFlag === 'Y' this.form = { @@ -245,7 +269,7 @@ export default { } }, // 非立库区域拉取全部站点。keepCurrent为真时保留扫描回显的位置,清单里没有也补进候选;失败时仍允许手输位置 - rqrq - loadStations(keepCurrent) { + loadStations (keepCurrent) { const areaId = this.form.areaId const currentLocation = keepCurrent ? (this.form.locationCode || '').trim() : '' if (!areaId || this.isStockArea) { @@ -294,7 +318,7 @@ export default { callback(suggestions) }, // 保存只要求已扫描栈板;位置留空时连同区域、货架点位置空,任务标记与货架选择空值按N提交 - rqrq - handleSave() { + handleSave () { if (this.pageBusy || !this.scanned || !this.form.palletId) { return } @@ -316,6 +340,8 @@ export default { ? '所在区域、位置和货架点位将置空' : (!areaId ? '所在区域和货架点位将置空' : (onShelfFlag === 'Y' ? '所在位置会同时写入货架点位' : '货架点位会被清空')) const batchWcsFlag = this.normalizeBatchWcsFlag() + // 确认框跨越页面重进或重新扫码时不再提交旧栈板,避免使用已清空的表单发请求 - rqrq + const requestSeq = this.scanRequestSeq if (batchWcsFlag === 0 || batchWcsFlag === 1) { const markText = batchWcsFlag === 1 ? '增量,表示未推送给立库' : '非增量,表示已经推送给立库' this.$confirm( @@ -331,7 +357,9 @@ export default { closeOnPressEscape: false } ).then(() => { - this.submitSave(saveFields, batchWcsFlag) + if (this.scanRequestSeq === requestSeq) { + this.submitSave(saveFields, batchWcsFlag) + } }).catch(() => {}) return } @@ -340,11 +368,13 @@ export default { '栈板特殊修改', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } ).then(() => { - this.submitSave(saveFields, null) + if (this.scanRequestSeq === requestSeq) { + this.submitSave(saveFields, null) + } }).catch(() => {}) }, // 空值不改明细;只接受增量1和非增量0 - rqrq - normalizeBatchWcsFlag() { + normalizeBatchWcsFlag () { if (this.isStockArea) { return null } @@ -357,8 +387,9 @@ export default { return null }, // 使用确认时固定的区域、位置和货架标记提交,避免弹窗期间表单变化导致预览与落库不一致;失败不刷新 - rqrq - submitSave(saveFields, batchWcsFlag) { + submitSave (saveFields, batchWcsFlag) { this.site = this.$store.state.user.site + const requestSeq = this.scanRequestSeq this.saveLoading = true const payload = { site: this.site, @@ -372,6 +403,9 @@ export default { payload.batchWcsFlag = batchWcsFlag } savePalletSpecialEdit(payload).then(({ data }) => { + if (this.scanRequestSeq !== requestSeq) { + return + } if (data && data.code === 0) { this.$message.success(data.msg || '保存成功') this.reloadAfterSave() @@ -379,9 +413,14 @@ export default { this.$alert((data && data.msg) || '保存失败', '错误', { confirmButtonText: '确定' }) } }).catch(error => { + if (this.scanRequestSeq !== requestSeq) { + return + } this.$message.error((error && error.message) || '保存失败') }).finally(() => { - this.saveLoading = false + if (this.scanRequestSeq === requestSeq) { + this.saveLoading = false + } }) }, // 强制置空前确认托盘编号;请求只传site和palletId,货架占用由服务端实时判断,成功后重新回显任务标记 - rqrq @@ -389,6 +428,7 @@ export default { if (this.pageBusy || !this.scanned || !this.form.palletId || this.wcsOccupied) { return } + const requestSeq = this.scanRequestSeq this.removeLoading = true try { await this.$confirm('确认强制置空托盘【' + this.form.palletId + '】?此操作会清空区域、位置、货架点位及占用备注,并将任务标记改为N。', '强制置空托盘', { @@ -397,16 +437,25 @@ export default { type: 'warning', closeOnClickModal: false }) + if (this.scanRequestSeq !== requestSeq) { + return + } // 显式传登录工厂与扫码托盘;接口失败不刷新页面,避免误示操作已成功 - rqrq this.site = this.$store.state.user.site const { data } = await forceRemovePalletSpecialEdit({ site: this.site, palletId: this.form.palletId }) + if (this.scanRequestSeq !== requestSeq) { + return + } if (data && data.code === 0) { // 先把页面改成置空后的库位,再按立库同步结果弹窗;同步失败也不回滚本地置空 - rqrq this.applyForceRemovedForm() await this.reloadAfterSave('置空') + if (this.scanRequestSeq !== requestSeq) { + return + } await this.$nextTick() const wcsSyncSuccess = !!(data.row && data.row.wcsSyncSuccess) if (wcsSyncSuccess) { @@ -432,11 +481,13 @@ export default { this.$alert((data && data.msg) || '强制置空托盘失败', '错误', { confirmButtonText: '确定' }) } } catch (error) { - if (error !== 'cancel' && error !== 'close') { + if (this.scanRequestSeq === requestSeq && error !== 'cancel' && error !== 'close') { this.$message.error((error && error.message) || '强制置空托盘失败') } } finally { - this.removeLoading = false + if (this.scanRequestSeq === requestSeq) { + this.removeLoading = false + } } }, // 强制置空成功后立刻清空页面库位,避免等重查才看到变化;区域和货架一并按已释放回显 - rqrq @@ -451,22 +502,31 @@ export default { }, // 保存或置空后重查同一托盘,页面回显数据库最新区域、位置和任务标记;刷新失败提示当前操作名称 - rqrq async reloadAfterSave (operationName = '保存') { + const requestSeq = this.scanRequestSeq + const palletId = this.form.palletId this.scanLoading = true try { const { data } = await scanPalletForSpecialEdit({ site: this.site, - palletId: this.form.palletId + palletId: palletId }) + if (this.scanRequestSeq !== requestSeq) { + return + } if (data && data.code === 0 && data.row) { - this.applyScanResult(data.row, this.form.palletId) + this.applyScanResult(data.row, palletId) } } catch (error) { - this.$message.error(operationName + '后刷新栈板失败') + if (this.scanRequestSeq === requestSeq) { + this.$message.error(operationName + '后刷新栈板失败') + } } finally { - this.scanLoading = false + if (this.scanRequestSeq === requestSeq) { + this.scanLoading = false + } } }, - clearScan() { + clearScan () { this.scanned = false this.wcsOccupied = false this.areaOptions = [] @@ -480,13 +540,25 @@ export default { batchWcsFlag: null } }, - focusPalletInput() { + focusPalletInput () { this.$nextTick(() => { if (this.$refs.palletInput) { this.$refs.palletInput.focus() } }) } + }, + // keep-alive每次激活均回到待扫码状态,避免再次进入时展示上次栈板 - rqrq + activated () { + this.resetPage(true) + }, + // 离开页面时清理缓存并使未完成查询失效,防止旧响应在下次进入后回填 - rqrq + beforeRouteLeave (to, from, next) { + this.resetPage(false) + next() + }, + mounted () { + this.resetPage(true) } }