You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
488 lines
15 KiB
488 lines
15 KiB
<template>
|
|
<div>
|
|
<div class="pda-container">
|
|
<!-- 头部栏 - rqrq -->
|
|
<div class="header-bar">
|
|
<div class="header-left" @click="handleBack">
|
|
<i class="el-icon-arrow-left"></i>
|
|
<span>空托盘组盘</span>
|
|
</div>
|
|
<div class="header-right" @click="goHome">
|
|
首页
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-body" style="max-height: 600px; overflow-y: auto;">
|
|
<div class="main-content form-section">
|
|
<!-- 栈板扫描 - rqrq -->
|
|
<div class="input-group">
|
|
<label class="input-label">托盘编码</label>
|
|
<el-input
|
|
v-model="palletCode"
|
|
placeholder="请扫描托盘编码"
|
|
class="form-input"
|
|
clearable
|
|
@keyup.enter.native="handlePalletScan"
|
|
ref="palletInput"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 托盘信息显示(扫描托盘后显示)- rqrq -->
|
|
<div v-if="palletScanned" class="pallet-info-section">
|
|
<!-- 托盘类型选择 - rqrq -->
|
|
<div class="input-group">
|
|
<label class="input-label">托盘类型</label>
|
|
<el-select
|
|
v-model="currentPalletType"
|
|
placeholder="请选择托盘类型"
|
|
style="width: 100%;"
|
|
@change="handlePalletTypeChange"
|
|
>
|
|
<el-option
|
|
v-for="type in palletTypeOptions"
|
|
:key="type.palletType"
|
|
:label="`${type.palletType} - ${type.typeDesc}`"
|
|
:value="type.palletType"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
|
|
<div class="input-group">
|
|
<label class="input-label">空托数量</label>
|
|
<el-select v-model="count" disabled>
|
|
<el-option value=1 label=1></el-option>
|
|
<el-option value=2 label=2></el-option>
|
|
<el-option value=3 label=3></el-option>
|
|
<el-option value=4 label=4></el-option>
|
|
<el-option value=5 label=5></el-option>
|
|
<el-option value=6 label=6></el-option>
|
|
</el-select>
|
|
</div>
|
|
|
|
<!-- 当前站点信息 - rqrq -->
|
|
<div class="info-row">
|
|
<label class="info-label">当前站点ID:</label>
|
|
<span class="info-value">{{ palletInfo.currentStationId || '-' }}</span>
|
|
</div>
|
|
|
|
<div class="info-row">
|
|
<label class="info-label">当前站点编码:</label>
|
|
<span class="info-value">{{ palletInfo.currentStationCode || '-' }}</span>
|
|
</div>
|
|
|
|
<!-- 操作按钮 - rqrq -->
|
|
<div class="button-row" style="display: flex; gap: 8px; margin-top: 16px;">
|
|
<button
|
|
class="action-btn primary"
|
|
@click="handleNotifyInbound"
|
|
:disabled="notifyLoading || !currentPalletType"
|
|
style="flex: 1;">
|
|
{{ notifyLoading ? '处理中...' : '通知入库' }}
|
|
</button>
|
|
<button
|
|
class="action-btn primary"
|
|
@click="handleInboundAndTransport"
|
|
:disabled="transportLoading || !currentPalletType"
|
|
style="flex: 1;">
|
|
{{ transportLoading ? '处理中...' : '入库并运输' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 通知入库口选择弹窗:必须明确选择入库口1/2后才允许提交 - rqrq -->
|
|
<el-dialog
|
|
title="请选择入库口"
|
|
:visible.sync="inboundPortDialogVisible"
|
|
width="90%"
|
|
:close-on-click-modal="false"
|
|
:show-close="false"
|
|
:append-to-body="true"
|
|
>
|
|
<div class="input-group">
|
|
<label class="input-label">入库口</label>
|
|
<el-select v-model="selectedInboundPort" placeholder="请选择入库口" style="width: 100%;">
|
|
<el-option
|
|
v-for="option in inboundPortOptions"
|
|
:key="option.value"
|
|
:label="option.label"
|
|
:value="option.value"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
<div slot="footer" class="dialog-footer">
|
|
<button class="action-btn secondary" @click="cancelInboundPortDialog">取消</button>
|
|
<button class="action-btn primary" @click="confirmNotifyInbound">确认</button>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
checkEmptyPallet,
|
|
getPalletTypes,
|
|
updatePalletTypeAndAutoSort,
|
|
notifyEmptyPalletInbound
|
|
} from '../../../api/haianAutoWarehouse/emptyPalletAssembly'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
// 海安PDA前端site唯一来源为store用户对象,兼容旧缓存兜底 - rqrq
|
|
site: (this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.site) || localStorage.getItem('site'),
|
|
|
|
// 托盘信息 - rqrq
|
|
palletCode: '',
|
|
palletScanned: false,
|
|
palletInfo: {
|
|
currentStationId: '',
|
|
currentStationCode: '',
|
|
palletType: '',
|
|
area: ''
|
|
},
|
|
|
|
// 托盘类型 - rqrq
|
|
currentPalletType: '',
|
|
palletTypeOptions: [],
|
|
count: 1,
|
|
// 通知入库口选择 - rqrq
|
|
inboundPortDialogVisible: false,
|
|
selectedInboundPort: '',
|
|
inboundPortOptions: [
|
|
{ label: '入库口1', value: 'INBOUND_PORT_1' },
|
|
{ label: '入库口2', value: 'INBOUND_PORT_2' }
|
|
],
|
|
// 加载状态 - rqrq
|
|
notifyLoading: false,
|
|
transportLoading: false
|
|
};
|
|
},
|
|
methods: {
|
|
// 返回上一页并清空页面状态,避免keep-alive导致脏数据残留 - rqrq
|
|
handleBack() {
|
|
this.resetPage(false);
|
|
this.$router.back();
|
|
},
|
|
|
|
// 回首页前清理状态,保证再次进入页面从干净态开始 - rqrq
|
|
goHome() {
|
|
this.resetPage(false);
|
|
this.$router.push({ path: '/' });
|
|
},
|
|
|
|
// 扫描托盘 - rqrq
|
|
handlePalletScan() {
|
|
if (!this.palletCode.trim()) {
|
|
this.$alert('请输入托盘编码', '提示', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
return;
|
|
}
|
|
|
|
checkEmptyPallet({
|
|
site: this.site,
|
|
palletId: this.palletCode
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
// 后端返回正确的6位栈板码,赋值给输入框 - rqrq
|
|
this.palletCode = data.row.palletId;
|
|
|
|
// 托盘信息 - rqrq
|
|
this.palletInfo = data.row;
|
|
this.currentPalletType = data.row.palletType || '';
|
|
this.palletScanned = true;
|
|
|
|
// 根据托盘的palletFamily加载托盘类型选项 - rqrq
|
|
this.loadPalletTypes(data.row.palletFamily);
|
|
|
|
} else {
|
|
this.$alert(data.msg || '托盘验证失败', '错误', {
|
|
confirmButtonText: '确定',
|
|
callback: () => {
|
|
this.palletCode = '';
|
|
this.$nextTick(() => {
|
|
if (this.$refs.palletInput) {
|
|
this.$refs.palletInput.focus();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}).catch(error => {
|
|
console.error('查询托盘失败:', error);
|
|
this.$alert(error.message || '查询托盘失败', '错误', {
|
|
confirmButtonText: '确定',
|
|
callback: () => {
|
|
this.palletCode = '';
|
|
this.$nextTick(() => {
|
|
if (this.$refs.palletInput) {
|
|
this.$refs.palletInput.focus();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
},
|
|
|
|
// 加载托盘类型选项(根据palletFamily过滤)- rqrq
|
|
loadPalletTypes(palletFamily) {
|
|
getPalletTypes({
|
|
site: this.site,
|
|
palletFamily: palletFamily || ''
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.palletTypeOptions = data.rows || [];
|
|
} else {
|
|
this.palletTypeOptions = [];
|
|
this.$alert('获取托盘类型失败', '错误', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
}
|
|
}).catch(error => {
|
|
console.error('获取托盘类型失败:', error);
|
|
this.palletTypeOptions = [];
|
|
});
|
|
},
|
|
|
|
// 托盘类型变更事件 - rqrq
|
|
handlePalletTypeChange() {
|
|
// 保存到数据库 - rqrq
|
|
updatePalletTypeAndAutoSort({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
palletType: this.currentPalletType,
|
|
autoSort: 'N',
|
|
forceFullPalletOut: false
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.$message.success('更新成功');
|
|
} else {
|
|
this.$alert(data.msg || '更新失败', '错误', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
}
|
|
}).catch(error => {
|
|
console.error('更新失败:', error);
|
|
this.$alert(error.message || '更新失败', '错误', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
});
|
|
},
|
|
|
|
// 通知入库前置校验:仅允许“外部回库”空托盘(area和location_code都为空)继续操作 - rqrq
|
|
validateNotifyInboundPalletStatus() {
|
|
const areaCode = this.palletInfo && this.palletInfo.area ? String(this.palletInfo.area).trim() : ''
|
|
const locationCode = this.palletInfo && this.palletInfo.locationCode
|
|
? String(this.palletInfo.locationCode).trim()
|
|
: (this.palletInfo && this.palletInfo.currentStationCode ? String(this.palletInfo.currentStationCode).trim() : '')
|
|
if (areaCode || locationCode) {
|
|
this.$alert('通知入库仅允许未绑定站点的空托盘', '提示', {
|
|
confirmButtonText: '确定'
|
|
})
|
|
return false
|
|
}
|
|
return true
|
|
},
|
|
|
|
// 通知入库 - rqrq
|
|
handleNotifyInbound() {
|
|
if (!this.currentPalletType) {
|
|
this.$alert('请先选择托盘类型', '提示', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
return;
|
|
}
|
|
if (!this.validateNotifyInboundPalletStatus()) {
|
|
return;
|
|
}
|
|
// 左按钮“通知入库”必须先选入库口,后端再把入库口映射为固定站点号 - rqrq
|
|
this.selectedInboundPort = '';
|
|
this.inboundPortDialogVisible = true;
|
|
},
|
|
|
|
// 关闭入库口弹窗并清理选择状态,避免上次选择串到本次提交 - rqrq
|
|
cancelInboundPortDialog() {
|
|
this.inboundPortDialogVisible = false;
|
|
this.selectedInboundPort = '';
|
|
},
|
|
|
|
// 确认通知入库:先校验入库口,再调用通知入库接口 - rqrq
|
|
confirmNotifyInbound() {
|
|
if (!this.selectedInboundPort) {
|
|
this.$alert('请选择入库口', '提示', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
return;
|
|
}
|
|
if (!this.validateNotifyInboundPalletStatus()) {
|
|
return;
|
|
}
|
|
this.inboundPortDialogVisible = false;
|
|
this.$confirm('确定要执行通知入库操作吗?', '确认操作', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
this.notifyLoading = true;
|
|
|
|
notifyEmptyPalletInbound({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
transportFlag: 'N',
|
|
count: Number(this.count),
|
|
inboundPort: this.selectedInboundPort,
|
|
}).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
this.$message.success('通知入库成功');
|
|
// 清空页面重新扫描 - rqrq
|
|
this.resetPage(true);
|
|
} else {
|
|
this.$alert(data.msg || '通知入库失败', '错误', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
}
|
|
}).catch(error => {
|
|
console.error('通知入库失败:', error);
|
|
this.$alert(error.message || '通知入库失败', '错误', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
}).finally(() => {
|
|
this.notifyLoading = false;
|
|
});
|
|
}).catch(() => {
|
|
// 用户取消操作,不提交通知入库 - rqrq
|
|
});
|
|
},
|
|
|
|
// 入库并运输 - rqrq
|
|
handleInboundAndTransport() {
|
|
if (!this.currentPalletType) {
|
|
this.$alert('请先选择托盘类型', '提示', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
return;
|
|
}
|
|
// 右按钮“入库并运输”前置校验:栈板必须绑定area,否则当前位置禁止空托入库 - rqrq
|
|
if (!this.palletInfo.area || !String(this.palletInfo.area).trim()) {
|
|
this.$alert('当前位置不允许空托入库', '提示', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
return;
|
|
}
|
|
|
|
this.$confirm('确定要执行入库并运输操作吗?', '确认操作', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
this.transportLoading = true;
|
|
|
|
notifyEmptyPalletInbound({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
transportFlag: 'Y',
|
|
count: Number(this.count),
|
|
}).then(({ data }) => {
|
|
if (data && data.code === 0) {
|
|
this.$message.success('入库并运输成功');
|
|
// 清空页面重新扫描 - rqrq
|
|
this.resetPage(true);
|
|
} else {
|
|
this.$alert(data.msg || '入库并运输失败', '错误', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
}
|
|
}).catch(error => {
|
|
console.error('入库并运输失败:', error);
|
|
this.$alert(error.message || '入库并运输失败', '错误', {
|
|
confirmButtonText: '确定'
|
|
});
|
|
}).finally(() => {
|
|
this.transportLoading = false;
|
|
});
|
|
}).catch(() => {
|
|
// 用户取消操作
|
|
});
|
|
},
|
|
|
|
// 重置页面并按需恢复扫码焦点,统一海安PDA页面生命周期清理行为 - rqrq
|
|
resetPage(needFocus) {
|
|
this.palletCode = '';
|
|
this.palletScanned = false;
|
|
this.palletInfo = {
|
|
currentStationId: '',
|
|
currentStationCode: '',
|
|
palletType: '',
|
|
area: ''
|
|
};
|
|
this.currentPalletType = '';
|
|
this.palletTypeOptions = [];
|
|
this.count = 1;
|
|
this.inboundPortDialogVisible = false;
|
|
this.selectedInboundPort = '';
|
|
|
|
if (needFocus) {
|
|
this.$nextTick(() => {
|
|
if (this.$refs.palletInput) {
|
|
this.$refs.palletInput.focus();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
},
|
|
mounted() {
|
|
this.$nextTick(() => {
|
|
if (this.$refs.palletInput) {
|
|
this.$refs.palletInput.focus();
|
|
}
|
|
});
|
|
},
|
|
activated() {
|
|
this.resetPage(true);
|
|
},
|
|
beforeRouteLeave(to, from, next) {
|
|
this.resetPage(false);
|
|
next();
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 托盘信息区域 - rqrq */
|
|
.pallet-info-section {
|
|
margin-top: 16px;
|
|
padding: 12px;
|
|
background: #f5f7fa;
|
|
border-radius: 6px;
|
|
}
|
|
|
|
.info-row {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 8px 0;
|
|
border-bottom: 1px solid #e4e7ed;
|
|
}
|
|
|
|
.info-row:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.info-label {
|
|
font-weight: bold;
|
|
color: #606266;
|
|
width: 120px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.info-value {
|
|
color: #303133;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.button-row {
|
|
margin-top: 12px;
|
|
}
|
|
</style>
|