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.
997 lines
28 KiB
997 lines
28 KiB
<template>
|
|
<div>
|
|
<div class="pda-container">
|
|
<!-- 头部栏 -->
|
|
<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="main-content form-section">
|
|
<!-- 第一行:栈板扫描 -->
|
|
<div class="input-group">
|
|
<label class="input-label">栈板编码</label>
|
|
<div style="display: flex; gap: 8px;">
|
|
<el-input
|
|
v-model="palletCode"
|
|
placeholder="请扫描栈板编码"
|
|
class="form-input"
|
|
style="flex: 0.75;"
|
|
clearable
|
|
@keyup.enter.native="handlePalletScan"
|
|
ref="palletInput"
|
|
/>
|
|
<button
|
|
class="action-btn secondary"
|
|
style="flex: 0.25; margin: 0;"
|
|
@click="handleCallPallet"
|
|
>
|
|
Call栈板
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 第二行:筛选条件 (扫描栈板后显示) -->
|
|
<div v-if="palletScanned" class="input-group">
|
|
<div style="display: flex; gap: 8px; align-items: end;">
|
|
<div style="flex: 1;">
|
|
<label class="input-label">位置</label>
|
|
<el-select
|
|
v-model="selectedPosition"
|
|
placeholder="请选择位置"
|
|
style="width: 100%;"
|
|
@change="handlePositionChange"
|
|
>
|
|
<el-option label="ALL" value=""></el-option>
|
|
<el-option
|
|
v-for="position in positionOptions"
|
|
:key="position"
|
|
:label="position"
|
|
:value="position"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
<div style="flex: 1;">
|
|
<label class="input-label">层数</label>
|
|
<el-select
|
|
v-model="selectedLayer"
|
|
placeholder="请选择层数"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option label="ALL" value=""></el-option>
|
|
<el-option
|
|
v-for="layer in layerOptions"
|
|
:key="layer"
|
|
:label="`第${layer}层`"
|
|
:value="layer"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
<button
|
|
class="action-btn secondary"
|
|
style="margin: 0; white-space: nowrap;"
|
|
@click="refreshTable"
|
|
>
|
|
刷新
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 第三行:扫进/扫出选择 (扫描栈板后显示) -->
|
|
<div v-if="palletScanned" class="input-group">
|
|
<div style="display: flex; gap: 8px; align-items: center; flex-wrap: nowrap;">
|
|
<div style="flex: 1; min-width: 0;">
|
|
<el-radio-group v-model="operationType" style="display: flex; flex-wrap: nowrap;">
|
|
<el-radio label="in" style="margin-right: 0px; white-space: nowrap;">扫进</el-radio>
|
|
<el-radio label="out" style="white-space: nowrap;">扫出</el-radio>
|
|
</el-radio-group>
|
|
</div>
|
|
<button
|
|
class="action-btn secondary"
|
|
style="margin: 0; white-space: nowrap; flex-shrink: 0;"
|
|
@click="showScanModal"
|
|
>
|
|
扫描二维码
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 栈板明细表格 (扫描栈板后显示) -->
|
|
<div v-if="palletScanned" class="rma-list">
|
|
<div class="list-title-row">
|
|
<div class="list-title">栈板明细</div>
|
|
<button class="action-btn secondary" style="margin-left: 10px;" @click="handleTransportOrder">运输指令</button>
|
|
</div>
|
|
<div class="detail-table">
|
|
<div class="table-header">
|
|
<div class="col-position">位置</div>
|
|
<div class="col-layer">层数</div>
|
|
<div class="col-serial">标签号</div>
|
|
<div class="col-part">物料编码</div>
|
|
</div>
|
|
<div
|
|
v-for="(detail, index) in detailList"
|
|
:key="index"
|
|
class="table-row"
|
|
@click="handleRowDblClick(detail, index)"
|
|
>
|
|
<div class="col-position">{{ detail.position }}</div>
|
|
<div class="col-layer">{{ detail.layer }}</div>
|
|
<div class="col-serial">{{ detail.serialNo }}</div>
|
|
<div class="col-part">{{ detail.partNo }}</div>
|
|
</div>
|
|
<!-- 暂无数据提示 -->
|
|
<div v-if="detailList.length === 0" class="table-row empty-row">
|
|
<div class="empty-hint">暂无栈板明细数据</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 扫码模态框 -->
|
|
<el-dialog
|
|
title="扫描标签"
|
|
:visible.sync="scanModalVisible"
|
|
width="90%"
|
|
:close-on-click-modal="false"
|
|
:show-close="false"
|
|
:modal="true"
|
|
:modal-append-to-body="true"
|
|
:append-to-body="true"
|
|
>
|
|
<div class="scan-modal-content">
|
|
<!-- 扫进时显示位置和层数选择 -->
|
|
<div v-if="operationType === 'in'" class="modal-form">
|
|
<div class="input-group">
|
|
<label class="input-label">位置</label>
|
|
<el-select
|
|
v-model="scanPosition"
|
|
placeholder="请选择位置"
|
|
style="width: 100%;"
|
|
@change="handleScanPositionChange"
|
|
>
|
|
<el-option
|
|
v-for="position in positionOptions"
|
|
:key="position"
|
|
:label="position"
|
|
:value="position"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
<div class="input-group">
|
|
<label class="input-label">层数</label>
|
|
<el-select
|
|
v-model="scanLayer"
|
|
placeholder="请选择层数"
|
|
@change="moveFocusToScanInput"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option
|
|
v-for="layer in scanLayerOptions"
|
|
:key="layer"
|
|
:label="`第${layer}层`"
|
|
:value="layer"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 标签扫描 -->
|
|
<div class="input-group">
|
|
<label class="input-label">标签二维码</label>
|
|
<el-input
|
|
v-model="scanCode"
|
|
placeholder="请扫描标签二维码"
|
|
class="form-input"
|
|
clearable
|
|
@keyup.enter.native="handleLabelScan"
|
|
ref="scanInput"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
<button class="action-btn secondary" style="margin-left: 10px;" @click="closeScanModal">取消</button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<!-- 修改位置模态框 -->
|
|
<el-dialog
|
|
title="修改标签位置"
|
|
:visible.sync="editPositionModalVisible"
|
|
width="90%"
|
|
:close-on-click-modal="false"
|
|
:show-close="false"
|
|
:modal="true"
|
|
:modal-append-to-body="true"
|
|
:append-to-body="true"
|
|
>
|
|
<div class="edit-modal-content">
|
|
<!-- 标签号(只读) -->
|
|
<div class="input-group">
|
|
<label class="input-label">标签号</label>
|
|
<el-input
|
|
v-model="editSerialNo"
|
|
placeholder="标签号"
|
|
class="form-input"
|
|
readonly
|
|
/>
|
|
</div>
|
|
|
|
<!-- 位置选择 -->
|
|
<div class="input-group">
|
|
<label class="input-label">位置</label>
|
|
<el-select
|
|
v-model="editPosition"
|
|
placeholder="请选择位置"
|
|
style="width: 100%;"
|
|
@change="handleEditPositionChange"
|
|
>
|
|
<el-option
|
|
v-for="position in positionOptions"
|
|
:key="position"
|
|
:label="position"
|
|
:value="position"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
|
|
<!-- 层数选择 -->
|
|
<div class="input-group">
|
|
<label class="input-label">层数</label>
|
|
<el-select
|
|
v-model="editLayer"
|
|
placeholder="请选择层数"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option
|
|
v-for="layer in editLayerOptions"
|
|
:key="layer"
|
|
:label="`第${layer}层`"
|
|
:value="layer"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
</div>
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
<button class="action-btn primary" @click="confirmEditPosition">确定</button>
|
|
<button class="action-btn secondary" style="margin-left: 10px;" @click="closeEditPositionModal">取消</button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<!-- 运输任务模态框 -->
|
|
<el-dialog
|
|
title="创建运输任务"
|
|
:visible.sync="transportModalVisible"
|
|
width="90%"
|
|
:close-on-click-modal="false"
|
|
:show-close="false"
|
|
:modal="true"
|
|
:modal-append-to-body="true"
|
|
:append-to-body="true"
|
|
>
|
|
<div class="transport-modal-content">
|
|
<!-- 栈板号(只读) -->
|
|
<div class="input-group">
|
|
<label class="input-label">栈板号</label>
|
|
<el-input
|
|
v-model="palletCode"
|
|
placeholder="栈板号"
|
|
class="form-input"
|
|
readonly
|
|
/>
|
|
</div>
|
|
|
|
<!-- 起点站点显示(只读,从栈板位置自动获取) -->
|
|
<div class="input-group">
|
|
<label class="input-label">起点站点</label>
|
|
<el-input
|
|
v-model="currentPalletStation"
|
|
placeholder="当前栈板位置"
|
|
class="form-input"
|
|
readonly
|
|
/>
|
|
</div>
|
|
|
|
<!-- 目标站点选择 -->
|
|
<div class="input-group">
|
|
<label class="input-label">目标站点</label>
|
|
<el-select
|
|
v-model="selectedTargetStation"
|
|
placeholder="请选择目标站点"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option
|
|
v-for="station in transportStationOptions"
|
|
:key="station.stationCode"
|
|
:label="`${station.stationCode} - ${station.stationName}`"
|
|
:value="station.stationCode"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
</div>
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
<button class="action-btn primary" @click="confirmTransportTask">确定</button>
|
|
<button class="action-btn secondary" style="margin-left: 10px;" @click="closeTransportModal">取消</button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<!-- Call栈板模态框 -->
|
|
<el-dialog
|
|
title="调用空托盘"
|
|
:visible.sync="callPalletModalVisible"
|
|
width="90%"
|
|
:close-on-click-modal="false"
|
|
:show-close="false"
|
|
:modal="true"
|
|
:modal-append-to-body="true"
|
|
:append-to-body="true"
|
|
>
|
|
<div class="call-modal-content">
|
|
<!-- 起始站点选择 -->
|
|
<div class="input-group">
|
|
<label class="input-label">起始站点</label>
|
|
<el-select
|
|
v-model="selectedCallStartStation"
|
|
placeholder="请选择起始站点"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option
|
|
v-for="station in callStationOptions"
|
|
:key="station.stationCode"
|
|
:label="`${station.stationCode} - ${station.stationName}`"
|
|
:value="station.stationCode"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
|
|
<!-- 目标站点选择 -->
|
|
<div class="input-group">
|
|
<label class="input-label">目标站点</label>
|
|
<el-select
|
|
v-model="selectedCallTargetStation"
|
|
placeholder="请选择目标站点"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option
|
|
v-for="station in callStationOptions"
|
|
:key="station.stationCode"
|
|
:label="`${station.stationCode} - ${station.stationName}`"
|
|
:value="station.stationCode"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
</div>
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
<button class="action-btn primary" @click="confirmCallPallet">确定</button>
|
|
<button class="action-btn secondary" style="margin-left: 10px;" @click="closeCallPalletModal">取消</button>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
checkPalletExists,
|
|
getPalletPositions,
|
|
getPalletDetails,
|
|
getLayersByPosition,
|
|
validateLabel,
|
|
savePalletDetail,
|
|
deletePalletDetail,
|
|
getLayersForEdit,
|
|
updatePalletDetailPosition,
|
|
getAgvStations,
|
|
callPalletToStation,
|
|
callPalletToStationWithUpdateZuPan
|
|
} from '../../../api/automatedWarehouse/palletPacking'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
site: localStorage.getItem('site'),
|
|
palletCode: '',
|
|
palletScanned: false,
|
|
operationType: 'in', // 'in' 或 'out'
|
|
|
|
// 筛选条件
|
|
selectedPosition: '',
|
|
selectedLayer: '',
|
|
positionOptions: [],
|
|
layerOptions: [],
|
|
|
|
// 扫码模态框
|
|
scanModalVisible: false,
|
|
scanCode: '',
|
|
scanPosition: '',
|
|
scanLayer: '',
|
|
scanLayerOptions: [],
|
|
needRefreshOnClose: false, // 标记是否需要在关闭模态框时刷新
|
|
|
|
// 栈板明细
|
|
detailList: [],
|
|
|
|
// 运输任务模态框
|
|
transportModalVisible: false,
|
|
transportStationOptions: [],
|
|
currentPalletStation: '',
|
|
selectedTargetStation: '',
|
|
|
|
// Call栈板模态框
|
|
callPalletModalVisible: false,
|
|
callStationOptions: [],
|
|
selectedCallStartStation: '',
|
|
selectedCallTargetStation: '',
|
|
|
|
// 修改位置模态框
|
|
editPositionModalVisible: false,
|
|
editSerialNo: '',
|
|
editPosition: '',
|
|
editLayer: '',
|
|
editLayerOptions: [],
|
|
editOriginalPosition: '',
|
|
editOriginalLayer: '',
|
|
};
|
|
},
|
|
methods: {
|
|
handleBack() {
|
|
this.$router.back();
|
|
},
|
|
|
|
// 扫描栈板
|
|
handlePalletScan() {
|
|
if (!this.palletCode.trim()) {
|
|
this.$message.error('请输入栈板编码');
|
|
return;
|
|
}
|
|
|
|
checkPalletExists({
|
|
site: this.site,
|
|
palletId: this.palletCode
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.palletScanned = true;
|
|
this.positionOptions = data.positions || [];
|
|
this.refreshTable();
|
|
} else {
|
|
this.$message.error(data.msg || '栈板不存在');
|
|
}
|
|
}).catch(error => {
|
|
console.error('验证栈板失败:', error);
|
|
this.$message.error('验证栈板失败');
|
|
});
|
|
},
|
|
|
|
// Call栈板 - 调用空托盘
|
|
handleCallPallet() {
|
|
this.callPalletModalVisible = true;
|
|
this.selectedCallStartStation = '';
|
|
this.selectedCallTargetStation = '';
|
|
|
|
// 获取AGV站点列表
|
|
getAgvStations({}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.callStationOptions = data.stations || [];
|
|
} else {
|
|
this.$message.error(data.msg || '获取站点列表失败');
|
|
}
|
|
}).catch(error => {
|
|
console.error('获取站点列表失败:', error);
|
|
this.$message.error('获取站点列表失败');
|
|
});
|
|
},
|
|
|
|
// 位置选择变化
|
|
handlePositionChange() {
|
|
if (this.selectedPosition) {
|
|
getLayersByPosition({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
position: this.selectedPosition
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.layerOptions = data.layers || [];
|
|
}
|
|
}).catch(error => {
|
|
console.error('获取层数失败:', error);
|
|
});
|
|
} else {
|
|
this.layerOptions = [];
|
|
}
|
|
this.selectedLayer = '';
|
|
},
|
|
|
|
// 刷新表格
|
|
refreshTable() {
|
|
getPalletDetails({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
position: this.selectedPosition,
|
|
layer: this.selectedLayer
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.detailList = data.details || [];
|
|
} else {
|
|
this.detailList = [];
|
|
}
|
|
}).catch(error => {
|
|
console.error('获取栈板明细失败:', error);
|
|
this.detailList = [];
|
|
});
|
|
},
|
|
|
|
// 显示扫码模态框
|
|
showScanModal() {
|
|
this.scanModalVisible = true;
|
|
this.scanCode = '';
|
|
this.scanPosition = '';
|
|
this.scanLayer = '';
|
|
this.scanLayerOptions = [];
|
|
this.needRefreshOnClose = false; // 重置刷新标记
|
|
|
|
this.$nextTick(() => {
|
|
if (this.$refs.scanInput) {
|
|
this.$refs.scanInput.focus();
|
|
}
|
|
});
|
|
},
|
|
moveFocusToScanInput(){
|
|
this.$nextTick(() => {
|
|
if (this.$refs.scanInput) {
|
|
this.$refs.scanInput.focus();
|
|
}
|
|
});
|
|
},
|
|
// 关闭扫码模态框
|
|
closeScanModal() {
|
|
this.scanModalVisible = false;
|
|
// 如果有操作成功,则在关闭时刷新外面的列表
|
|
if (this.needRefreshOnClose) {
|
|
this.refreshTable();
|
|
this.needRefreshOnClose = false;
|
|
}
|
|
},
|
|
|
|
// 扫码模态框中位置变化
|
|
handleScanPositionChange() {
|
|
if (this.scanPosition) {
|
|
getLayersByPosition({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
position: this.scanPosition
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
const maxLayer = data.layers && data.layers.length > 0
|
|
? Math.max(...data.layers)
|
|
: 0;
|
|
|
|
this.scanLayerOptions = Array.from({ length: maxLayer+1 }, (_, i) => i + 1)
|
|
}
|
|
}).catch(error => {
|
|
console.error('获取层数失败:', error);
|
|
this.scanLayerOptions = [1];
|
|
});
|
|
} else {
|
|
this.scanLayerOptions = [];
|
|
}
|
|
this.scanLayer = '';
|
|
},
|
|
|
|
// 处理标签扫描
|
|
handleLabelScan() {
|
|
if (!this.scanCode.trim()) {
|
|
this.$message.error('请输入标签编码');
|
|
return;
|
|
}
|
|
|
|
if (this.operationType === 'in') {
|
|
// 扫进操作
|
|
if (!this.scanPosition) {
|
|
this.$message.error('请选择位置');
|
|
return;
|
|
}
|
|
if (!this.scanLayer) {
|
|
this.$message.error('请选择层数');
|
|
return;
|
|
}
|
|
|
|
savePalletDetail({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
position: this.scanPosition,
|
|
layer: this.scanLayer,
|
|
serialNo: this.scanCode
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.$message.success('扫进成功');
|
|
this.needRefreshOnClose = true; // 标记需要在关闭时刷新
|
|
this.scanCode = ''; // 清空扫描码,准备下次扫描
|
|
this.$refs.scanInput.focus();
|
|
} else {
|
|
this.$message.error(data.msg || '扫进失败');
|
|
}
|
|
}).catch(error => {
|
|
console.error('扫进失败:', error);
|
|
this.$message.error('扫进失败');
|
|
});
|
|
} else {
|
|
// 扫出操作
|
|
deletePalletDetail({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
serialNo: this.scanCode
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.$message.success('扫出成功');
|
|
this.needRefreshOnClose = true; // 标记需要在关闭时刷新
|
|
this.scanCode = ''; // 清空扫描码,准备下次扫描
|
|
this.$refs.scanInput.focus();
|
|
} else {
|
|
this.$message.error(data.msg || '扫出失败');
|
|
}
|
|
}).catch(error => {
|
|
console.error('扫出失败:', error);
|
|
this.$message.error('扫出失败');
|
|
});
|
|
}
|
|
},
|
|
|
|
// 双击行事件 - 修改位置
|
|
handleRowDblClick(detail, index) {
|
|
|
|
this.editSerialNo = detail.serialNo;
|
|
this.editPosition = detail.position;
|
|
this.editLayer = detail.layer;
|
|
this.editOriginalPosition = detail.position;
|
|
this.editOriginalLayer = detail.layer;
|
|
|
|
// 获取当前位置的层数选项(排除自己)
|
|
this.handleEditPositionChange();
|
|
|
|
this.editPositionModalVisible = true;
|
|
},
|
|
|
|
// 编辑位置选择变化
|
|
handleEditPositionChange() {
|
|
if (this.editPosition) {
|
|
getLayersForEdit({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
position: this.editPosition,
|
|
excludeSerialNo: this.editSerialNo
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.editLayerOptions = data.layers || [];
|
|
// 如果当前选择的层数不在新的选项中,清空选择
|
|
// if (!this.editLayerOptions.includes(this.editLayer)) {
|
|
// this.editLayer = '';
|
|
// }
|
|
}
|
|
}).catch(error => {
|
|
console.error('获取层数失败:', error);
|
|
this.editLayerOptions = [];
|
|
});
|
|
} else {
|
|
this.editLayerOptions = [];
|
|
this.editLayer = '';
|
|
}
|
|
},
|
|
|
|
// 确定修改位置
|
|
confirmEditPosition() {
|
|
if (!this.editPosition) {
|
|
this.$message.error('请选择位置');
|
|
return;
|
|
}
|
|
if (!this.editLayer) {
|
|
this.$message.error('请选择层数');
|
|
return;
|
|
}
|
|
|
|
// 检查是否有变化
|
|
if (this.editPosition === this.editOriginalPosition && this.editLayer === this.editOriginalLayer) {
|
|
this.$message.warning('位置没有变化');
|
|
return;
|
|
}
|
|
|
|
updatePalletDetailPosition({
|
|
site: this.site,
|
|
palletId: this.palletCode,
|
|
serialNo: this.editSerialNo,
|
|
newPosition: this.editPosition,
|
|
newLayer: this.editLayer
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.$message.success('位置修改成功');
|
|
this.closeEditPositionModal();
|
|
this.refreshTable();
|
|
} else {
|
|
this.$message.error(data.msg || '位置修改失败');
|
|
}
|
|
}).catch(error => {
|
|
console.error('位置修改失败:', error);
|
|
this.$message.error('位置修改失败');
|
|
});
|
|
},
|
|
|
|
// 关闭修改位置模态框
|
|
closeEditPositionModal() {
|
|
this.editPositionModalVisible = false;
|
|
this.editSerialNo = '';
|
|
this.editPosition = '';
|
|
this.editLayer = '';
|
|
this.editLayerOptions = [];
|
|
this.editOriginalPosition = '';
|
|
this.editOriginalLayer = '';
|
|
},
|
|
|
|
// 运输指令按钮点击事件
|
|
handleTransportOrder() {
|
|
if (!this.palletCode) {
|
|
this.$message.error('请先扫描栈板');
|
|
return;
|
|
}
|
|
|
|
// 首先获取当前栈板信息
|
|
checkPalletExists({
|
|
site: this.site,
|
|
palletId: this.palletCode
|
|
}).then(({ data }) => {
|
|
if (data.code == 0) {
|
|
// 从返回数据中获取栈板位置信息
|
|
this.currentPalletStation = data.locationCode || '';
|
|
if (!this.currentPalletStation) {
|
|
this.$message.error('无法获取当前栈板位置');
|
|
return;
|
|
}
|
|
|
|
this.transportModalVisible = true;
|
|
this.selectedTargetStation = '';
|
|
this.transportStationOptions = [];
|
|
|
|
// 获取所有AGV站点列表(和Call栈板一样的逻辑)
|
|
getAgvStations({}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.transportStationOptions = data.stations || [];
|
|
} else {
|
|
this.$message.error(data.msg || '获取站点列表失败');
|
|
}
|
|
}).catch(error => {
|
|
console.error('获取站点列表失败:', error);
|
|
this.$message.error('获取站点列表失败');
|
|
});
|
|
} else {
|
|
this.$message.error(data.msg || '获取栈板信息失败');
|
|
}
|
|
}).catch(error => {
|
|
console.error('获取栈板信息失败:', error);
|
|
this.$message.error('获取栈板信息失败');
|
|
});
|
|
},
|
|
|
|
// 确认创建运输任务
|
|
confirmTransportTask() {
|
|
if (!this.currentPalletStation) {
|
|
this.$message.error('无法获取当前栈板位置');
|
|
return;
|
|
}
|
|
if (!this.selectedTargetStation) {
|
|
this.$message.error('请选择目标站点');
|
|
return;
|
|
}
|
|
|
|
// 前端验证:起始站点和目标站点不能一样
|
|
if (this.currentPalletStation === this.selectedTargetStation) {
|
|
this.$message.error('起始站点和目标站点不能相同');
|
|
return;
|
|
}
|
|
|
|
// 调用包含组盘处理的接口
|
|
callPalletToStationWithUpdateZuPan({
|
|
site: this.site,
|
|
startStation: this.currentPalletStation,
|
|
targetStation: this.selectedTargetStation
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.$message.success('栈板运输任务创建成功');
|
|
this.closeTransportModal();
|
|
// 可能需要刷新栈板明细来反映组盘状态的变化
|
|
this.refreshTable();
|
|
} else {
|
|
this.$message.error(data.msg || '创建运输任务失败');
|
|
}
|
|
}).catch(error => {
|
|
console.error('创建运输任务失败:', error);
|
|
this.$message.error('创建运输任务失败');
|
|
});
|
|
},
|
|
|
|
// 关闭运输任务模态框
|
|
closeTransportModal() {
|
|
this.transportModalVisible = false;
|
|
this.currentPalletStation = '';
|
|
this.selectedTargetStation = '';
|
|
this.transportStationOptions = [];
|
|
},
|
|
|
|
// 确认Call栈板
|
|
confirmCallPallet() {
|
|
if (!this.selectedCallStartStation) {
|
|
this.$message.error('请选择起始站点');
|
|
return;
|
|
}
|
|
if (!this.selectedCallTargetStation) {
|
|
this.$message.error('请选择目标站点');
|
|
return;
|
|
}
|
|
|
|
// 前端验证:两个站点不能一样
|
|
if (this.selectedCallStartStation === this.selectedCallTargetStation) {
|
|
this.$message.error('起始站点和目标站点不能相同');
|
|
return;
|
|
}
|
|
|
|
callPalletToStation({
|
|
site: this.site,
|
|
startStation: this.selectedCallStartStation,
|
|
targetStation: this.selectedCallTargetStation
|
|
}).then(({ data }) => {
|
|
if (data.code === 0) {
|
|
this.$message.success('空托盘调用任务创建成功');
|
|
this.closeCallPalletModal();
|
|
} else {
|
|
this.$message.error(data.msg || '调用空托盘失败');
|
|
}
|
|
}).catch(error => {
|
|
console.error('调用空托盘失败:', error);
|
|
this.$message.error('异常:'+error);
|
|
});
|
|
},
|
|
|
|
// 关闭Call栈板模态框
|
|
closeCallPalletModal() {
|
|
this.callPalletModalVisible = false;
|
|
this.selectedCallStartStation = '';
|
|
this.selectedCallTargetStation = '';
|
|
this.callStationOptions = [];
|
|
},
|
|
|
|
},
|
|
mounted() {
|
|
this.$nextTick(() => {
|
|
if (this.$refs.palletInput) {
|
|
this.$refs.palletInput.focus();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 表格样式 */
|
|
.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: 2;
|
|
text-align: center;
|
|
}
|
|
|
|
.col-part {
|
|
flex: 2;
|
|
text-align: center;
|
|
}
|
|
|
|
/* 空数据提示 */
|
|
.empty-hint {
|
|
text-align: center;
|
|
color: #999;
|
|
padding: 20px;
|
|
background: white;
|
|
border-radius: 6px;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
/* 模态框样式 */
|
|
.scan-modal-content {
|
|
padding: 10px 0;
|
|
}
|
|
|
|
.modal-form {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.dialog-footer {
|
|
text-align: center;
|
|
}
|
|
|
|
/* 修复模态框层级问题 */
|
|
::v-deep .el-dialog__wrapper {
|
|
z-index: 2000 !important;
|
|
}
|
|
|
|
::v-deep .el-overlay {
|
|
z-index: 2000 !important;
|
|
}
|
|
|
|
/* 修复单选框样式 */
|
|
::v-deep .el-radio {
|
|
margin-right: 8px !important;
|
|
}
|
|
|
|
::v-deep .el-radio__label {
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* 标题行样式 */
|
|
.list-title-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.list-title-row .list-title {
|
|
margin: 0;
|
|
flex: 1;
|
|
}
|
|
|
|
/* 空数据行样式 */
|
|
.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>
|