|
|
@ -5,7 +5,7 @@ |
|
|
<div class="header-bar"> |
|
|
<div class="header-bar"> |
|
|
<div class="header-left" @click="handleBack"> |
|
|
<div class="header-left" @click="handleBack"> |
|
|
<i class="el-icon-arrow-left"></i> |
|
|
<i class="el-icon-arrow-left"></i> |
|
|
<span>打托</span> |
|
|
|
|
|
|
|
|
<span>组托</span> |
|
|
</div> |
|
|
</div> |
|
|
<div class="header-right" @click="$router.push({ path: '/' })"> |
|
|
<div class="header-right" @click="$router.push({ path: '/' })"> |
|
|
首页 |
|
|
首页 |
|
|
@ -36,45 +36,62 @@ |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<!-- 第二行:筛选条件 (扫描栈板后显示) --> |
|
|
|
|
|
|
|
|
<!-- 第二行:栈板类型和自动分拣 (扫描栈板后显示) --> |
|
|
<div v-if="palletScanned" class="input-group"> |
|
|
<div v-if="palletScanned" class="input-group"> |
|
|
<div style="display: flex; gap: 8px; align-items: end;"> |
|
|
<div style="display: flex; gap: 8px; align-items: end;"> |
|
|
<div style="flex: 1;"> |
|
|
|
|
|
<label class="input-label">位置</label> |
|
|
|
|
|
|
|
|
<div style="flex: 0.65;"> |
|
|
|
|
|
<label class="input-label">栈板类型</label> |
|
|
<el-select |
|
|
<el-select |
|
|
v-model="selectedPosition" |
|
|
|
|
|
placeholder="请选择位置" |
|
|
|
|
|
|
|
|
v-model="currentPalletType" |
|
|
|
|
|
placeholder="请选择栈板类型" |
|
|
style="width: 100%;" |
|
|
style="width: 100%;" |
|
|
@change="handlePositionChange" |
|
|
|
|
|
|
|
|
:disabled="palletTypeDisabled" |
|
|
|
|
|
@change="handlePalletTypeChange" |
|
|
> |
|
|
> |
|
|
<el-option label="ALL" value=""></el-option> |
|
|
|
|
|
<el-option |
|
|
<el-option |
|
|
v-for="position in positionOptions" |
|
|
|
|
|
:key="position" |
|
|
|
|
|
:label="position" |
|
|
|
|
|
:value="position" |
|
|
|
|
|
|
|
|
v-for="type in palletTypeOptions" |
|
|
|
|
|
:key="type.palletType" |
|
|
|
|
|
:label="`${type.palletType} - ${type.typeDesc}`" |
|
|
|
|
|
:value="type.palletType" |
|
|
/> |
|
|
/> |
|
|
</el-select> |
|
|
</el-select> |
|
|
</div> |
|
|
</div> |
|
|
<div style="flex: 1;"> |
|
|
|
|
|
<label class="input-label">层数</label> |
|
|
|
|
|
|
|
|
<div style="flex: 0.35;"> |
|
|
|
|
|
<label class="input-label">自动分拣</label> |
|
|
<el-select |
|
|
<el-select |
|
|
v-model="selectedLayer" |
|
|
|
|
|
placeholder="请选择层数" |
|
|
|
|
|
|
|
|
v-model="currentAutoSort" |
|
|
|
|
|
placeholder="请选择" |
|
|
style="width: 100%;" |
|
|
style="width: 100%;" |
|
|
|
|
|
:disabled="autoSortDisabled" |
|
|
|
|
|
@change="handleAutoSortChange" |
|
|
> |
|
|
> |
|
|
<el-option label="ALL" value=""></el-option> |
|
|
|
|
|
<el-option |
|
|
|
|
|
v-for="layer in layerOptions" |
|
|
|
|
|
:key="layer" |
|
|
|
|
|
:label="`第${layer}层`" |
|
|
|
|
|
:value="layer" |
|
|
|
|
|
/> |
|
|
|
|
|
|
|
|
<el-option label="是" value="Y"></el-option> |
|
|
|
|
|
<el-option label="否" value="N"></el-option> |
|
|
</el-select> |
|
|
</el-select> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 第三行:筛选条件 (扫描栈板后显示) --> |
|
|
|
|
|
<div v-if="palletScanned" class="input-group"> |
|
|
|
|
|
<label class="input-label">位置</label> |
|
|
|
|
|
<div style="display: flex; gap: 8px;"> |
|
|
|
|
|
<el-select |
|
|
|
|
|
v-model="selectedPosition" |
|
|
|
|
|
placeholder="请选择位置" |
|
|
|
|
|
style="flex: 0.75;" |
|
|
|
|
|
> |
|
|
|
|
|
<el-option label="ALL" value=""></el-option> |
|
|
|
|
|
<el-option |
|
|
|
|
|
v-for="position in positionOptions" |
|
|
|
|
|
:key="position" |
|
|
|
|
|
:label="position" |
|
|
|
|
|
:value="position" |
|
|
|
|
|
/> |
|
|
|
|
|
</el-select> |
|
|
<button |
|
|
<button |
|
|
class="action-btn secondary" |
|
|
class="action-btn secondary" |
|
|
style="margin: 0; white-space: nowrap;" |
|
|
|
|
|
|
|
|
style="flex: 0.25; margin: 0; white-space: nowrap;" |
|
|
@click="refreshTable" |
|
|
@click="refreshTable" |
|
|
> |
|
|
> |
|
|
刷新 |
|
|
刷新 |
|
|
@ -82,21 +99,21 @@ |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<!-- 第三行:扫进/扫出选择 (扫描栈板后显示) --> |
|
|
|
|
|
|
|
|
<!-- 第四行:扫进/扫出选择 (扫描栈板后显示) --> |
|
|
<div v-if="palletScanned" class="input-group"> |
|
|
<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;"> |
|
|
|
|
|
|
|
|
<div style="display: flex; gap: 8px; align-items: center;"> |
|
|
|
|
|
<div style="flex: 0.75;"> |
|
|
|
|
|
<el-radio-group v-model="operationType" style="display: flex;"> |
|
|
<el-radio label="in" style="margin-right: 0px; white-space: nowrap;">扫进</el-radio> |
|
|
<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 label="out" style="white-space: nowrap;">扫出</el-radio> |
|
|
</el-radio-group> |
|
|
</el-radio-group> |
|
|
</div> |
|
|
</div> |
|
|
<button |
|
|
<button |
|
|
class="action-btn secondary" |
|
|
class="action-btn secondary" |
|
|
style="margin: 0; white-space: nowrap; flex-shrink: 0;" |
|
|
|
|
|
|
|
|
style="flex: 0.25; margin: 0; white-space: nowrap;" |
|
|
@click="showScanModal" |
|
|
@click="showScanModal" |
|
|
> |
|
|
> |
|
|
扫描二维码 |
|
|
|
|
|
|
|
|
扫描条码 |
|
|
</button> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
@ -104,16 +121,17 @@ |
|
|
|
|
|
|
|
|
<!-- 栈板明细表格 (扫描栈板后显示) --> |
|
|
<!-- 栈板明细表格 (扫描栈板后显示) --> |
|
|
<div v-if="palletScanned" class="rma-list"> |
|
|
<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 class="list-title-row" style="display: flex; gap: 8px; align-items: center; padding: 0;"> |
|
|
|
|
|
<div class="list-title" style="flex: 0.75; margin: 0;">栈板明细</div> |
|
|
|
|
|
<button class="action-btn primary" style="flex: 0.25; margin: 0;" @click="handleCompleteAssembly" :disabled="completeAssemblyLoading"> |
|
|
|
|
|
{{ completeAssemblyLoading ? '处理中...' : '完成组托' }} |
|
|
|
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
<div class="detail-table"> |
|
|
<div class="detail-table"> |
|
|
<div class="table-header"> |
|
|
<div class="table-header"> |
|
|
<div class="col-position">位置</div> |
|
|
<div class="col-position">位置</div> |
|
|
<div class="col-layer">层数</div> |
|
|
<div class="col-layer">层数</div> |
|
|
<div class="col-serial">标签号</div> |
|
|
<div class="col-serial">标签号</div> |
|
|
<div class="col-part">物料编码</div> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
<div |
|
|
<div |
|
|
v-for="(detail, index) in detailList" |
|
|
v-for="(detail, index) in detailList" |
|
|
@ -124,7 +142,6 @@ |
|
|
<div class="col-position">{{ detail.position }}</div> |
|
|
<div class="col-position">{{ detail.position }}</div> |
|
|
<div class="col-layer">{{ detail.layer }}</div> |
|
|
<div class="col-layer">{{ detail.layer }}</div> |
|
|
<div class="col-serial">{{ detail.serialNo }}</div> |
|
|
<div class="col-serial">{{ detail.serialNo }}</div> |
|
|
<div class="col-part">{{ detail.partNo }}</div> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
<!-- 暂无数据提示 --> |
|
|
<!-- 暂无数据提示 --> |
|
|
<div v-if="detailList.length === 0" class="table-row empty-row"> |
|
|
<div v-if="detailList.length === 0" class="table-row empty-row"> |
|
|
@ -169,6 +186,7 @@ |
|
|
<el-select |
|
|
<el-select |
|
|
v-model="scanLayer" |
|
|
v-model="scanLayer" |
|
|
placeholder="请选择层数" |
|
|
placeholder="请选择层数" |
|
|
|
|
|
@change="moveFocusToScanInput" |
|
|
style="width: 100%;" |
|
|
style="width: 100%;" |
|
|
> |
|
|
> |
|
|
<el-option |
|
|
<el-option |
|
|
@ -260,15 +278,17 @@ |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div slot="footer" class="dialog-footer"> |
|
|
<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> |
|
|
|
|
|
|
|
|
<button class="action-btn primary" @click="confirmEditPosition" :disabled="editPositionLoading"> |
|
|
|
|
|
{{ editPositionLoading ? '处理中...' : '确定' }} |
|
|
|
|
|
</button> |
|
|
|
|
|
<button class="action-btn secondary" style="margin-left: 10px;" @click="closeEditPositionModal" :disabled="editPositionLoading">取消</button> |
|
|
</div> |
|
|
</div> |
|
|
</el-dialog> |
|
|
</el-dialog> |
|
|
|
|
|
|
|
|
<!-- 运输任务模态框 --> |
|
|
|
|
|
|
|
|
<!-- Call栈板模态框 --> |
|
|
<el-dialog |
|
|
<el-dialog |
|
|
title="创建运输任务" |
|
|
|
|
|
:visible.sync="transportModalVisible" |
|
|
|
|
|
|
|
|
title="调用空托盘" |
|
|
|
|
|
:visible.sync="callPalletModalVisible" |
|
|
width="90%" |
|
|
width="90%" |
|
|
:close-on-click-modal="false" |
|
|
:close-on-click-modal="false" |
|
|
:show-close="false" |
|
|
:show-close="false" |
|
|
@ -276,29 +296,18 @@ |
|
|
:modal-append-to-body="true" |
|
|
:modal-append-to-body="true" |
|
|
: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="call-modal-content"> |
|
|
|
|
|
<!-- 起始站点选择 --> |
|
|
<div class="input-group"> |
|
|
<div class="input-group"> |
|
|
<label class="input-label">起点站点</label> |
|
|
|
|
|
|
|
|
<label class="input-label">起始站点</label> |
|
|
<el-select |
|
|
<el-select |
|
|
v-model="selectedStartStation" |
|
|
|
|
|
placeholder="请选择起点站点" |
|
|
|
|
|
|
|
|
v-model="selectedCallStartStation" |
|
|
|
|
|
placeholder="请选择起始站点" |
|
|
style="width: 100%;" |
|
|
style="width: 100%;" |
|
|
@change="handleStartStationChange" |
|
|
|
|
|
|
|
|
@change="handleCallStartStationChange" |
|
|
> |
|
|
> |
|
|
<el-option |
|
|
<el-option |
|
|
v-for="station in startStationOptions" |
|
|
|
|
|
|
|
|
v-for="station in callStartStationOptions" |
|
|
:key="station.stationCode" |
|
|
:key="station.stationCode" |
|
|
:label="`${station.stationCode} - ${station.stationName}`" |
|
|
:label="`${station.stationCode} - ${station.stationName}`" |
|
|
:value="station.stationCode" |
|
|
:value="station.stationCode" |
|
|
@ -306,84 +315,46 @@ |
|
|
</el-select> |
|
|
</el-select> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<!-- 目标站点选择 --> |
|
|
|
|
|
|
|
|
<!-- 目标站点输入 --> |
|
|
<div class="input-group"> |
|
|
<div class="input-group"> |
|
|
<label class="input-label">目标站点</label> |
|
|
<label class="input-label">目标站点</label> |
|
|
<el-select |
|
|
|
|
|
v-model="selectedTargetStation" |
|
|
|
|
|
placeholder="请先选择起点站点" |
|
|
|
|
|
|
|
|
<el-input |
|
|
|
|
|
ref="callTargetStationInput" |
|
|
|
|
|
v-model="selectedCallTargetStation" |
|
|
|
|
|
placeholder="请扫描或输入目标站点" |
|
|
|
|
|
clearable |
|
|
style="width: 100%;" |
|
|
style="width: 100%;" |
|
|
:disabled="!selectedStartStation" |
|
|
|
|
|
> |
|
|
|
|
|
<el-option |
|
|
|
|
|
v-for="target in targetStationOptions" |
|
|
|
|
|
:key="target.stationCode" |
|
|
|
|
|
:label="`${target.stationCode} - ${target.stationName}`" |
|
|
|
|
|
:value="target.stationCode" |
|
|
|
|
|
/> |
|
|
|
|
|
</el-select> |
|
|
|
|
|
|
|
|
/> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div slot="footer" class="dialog-footer"> |
|
|
<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> |
|
|
|
|
|
|
|
|
<button class="action-btn primary" @click="confirmCallPallet" :disabled="callPalletLoading"> |
|
|
|
|
|
{{ callPalletLoading ? '调用中...' : '确定' }} |
|
|
|
|
|
</button> |
|
|
|
|
|
<button class="action-btn secondary" style="margin-left: 10px;" @click="closeCallPalletModal" :disabled="callPalletLoading">取消</button> |
|
|
</div> |
|
|
</div> |
|
|
</el-dialog> |
|
|
</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="selectedCallStation" |
|
|
|
|
|
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> |
|
|
</div> |
|
|
</template> |
|
|
</template> |
|
|
|
|
|
|
|
|
<script> |
|
|
<script> |
|
|
import { |
|
|
import { |
|
|
checkPalletExists, |
|
|
checkPalletExists, |
|
|
getPalletPositions, |
|
|
|
|
|
getPalletDetails, |
|
|
getPalletDetails, |
|
|
getLayersByPosition, |
|
|
getLayersByPosition, |
|
|
validateLabel, |
|
|
|
|
|
savePalletDetail, |
|
|
savePalletDetail, |
|
|
deletePalletDetail, |
|
|
deletePalletDetail, |
|
|
getLayersForEdit, |
|
|
getLayersForEdit, |
|
|
updatePalletDetailPosition, |
|
|
updatePalletDetailPosition, |
|
|
|
|
|
getPalletInfo, |
|
|
|
|
|
getPalletTypeList, |
|
|
|
|
|
getPalletTypeAreas, |
|
|
|
|
|
updatePalletTypeAndAutoSort, |
|
|
getAgvStations, |
|
|
getAgvStations, |
|
|
getTargetStations, |
|
|
|
|
|
createPalletTransportTask, |
|
|
|
|
|
callPalletToStation |
|
|
|
|
|
|
|
|
callPalletToStation, |
|
|
|
|
|
completePalletAssembly |
|
|
} from '../../../api/automatedWarehouse/palletPacking' |
|
|
} from '../../../api/automatedWarehouse/palletPacking' |
|
|
|
|
|
|
|
|
export default { |
|
|
export default { |
|
|
@ -394,6 +365,16 @@ export default { |
|
|
palletScanned: false, |
|
|
palletScanned: false, |
|
|
operationType: 'in', // 'in' 或 'out' |
|
|
operationType: 'in', // 'in' 或 'out' |
|
|
|
|
|
|
|
|
|
|
|
// 栈板类型和自动分拣 |
|
|
|
|
|
currentPalletFamily: '', // 当前栈板大分类(固定不可改) |
|
|
|
|
|
currentPalletType: '', // 当前栈板类型 |
|
|
|
|
|
currentAutoSort: '', // 当前是否自动分拣 Y/N |
|
|
|
|
|
palletTypeOptions: [], // 托盘类型选项列表 |
|
|
|
|
|
palletTypeDisabled: false, // 栈板类型下拉框是否禁用(有明细数据时禁用) |
|
|
|
|
|
autoSortDisabled: false, // 自动分拣下拉框是否禁用 |
|
|
|
|
|
currentWcsAutoSort: '', // 当前托盘类型的wcsAutoSort值 |
|
|
|
|
|
currentMaxLayer: 0, // 当前托盘类型的最大层数,0=无限 |
|
|
|
|
|
|
|
|
// 筛选条件 |
|
|
// 筛选条件 |
|
|
selectedPosition: '', |
|
|
selectedPosition: '', |
|
|
selectedLayer: '', |
|
|
selectedLayer: '', |
|
|
@ -411,17 +392,12 @@ export default { |
|
|
// 栈板明细 |
|
|
// 栈板明细 |
|
|
detailList: [], |
|
|
detailList: [], |
|
|
|
|
|
|
|
|
// 运输任务模态框 |
|
|
|
|
|
transportModalVisible: false, |
|
|
|
|
|
startStationOptions: [], |
|
|
|
|
|
targetStationOptions: [], |
|
|
|
|
|
selectedStartStation: '', |
|
|
|
|
|
selectedTargetStation: '', |
|
|
|
|
|
|
|
|
|
|
|
// Call栈板模态框 |
|
|
// Call栈板模态框 |
|
|
callPalletModalVisible: false, |
|
|
callPalletModalVisible: false, |
|
|
callStationOptions: [], |
|
|
|
|
|
selectedCallStation: '', |
|
|
|
|
|
|
|
|
callStartStationOptions: [], // 起始站点选项(statusDb=1,有货) |
|
|
|
|
|
callTargetStationOptions: [], // 目标站点选项(statusDb=0,空闲) |
|
|
|
|
|
selectedCallStartStation: '', |
|
|
|
|
|
selectedCallTargetStation: '', |
|
|
|
|
|
|
|
|
// 修改位置模态框 |
|
|
// 修改位置模态框 |
|
|
editPositionModalVisible: false, |
|
|
editPositionModalVisible: false, |
|
|
@ -431,6 +407,11 @@ export default { |
|
|
editLayerOptions: [], |
|
|
editLayerOptions: [], |
|
|
editOriginalPosition: '', |
|
|
editOriginalPosition: '', |
|
|
editOriginalLayer: '', |
|
|
editOriginalLayer: '', |
|
|
|
|
|
|
|
|
|
|
|
// 按钮loading状态(防止重复点击) |
|
|
|
|
|
editPositionLoading: false, // 修改位置按钮 |
|
|
|
|
|
callPalletLoading: false, // Call栈板按钮 |
|
|
|
|
|
completeAssemblyLoading: false, // 完成组托按钮 |
|
|
}; |
|
|
}; |
|
|
}, |
|
|
}, |
|
|
methods: { |
|
|
methods: { |
|
|
@ -438,6 +419,59 @@ export default { |
|
|
this.$router.back(); |
|
|
this.$router.back(); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 重置页面到初始状态 |
|
|
|
|
|
resetPage() { |
|
|
|
|
|
// 清空栈板信息 |
|
|
|
|
|
this.palletCode = ''; |
|
|
|
|
|
this.palletScanned = false; |
|
|
|
|
|
this.operationType = 'in'; |
|
|
|
|
|
|
|
|
|
|
|
// 清空栈板类型和自动分拣 |
|
|
|
|
|
this.currentPalletFamily = ''; |
|
|
|
|
|
this.currentPalletType = ''; |
|
|
|
|
|
this.currentAutoSort = ''; |
|
|
|
|
|
this.palletTypeOptions = []; |
|
|
|
|
|
this.palletTypeDisabled = false; |
|
|
|
|
|
this.autoSortDisabled = false; |
|
|
|
|
|
this.currentWcsAutoSort = ''; |
|
|
|
|
|
this.currentMaxLayer = 0; |
|
|
|
|
|
|
|
|
|
|
|
// 清空筛选条件 |
|
|
|
|
|
this.selectedPosition = ''; |
|
|
|
|
|
this.selectedLayer = ''; |
|
|
|
|
|
this.positionOptions = []; |
|
|
|
|
|
this.layerOptions = []; |
|
|
|
|
|
|
|
|
|
|
|
// 清空栈板明细 |
|
|
|
|
|
this.detailList = []; |
|
|
|
|
|
|
|
|
|
|
|
// 清空扫码模态框 |
|
|
|
|
|
this.scanModalVisible = false; |
|
|
|
|
|
this.scanCode = ''; |
|
|
|
|
|
this.scanPosition = ''; |
|
|
|
|
|
this.scanLayer = ''; |
|
|
|
|
|
this.scanLayerOptions = []; |
|
|
|
|
|
this.needRefreshOnClose = false; |
|
|
|
|
|
|
|
|
|
|
|
// 清空修改位置模态框 |
|
|
|
|
|
this.editPositionModalVisible = false; |
|
|
|
|
|
this.editSerialNo = ''; |
|
|
|
|
|
this.editPosition = ''; |
|
|
|
|
|
this.editLayer = ''; |
|
|
|
|
|
this.editLayerOptions = []; |
|
|
|
|
|
this.editOriginalPosition = ''; |
|
|
|
|
|
this.editOriginalLayer = ''; |
|
|
|
|
|
|
|
|
|
|
|
// 聚焦到栈板输入框 |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
if (this.$refs.palletInput) { |
|
|
|
|
|
this.$refs.palletInput.focus(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
console.log('页面已重置到初始状态'); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
// 扫描栈板 |
|
|
// 扫描栈板 |
|
|
handlePalletScan() { |
|
|
handlePalletScan() { |
|
|
if (!this.palletCode.trim()) { |
|
|
if (!this.palletCode.trim()) { |
|
|
@ -452,7 +486,10 @@ export default { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
this.palletScanned = true; |
|
|
this.palletScanned = true; |
|
|
this.positionOptions = data.positions || []; |
|
|
this.positionOptions = data.positions || []; |
|
|
this.$message.success('栈板验证成功'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取栈板详细信息(包括palletType和autoSort) |
|
|
|
|
|
this.loadPalletInfo(); |
|
|
|
|
|
|
|
|
this.refreshTable(); |
|
|
this.refreshTable(); |
|
|
} else { |
|
|
} else { |
|
|
this.$message.error(data.msg || '栈板不存在'); |
|
|
this.$message.error(data.msg || '栈板不存在'); |
|
|
@ -463,15 +500,155 @@ export default { |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 加载栈板信息 |
|
|
|
|
|
loadPalletInfo() { |
|
|
|
|
|
getPalletInfo({ |
|
|
|
|
|
site: this.site, |
|
|
|
|
|
palletId: this.palletCode |
|
|
|
|
|
}).then(({ data }) => { |
|
|
|
|
|
if (data.code === 0) { |
|
|
|
|
|
const palletInfo = data.row || {}; |
|
|
|
|
|
this.currentPalletFamily = palletInfo.palletFamily || ''; |
|
|
|
|
|
this.currentPalletType = palletInfo.palletType || ''; |
|
|
|
|
|
this.currentAutoSort = palletInfo.autoSort || 'N'; |
|
|
|
|
|
|
|
|
|
|
|
// 加载托盘类型列表(根据palletFamily过滤) |
|
|
|
|
|
this.loadPalletTypeList(); |
|
|
|
|
|
} else { |
|
|
|
|
|
this.$message.error(data.msg || '获取栈板信息失败'); |
|
|
|
|
|
} |
|
|
|
|
|
}).catch(error => { |
|
|
|
|
|
console.error('获取栈板信息失败:', error); |
|
|
|
|
|
this.$message.error('获取栈板信息失败'); |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 加载托盘类型列表 |
|
|
|
|
|
loadPalletTypeList() { |
|
|
|
|
|
getPalletTypeList({ |
|
|
|
|
|
site: this.site, |
|
|
|
|
|
palletFamily: this.currentPalletFamily, |
|
|
|
|
|
active: 'Y' |
|
|
|
|
|
}).then(({ data }) => { |
|
|
|
|
|
if (data.code === 0) { |
|
|
|
|
|
this.palletTypeOptions = data.rows || []; |
|
|
|
|
|
|
|
|
|
|
|
// 设置当前托盘类型的wcsAutoSort值和maxLayer |
|
|
|
|
|
const currentType = this.palletTypeOptions.find(t => t.palletType === this.currentPalletType); |
|
|
|
|
|
if (currentType) { |
|
|
|
|
|
this.currentWcsAutoSort = currentType.wcsAutoSort || 'N'; |
|
|
|
|
|
this.currentMaxLayer = currentType.maxLayer || 0; |
|
|
|
|
|
this.updateAutoSortControl(); |
|
|
|
|
|
|
|
|
|
|
|
// 加载当前托盘类型的区域列表 |
|
|
|
|
|
this.loadPalletTypeAreas(); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
this.palletTypeOptions = []; |
|
|
|
|
|
} |
|
|
|
|
|
}).catch(error => { |
|
|
|
|
|
console.error('获取托盘类型列表失败:', error); |
|
|
|
|
|
this.palletTypeOptions = []; |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 加载托盘类型的区域列表 |
|
|
|
|
|
loadPalletTypeAreas() { |
|
|
|
|
|
getPalletTypeAreas({ |
|
|
|
|
|
site: this.site, |
|
|
|
|
|
palletType: this.currentPalletType |
|
|
|
|
|
}).then(({ data }) => { |
|
|
|
|
|
if (data.code === 0) { |
|
|
|
|
|
// 从pallet_type_area获取position列表 |
|
|
|
|
|
const areas = data.rows || []; |
|
|
|
|
|
this.positionOptions = areas.map(area => area.position); |
|
|
|
|
|
} else { |
|
|
|
|
|
this.positionOptions = []; |
|
|
|
|
|
} |
|
|
|
|
|
}).catch(error => { |
|
|
|
|
|
console.error('获取托盘区域列表失败:', error); |
|
|
|
|
|
this.positionOptions = []; |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 托盘类型变更事件 |
|
|
|
|
|
handlePalletTypeChange() { |
|
|
|
|
|
// 查找选中的托盘类型 |
|
|
|
|
|
const selectedType = this.palletTypeOptions.find(t => t.palletType === this.currentPalletType); |
|
|
|
|
|
|
|
|
|
|
|
if (selectedType) { |
|
|
|
|
|
this.currentWcsAutoSort = selectedType.wcsAutoSort || 'N'; |
|
|
|
|
|
this.currentMaxLayer = selectedType.maxLayer || 0; |
|
|
|
|
|
|
|
|
|
|
|
// 默认值:从托盘类型表取 |
|
|
|
|
|
this.currentAutoSort = this.currentWcsAutoSort; |
|
|
|
|
|
|
|
|
|
|
|
// 更新自动分拣控制 |
|
|
|
|
|
this.updateAutoSortControl(); |
|
|
|
|
|
|
|
|
|
|
|
// 重新查询pallet_type_area,更新位置下拉框 |
|
|
|
|
|
this.loadPalletTypeAreas(); |
|
|
|
|
|
|
|
|
|
|
|
// 保存到数据库 |
|
|
|
|
|
this.savePalletTypeAndAutoSort(); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 更新自动分拣控制逻辑 |
|
|
|
|
|
updateAutoSortControl() { |
|
|
|
|
|
if (this.currentWcsAutoSort === 'N') { |
|
|
|
|
|
// 不支持自动分拣,锁定为N,禁用选择 |
|
|
|
|
|
this.currentAutoSort = 'N'; |
|
|
|
|
|
this.autoSortDisabled = true; |
|
|
|
|
|
} else { |
|
|
|
|
|
// 支持自动分拣,可以选择Y或N |
|
|
|
|
|
this.autoSortDisabled = false; |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 是否自动分拣变更事件 |
|
|
|
|
|
handleAutoSortChange() { |
|
|
|
|
|
// 保存到数据库 |
|
|
|
|
|
this.savePalletTypeAndAutoSort(); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 保存栈板类型和自动分拣标志 |
|
|
|
|
|
savePalletTypeAndAutoSort() { |
|
|
|
|
|
updatePalletTypeAndAutoSort({ |
|
|
|
|
|
site: this.site, |
|
|
|
|
|
palletId: this.palletCode, |
|
|
|
|
|
palletType: this.currentPalletType, |
|
|
|
|
|
autoSort: this.currentAutoSort |
|
|
|
|
|
}).then(({ data }) => { |
|
|
|
|
|
if (data.code === 0) { |
|
|
|
|
|
this.$message.success('更新成功'); |
|
|
|
|
|
} else { |
|
|
|
|
|
this.$message.error(data.msg || '更新失败'); |
|
|
|
|
|
} |
|
|
|
|
|
}).catch(error => { |
|
|
|
|
|
console.error('更新失败:', error); |
|
|
|
|
|
this.$message.error('更新失败'); |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
// Call栈板 - 调用空托盘 |
|
|
// Call栈板 - 调用空托盘 |
|
|
handleCallPallet() { |
|
|
handleCallPallet() { |
|
|
this.callPalletModalVisible = true; |
|
|
this.callPalletModalVisible = true; |
|
|
this.selectedCallStation = ''; |
|
|
|
|
|
|
|
|
this.selectedCallStartStation = ''; |
|
|
|
|
|
this.selectedCallTargetStation = ''; |
|
|
|
|
|
|
|
|
// 获取AGV站点列表 |
|
|
|
|
|
|
|
|
// 获取AGV站点列表,分别过滤起始站点和目标站点 |
|
|
getAgvStations({}).then(({ data }) => { |
|
|
getAgvStations({}).then(({ data }) => { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
this.callStationOptions = data.stations || []; |
|
|
|
|
|
|
|
|
const allStations = data.stations || []; |
|
|
|
|
|
// 起始站点:过滤出statusDb为1(有货)且为正式站点的站点 |
|
|
|
|
|
this.callStartStationOptions = allStations.filter(station => |
|
|
|
|
|
station.statusDb === 1 && station.stationType === '正式站点' |
|
|
|
|
|
); |
|
|
|
|
|
// 目标站点:过滤出statusDb为0(空闲)且为正式站点的站点 |
|
|
|
|
|
this.callTargetStationOptions = allStations.filter(station => |
|
|
|
|
|
station.statusDb === 0 && station.stationType === '正式站点' |
|
|
|
|
|
); |
|
|
} else { |
|
|
} else { |
|
|
this.$message.error(data.msg || '获取站点列表失败'); |
|
|
this.$message.error(data.msg || '获取站点列表失败'); |
|
|
} |
|
|
} |
|
|
@ -481,7 +658,16 @@ export default { |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 位置选择变化 |
|
|
|
|
|
|
|
|
// 起始站点选择change事件,自动聚焦到目标站点输入框 |
|
|
|
|
|
handleCallStartStationChange() { |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
if (this.$refs.callTargetStationInput) { |
|
|
|
|
|
this.$refs.callTargetStationInput.focus(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 位置选择变化 |
|
|
handlePositionChange() { |
|
|
handlePositionChange() { |
|
|
if (this.selectedPosition) { |
|
|
if (this.selectedPosition) { |
|
|
getLayersByPosition({ |
|
|
getLayersByPosition({ |
|
|
@ -511,12 +697,27 @@ export default { |
|
|
}).then(({ data }) => { |
|
|
}).then(({ data }) => { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
this.detailList = data.details || []; |
|
|
this.detailList = data.details || []; |
|
|
|
|
|
|
|
|
|
|
|
// 如果栈板有明细数据,禁用栈板类型和自动分拣的修改 |
|
|
|
|
|
const hasDetails = this.detailList.length > 0; |
|
|
|
|
|
this.palletTypeDisabled = hasDetails; |
|
|
|
|
|
|
|
|
|
|
|
// 如果有明细数据,自动分拣也要禁用;否则根据wcsAutoSort判断 |
|
|
|
|
|
if (hasDetails) { |
|
|
|
|
|
this.autoSortDisabled = true; |
|
|
|
|
|
} else { |
|
|
|
|
|
this.updateAutoSortControl(); |
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
this.detailList = []; |
|
|
this.detailList = []; |
|
|
|
|
|
this.palletTypeDisabled = false; |
|
|
|
|
|
this.updateAutoSortControl(); |
|
|
} |
|
|
} |
|
|
}).catch(error => { |
|
|
}).catch(error => { |
|
|
console.error('获取栈板明细失败:', error); |
|
|
console.error('获取栈板明细失败:', error); |
|
|
this.detailList = []; |
|
|
this.detailList = []; |
|
|
|
|
|
this.palletTypeDisabled = false; |
|
|
|
|
|
this.updateAutoSortControl(); |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
@ -535,6 +736,13 @@ export default { |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
moveFocusToScanInput(){ |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
if (this.$refs.scanInput) { |
|
|
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
// 关闭扫码模态框 |
|
|
// 关闭扫码模态框 |
|
|
closeScanModal() { |
|
|
closeScanModal() { |
|
|
this.scanModalVisible = false; |
|
|
this.scanModalVisible = false; |
|
|
@ -548,17 +756,29 @@ export default { |
|
|
// 扫码模态框中位置变化 |
|
|
// 扫码模态框中位置变化 |
|
|
handleScanPositionChange() { |
|
|
handleScanPositionChange() { |
|
|
if (this.scanPosition) { |
|
|
if (this.scanPosition) { |
|
|
|
|
|
// maxLayer=0表示混装托盘,只能选第1层 |
|
|
|
|
|
if (this.currentMaxLayer === 0) { |
|
|
|
|
|
this.scanLayerOptions = [1]; |
|
|
|
|
|
this.scanLayer = 1; // 自动选中第1层 |
|
|
|
|
|
this.moveFocusToScanInput(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// maxLayer>0,根据已有层数和maxLayer计算可选层数 |
|
|
getLayersByPosition({ |
|
|
getLayersByPosition({ |
|
|
site: this.site, |
|
|
site: this.site, |
|
|
palletId: this.palletCode, |
|
|
palletId: this.palletCode, |
|
|
position: this.scanPosition |
|
|
position: this.scanPosition |
|
|
}).then(({ data }) => { |
|
|
}).then(({ data }) => { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
const maxLayer = data.layers && data.layers.length > 0 |
|
|
|
|
|
|
|
|
const existingMaxLayer = data.layers && data.layers.length > 0 |
|
|
? Math.max(...data.layers) |
|
|
? Math.max(...data.layers) |
|
|
: 0; |
|
|
: 0; |
|
|
|
|
|
|
|
|
this.scanLayerOptions = Array.from({ length: maxLayer+1 }, (_, i) => i + 1) |
|
|
|
|
|
|
|
|
// 有maxLayer限制,取已有最大层+1和maxLayer的较小值 |
|
|
|
|
|
const layerCount = Math.min(existingMaxLayer + 1, this.currentMaxLayer); |
|
|
|
|
|
|
|
|
|
|
|
this.scanLayerOptions = Array.from({ length: layerCount }, (_, i) => i + 1); |
|
|
} |
|
|
} |
|
|
}).catch(error => { |
|
|
}).catch(error => { |
|
|
console.error('获取层数失败:', error); |
|
|
console.error('获取层数失败:', error); |
|
|
@ -647,6 +867,14 @@ export default { |
|
|
// 编辑位置选择变化 |
|
|
// 编辑位置选择变化 |
|
|
handleEditPositionChange() { |
|
|
handleEditPositionChange() { |
|
|
if (this.editPosition) { |
|
|
if (this.editPosition) { |
|
|
|
|
|
// maxLayer=0表示混装托盘,只能选第1层 |
|
|
|
|
|
if (this.currentMaxLayer === 0) { |
|
|
|
|
|
this.editLayerOptions = [1]; |
|
|
|
|
|
this.editLayer = 1; // 自动选中第1层 |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// maxLayer>0,根据已有层数和maxLayer计算可选层数 |
|
|
getLayersForEdit({ |
|
|
getLayersForEdit({ |
|
|
site: this.site, |
|
|
site: this.site, |
|
|
palletId: this.palletCode, |
|
|
palletId: this.palletCode, |
|
|
@ -654,7 +882,15 @@ export default { |
|
|
excludeSerialNo: this.editSerialNo |
|
|
excludeSerialNo: this.editSerialNo |
|
|
}).then(({ data }) => { |
|
|
}).then(({ data }) => { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
this.editLayerOptions = data.layers || []; |
|
|
|
|
|
|
|
|
let layerOptions = data.layers || []; |
|
|
|
|
|
|
|
|
|
|
|
// 根据maxLayer限制层数选项 |
|
|
|
|
|
if (this.currentMaxLayer > 0) { |
|
|
|
|
|
// 过滤掉超过maxLayer的层数 |
|
|
|
|
|
layerOptions = layerOptions.filter(layer => layer <= this.currentMaxLayer); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.editLayerOptions = layerOptions; |
|
|
// 如果当前选择的层数不在新的选项中,清空选择 |
|
|
// 如果当前选择的层数不在新的选项中,清空选择 |
|
|
// if (!this.editLayerOptions.includes(this.editLayer)) { |
|
|
// if (!this.editLayerOptions.includes(this.editLayer)) { |
|
|
// this.editLayer = ''; |
|
|
// this.editLayer = ''; |
|
|
@ -687,6 +923,9 @@ export default { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 设置loading状态,防止重复点击 |
|
|
|
|
|
this.editPositionLoading = true; |
|
|
|
|
|
|
|
|
updatePalletDetailPosition({ |
|
|
updatePalletDetailPosition({ |
|
|
site: this.site, |
|
|
site: this.site, |
|
|
palletId: this.palletCode, |
|
|
palletId: this.palletCode, |
|
|
@ -704,6 +943,9 @@ export default { |
|
|
}).catch(error => { |
|
|
}).catch(error => { |
|
|
console.error('位置修改失败:', error); |
|
|
console.error('位置修改失败:', error); |
|
|
this.$message.error('位置修改失败'); |
|
|
this.$message.error('位置修改失败'); |
|
|
|
|
|
}).finally(() => { |
|
|
|
|
|
// 无论成功或失败,都要恢复按钮状态 |
|
|
|
|
|
this.editPositionLoading = false; |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
@ -718,100 +960,80 @@ export default { |
|
|
this.editOriginalLayer = ''; |
|
|
this.editOriginalLayer = ''; |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 运输指令按钮点击事件 |
|
|
|
|
|
handleTransportOrder() { |
|
|
|
|
|
|
|
|
// 完成组托按钮点击事件 |
|
|
|
|
|
handleCompleteAssembly() { |
|
|
if (!this.palletCode) { |
|
|
if (!this.palletCode) { |
|
|
this.$message.error('请先扫描栈板'); |
|
|
this.$message.error('请先扫描栈板'); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
this.transportModalVisible = true; |
|
|
|
|
|
this.selectedStartStation = ''; |
|
|
|
|
|
this.selectedTargetStation = ''; |
|
|
|
|
|
this.targetStationOptions = []; |
|
|
|
|
|
|
|
|
// 检查是否有栈板明细 |
|
|
|
|
|
if (!this.detailList || this.detailList.length === 0) { |
|
|
|
|
|
this.$message.error('栈板明细为空,请先扫进物料'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 获取AGV站点列表 |
|
|
|
|
|
getAgvStations({}).then(({ data }) => { |
|
|
|
|
|
if (data.code === 0) { |
|
|
|
|
|
this.startStationOptions = data.stations || []; |
|
|
|
|
|
} else { |
|
|
|
|
|
this.$message.error(data.msg || '获取站点列表失败'); |
|
|
|
|
|
} |
|
|
|
|
|
}).catch(error => { |
|
|
|
|
|
console.error('获取站点列表失败:', error); |
|
|
|
|
|
this.$message.error('获取站点列表失败'); |
|
|
|
|
|
|
|
|
// 确认操作 |
|
|
|
|
|
this.$confirm('确认完成组托并推送数据到WCS系统吗?', '提示', { |
|
|
|
|
|
confirmButtonText: '确定', |
|
|
|
|
|
cancelButtonText: '取消', |
|
|
|
|
|
type: 'warning' |
|
|
|
|
|
}).then(() => { |
|
|
|
|
|
this.doCompleteAssembly(); |
|
|
|
|
|
}).catch(() => { |
|
|
|
|
|
// 用户取消 |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 起点站点选择变化 |
|
|
|
|
|
handleStartStationChange() { |
|
|
|
|
|
this.selectedTargetStation = ''; |
|
|
|
|
|
this.targetStationOptions = []; |
|
|
|
|
|
|
|
|
|
|
|
if (this.selectedStartStation) { |
|
|
|
|
|
getTargetStations({ |
|
|
|
|
|
startStation: this.selectedStartStation |
|
|
|
|
|
}).then(({ data }) => { |
|
|
|
|
|
if (data.code === 0) { |
|
|
|
|
|
this.targetStationOptions = data.targets || []; |
|
|
|
|
|
} else { |
|
|
|
|
|
this.$message.error(data.msg || '获取目标站点失败'); |
|
|
|
|
|
} |
|
|
|
|
|
}).catch(error => { |
|
|
|
|
|
console.error('获取目标站点失败:', error); |
|
|
|
|
|
this.$message.error('获取目标站点失败'); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 确认创建运输任务 |
|
|
|
|
|
confirmTransportTask() { |
|
|
|
|
|
if (!this.selectedStartStation) { |
|
|
|
|
|
this.$message.error('请选择起点站点'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if (!this.selectedTargetStation) { |
|
|
|
|
|
this.$message.error('请选择目标站点'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 执行完成组托 |
|
|
|
|
|
doCompleteAssembly() { |
|
|
|
|
|
// 设置loading状态,防止重复点击 |
|
|
|
|
|
this.completeAssemblyLoading = true; |
|
|
|
|
|
|
|
|
createPalletTransportTask({ |
|
|
|
|
|
|
|
|
completePalletAssembly({ |
|
|
site: this.site, |
|
|
site: this.site, |
|
|
palletId: this.palletCode, |
|
|
|
|
|
startStation: this.selectedStartStation, |
|
|
|
|
|
endStation: this.selectedTargetStation |
|
|
|
|
|
|
|
|
palletId: this.palletCode |
|
|
}).then(({ data }) => { |
|
|
}).then(({ data }) => { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
this.$message.success('运输任务创建成功'); |
|
|
|
|
|
this.closeTransportModal(); |
|
|
|
|
|
|
|
|
this.$message.success('组托完成,数据已推送到WCS系统'); |
|
|
|
|
|
// 清空页面数据,初始化页面 |
|
|
|
|
|
this.resetPage(); |
|
|
} else { |
|
|
} else { |
|
|
this.$message.error(data.msg || '创建运输任务失败'); |
|
|
|
|
|
|
|
|
this.$message.error(data.msg || '完成组托失败'); |
|
|
} |
|
|
} |
|
|
}).catch(error => { |
|
|
}).catch(error => { |
|
|
console.error('创建运输任务失败:', error); |
|
|
|
|
|
this.$message.error('创建运输任务失败'); |
|
|
|
|
|
|
|
|
console.error('完成组托失败:', error); |
|
|
|
|
|
this.$message.error('完成组托失败'); |
|
|
|
|
|
}).finally(() => { |
|
|
|
|
|
// 无论成功或失败,都要恢复按钮状态 |
|
|
|
|
|
this.completeAssemblyLoading = false; |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 关闭运输任务模态框 |
|
|
|
|
|
closeTransportModal() { |
|
|
|
|
|
this.transportModalVisible = false; |
|
|
|
|
|
this.selectedStartStation = ''; |
|
|
|
|
|
this.selectedTargetStation = ''; |
|
|
|
|
|
this.startStationOptions = []; |
|
|
|
|
|
this.targetStationOptions = []; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 确认Call栈板 |
|
|
// 确认Call栈板 |
|
|
confirmCallPallet() { |
|
|
confirmCallPallet() { |
|
|
if (!this.selectedCallStation) { |
|
|
|
|
|
this.$message.error('请选择站点'); |
|
|
|
|
|
|
|
|
if (!this.selectedCallStartStation) { |
|
|
|
|
|
this.$message.error('请选择起始站点'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if (!this.selectedCallTargetStation) { |
|
|
|
|
|
this.$message.error('请选择目标站点'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 前端验证:两个站点不能一样 |
|
|
|
|
|
if (this.selectedCallStartStation === this.selectedCallTargetStation) { |
|
|
|
|
|
this.$message.error('起始站点和目标站点不能相同'); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 设置loading状态,防止重复点击 |
|
|
|
|
|
this.callPalletLoading = true; |
|
|
|
|
|
|
|
|
callPalletToStation({ |
|
|
callPalletToStation({ |
|
|
site: this.site, |
|
|
site: this.site, |
|
|
station: this.selectedCallStation |
|
|
|
|
|
|
|
|
startStation: this.selectedCallStartStation, |
|
|
|
|
|
targetStation: this.selectedCallTargetStation |
|
|
}).then(({ data }) => { |
|
|
}).then(({ data }) => { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
this.$message.success('空托盘调用任务创建成功'); |
|
|
this.$message.success('空托盘调用任务创建成功'); |
|
|
@ -821,15 +1043,20 @@ export default { |
|
|
} |
|
|
} |
|
|
}).catch(error => { |
|
|
}).catch(error => { |
|
|
console.error('调用空托盘失败:', error); |
|
|
console.error('调用空托盘失败:', error); |
|
|
this.$message.error('调用空托盘失败'); |
|
|
|
|
|
|
|
|
this.$message.error('异常:'+error); |
|
|
|
|
|
}).finally(() => { |
|
|
|
|
|
// 无论成功或失败,都要恢复按钮状态 |
|
|
|
|
|
this.callPalletLoading = false; |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 关闭Call栈板模态框 |
|
|
// 关闭Call栈板模态框 |
|
|
closeCallPalletModal() { |
|
|
closeCallPalletModal() { |
|
|
this.callPalletModalVisible = false; |
|
|
this.callPalletModalVisible = false; |
|
|
this.selectedCallStation = ''; |
|
|
|
|
|
this.callStationOptions = []; |
|
|
|
|
|
|
|
|
this.selectedCallStartStation = ''; |
|
|
|
|
|
this.selectedCallTargetStation = ''; |
|
|
|
|
|
this.callStartStationOptions = []; |
|
|
|
|
|
this.callTargetStationOptions = []; |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
}, |
|
|
}, |
|
|
@ -885,13 +1112,9 @@ export default { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.col-serial { |
|
|
.col-serial { |
|
|
flex: 2; |
|
|
|
|
|
text-align: center; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.col-part { |
|
|
|
|
|
flex: 2; |
|
|
|
|
|
|
|
|
flex: 4; |
|
|
text-align: center; |
|
|
text-align: center; |
|
|
|
|
|
word-break: break-all; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 空数据提示 */ |
|
|
/* 空数据提示 */ |
|
|
@ -961,4 +1184,12 @@ export default { |
|
|
color: #999; |
|
|
color: #999; |
|
|
width: 100%; |
|
|
width: 100%; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 按钮禁用状态样式 */ |
|
|
|
|
|
.action-btn:disabled { |
|
|
|
|
|
opacity: 0.6; |
|
|
|
|
|
cursor: not-allowed; |
|
|
|
|
|
background-color: #ccc !important; |
|
|
|
|
|
border-color: #ccc !important; |
|
|
|
|
|
} |
|
|
</style> |
|
|
</style> |