Browse Source

提交栈板

dev
常熟吴彦祖 1 year ago
parent
commit
ae21f71d37
  1. 1
      src/api/automatedWarehouse/palletPacking.js
  2. 4
      src/router/index.js
  3. 9
      src/views/main.vue
  4. 645
      src/views/modules/automatedWarehouse/palletAssembly.vue
  5. 85
      src/views/modules/automatedWarehouse/palletPacking.vue

1
src/api/automatedWarehouse/palletPacking.js

@ -53,3 +53,4 @@ export const getPalletTypeAreas = data => createAPI(`/base/palletTypeArea/list`,
// 更新栈板类型和自动分拣标志 - AI制作
export const updatePalletTypeAndAutoSort = data => createAPI(`/wcsIntegration/updatePalletTypeAndAutoSort`,'post',data)
export const completePalletAssembly = data => createAPI(`/wcsIntegration/completePalletAssembly`,'post',data)

4
src/router/index.js

@ -103,7 +103,7 @@ const globalRoutes = [
{path: "/mrissue",name: "mrissue", component: resolve => require(["@/views/modules/mr-issue/index.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/mrPicking",name: "mrPicking", component: resolve => require(["@/views/modules/mr-issue/mrPicking.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/mrPickingDetail/:orderNo/:lineNo/:partNo/:material",name: "mrPickingDetail", component: resolve => require(["@/views/modules/mr-issue/mrPickingDetail.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
// MR退料
{path: "/mrPickingReturn", name: "mrPickingReturn", component: resolve => require(["@/views/modules/mr-issue/mrPickingReturn.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
{path: "/mrReturnIssueList", name: "mrReturnIssueList", component: resolve => require(["@/views/modules/mr-issue/mrReturnIssueList.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
@ -118,6 +118,8 @@ const globalRoutes = [
{path: "/callOut",name: "callOut", component: resolve => require(["@/views/modules/automatedWarehouse/callOut.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
// 立库-打托
{path: "/palletPacking",name: "palletPacking", component: resolve => require(["@/views/modules/automatedWarehouse/palletPacking.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
// 立库-打托
{path: "/palletAssembly",name: "palletAssembly", component: resolve => require(["@/views/modules/automatedWarehouse/palletAssembly.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
]

9
src/views/main.vue

@ -133,9 +133,14 @@
<div class="menu-icon purchase">
<van-icon name="shopping-cart-o" size="24" />
</div>
<div class="menu-text">立库打托</div>
<div class="menu-text">组盘入库</div>
</div>
<div class="menu-item" @click="navigateWithWarehouseCheck('palletAssembly')">
<div class="menu-icon purchase">
<van-icon name="shopping-cart-o" size="24" />
</div>
<div class="menu-text">直接组盘</div>
</div>
</div>
</div>
<!-- 库内管理 -->

645
src/views/modules/automatedWarehouse/palletPacking2.vue → src/views/modules/automatedWarehouse/palletAssembly.vue

@ -5,7 +5,7 @@
<div class="header-bar">
<div class="header-left" @click="handleBack">
<i class="el-icon-arrow-left"></i>
<span>打托</span>
<span>组托</span>
</div>
<div class="header-right" @click="$router.push({ path: '/' })">
首页
@ -36,45 +36,62 @@
</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>
<div style="flex: 0.65;">
<label class="input-label">栈板类型</label>
<el-select
v-model="selectedPosition"
placeholder="请选择位置"
v-model="currentPalletType"
placeholder="请选择栈板类型"
style="width: 100%;"
@change="handlePositionChange"
:disabled="palletTypeDisabled"
@change="handlePalletTypeChange"
>
<el-option label="ALL" value=""></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>
</div>
<div style="flex: 1;">
<label class="input-label">层数</label>
<div style="flex: 0.35;">
<label class="input-label">自动分拣</label>
<el-select
v-model="selectedLayer"
placeholder="请选择层数"
v-model="currentAutoSort"
placeholder="请选择"
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>
</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
class="action-btn secondary"
style="margin: 0; white-space: nowrap;"
style="flex: 0.25; margin: 0; white-space: nowrap;"
@click="refreshTable"
>
刷新
@ -82,21 +99,21 @@
</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;">
<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="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;"
style="flex: 0.25; margin: 0; white-space: nowrap;"
@click="showScanModal"
>
扫描二维码
扫描条码
</button>
</div>
</div>
@ -104,16 +121,17 @@
<!-- 栈板明细表格 (扫描栈板后显示) -->
<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 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"
@ -124,7 +142,6 @@
<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">
@ -169,6 +186,7 @@
<el-select
v-model="scanLayer"
placeholder="请选择层数"
@change="moveFocusToScanInput"
style="width: 100%;"
>
<el-option
@ -260,15 +278,17 @@
</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>
<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>
</el-dialog>
<!-- 运输任务模态框 -->
<!-- Call栈板模态框 -->
<el-dialog
title="创建运输任务"
:visible.sync="transportModalVisible"
title="调用空托盘"
:visible.sync="callPalletModalVisible"
width="90%"
:close-on-click-modal="false"
:show-close="false"
@ -276,29 +296,18 @@
: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="call-modal-content">
<!-- 起始站点选择 -->
<div class="input-group">
<label class="input-label">起点站点</label>
<label class="input-label">起始站点</label>
<el-select
v-model="selectedStartStation"
placeholder="请选择起点站点"
v-model="selectedCallStartStation"
placeholder="请选择起始站点"
style="width: 100%;"
@change="handleStartStationChange"
@change="handleCallStartStationChange"
>
<el-option
v-for="station in startStationOptions"
v-for="station in callStartStationOptions"
:key="station.stationCode"
:label="`${station.stationCode} - ${station.stationName}`"
:value="station.stationCode"
@ -306,84 +315,46 @@
</el-select>
</div>
<!-- 目标站点选择 -->
<!-- 目标站点输入 -->
<div class="input-group">
<label class="input-label">目标站点</label>
<el-select
v-model="selectedTargetStation"
placeholder="请先选择起点站点"
<el-input
ref="callTargetStationInput"
v-model="selectedCallTargetStation"
placeholder="请扫描或输入目标站点"
clearable
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 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>
</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>
</template>
<script>
import {
checkPalletExists,
getPalletPositions,
getPalletDetails,
getLayersByPosition,
validateLabel,
savePalletDetail,
deletePalletDetail,
getLayersForEdit,
updatePalletDetailPosition,
getPalletInfo,
getPalletTypeList,
getPalletTypeAreas,
updatePalletTypeAndAutoSort,
getAgvStations,
getTargetStations,
createPalletTransportTask,
callPalletToStation
callPalletToStation,
completePalletAssembly
} from '../../../api/automatedWarehouse/palletPacking'
export default {
@ -394,6 +365,16 @@ export default {
palletScanned: false,
operationType: 'in', // 'in' 或 'out'
// 栈板类型和自动分拣
currentPalletFamily: '', // 当前栈板大分类(固定不可改)
currentPalletType: '', // 当前栈板类型
currentAutoSort: '', // 当前是否自动分拣 Y/N
palletTypeOptions: [], // 托盘类型选项列表
palletTypeDisabled: false, // 栈板类型下拉框是否禁用(有明细数据时禁用)
autoSortDisabled: false, // 自动分拣下拉框是否禁用
currentWcsAutoSort: '', // 当前托盘类型的wcsAutoSort值
currentMaxLayer: 0, // 当前托盘类型的最大层数,0=无限
// 筛选条件
selectedPosition: '',
selectedLayer: '',
@ -411,17 +392,12 @@ export default {
// 栈板明细
detailList: [],
// 运输任务模态框
transportModalVisible: false,
startStationOptions: [],
targetStationOptions: [],
selectedStartStation: '',
selectedTargetStation: '',
// Call栈板模态框
callPalletModalVisible: false,
callStationOptions: [],
selectedCallStation: '',
callStartStationOptions: [], // 起始站点选项(statusDb=1,有货)
callTargetStationOptions: [], // 目标站点选项(statusDb=0,空闲)
selectedCallStartStation: '',
selectedCallTargetStation: '',
// 修改位置模态框
editPositionModalVisible: false,
@ -431,6 +407,11 @@ export default {
editLayerOptions: [],
editOriginalPosition: '',
editOriginalLayer: '',
// 按钮loading状态(防止重复点击)
editPositionLoading: false, // 修改位置按钮
callPalletLoading: false, // Call栈板按钮
completeAssemblyLoading: false, // 完成组托按钮
};
},
methods: {
@ -438,6 +419,59 @@ export default {
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() {
if (!this.palletCode.trim()) {
@ -452,7 +486,10 @@ export default {
if (data.code === 0) {
this.palletScanned = true;
this.positionOptions = data.positions || [];
this.$message.success('栈板验证成功');
// 获取栈板详细信息(包括palletType和autoSort)
this.loadPalletInfo();
this.refreshTable();
} else {
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栈板 - 调用空托盘
handleCallPallet() {
this.callPalletModalVisible = true;
this.selectedCallStation = '';
this.selectedCallStartStation = '';
this.selectedCallTargetStation = '';
// 获取AGV站点列表
// 获取AGV站点列表,分别过滤起始站点和目标站点
getAgvStations({}).then(({ data }) => {
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 {
this.$message.error(data.msg || '获取站点列表失败');
}
@ -481,7 +658,16 @@ export default {
});
},
// 位置选择变化
// 起始站点选择change事件,自动聚焦到目标站点输入框
handleCallStartStationChange() {
this.$nextTick(() => {
if (this.$refs.callTargetStationInput) {
this.$refs.callTargetStationInput.focus();
}
});
},
// 位置选择变化
handlePositionChange() {
if (this.selectedPosition) {
getLayersByPosition({
@ -511,12 +697,27 @@ export default {
}).then(({ data }) => {
if (data.code === 0) {
this.detailList = data.details || [];
// 如果栈板有明细数据,禁用栈板类型和自动分拣的修改
const hasDetails = this.detailList.length > 0;
this.palletTypeDisabled = hasDetails;
// 如果有明细数据,自动分拣也要禁用;否则根据wcsAutoSort判断
if (hasDetails) {
this.autoSortDisabled = true;
} else {
this.updateAutoSortControl();
}
} else {
this.detailList = [];
this.palletTypeDisabled = false;
this.updateAutoSortControl();
}
}).catch(error => {
console.error('获取栈板明细失败:', error);
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() {
this.scanModalVisible = false;
@ -548,17 +756,29 @@ export default {
// 扫码模态框中位置变化
handleScanPositionChange() {
if (this.scanPosition) {
// maxLayer=0表示混装托盘,只能选第1层
if (this.currentMaxLayer === 0) {
this.scanLayerOptions = [1];
this.scanLayer = 1; // 自动选中第1层
this.moveFocusToScanInput();
return;
}
// maxLayer>0,根据已有层数和maxLayer计算可选层数
getLayersByPosition({
site: this.site,
palletId: this.palletCode,
position: this.scanPosition
}).then(({ data }) => {
if (data.code === 0) {
const maxLayer = data.layers && data.layers.length > 0
const existingMaxLayer = data.layers && data.layers.length > 0
? Math.max(...data.layers)
: 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 => {
console.error('获取层数失败:', error);
@ -647,6 +867,14 @@ export default {
// 编辑位置选择变化
handleEditPositionChange() {
if (this.editPosition) {
// maxLayer=0表示混装托盘,只能选第1层
if (this.currentMaxLayer === 0) {
this.editLayerOptions = [1];
this.editLayer = 1; // 自动选中第1层
return;
}
// maxLayer>0,根据已有层数和maxLayer计算可选层数
getLayersForEdit({
site: this.site,
palletId: this.palletCode,
@ -654,7 +882,15 @@ export default {
excludeSerialNo: this.editSerialNo
}).then(({ data }) => {
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)) {
// this.editLayer = '';
@ -687,6 +923,9 @@ export default {
return;
}
// 设置loading状态,防止重复点击
this.editPositionLoading = true;
updatePalletDetailPosition({
site: this.site,
palletId: this.palletCode,
@ -704,6 +943,9 @@ export default {
}).catch(error => {
console.error('位置修改失败:', error);
this.$message.error('位置修改失败');
}).finally(() => {
// 无论成功或失败,都要恢复按钮状态
this.editPositionLoading = false;
});
},
@ -718,100 +960,80 @@ export default {
this.editOriginalLayer = '';
},
// 运输指令按钮点击事件
handleTransportOrder() {
// 完成组托按钮点击事件
handleCompleteAssembly() {
if (!this.palletCode) {
this.$message.error('请先扫描栈板');
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,
palletId: this.palletCode,
startStation: this.selectedStartStation,
endStation: this.selectedTargetStation
palletId: this.palletCode
}).then(({ data }) => {
if (data.code === 0) {
this.$message.success('运输任务创建成功');
this.closeTransportModal();
this.$message.success('组托完成,数据已推送到WCS系统');
// 清空页面数据,初始化页面
this.resetPage();
} else {
this.$message.error(data.msg || '创建运输任务失败');
this.$message.error(data.msg || '完成组托失败');
}
}).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栈板
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;
}
// 设置loading状态,防止重复点击
this.callPalletLoading = true;
callPalletToStation({
site: this.site,
station: this.selectedCallStation
startStation: this.selectedCallStartStation,
targetStation: this.selectedCallTargetStation
}).then(({ data }) => {
if (data.code === 0) {
this.$message.success('空托盘调用任务创建成功');
@ -821,15 +1043,20 @@ export default {
}
}).catch(error => {
console.error('调用空托盘失败:', error);
this.$message.error('调用空托盘失败');
this.$message.error('异常:'+error);
}).finally(() => {
// 无论成功或失败,都要恢复按钮状态
this.callPalletLoading = false;
});
},
// 关闭Call栈板模态框
closeCallPalletModal() {
this.callPalletModalVisible = false;
this.selectedCallStation = '';
this.callStationOptions = [];
this.selectedCallStartStation = '';
this.selectedCallTargetStation = '';
this.callStartStationOptions = [];
this.callTargetStationOptions = [];
},
},
@ -885,13 +1112,9 @@ export default {
}
.col-serial {
flex: 2;
text-align: center;
}
.col-part {
flex: 2;
flex: 4;
text-align: center;
word-break: break-all;
}
/* 空数据提示 */
@ -961,4 +1184,12 @@ export default {
color: #999;
width: 100%;
}
/* 按钮禁用状态样式 */
.action-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
background-color: #ccc !important;
border-color: #ccc !important;
}
</style>

85
src/views/modules/automatedWarehouse/palletPacking.vue

@ -484,6 +484,65 @@ export default {
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.transportModalVisible = false;
this.transportAreaOptions = [];
this.currentPalletStation = '';
this.selectedTargetArea = '';
// 清空修改位置模态框
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() {
if (!this.palletCode.trim()) {
@ -653,10 +712,14 @@ export default {
getAgvStations({}).then(({ data }) => {
if (data.code === 0) {
const allStations = data.stations || [];
// 起始站点:过滤出statusDb为1(有货)的站点
this.callStartStationOptions = allStations.filter(station => station.statusDb === '1');
// 目标站点:过滤出statusDb为0(空闲)的站点
this.callTargetStationOptions = allStations.filter(station => station.statusDb === '0');
// 起始站点:过滤出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 {
this.$message.error(data.msg || '获取站点列表失败');
}
@ -992,13 +1055,15 @@ export default {
this.selectedTargetArea = '';
this.transportAreaOptions = [];
// 获取所有AGV站点列表,只显示空闲站点(statusDb = 0)的区域
// 获取所有AGV站点列表,只显示空闲站点(statusDb = 0)且站点类型为正式站点的区域
getAgvStations({}).then(({ data }) => {
if (data.code === 0) {
// 过滤出statusDb为0(空闲)的站点
const freeStations = (data.stations || []).filter(station => station.statusDb === 0);
// 过滤出statusDb为0(空闲)且stationType为'正式站点'的站点
const freeStations = (data.stations || []).filter(station =>
station.statusDb === 0 && station.stationType === '正式站点'
);
console.log('空闲站点数量:', freeStations.length);
console.log('空闲且为正式站点的数量:', freeStations.length);
// 提取station_area并去重(只提取有stationArea的站点)
const areaMap = new Map();
@ -1060,8 +1125,8 @@ export default {
if (data.code === 0) {
this.$message.success('栈板运输任务创建成功');
this.closeTransportModal();
// 可能需要刷新栈板明细来反映组盘状态的变化
this.refreshTable();
// 清空页面数据,初始化页面
this.resetPage();
} else {
this.$message.error(data.msg || '创建运输任务失败');
}

Loading…
Cancel
Save