7 changed files with 21276 additions and 0 deletions
-
20083package-lock.json
-
16src/api/automatedWarehouse/palletChangeStation.js
-
19src/api/automatedWarehouse/palletManualMove.js
-
2src/router/index.js
-
12src/views/main.vue
-
527src/views/modules/automatedWarehouse/palletChangeStation.vue
-
617src/views/modules/automatedWarehouse/palletManualMove.vue
20083
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,16 @@ |
|||
import { createAPI } from "@/utils/httpRequest.js"; |
|||
|
|||
// ========== 栈板换站相关 ========== - rqrq
|
|||
|
|||
// 检查栈板是否可以换站(判断calling_flag和获取当前站点信息)- rqrq
|
|||
export const checkPalletForChangeStation = data => createAPI(`/wcsIntegration/checkPalletForChangeStation`, 'post', data) |
|||
|
|||
// 获取可选择的区域列表(choose_able为Y)- rqrq
|
|||
export const getAreaOptionsForChange = data => createAPI(`/wcsIntegration/getAreaOptionsForChange`, 'post', data) |
|||
|
|||
// 根据区域获取可用站点列表 - rqrq
|
|||
export const getStationsByArea = data => createAPI(`/wcsIntegration/getStationsByArea`, 'post', data) |
|||
|
|||
// 提交栈板换站任务 - rqrq
|
|||
export const submitChangeStationTask = data => createAPI(`/wcsIntegration/submitChangeStationTask`, 'post', data) |
|||
|
|||
@ -0,0 +1,19 @@ |
|||
import { createAPI } from "@/utils/httpRequest.js"; |
|||
|
|||
// ========== 手工移动托盘相关 ========== - rqrq
|
|||
|
|||
// 检查托盘是否可以手工移动(判断calling_flag和站点类型)- rqrq
|
|||
export const checkPalletForManualMove = data => createAPI(`/wcsIntegration/checkPalletForManualMove`, 'post', data) |
|||
|
|||
// 移出站点 - rqrq
|
|||
export const removeFromStation = data => createAPI(`/wcsIntegration/removeFromStation`, 'post', data) |
|||
|
|||
// 获取可绑定的区域列表(choose_able为Y)- rqrq
|
|||
export const getAreaOptionsForBind = data => createAPI(`/wcsIntegration/getAreaOptionsForBind`, 'post', data) |
|||
|
|||
// 根据区域获取可绑定的站点列表 - rqrq
|
|||
export const getStationsForBind = data => createAPI(`/wcsIntegration/getStationsForBind`, 'post', data) |
|||
|
|||
// 绑定托盘到站点 - rqrq
|
|||
export const bindPalletToStation = data => createAPI(`/wcsIntegration/bindPalletToStation`, 'post', data) |
|||
|
|||
@ -0,0 +1,527 @@ |
|||
<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="$router.push({ path: '/' })"> |
|||
首页 |
|||
</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="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"> |
|||
<button class="action-btn primary" @click="showDetailModal" style="width: 100%;"> |
|||
浏览明细 ({{ detailList.length }}条) |
|||
</button> |
|||
</div> |
|||
|
|||
<!-- 选择区域和站点(只有栈板未被调用时才显示)- rqrq --> |
|||
<div v-if="palletInfo.callingFlag !== 'Y'" style="margin-top: 8px"> |
|||
<!-- 选择区域 - rqrq --> |
|||
<div class="input-group"> |
|||
<label class="input-label">选择区域</label> |
|||
<el-select |
|||
v-model="selectedArea" |
|||
placeholder="请选择区域" |
|||
style="width: 100%;" |
|||
@change="handleAreaChange" |
|||
> |
|||
<el-option |
|||
v-for="area in areaOptions" |
|||
:key="area.areaId" |
|||
:label="area.areaDesc" |
|||
:value="area.areaId" |
|||
/> |
|||
</el-select> |
|||
</div> |
|||
|
|||
<!-- 选择站点 - rqrq --> |
|||
<div class="input-group"> |
|||
<label class="input-label">选择站点</label> |
|||
<el-select |
|||
v-model="selectedStation" |
|||
placeholder="请选择站点" |
|||
style="width: 100%;" |
|||
:disabled="!selectedArea" |
|||
> |
|||
<el-option label="自动分配" value=""></el-option> |
|||
<el-option |
|||
v-for="station in stationOptions" |
|||
:key="station.stationId" |
|||
:label="`${station.stationId} (${station.stationCode})`" |
|||
:value="station.stationCode" |
|||
/> |
|||
</el-select> |
|||
</div> |
|||
|
|||
<!-- 操作按钮 - rqrq --> |
|||
<div class="button-row" style="display: flex; gap: 8px;"> |
|||
<button class="action-btn secondary" @click="handleReset" style="flex: 1;"> |
|||
重置 |
|||
</button> |
|||
<button |
|||
class="action-btn primary" |
|||
@click="handleSubmitTask" |
|||
:disabled="submitLoading" |
|||
style="flex: 1;"> |
|||
{{ submitLoading ? '下达中...' : '下达任务' }} |
|||
</button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 浏览明细弹窗 - rqrq --> |
|||
<el-dialog |
|||
:title="'栈板明细 (共'+detailList.length+'条)'" |
|||
:visible.sync="detailModalVisible" |
|||
width="90%" |
|||
:close-on-click-modal="false" |
|||
:show-close="false" |
|||
:modal="true" |
|||
:modal-append-to-body="true" |
|||
:append-to-body="true" |
|||
> |
|||
<div class="table-body" style="max-height: 400px; overflow-y: auto;"> |
|||
<div class="detail-table"> |
|||
<div class="table-header"> |
|||
<div class="col-position">位置</div> |
|||
<div class="col-layer">层数</div> |
|||
<div class="col-serial">标签号</div> |
|||
</div> |
|||
<div |
|||
v-for="(detail, index) in detailList" |
|||
:key="index" |
|||
class="table-row" |
|||
> |
|||
<div class="col-position">{{ detail.position }}</div> |
|||
<div class="col-layer">{{ detail.layer }}</div> |
|||
<div class="col-serial">{{ detail.serialNo }}</div> |
|||
</div> |
|||
<!-- 暂无数据提示 --> |
|||
<div v-if="detailList.length === 0" class="table-row empty-row"> |
|||
<div class="empty-hint">暂无栈板明细数据</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div slot="footer" class="dialog-footer"> |
|||
<button class="action-btn secondary" @click="detailModalVisible=false">关闭</button> |
|||
</div> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { |
|||
getPalletDetails |
|||
} from '../../../api/automatedWarehouse/palletPacking' |
|||
import { |
|||
checkPalletForChangeStation, |
|||
getAreaOptionsForChange, |
|||
getStationsByArea, |
|||
submitChangeStationTask |
|||
} from '../../../api/automatedWarehouse/palletChangeStation' |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
site: localStorage.getItem('site'), |
|||
|
|||
// 栈板信息 - rqrq |
|||
palletCode: '', |
|||
palletScanned: false, |
|||
palletInfo: { |
|||
callingFlag: '', |
|||
currentStationId: '', |
|||
currentStationCode: '' |
|||
}, |
|||
|
|||
// 区域和站点 - rqrq |
|||
selectedArea: '', |
|||
selectedStation: '', |
|||
areaOptions: [], |
|||
stationOptions: [], |
|||
|
|||
// 栈板明细 - rqrq |
|||
detailList: [], |
|||
detailModalVisible: false, |
|||
|
|||
// 加载状态 - rqrq |
|||
submitLoading: false |
|||
}; |
|||
}, |
|||
methods: { |
|||
// 返回上一页 - rqrq |
|||
handleBack() { |
|||
this.$router.back(); |
|||
}, |
|||
|
|||
// 扫描栈板 - rqrq |
|||
handlePalletScan() { |
|||
if (!this.palletCode.trim()) { |
|||
this.$message.error('请输入栈板编码'); |
|||
return; |
|||
} |
|||
|
|||
checkPalletForChangeStation({ |
|||
site: this.site, |
|||
palletId: this.palletCode |
|||
}).then(({ data }) => { |
|||
if (data.code === 0) { |
|||
// 如果栈板被调用,提示并清空 - rqrq |
|||
if (data.row.callingFlag === 'Y') { |
|||
this.$alert('栈板被调用,请选择其他栈板', '提示', { |
|||
confirmButtonText: '确定', |
|||
callback: () => { |
|||
this.palletCode = ''; |
|||
this.$nextTick(() => { |
|||
if (this.$refs.palletInput) { |
|||
this.$refs.palletInput.focus(); |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
// 栈板未被调用,显示信息并加载区域选项 - rqrq |
|||
this.palletInfo = data.row; |
|||
this.palletScanned = true; |
|||
|
|||
// 加载栈板明细 - rqrq |
|||
this.loadPalletDetails(); |
|||
|
|||
// 加载区域选项 - rqrq |
|||
this.loadAreaOptions(); |
|||
|
|||
} 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(); |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
}); |
|||
}, |
|||
|
|||
// 加载栈板明细 - rqrq |
|||
loadPalletDetails() { |
|||
getPalletDetails({ |
|||
site: this.site, |
|||
palletId: this.palletCode, |
|||
position: '', |
|||
layer: '' |
|||
}).then(({ data }) => { |
|||
if (data.code === 0) { |
|||
this.detailList = data.details || []; |
|||
} else { |
|||
this.detailList = []; |
|||
} |
|||
}).catch(error => { |
|||
console.error('获取栈板明细失败:', error); |
|||
this.detailList = []; |
|||
}); |
|||
}, |
|||
|
|||
// 显示明细弹窗 - rqrq |
|||
showDetailModal() { |
|||
this.detailModalVisible = true; |
|||
}, |
|||
|
|||
// 加载区域选项 - rqrq |
|||
loadAreaOptions() { |
|||
getAreaOptionsForChange({ |
|||
site: this.site |
|||
}).then(({ data }) => { |
|||
if (data.code === 0) { |
|||
this.areaOptions = data.rows || []; |
|||
} else { |
|||
this.areaOptions = []; |
|||
this.$message.error('获取区域选项失败'); |
|||
} |
|||
}).catch(error => { |
|||
console.error('获取区域选项失败:', error); |
|||
this.areaOptions = []; |
|||
}); |
|||
}, |
|||
|
|||
// 区域变化 - rqrq |
|||
handleAreaChange(areaId) { |
|||
// 清空站点选择 - rqrq |
|||
this.selectedStation = ''; |
|||
this.stationOptions = []; |
|||
|
|||
if (!areaId) { |
|||
return; |
|||
} |
|||
|
|||
// 加载站点选项 - rqrq |
|||
getStationsByArea({ |
|||
site: this.site, |
|||
areaId: areaId |
|||
}).then(({ data }) => { |
|||
if (data.code === 0) { |
|||
this.stationOptions = data.rows || []; |
|||
} else { |
|||
this.stationOptions = []; |
|||
this.$message.error('获取站点选项失败'); |
|||
} |
|||
}).catch(error => { |
|||
console.error('获取站点选项失败:', error); |
|||
this.stationOptions = []; |
|||
}); |
|||
}, |
|||
|
|||
// 重置 - rqrq |
|||
handleReset() { |
|||
this.palletCode = ''; |
|||
this.palletScanned = false; |
|||
this.palletInfo = { |
|||
callingFlag: '', |
|||
currentStationId: '', |
|||
currentStationCode: '' |
|||
}; |
|||
this.selectedArea = ''; |
|||
this.selectedStation = ''; |
|||
this.areaOptions = []; |
|||
this.stationOptions = []; |
|||
this.detailList = []; |
|||
this.detailModalVisible = false; |
|||
|
|||
// 聚焦到栈板输入框 - rqrq |
|||
this.$nextTick(() => { |
|||
if (this.$refs.palletInput) { |
|||
this.$refs.palletInput.focus(); |
|||
} |
|||
}); |
|||
}, |
|||
|
|||
// 下达任务 - rqrq |
|||
handleSubmitTask() { |
|||
// 校验当前站点编码 - rqrq |
|||
if (!this.palletInfo.currentStationCode) { |
|||
this.$message.error('当前站点编码不能为空'); |
|||
return; |
|||
} |
|||
|
|||
// 校验选择区域 - rqrq |
|||
if (!this.selectedArea) { |
|||
this.$message.error('请选择目标区域'); |
|||
return; |
|||
} |
|||
|
|||
this.submitLoading = true; |
|||
|
|||
const params = { |
|||
site: this.site, |
|||
palletId: this.palletCode, |
|||
startStation: this.palletInfo.currentStationCode, |
|||
targetArea: this.selectedArea, |
|||
targetStation: this.selectedStation || '' // 空表示自动分配 - rqrq |
|||
}; |
|||
this.$confirm('确定下达任务?', '提示', { |
|||
confirmButtonText: '确认', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
submitChangeStationTask(params).then(({data}) => { |
|||
if (data && data.code === 0) { |
|||
this.$message.success('任务下达成功'); |
|||
// 重置页面 - rqrq |
|||
this.handleReset(); |
|||
} else { |
|||
this.$alert(data.msg || '任务下达失败', '错误', { |
|||
confirmButtonText: '确定' |
|||
}); |
|||
} |
|||
}).catch(error => { |
|||
console.error('任务下达失败:', error); |
|||
this.$message.error(error.message || '任务下达失败'); |
|||
}).finally(() => { |
|||
this.submitLoading = false; |
|||
}); |
|||
}) |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.$nextTick(() => { |
|||
if (this.$refs.palletInput) { |
|||
this.$refs.palletInput.focus(); |
|||
} |
|||
}); |
|||
} |
|||
}; |
|||
</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; |
|||
} |
|||
|
|||
/* 表格样式 - rqrq */ |
|||
.detail-table { |
|||
background: white; |
|||
border-radius: 6px; |
|||
overflow: hidden; |
|||
border: 1px solid #e0e0e0; |
|||
} |
|||
|
|||
.table-header, |
|||
.table-row { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 8px; |
|||
border-bottom: 1px solid #e0e0e0; |
|||
} |
|||
|
|||
.table-header { |
|||
background: #f5f5f5; |
|||
font-weight: bold; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.table-row { |
|||
font-size: 13px; |
|||
} |
|||
|
|||
.table-row:last-child { |
|||
border-bottom: none; |
|||
} |
|||
|
|||
.col-position { |
|||
flex: 1; |
|||
text-align: center; |
|||
} |
|||
|
|||
.col-layer { |
|||
flex: 1; |
|||
text-align: center; |
|||
} |
|||
|
|||
.col-serial { |
|||
flex: 4; |
|||
text-align: center; |
|||
word-break: break-all; |
|||
} |
|||
|
|||
/* 空数据提示 - rqrq */ |
|||
.empty-hint { |
|||
text-align: center; |
|||
color: #999; |
|||
padding: 20px; |
|||
background: white; |
|||
border-radius: 6px; |
|||
} |
|||
|
|||
.dialog-footer { |
|||
text-align: center; |
|||
} |
|||
|
|||
/* 修复模态框层级问题 - rqrq */ |
|||
::v-deep .el-dialog__wrapper { |
|||
z-index: 2000 !important; |
|||
} |
|||
|
|||
::v-deep .el-overlay { |
|||
z-index: 2000 !important; |
|||
} |
|||
|
|||
/* 空数据行样式 - rqrq */ |
|||
.empty-row { |
|||
justify-content: center; |
|||
align-items: center; |
|||
padding: 20px; |
|||
border-bottom: none; |
|||
} |
|||
|
|||
.empty-row .empty-hint { |
|||
text-align: center; |
|||
color: #999; |
|||
width: 100%; |
|||
} |
|||
</style> |
|||
|
|||
@ -0,0 +1,617 @@ |
|||
<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="$router.push({ path: '/' })"> |
|||
首页 |
|||
</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"> |
|||
|
|||
<div class="info-row"> |
|||
<label class="info-label">当前站点ID:</label> |
|||
<span class="info-value">{{ palletInfo.currentStationId || '-' }}</span> |
|||
</div> |
|||
|
|||
<!-- 当前站点信息 - rqrq --> |
|||
<div class="info-row"> |
|||
<label class="info-label">当前站点编码:</label> |
|||
<span class="info-value">{{ palletInfo.currentStationCode || '未绑定站点' }}</span> |
|||
</div> |
|||
|
|||
<!-- 浏览明细按钮 - rqrq --> |
|||
<div class="button-row"> |
|||
<button class="action-btn primary" @click="showDetailModal" style="width: 100%;"> |
|||
浏览明细 ({{ detailList.length }}条) |
|||
</button> |
|||
</div> |
|||
|
|||
<!-- 操作按钮(只有托盘未被调用且站点可操作时才显示)- rqrq --> |
|||
<div v-if="palletInfo.callingFlag !== 'Y' && palletInfo.canOperate"> |
|||
<!-- 有站点:显示移出站点按钮 - rqrq --> |
|||
<div v-if="palletInfo.currentStationCode" class="button-row"> |
|||
<button |
|||
class="action-btn primary" |
|||
@click="handleRemoveFromStation" |
|||
:disabled="removeLoading" |
|||
style="width: 100%;"> |
|||
{{ removeLoading ? '移出中...' : '移出站点' }} |
|||
</button> |
|||
</div> |
|||
|
|||
<!-- 无站点:显示绑定站点按钮 - rqrq --> |
|||
<div v-if="!palletInfo.currentStationCode" class="button-row"> |
|||
<button |
|||
class="action-btn primary" |
|||
@click="showBindStationDialog" |
|||
style="width: 100%;"> |
|||
绑定站点 |
|||
</button> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 不可操作提示 - rqrq --> |
|||
<div v-if="!palletInfo.canOperate" class="warning-hint"> |
|||
当前站点位置不可变更 |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 浏览明细弹窗 - rqrq --> |
|||
<el-dialog |
|||
:title="'托盘明细 (共'+detailList.length+'条)'" |
|||
:visible.sync="detailModalVisible" |
|||
width="90%" |
|||
:close-on-click-modal="false" |
|||
:show-close="false" |
|||
:modal="true" |
|||
:modal-append-to-body="true" |
|||
:append-to-body="true" |
|||
> |
|||
<div class="table-body" style="max-height: 400px; overflow-y: auto;"> |
|||
<div class="detail-table"> |
|||
<div class="table-header"> |
|||
<div class="col-position">位置</div> |
|||
<div class="col-layer">层数</div> |
|||
<div class="col-serial">标签号</div> |
|||
</div> |
|||
<div |
|||
v-for="(detail, index) in detailList" |
|||
:key="index" |
|||
class="table-row" |
|||
> |
|||
<div class="col-position">{{ detail.position }}</div> |
|||
<div class="col-layer">{{ detail.layer }}</div> |
|||
<div class="col-serial">{{ detail.serialNo }}</div> |
|||
</div> |
|||
<!-- 暂无数据提示 --> |
|||
<div v-if="detailList.length === 0" class="table-row empty-row"> |
|||
<div class="empty-hint">暂无托盘明细数据</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div slot="footer" class="dialog-footer"> |
|||
<button class="action-btn secondary" @click="detailModalVisible=false">关闭</button> |
|||
</div> |
|||
</el-dialog> |
|||
|
|||
<!-- 绑定站点弹窗 - rqrq --> |
|||
<el-dialog |
|||
title="绑定站点" |
|||
:visible.sync="bindDialogVisible" |
|||
width="90%" |
|||
:close-on-click-modal="false" |
|||
:show-close="false" |
|||
:modal="true" |
|||
:modal-append-to-body="true" |
|||
:append-to-body="true" |
|||
> |
|||
<div class="bind-dialog-content"> |
|||
<!-- 选择区域 - rqrq --> |
|||
<div class="input-group"> |
|||
<label class="input-label">选择区域 <span style="color: red;">*</span></label> |
|||
<el-select |
|||
v-model="selectedArea" |
|||
placeholder="请选择区域" |
|||
style="width: 100%;" |
|||
@change="handleAreaChange" |
|||
> |
|||
<el-option |
|||
v-for="area in areaOptions" |
|||
:key="area.areaId" |
|||
:label="area.areaDesc" |
|||
:value="area.areaId" |
|||
/> |
|||
</el-select> |
|||
</div> |
|||
|
|||
<!-- 选择站点(必须选择具体站点,无自动分配)- rqrq --> |
|||
<div class="input-group"> |
|||
<label class="input-label">选择站点 <span style="color: red;">*</span></label> |
|||
<el-select |
|||
v-model="selectedStation" |
|||
placeholder="请选择站点" |
|||
style="width: 100%;" |
|||
:disabled="!selectedArea" |
|||
> |
|||
<el-option |
|||
v-for="station in stationOptions" |
|||
:key="station.stationId" |
|||
:label="`${station.stationId} (${station.stationCode})`" |
|||
:value="station.stationCode" |
|||
/> |
|||
</el-select> |
|||
</div> |
|||
</div> |
|||
|
|||
<div slot="footer" class="dialog-footer"> |
|||
<button |
|||
class="action-btn primary" |
|||
@click="confirmBindStation" |
|||
:disabled="bindLoading" |
|||
style="flex: 1; margin-right: 8px;"> |
|||
{{ bindLoading ? '绑定中...' : '确定' }} |
|||
</button> |
|||
<button |
|||
class="action-btn secondary" |
|||
@click="closeBindDialog" |
|||
:disabled="bindLoading" |
|||
style="flex: 1;"> |
|||
取消 |
|||
</button> |
|||
</div> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { |
|||
getPalletDetails |
|||
} from '../../../api/automatedWarehouse/palletPacking' |
|||
import { |
|||
checkPalletForManualMove, |
|||
removeFromStation, |
|||
getAreaOptionsForBind, |
|||
getStationsForBind, |
|||
bindPalletToStation |
|||
} from '../../../api/automatedWarehouse/palletManualMove' |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
site: localStorage.getItem('site'), |
|||
|
|||
// 托盘信息 - rqrq |
|||
palletCode: '', |
|||
palletScanned: false, |
|||
palletInfo: { |
|||
callingFlag: '', |
|||
currentStationCode: '', |
|||
currentStationId: '', |
|||
stationType: '', |
|||
canOperate: false |
|||
}, |
|||
|
|||
// 绑定站点弹窗 - rqrq |
|||
bindDialogVisible: false, |
|||
selectedArea: '', |
|||
selectedStation: '', |
|||
areaOptions: [], |
|||
stationOptions: [], |
|||
|
|||
// 托盘明细 - rqrq |
|||
detailList: [], |
|||
detailModalVisible: false, |
|||
|
|||
// 加载状态 - rqrq |
|||
removeLoading: false, |
|||
bindLoading: false |
|||
}; |
|||
}, |
|||
methods: { |
|||
// 返回上一页 - rqrq |
|||
handleBack() { |
|||
this.$router.back(); |
|||
}, |
|||
|
|||
// 扫描托盘 - rqrq |
|||
handlePalletScan() { |
|||
if (!this.palletCode.trim()) { |
|||
this.$message.error('请输入托盘编码'); |
|||
return; |
|||
} |
|||
|
|||
checkPalletForManualMove({ |
|||
site: this.site, |
|||
palletId: this.palletCode |
|||
}).then(({ data }) => { |
|||
if (data.code === 0) { |
|||
// 如果托盘被调用,提示用户 - rqrq |
|||
if (data.row.callingFlag === 'Y') { |
|||
this.$alert('托盘被调用,无法进行移动操作', '提示', { |
|||
confirmButtonText: '确定', |
|||
callback: () => { |
|||
this.palletCode = ''; |
|||
this.$nextTick(() => { |
|||
if (this.$refs.palletInput) { |
|||
this.$refs.palletInput.focus(); |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
// 托盘未被调用,显示信息 - rqrq |
|||
this.palletInfo = data.row; |
|||
this.palletScanned = true; |
|||
|
|||
// 加载托盘明细 - rqrq |
|||
this.loadPalletDetails(); |
|||
|
|||
} 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(); |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
}); |
|||
}, |
|||
|
|||
// 加载托盘明细 - rqrq |
|||
loadPalletDetails() { |
|||
getPalletDetails({ |
|||
site: this.site, |
|||
palletId: this.palletCode, |
|||
position: '', |
|||
layer: '' |
|||
}).then(({ data }) => { |
|||
if (data.code === 0) { |
|||
this.detailList = data.details || []; |
|||
} else { |
|||
this.detailList = []; |
|||
} |
|||
}).catch(error => { |
|||
console.error('获取托盘明细失败:', error); |
|||
this.detailList = []; |
|||
}); |
|||
}, |
|||
|
|||
// 显示明细弹窗 - rqrq |
|||
showDetailModal() { |
|||
this.detailModalVisible = true; |
|||
}, |
|||
|
|||
// 移出站点 - rqrq |
|||
handleRemoveFromStation() { |
|||
this.$confirm('确定要将托盘从当前站点移出吗?', '确认操作', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
this.removeLoading = true; |
|||
|
|||
removeFromStation({ |
|||
site: this.site, |
|||
palletId: this.palletCode, |
|||
stationCode: this.palletInfo.currentStationCode |
|||
}).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
this.$message.success('移出站点成功'); |
|||
// 重新扫描刷新信息 - rqrq |
|||
this.handlePalletScan(); |
|||
} else { |
|||
this.$alert(data.msg || '移出站点失败', '错误'); |
|||
} |
|||
}).catch(error => { |
|||
console.error('移出站点失败:', error); |
|||
this.$message.error(error.message || '移出站点失败'); |
|||
}).finally(() => { |
|||
this.removeLoading = false; |
|||
}); |
|||
}).catch(() => { |
|||
// 用户取消操作 |
|||
}); |
|||
}, |
|||
|
|||
// 显示绑定站点弹窗 - rqrq |
|||
showBindStationDialog() { |
|||
this.bindDialogVisible = true; |
|||
this.selectedArea = ''; |
|||
this.selectedStation = ''; |
|||
this.areaOptions = []; |
|||
this.stationOptions = []; |
|||
|
|||
// 加载区域选项 - rqrq |
|||
this.loadAreaOptions(); |
|||
}, |
|||
|
|||
// 关闭绑定站点弹窗 - rqrq |
|||
closeBindDialog() { |
|||
this.bindDialogVisible = false; |
|||
this.selectedArea = ''; |
|||
this.selectedStation = ''; |
|||
this.areaOptions = []; |
|||
this.stationOptions = []; |
|||
}, |
|||
|
|||
// 加载区域选项 - rqrq |
|||
loadAreaOptions() { |
|||
getAreaOptionsForBind({ |
|||
site: this.site |
|||
}).then(({ data }) => { |
|||
if (data.code === 0) { |
|||
this.areaOptions = data.rows || []; |
|||
} else { |
|||
this.areaOptions = []; |
|||
this.$message.error('获取区域选项失败'); |
|||
} |
|||
}).catch(error => { |
|||
console.error('获取区域选项失败:', error); |
|||
this.areaOptions = []; |
|||
}); |
|||
}, |
|||
|
|||
// 区域变化 - rqrq |
|||
handleAreaChange(areaId) { |
|||
// 清空站点选择 - rqrq |
|||
this.selectedStation = ''; |
|||
this.stationOptions = []; |
|||
|
|||
if (!areaId) { |
|||
return; |
|||
} |
|||
|
|||
// 加载站点选项 - rqrq |
|||
getStationsForBind({ |
|||
site: this.site, |
|||
areaId: areaId |
|||
}).then(({ data }) => { |
|||
if (data.code === 0) { |
|||
this.stationOptions = data.rows || []; |
|||
} else { |
|||
this.stationOptions = []; |
|||
this.$message.error('获取站点选项失败'); |
|||
} |
|||
}).catch(error => { |
|||
console.error('获取站点选项失败:', error); |
|||
this.stationOptions = []; |
|||
}); |
|||
}, |
|||
|
|||
// 确认绑定站点 - rqrq |
|||
confirmBindStation() { |
|||
// 校验必填项 - rqrq |
|||
if (!this.selectedArea) { |
|||
this.$message.error('请选择区域'); |
|||
return; |
|||
} |
|||
if (!this.selectedStation) { |
|||
this.$message.error('请选择站点'); |
|||
return; |
|||
} |
|||
|
|||
// 二次确认 - rqrq |
|||
this.$confirm('确定要将托盘绑定到选中的站点吗?', '确认操作', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
this.bindLoading = true; |
|||
|
|||
bindPalletToStation({ |
|||
site: this.site, |
|||
palletId: this.palletCode, |
|||
stationCode: this.selectedStation |
|||
}).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
this.$message.success('绑定站点成功'); |
|||
this.closeBindDialog(); |
|||
// 重新扫描刷新信息 - rqrq |
|||
this.handlePalletScan(); |
|||
} else { |
|||
this.$alert(data.msg || '绑定站点失败', '错误'); |
|||
} |
|||
}).catch(error => { |
|||
console.error('绑定站点失败:', error); |
|||
this.$message.error(error.message || '绑定站点失败'); |
|||
}).finally(() => { |
|||
this.bindLoading = false; |
|||
}); |
|||
}).catch(() => { |
|||
// 用户取消操作 |
|||
}); |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.$nextTick(() => { |
|||
if (this.$refs.palletInput) { |
|||
this.$refs.palletInput.focus(); |
|||
} |
|||
}); |
|||
} |
|||
}; |
|||
</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: 100px; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.info-value { |
|||
color: #303133; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.button-row { |
|||
margin-top: 12px; |
|||
} |
|||
|
|||
/* 警告提示 - rqrq */ |
|||
.warning-hint { |
|||
margin-top: 12px; |
|||
padding: 10px; |
|||
background: #fff3cd; |
|||
color: #856404; |
|||
border: 1px solid #ffeaa7; |
|||
border-radius: 4px; |
|||
text-align: center; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
/* 绑定弹窗内容 - rqrq */ |
|||
.bind-dialog-content { |
|||
padding: 10px 0; |
|||
} |
|||
|
|||
/* 表格样式 - rqrq */ |
|||
.detail-table { |
|||
background: white; |
|||
border-radius: 6px; |
|||
overflow: hidden; |
|||
border: 1px solid #e0e0e0; |
|||
} |
|||
|
|||
.table-header, |
|||
.table-row { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 8px; |
|||
border-bottom: 1px solid #e0e0e0; |
|||
} |
|||
|
|||
.table-header { |
|||
background: #f5f5f5; |
|||
font-weight: bold; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.table-row { |
|||
font-size: 13px; |
|||
} |
|||
|
|||
.table-row:last-child { |
|||
border-bottom: none; |
|||
} |
|||
|
|||
.col-position { |
|||
flex: 1; |
|||
text-align: center; |
|||
} |
|||
|
|||
.col-layer { |
|||
flex: 1; |
|||
text-align: center; |
|||
} |
|||
|
|||
.col-serial { |
|||
flex: 4; |
|||
text-align: center; |
|||
word-break: break-all; |
|||
} |
|||
|
|||
/* 空数据提示 - rqrq */ |
|||
.empty-hint { |
|||
text-align: center; |
|||
color: #999; |
|||
padding: 20px; |
|||
background: white; |
|||
border-radius: 6px; |
|||
} |
|||
|
|||
/* 空数据行样式 - rqrq */ |
|||
.empty-row { |
|||
justify-content: center; |
|||
align-items: center; |
|||
padding: 20px; |
|||
border-bottom: none; |
|||
} |
|||
|
|||
.empty-row .empty-hint { |
|||
text-align: center; |
|||
color: #999; |
|||
width: 100%; |
|||
} |
|||
|
|||
.dialog-footer { |
|||
display: flex; |
|||
gap: 8px; |
|||
text-align: center; |
|||
} |
|||
|
|||
/* 修复模态框层级问题 - rqrq */ |
|||
::v-deep .el-dialog__wrapper { |
|||
z-index: 2000 !important; |
|||
} |
|||
|
|||
::v-deep .el-overlay { |
|||
z-index: 2000 !important; |
|||
} |
|||
</style> |
|||
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue