6 changed files with 783 additions and 0 deletions
-
7src/api/haianAutoWarehouse/palletRelocate.js
-
7src/api/haianAutoWarehouse/palletSpecialEdit.js
-
2src/router/index.js
-
12src/views/main.vue
-
400src/views/modules/haianAutoWarehouse/haianPalletRelocate.vue
-
355src/views/modules/haianAutoWarehouse/haianPalletSpecialEdit.vue
@ -0,0 +1,7 @@ |
|||||
|
import { createAPI } from "@/utils/httpRequest.js"; |
||||
|
|
||||
|
// 海安栈板重移库:扫描托盘,返回当前区域和库位不一致的标签 - rqrq
|
||||
|
export const scanPalletForRelocate = data => createAPI(`/haiAnWcsIntegration/scanPalletForRelocate`, 'post', data) |
||||
|
|
||||
|
// 海安栈板重移库:按当前区域再次调用自动移库 - rqrq
|
||||
|
export const retryPalletRelocate = data => createAPI(`/haiAnWcsIntegration/retryPalletRelocate`, 'post', data) |
||||
@ -0,0 +1,7 @@ |
|||||
|
import { createAPI } from "@/utils/httpRequest.js"; |
||||
|
|
||||
|
// 海安栈板特殊修改:扫描托盘,回显任务标记、区域、位置和是否在货架 - rqrq
|
||||
|
export const scanPalletForSpecialEdit = data => createAPI(`/haiAnWcsIntegration/scanPalletForSpecialEdit`, 'post', data) |
||||
|
|
||||
|
// 海安栈板特殊修改:在货架为是时位置同时写入location_code和wcs_location,为否时清空wcs_location - rqrq
|
||||
|
export const savePalletSpecialEdit = data => createAPI(`/haiAnWcsIntegration/savePalletSpecialEdit`, 'post', data) |
||||
@ -0,0 +1,400 @@ |
|||||
|
<template> |
||||
|
<div> |
||||
|
<div class="pda-container"> |
||||
|
<div class="header-bar"> |
||||
|
<div class="header-left" :class="{ 'header-action-disabled': pageBusy }" @click="handleBack"> |
||||
|
<i class="el-icon-arrow-left"></i> |
||||
|
<span>栈板重移库</span> |
||||
|
</div> |
||||
|
<div class="header-right" :class="{ 'header-action-disabled': pageBusy }" @click="goHome"> |
||||
|
首页 |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="table-body"> |
||||
|
<div class="main-content"> |
||||
|
<!-- 回车触发扫描;成功后展示区域,失败清空并重新聚焦 - rqrq --> |
||||
|
<div class="input-group"> |
||||
|
<label class="input-label">栈板编码</label> |
||||
|
<el-input |
||||
|
v-model="palletCode" |
||||
|
placeholder="请扫描栈板编码" |
||||
|
class="form-input" |
||||
|
clearable |
||||
|
:disabled="pageBusy" |
||||
|
inputmode="none" |
||||
|
autocomplete="off" |
||||
|
autocorrect="off" |
||||
|
spellcheck="false" |
||||
|
@keyup.enter.native="handlePalletScan" |
||||
|
ref="palletInput" |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
<div v-if="scanned" class="info-section"> |
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">区域</span> |
||||
|
<span class="info-value">{{ scanResult.areaDesc || scanResult.areaId || '-' }}</span> |
||||
|
</div> |
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">仓库</span> |
||||
|
<span class="info-value">{{ scanResult.warehouseId || '-' }}</span> |
||||
|
</div> |
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">库位</span> |
||||
|
<span class="info-value">{{ scanResult.locationId || '-' }}</span> |
||||
|
</div> |
||||
|
<div class="hint">下面只显示和这个区域仓库或库位不一致的标签。在库且数量大于0的才会进入本次移库。</div> |
||||
|
|
||||
|
<div class="mismatch-list"> |
||||
|
<div v-if="mismatchRows.length === 0" class="empty-hint">没有库位不一致的标签</div> |
||||
|
<div v-for="(row, index) in mismatchRows" :key="index" class="mismatch-card"> |
||||
|
<div class="card-title">{{ row.serialNo || '-' }}</div> |
||||
|
<div class="card-line">物料 {{ row.partNo || '-' }} {{ row.partDesc || '' }}</div> |
||||
|
<div class="card-line">仓库 {{ row.warehouseId || '-' }} / 库位 {{ row.locationId || '-' }} / 数量 {{ formatQty(row.qty) }}</div> |
||||
|
<div class="card-line" :class="row.willTransfer ? 'will-move' : 'will-skip'"> |
||||
|
{{ row.willTransfer ? '本次会移库' : (row.skipReason || '本次不移库') }} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 确认后按当前区域重跑自动移库,结束后重新扫描刷新差异列表 - rqrq --> |
||||
|
<div class="bottom-actions"> |
||||
|
<button class="action-btn primary" :disabled="retryLoading || pageBusy" @click="handleRetry"> |
||||
|
{{ retryLoading ? '移库中...' : '重新移库' }} |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { scanPalletForRelocate, retryPalletRelocate } from '../../../api/haianAutoWarehouse/palletRelocate' |
||||
|
|
||||
|
export default { |
||||
|
name: 'haianPalletRelocate', |
||||
|
data() { |
||||
|
return { |
||||
|
// 海安PDA的site只取登录用户工厂,扫描和重移库都显式传给后端 - rqrq |
||||
|
site: this.$store.state.user.site, |
||||
|
palletCode: '', |
||||
|
scanned: false, |
||||
|
scanLoading: false, |
||||
|
retryLoading: false, |
||||
|
scanResult: { |
||||
|
palletId: '', |
||||
|
areaId: '', |
||||
|
areaDesc: '', |
||||
|
warehouseId: '', |
||||
|
locationId: '', |
||||
|
mismatchRows: [] |
||||
|
}, |
||||
|
// 重移库成功后的5秒、10秒刷新句柄,离开页面或改扫栈板时必须清掉 - rqrq |
||||
|
relocateRefreshTimers: [] |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
// 扫描和重移库互斥,避免回车和按钮同时打到后台 - rqrq |
||||
|
pageBusy() { |
||||
|
return this.scanLoading || this.retryLoading |
||||
|
}, |
||||
|
mismatchRows() { |
||||
|
return (this.scanResult && this.scanResult.mismatchRows) || [] |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.palletInput) { |
||||
|
this.$refs.palletInput.focus() |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
// 页面被缓存切走或真正销毁时都停掉定时刷新,避免回到首页后还在打扫描接口 - rqrq |
||||
|
deactivated() { |
||||
|
this.clearRelocateRefreshTimers() |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
this.clearRelocateRefreshTimers() |
||||
|
}, |
||||
|
methods: { |
||||
|
handleBack() { |
||||
|
if (this.pageBusy) { |
||||
|
return |
||||
|
} |
||||
|
this.$router.back() |
||||
|
}, |
||||
|
goHome() { |
||||
|
if (this.pageBusy) { |
||||
|
return |
||||
|
} |
||||
|
this.$router.push({ path: '/' }) |
||||
|
}, |
||||
|
// 数量去尾零,空值显示0,避免固定小数位 - rqrq |
||||
|
formatQty(qty) { |
||||
|
if (qty === null || qty === undefined || qty === '') { |
||||
|
return '0' |
||||
|
} |
||||
|
const numberValue = Number(qty) |
||||
|
if (Number.isNaN(numberValue)) { |
||||
|
return String(qty) |
||||
|
} |
||||
|
return String(numberValue) |
||||
|
}, |
||||
|
// 扫描栈板:无区域或区域未配置仓库库位时后端拒绝,页面清空并重新聚焦 - rqrq |
||||
|
handlePalletScan() { |
||||
|
if (this.pageBusy) { |
||||
|
return |
||||
|
} |
||||
|
const scannedCode = (this.palletCode || '').replace(/\s+/g, '') |
||||
|
this.palletCode = scannedCode |
||||
|
if (!scannedCode) { |
||||
|
this.$alert('请扫描栈板编码', '错误', { confirmButtonText: '确定' }) |
||||
|
return |
||||
|
} |
||||
|
// 改扫其他栈板时取消上一盘的延迟刷新,避免旧结果覆盖新扫描 - rqrq |
||||
|
this.clearRelocateRefreshTimers() |
||||
|
this.site = this.$store.state.user.site |
||||
|
this.scanLoading = true |
||||
|
scanPalletForRelocate({ |
||||
|
site: this.site, |
||||
|
palletId: scannedCode |
||||
|
}).then(({ data }) => { |
||||
|
if (data && data.code === 0 && data.row) { |
||||
|
this.scanResult = data.row |
||||
|
this.palletCode = data.row.palletId || scannedCode |
||||
|
this.scanned = true |
||||
|
} else { |
||||
|
this.clearScan() |
||||
|
this.$alert((data && data.msg) || '栈板扫描失败', '错误', { confirmButtonText: '确定' }) |
||||
|
this.focusPalletInput() |
||||
|
} |
||||
|
}).catch(error => { |
||||
|
this.clearScan() |
||||
|
this.$message.error((error && error.message) || '栈板扫描失败') |
||||
|
this.focusPalletInput() |
||||
|
}).finally(() => { |
||||
|
this.scanLoading = false |
||||
|
}) |
||||
|
}, |
||||
|
// 重新移库前确认;成功后按同一栈板再查一次,看差异是否还在 - rqrq |
||||
|
handleRetry() { |
||||
|
if (this.pageBusy || !this.scanned || !this.scanResult.palletId) { |
||||
|
return |
||||
|
} |
||||
|
this.$confirm( |
||||
|
'确定按区域【' + (this.scanResult.areaDesc || this.scanResult.areaId) + '】的仓库库位,重新移库不一致的标签吗?', |
||||
|
'重新移库', |
||||
|
{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } |
||||
|
).then(() => { |
||||
|
this.site = this.$store.state.user.site |
||||
|
this.retryLoading = true |
||||
|
retryPalletRelocate({ |
||||
|
site: this.site, |
||||
|
palletId: this.scanResult.palletId |
||||
|
}).then(({ data }) => { |
||||
|
if (data && data.code === 0) { |
||||
|
this.$message.success(data.msg || '重新移库已提交') |
||||
|
this.palletCode = this.scanResult.palletId |
||||
|
this.refreshAfterRetry() |
||||
|
// 移库只是入队,5秒和10秒后再拉明细,等队列处理完把已对齐标签刷掉 - rqrq |
||||
|
this.scheduleRelocateRefresh() |
||||
|
} else { |
||||
|
this.$alert((data && data.msg) || '重新移库失败', '错误', { confirmButtonText: '确定' }) |
||||
|
} |
||||
|
}).catch(error => { |
||||
|
this.$message.error((error && error.message) || '重新移库失败') |
||||
|
}).finally(() => { |
||||
|
this.retryLoading = false |
||||
|
}) |
||||
|
}).catch(() => {}) |
||||
|
}, |
||||
|
// 清掉尚未触发的5秒、10秒刷新。重复点重移库或离开页面时调用,防止同一栈板被刷多次 - rqrq |
||||
|
clearRelocateRefreshTimers() { |
||||
|
;(this.relocateRefreshTimers || []).forEach(timerId => clearTimeout(timerId)) |
||||
|
this.relocateRefreshTimers = [] |
||||
|
}, |
||||
|
// 入队成功后预约两次静默刷新;若期间栈板已换,到点不再覆盖当前画面 - rqrq |
||||
|
scheduleRelocateRefresh() { |
||||
|
this.clearRelocateRefreshTimers() |
||||
|
const palletId = this.scanResult.palletId |
||||
|
;[5000, 10000].forEach(delay => { |
||||
|
const timerId = setTimeout(() => { |
||||
|
if (!this.scanned || this.scanResult.palletId !== palletId) { |
||||
|
return |
||||
|
} |
||||
|
this.refreshMismatchQuiet(palletId) |
||||
|
}, delay) |
||||
|
this.relocateRefreshTimers.push(timerId) |
||||
|
}) |
||||
|
}, |
||||
|
// 定时刷新不占用扫描按钮,失败只提示,不把已展示的差异列表清掉 - rqrq |
||||
|
refreshMismatchQuiet(palletId) { |
||||
|
scanPalletForRelocate({ |
||||
|
site: this.site, |
||||
|
palletId: palletId |
||||
|
}).then(({ data }) => { |
||||
|
if (data && data.code === 0 && data.row && this.scanResult.palletId === palletId) { |
||||
|
this.scanResult = data.row |
||||
|
this.scanned = true |
||||
|
} |
||||
|
}).catch(() => { |
||||
|
this.$message.error('移库后刷新差异标签失败') |
||||
|
}) |
||||
|
}, |
||||
|
// 移库入队后先立即重查一次,5秒和10秒的刷新另外预约 - rqrq |
||||
|
refreshAfterRetry() { |
||||
|
this.scanLoading = true |
||||
|
scanPalletForRelocate({ |
||||
|
site: this.site, |
||||
|
palletId: this.scanResult.palletId |
||||
|
}).then(({ data }) => { |
||||
|
if (data && data.code === 0 && data.row) { |
||||
|
this.scanResult = data.row |
||||
|
this.scanned = true |
||||
|
} |
||||
|
}).catch(() => { |
||||
|
this.$message.error('移库后刷新差异标签失败') |
||||
|
}).finally(() => { |
||||
|
this.scanLoading = false |
||||
|
}) |
||||
|
}, |
||||
|
clearScan() { |
||||
|
this.clearRelocateRefreshTimers() |
||||
|
this.scanned = false |
||||
|
this.scanResult = { |
||||
|
palletId: '', |
||||
|
areaId: '', |
||||
|
areaDesc: '', |
||||
|
warehouseId: '', |
||||
|
locationId: '', |
||||
|
mismatchRows: [] |
||||
|
} |
||||
|
}, |
||||
|
focusPalletInput() { |
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.palletInput) { |
||||
|
this.$refs.palletInput.focus() |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.header-action-disabled { |
||||
|
opacity: 0.5; |
||||
|
pointer-events: none; |
||||
|
} |
||||
|
.pda-container { |
||||
|
width: 100vw; |
||||
|
height: 100vh; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
background: #f5f5f5; |
||||
|
} |
||||
|
.header-bar { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 8px 16px; |
||||
|
background: #17B3A3; |
||||
|
color: white; |
||||
|
height: 40px; |
||||
|
} |
||||
|
.header-left, .header-right { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
.header-left i { |
||||
|
margin-right: 8px; |
||||
|
} |
||||
|
.table-body { |
||||
|
flex: 1; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
.main-content { |
||||
|
padding: 16px; |
||||
|
} |
||||
|
.input-label { |
||||
|
display: block; |
||||
|
margin-bottom: 8px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
.form-input { |
||||
|
width: 100%; |
||||
|
} |
||||
|
.info-section { |
||||
|
margin-top: 16px; |
||||
|
background: white; |
||||
|
border-radius: 8px; |
||||
|
padding: 12px; |
||||
|
} |
||||
|
.info-row { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
padding: 8px 0; |
||||
|
border-bottom: 1px solid #f0f0f0; |
||||
|
} |
||||
|
.info-label { |
||||
|
color: #666; |
||||
|
} |
||||
|
.info-value { |
||||
|
color: #333; |
||||
|
font-weight: 500; |
||||
|
word-break: break-all; |
||||
|
text-align: right; |
||||
|
} |
||||
|
.hint { |
||||
|
margin-top: 10px; |
||||
|
color: #909399; |
||||
|
font-size: 13px; |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
.mismatch-card { |
||||
|
margin-top: 10px; |
||||
|
padding: 10px; |
||||
|
border: 1px solid #ebeef5; |
||||
|
border-radius: 6px; |
||||
|
} |
||||
|
.card-title { |
||||
|
font-weight: 600; |
||||
|
margin-bottom: 4px; |
||||
|
} |
||||
|
.card-line { |
||||
|
font-size: 13px; |
||||
|
color: #606266; |
||||
|
line-height: 1.6; |
||||
|
word-break: break-all; |
||||
|
} |
||||
|
.will-move { |
||||
|
color: #67C23A; |
||||
|
} |
||||
|
.will-skip { |
||||
|
color: #F56C6C; |
||||
|
} |
||||
|
.empty-hint { |
||||
|
margin-top: 12px; |
||||
|
color: #909399; |
||||
|
text-align: center; |
||||
|
} |
||||
|
.bottom-actions { |
||||
|
margin-top: 16px; |
||||
|
} |
||||
|
.action-btn { |
||||
|
width: 100%; |
||||
|
padding: 12px; |
||||
|
border: none; |
||||
|
border-radius: 6px; |
||||
|
font-size: 16px; |
||||
|
color: white; |
||||
|
background: #17B3A3; |
||||
|
} |
||||
|
.action-btn:disabled { |
||||
|
opacity: 0.6; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,355 @@ |
|||||
|
<template> |
||||
|
<div> |
||||
|
<div class="pda-container"> |
||||
|
<div class="header-bar"> |
||||
|
<div class="header-left" :class="{ 'header-action-disabled': pageBusy }" @click="handleBack"> |
||||
|
<i class="el-icon-arrow-left"></i> |
||||
|
<span>栈板特殊修改</span> |
||||
|
</div> |
||||
|
<div class="header-right" :class="{ 'header-action-disabled': pageBusy }" @click="goHome"> |
||||
|
首页 |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="table-body"> |
||||
|
<div class="main-content"> |
||||
|
<!-- 回车扫描栈板;成功后回显四个可改字段,失败清空并重新聚焦 - rqrq --> |
||||
|
<div class="input-group"> |
||||
|
<label class="input-label">栈板编码</label> |
||||
|
<el-input |
||||
|
v-model="palletCode" |
||||
|
placeholder="请扫描栈板编码" |
||||
|
class="form-input" |
||||
|
clearable |
||||
|
:disabled="pageBusy" |
||||
|
inputmode="none" |
||||
|
autocomplete="off" |
||||
|
autocorrect="off" |
||||
|
spellcheck="false" |
||||
|
@keyup.enter.native="handlePalletScan" |
||||
|
ref="palletInput" |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
<div v-if="scanned" class="info-section"> |
||||
|
<div class="form-row"> |
||||
|
<label class="input-label">任务标记</label> |
||||
|
<el-select v-model="form.callingFlag" placeholder="请选择任务标记" style="width: 100%;" :disabled="pageBusy"> |
||||
|
<el-option label="Y" value="Y"></el-option> |
||||
|
<el-option label="N" value="N"></el-option> |
||||
|
</el-select> |
||||
|
</div> |
||||
|
<div class="form-row"> |
||||
|
<label class="input-label">所在区域</label> |
||||
|
<el-select v-model="form.areaId" placeholder="请选择所在区域" filterable style="width: 100%;" :disabled="pageBusy"> |
||||
|
<el-option |
||||
|
v-for="area in areaOptions" |
||||
|
:key="area.areaId" |
||||
|
:label="formatAreaLabel(area)" |
||||
|
:value="area.areaId" |
||||
|
></el-option> |
||||
|
</el-select> |
||||
|
</div> |
||||
|
<div class="form-row"> |
||||
|
<label class="input-label">所在位置</label> |
||||
|
<el-input |
||||
|
v-model="form.locationCode" |
||||
|
placeholder="请输入所在位置" |
||||
|
class="form-input" |
||||
|
clearable |
||||
|
:disabled="pageBusy" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="form-row"> |
||||
|
<label class="input-label">是否在货架</label> |
||||
|
<el-select v-model="form.onShelfFlag" placeholder="请选择是否在货架" style="width: 100%;" :disabled="pageBusy"> |
||||
|
<el-option label="是" value="Y"></el-option> |
||||
|
<el-option label="否" value="N"></el-option> |
||||
|
</el-select> |
||||
|
</div> |
||||
|
<div class="hint">选择是时,所在位置会同时写入地面点位和货架点位。选择否时,只清空货架点位,所在位置仍按输入框保存。</div> |
||||
|
|
||||
|
<!-- 保存前确认;成功后按同一栈板再查一次,回显数据库里的最新值 - rqrq --> |
||||
|
<div class="bottom-actions"> |
||||
|
<button class="action-btn primary" :disabled="saveLoading || pageBusy" @click="handleSave"> |
||||
|
{{ saveLoading ? '保存中...' : '保存' }} |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { scanPalletForSpecialEdit, savePalletSpecialEdit } from '../../../api/haianAutoWarehouse/palletSpecialEdit' |
||||
|
|
||||
|
export default { |
||||
|
name: 'haianPalletSpecialEdit', |
||||
|
data() { |
||||
|
return { |
||||
|
// 海安PDA的site只取登录用户工厂,扫描和保存都显式传给后端 - rqrq |
||||
|
site: this.$store.state.user.site, |
||||
|
palletCode: '', |
||||
|
scanned: false, |
||||
|
scanLoading: false, |
||||
|
saveLoading: false, |
||||
|
areaOptions: [], |
||||
|
form: { |
||||
|
palletId: '', |
||||
|
callingFlag: 'N', |
||||
|
areaId: '', |
||||
|
locationCode: '', |
||||
|
onShelfFlag: 'N' |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
// 扫描和保存互斥,避免回车和按钮同时打到后台 - rqrq |
||||
|
pageBusy() { |
||||
|
return this.scanLoading || this.saveLoading |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.palletInput) { |
||||
|
this.$refs.palletInput.focus() |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
methods: { |
||||
|
handleBack() { |
||||
|
if (this.pageBusy) { |
||||
|
return |
||||
|
} |
||||
|
this.$router.back() |
||||
|
}, |
||||
|
goHome() { |
||||
|
if (this.pageBusy) { |
||||
|
return |
||||
|
} |
||||
|
this.$router.push({ path: '/' }) |
||||
|
}, |
||||
|
// 区域下拉同时展示描述和编码,避免同名区域选错 - rqrq |
||||
|
formatAreaLabel(area) { |
||||
|
if (!area) { |
||||
|
return '' |
||||
|
} |
||||
|
if (area.areaDesc && area.areaDesc !== area.areaId) { |
||||
|
return area.areaDesc + '(' + area.areaId + ')' |
||||
|
} |
||||
|
return area.areaId || '' |
||||
|
}, |
||||
|
// 扫描栈板:后端按wcs_location是否为空回显是否在货架 - rqrq |
||||
|
handlePalletScan() { |
||||
|
if (this.pageBusy) { |
||||
|
return |
||||
|
} |
||||
|
const scannedCode = (this.palletCode || '').replace(/\s+/g, '') |
||||
|
this.palletCode = scannedCode |
||||
|
if (!scannedCode) { |
||||
|
this.$alert('请扫描栈板编码', '错误', { confirmButtonText: '确定' }) |
||||
|
return |
||||
|
} |
||||
|
this.site = this.$store.state.user.site |
||||
|
this.scanLoading = true |
||||
|
scanPalletForSpecialEdit({ |
||||
|
site: this.site, |
||||
|
palletId: scannedCode |
||||
|
}).then(({ data }) => { |
||||
|
if (data && data.code === 0 && data.row) { |
||||
|
this.applyScanResult(data.row, scannedCode) |
||||
|
} else { |
||||
|
this.clearScan() |
||||
|
this.$alert((data && data.msg) || '栈板扫描失败', '错误', { confirmButtonText: '确定' }) |
||||
|
this.focusPalletInput() |
||||
|
} |
||||
|
}).catch(error => { |
||||
|
this.clearScan() |
||||
|
this.$message.error((error && error.message) || '栈板扫描失败') |
||||
|
this.focusPalletInput() |
||||
|
}).finally(() => { |
||||
|
this.scanLoading = false |
||||
|
}) |
||||
|
}, |
||||
|
// 把扫描结果写进表单;区域列表为空时仍保留当前区域编码,避免下拉空白 - rqrq |
||||
|
applyScanResult(row, scannedCode) { |
||||
|
this.form = { |
||||
|
palletId: row.palletId || scannedCode, |
||||
|
callingFlag: row.callingFlag === 'Y' ? 'Y' : 'N', |
||||
|
areaId: row.areaId || '', |
||||
|
locationCode: row.locationCode || '', |
||||
|
onShelfFlag: row.onShelfFlag === 'Y' ? 'Y' : 'N' |
||||
|
} |
||||
|
this.areaOptions = row.areaOptions || [] |
||||
|
this.palletCode = this.form.palletId |
||||
|
this.scanned = true |
||||
|
}, |
||||
|
// 保存前校验页面必填项;在货架为是时位置不能空,为否时允许位置为空 - rqrq |
||||
|
handleSave() { |
||||
|
if (this.pageBusy || !this.scanned || !this.form.palletId) { |
||||
|
return |
||||
|
} |
||||
|
if (this.form.callingFlag !== 'Y' && this.form.callingFlag !== 'N') { |
||||
|
this.$alert('任务标记只能选择Y或N', '错误', { confirmButtonText: '确定' }) |
||||
|
return |
||||
|
} |
||||
|
if (!this.form.areaId) { |
||||
|
this.$alert('请选择所在区域', '错误', { confirmButtonText: '确定' }) |
||||
|
return |
||||
|
} |
||||
|
const locationCode = (this.form.locationCode || '').trim() |
||||
|
if (this.form.onShelfFlag === 'Y' && !locationCode) { |
||||
|
this.$alert('选择在货架时,所在位置不能为空', '错误', { confirmButtonText: '确定' }) |
||||
|
return |
||||
|
} |
||||
|
if (this.form.onShelfFlag !== 'Y' && this.form.onShelfFlag !== 'N') { |
||||
|
this.$alert('请选择是否在货架', '错误', { confirmButtonText: '确定' }) |
||||
|
return |
||||
|
} |
||||
|
const shelfText = this.form.onShelfFlag === 'Y' ? '是,所在位置会同时写入货架点位' : '否,货架点位会被清空' |
||||
|
this.$confirm( |
||||
|
'确定保存栈板【' + this.form.palletId + '】吗?是否在货架:' + shelfText + '。', |
||||
|
'栈板特殊修改', |
||||
|
{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } |
||||
|
).then(() => { |
||||
|
this.submitSave(locationCode) |
||||
|
}).catch(() => {}) |
||||
|
}, |
||||
|
// 保存成功后按同一栈板再查一次,确认页面和数据库一致 - rqrq |
||||
|
submitSave(locationCode) { |
||||
|
this.site = this.$store.state.user.site |
||||
|
this.saveLoading = true |
||||
|
savePalletSpecialEdit({ |
||||
|
site: this.site, |
||||
|
palletId: this.form.palletId, |
||||
|
callingFlag: this.form.callingFlag, |
||||
|
areaId: this.form.areaId, |
||||
|
locationCode: locationCode, |
||||
|
onShelfFlag: this.form.onShelfFlag |
||||
|
}).then(({ data }) => { |
||||
|
if (data && data.code === 0) { |
||||
|
this.$message.success(data.msg || '保存成功') |
||||
|
this.reloadAfterSave() |
||||
|
} else { |
||||
|
this.$alert((data && data.msg) || '保存失败', '错误', { confirmButtonText: '确定' }) |
||||
|
} |
||||
|
}).catch(error => { |
||||
|
this.$message.error((error && error.message) || '保存失败') |
||||
|
}).finally(() => { |
||||
|
this.saveLoading = false |
||||
|
}) |
||||
|
}, |
||||
|
reloadAfterSave() { |
||||
|
this.scanLoading = true |
||||
|
scanPalletForSpecialEdit({ |
||||
|
site: this.site, |
||||
|
palletId: this.form.palletId |
||||
|
}).then(({ data }) => { |
||||
|
if (data && data.code === 0 && data.row) { |
||||
|
this.applyScanResult(data.row, this.form.palletId) |
||||
|
} |
||||
|
}).catch(() => { |
||||
|
this.$message.error('保存后刷新栈板失败') |
||||
|
}).finally(() => { |
||||
|
this.scanLoading = false |
||||
|
}) |
||||
|
}, |
||||
|
clearScan() { |
||||
|
this.scanned = false |
||||
|
this.areaOptions = [] |
||||
|
this.form = { |
||||
|
palletId: '', |
||||
|
callingFlag: 'N', |
||||
|
areaId: '', |
||||
|
locationCode: '', |
||||
|
onShelfFlag: 'N' |
||||
|
} |
||||
|
}, |
||||
|
focusPalletInput() { |
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.palletInput) { |
||||
|
this.$refs.palletInput.focus() |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.header-action-disabled { |
||||
|
opacity: 0.5; |
||||
|
pointer-events: none; |
||||
|
} |
||||
|
.pda-container { |
||||
|
width: 100vw; |
||||
|
height: 100vh; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
background: #f5f5f5; |
||||
|
} |
||||
|
.header-bar { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 8px 16px; |
||||
|
background: #17B3A3; |
||||
|
color: white; |
||||
|
height: 40px; |
||||
|
} |
||||
|
.header-left, .header-right { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
.header-left i { |
||||
|
margin-right: 8px; |
||||
|
} |
||||
|
.table-body { |
||||
|
flex: 1; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
.main-content { |
||||
|
padding: 16px; |
||||
|
} |
||||
|
.input-label { |
||||
|
display: block; |
||||
|
margin-bottom: 8px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
.form-input { |
||||
|
width: 100%; |
||||
|
} |
||||
|
.info-section { |
||||
|
margin-top: 16px; |
||||
|
background: white; |
||||
|
border-radius: 8px; |
||||
|
padding: 12px; |
||||
|
} |
||||
|
.form-row { |
||||
|
margin-bottom: 14px; |
||||
|
} |
||||
|
.hint { |
||||
|
margin-top: 4px; |
||||
|
color: #909399; |
||||
|
font-size: 13px; |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
.bottom-actions { |
||||
|
margin-top: 16px; |
||||
|
} |
||||
|
.action-btn { |
||||
|
width: 100%; |
||||
|
padding: 12px; |
||||
|
border: none; |
||||
|
border-radius: 6px; |
||||
|
font-size: 16px; |
||||
|
color: white; |
||||
|
background: #17B3A3; |
||||
|
} |
||||
|
.action-btn:disabled { |
||||
|
opacity: 0.6; |
||||
|
} |
||||
|
</style> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue