常熟吴彦祖 21 hours ago
parent
commit
2274aded40
  1. 7
      src/api/haianAutoWarehouse/callOut.js
  2. 4
      src/api/haianAutoWarehouse/callOutToStation.js
  3. 7
      src/api/haianAutoWarehouse/palletChangeStation.js
  4. 75
      src/api/haianAutoWarehouse/palletPacking.js
  5. 5
      src/router/index.js
  6. 33
      src/views/main.vue
  7. 538
      src/views/modules/haianAutoWarehouse/haianCallOutToStation.vue
  8. 1216
      src/views/modules/haianAutoWarehouse/haianPalletPacking.vue
  9. 601
      src/views/modules/haianAutoWarehouse/haianPalletSearch.vue
  10. 1064
      src/views/modules/haianAutoWarehouse/haianPalletSorting.vue

7
src/api/haianAutoWarehouse/callOut.js

@ -0,0 +1,7 @@
import { createAPI } from "@/utils/httpRequest.js";
// 海安-按物料/批次/托盘号查询可Call料栈板清单 - rqrq
export const getPalletList = data => createAPI(`/haiAnWcsIntegration/palletListForPartNo`, 'post', data)
// 海安-旧页面兼容占位:当前页面未实际使用IFS查料接口 - rqrq
export const getShopOrderFromIFSWithOrderNo = data => createAPI(`/haiAnWcsIntegration/palletListForPartNo`, 'post', data)

4
src/api/haianAutoWarehouse/callOutToStation.js

@ -0,0 +1,4 @@
import { createAPI } from "@/utils/httpRequest.js";
// 海安-Call料到指定区域/站点(立库开关分流)- rqrq
export const callOutToStation = data => createAPI(`/haiAnWcsIntegration/callOutToStation`, 'post', data)

7
src/api/haianAutoWarehouse/palletChangeStation.js

@ -0,0 +1,7 @@
import { createAPI } from "@/utils/httpRequest.js";
// 海安-获取可选区域(choose_able=Y)- rqrq
export const getAreaOptionsForChange = data => createAPI(`/haiAnWcsIntegration/getAreaOptionsForChange`, 'post', data)
// 海安-按区域获取站点清单(locationCode/status)- rqrq
export const getStationsByArea = data => createAPI(`/haiAnWcsIntegration/getStationsByArea`, 'post', data)

75
src/api/haianAutoWarehouse/palletPacking.js

@ -0,0 +1,75 @@
import { createAPI } from "@/utils/httpRequest.js";
// 海安-检查栈板并返回基础信息(含位置清单)- rqrq
export const checkPalletExists = data => createAPI(`/haiAnWcsIntegration/checkPalletExists`, 'post', data)
// 海安-简单查询栈板信息(查看托盘入口)- rqrq
export const getPalletInfoSimple = data => createAPI(`/haiAnWcsIntegration/getPalletInfoSimple`, 'post', data)
// 海安-获取栈板明细 - rqrq
export const getPalletDetails = data => createAPI(`/haiAnWcsIntegration/getPalletDetails`, 'post', data)
// 海安-扫进保存明细 - rqrq
export const savePalletDetail = data => createAPI(`/haiAnWcsIntegration/savePalletDetail`, 'post', data)
// 海安-扫出删除明细 - rqrq
export const deletePalletDetail = data => createAPI(`/haiAnWcsIntegration/deletePalletDetail`, 'post', data)
// 海安-分拣扫回恢复原明细 - rqrq
export const restorePalletDetail = data => createAPI(`/haiAnWcsIntegration/restorePalletDetail`, 'post', data)
// 海安-查询标签当前所在明细 - rqrq
export const getLabelInfo = data => createAPI(`/haiAnWcsIntegration/getLabelInfo`, 'post', data)
// 海安-编辑位置时获取可用层数 - rqrq
export const getLayersForEdit = data => createAPI(`/haiAnWcsIntegration/getLayersForEdit`, 'post', data)
// 海安-更新标签位置层数 - rqrq
export const updatePalletDetailPosition = data => createAPI(`/haiAnWcsIntegration/updatePalletDetailPosition`, 'post', data)
// 海安-获取指定层可用位置 - rqrq
export const getAvailablePositionsForLayer = data => createAPI(`/haiAnWcsIntegration/getAvailablePositionsForLayer`, 'post', data)
// 海安-获取栈板扩展信息(托盘类型/站点等)- rqrq
export const getPalletInfo = data => createAPI(`/haiAnWcsIntegration/getPalletInfo`, 'post', data)
// 海安-获取托盘类型列表(由海安后端统一路由)- rqrq
export const getPalletTypeList = data => createAPI(`/haiAnWcsIntegration/getPalletTypeList`, 'post', data)
// 海安-获取托盘类型位置配置(由海安后端统一路由)- rqrq
export const getPalletTypeAreas = data => createAPI(`/haiAnWcsIntegration/getPalletTypeAreas`, 'post', data)
// 海安-更新栈板类型与自动分拣配置 - rqrq
export const updatePalletTypeAndAutoSort = data => createAPI(`/haiAnWcsIntegration/updatePalletTypeAndAutoSort`, 'post', data)
// 海安-提交分拣 - rqrq
export const completePalletAssemblyForFenJian = data => createAPI(`/haiAnWcsIntegration/completePalletAssemblyForFenJian`, 'post', data)
// 海安-组盘运输入库(立库接口分流)- rqrq
export const callPalletToStationWithUpdateZuPan = data => createAPI(`/haiAnWcsIntegration/callPalletToStationWithUpdateZuPan`, 'post', data)
// 海安-调用空托盘 - rqrq
export const callEmptyPalletToStation = data => createAPI(`/haiAnWcsIntegration/callEmptyPalletToStation`, 'post', data)
// 海安-结束分拣 - rqrq
export const finishSorting = data => createAPI(`/haiAnWcsIntegration/finishSorting`, 'post', data)
// 海安-查询分拣清单 - rqrq
export const getSortingList = data => createAPI(`/haiAnWcsIntegration/getSortingList`, 'post', data)
// 海安-查看托盘预留标签列表 - rqrq
export const getPalletReservedLabels = data => createAPI(`/haiAnWcsIntegration/getPalletReservedLabels`, 'post', data)
// 海安-一键取消托盘预留 - rqrq
export const batchCancelReserve = data => createAPI(`/haiAnWcsIntegration/batchCancelReserve`, 'post', data)
// 海安-旧页面兼容占位(当前无需调用)- rqrq
export const getPalletPositions = data => createAPI(`/haiAnWcsIntegration/checkPalletExists`, 'post', data)
export const getLayersByPosition = data => createAPI(`/haiAnWcsIntegration/getLayersForEdit`, 'post', data)
export const validateLabel = data => createAPI(`/haiAnWcsIntegration/getLabelInfo`, 'post', data)
export const getAgvStations = data => createAPI(`/haiAnWcsIntegration/getStationsByArea`, 'post', data)
export const getAvailableAgvStations = data => createAPI(`/haiAnWcsIntegration/getStationsByArea`, 'post', data)
export const callPalletToStation = data => createAPI(`/haiAnWcsIntegration/callPalletToStationWithUpdateZuPan`, 'post', data)
export const createPalletTransportTask = data => createAPI(`/haiAnWcsIntegration/callPalletToStationWithUpdateZuPan`, 'post', data)
export const completePalletAssembly = data => createAPI(`/haiAnWcsIntegration/completePalletAssemblyForFenJian`, 'post', data)
export const finishSortingNoAgv = data => createAPI(`/haiAnWcsIntegration/finishSorting`, 'post', data)

5
src/router/index.js

@ -148,6 +148,11 @@ const globalRoutes = [
{path: "/palletSortingNoAgv",name: "palletSortingNoAgv", component: resolve => require(["@/views/modules/automatedWarehouse/palletSortingNoAgv.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/palletMerge",name: "palletMerge", component: resolve => require(["@/views/modules/automatedWarehouse/palletMerge.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/callOutForHetuo",name: "palletMerge", component: resolve => require(["@/views/modules/automatedWarehouse/callOutForHetuo.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
// 海安立库固定路由(工厂54)- rqrq
{path: "/haianCallOutToStation",name: "haianCallOutToStation", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianCallOutToStation.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/haianPalletPacking",name: "haianPalletPacking", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletPacking.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/haianPalletSorting",name: "haianPalletSorting", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletSorting.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/haianPalletSearch",name: "haianPalletSearch", component: resolve => require(["@/views/modules/haianAutoWarehouse/haianPalletSearch.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
]

33
src/views/main.vue

@ -120,6 +120,39 @@
</div> -->
</div>
</div>
<!-- 海安立库操作固定开放工厂54- rqrq -->
<div class="section" v-site-auth="'54'">
<div class="section-header">
<span class="bullet"></span>
<span class="section-title">海安立库操作</span>
</div>
<div class="button-grid">
<div class="menu-item" v-site-auth="'54'" @click="navigateWithWarehouseCheck('haianCallOutToStation')">
<div class="menu-icon purchase">
<van-icon name="shopping-cart-o" size="24" />
</div>
<div class="menu-text">海安立库取货</div>
</div>
<div class="menu-item" v-site-auth="'54'" @click="navigateWithWarehouseCheck('haianPalletPacking')">
<div class="menu-icon purchase">
<van-icon name="shopping-cart-o" size="24" />
</div>
<div class="menu-text">海安组盘入库</div>
</div>
<div class="menu-item" v-site-auth="'54'" @click="navigateWithWarehouseCheck('haianPalletSorting')">
<div class="menu-icon purchase">
<van-icon name="shopping-cart-o" size="24" />
</div>
<div class="menu-text">海安分拣组盘</div>
</div>
<div class="menu-item" v-site-auth="'54'" @click="navigateWithWarehouseCheck('haianPalletSearch')">
<div class="menu-icon purchase">
<van-icon name="shopping-cart-o" size="24" />
</div>
<div class="menu-text">海安查看托盘</div>
</div>
</div>
</div>
<div class="section" v-site-auth="'55'">
<div class="section-header">
<span class="bullet"></span>

538
src/views/modules/haianAutoWarehouse/haianCallOutToStation.vue

@ -0,0 +1,538 @@
<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>Call料到指定位置</span>
</div>
<div class="header-right" @click="$router.push({ path: '/' })">
首页
</div>
</div>
<div class="table-body" style="max-height: 500px; overflow-y: auto;">
<div class="main-content form-section">
<!-- 表单区域 - rqrq -->
<div class="input-group">
<label class="input-label">物料编码</label>
<el-input
v-model="formData.partNo"
placeholder="请输入物料编码"
class="form-input"
ref="partNoInput"
clearable
/>
</div>
<!-- @blur="handlePartNoBlur"-->
<!-- 栈板编码搜索框 - rqrq -->
<div class="input-group">
<label class="input-label">栈板编码</label>
<el-input
v-model="formData.palletId"
placeholder="请输入栈板编码"
class="form-input"
clearable
/>
</div>
<!-- <div class="input-group">-->
<!-- <label class="input-label">物料名称</label>-->
<!-- <el-input-->
<!-- v-model="formData.partDesc"-->
<!-- disabled-->
<!-- class="form-input"-->
<!-- />-->
<!-- </div>-->
<div class="input-group">
<label class="input-label">批号</label>
<el-input
v-model="formData.batchNo"
class="form-input"
clearable
/>
</div>
<div class="bottom-actions" style="display: flex; gap: 10px; flex-wrap: nowrap;">
<button class="action-btn secondary" @click="confirmDo" style="flex: 1;">
查询
</button>
<button class="action-btn secondary" @click="cleanData" style="flex: 1;">
清空
</button>
<button
class="action-btn secondary"
@click="handleTransportPallet"
:disabled="!selectedPallet"
style="flex: 1;"
>
运输栈板
</button>
</div>
</div>
<!-- 栈板列表 - rqrq单选模式-->
<div v-if="palletList.length > 0" class="rma-list">
<div class="list-title" style="flex: 0.75">可用栈板列表单选</div>
<el-form>
<el-row v-for="(pallet, index) in palletList" :key="index" class="rma-row">
<el-col :span="24">
<div class="rma-item" @click="selectPallet(pallet)" :class="{ 'selected': isSelected(pallet) }">
<div class="item-info">
<span class="part-no">栈板号: {{ pallet.palletId }}</span>
<!-- rqrq - 如果有物料编码显示明细否则只显示栈板 -->
<span class="batch-qty" v-if="pallet.partNo">
物料: {{ pallet.partNo }} | 数量: {{ pallet.qty }}
</span>
<span class="batch-qty" v-if="pallet.partNo && pallet.batchNo">
| 批号: {{ pallet.batchNo }}
</span>
<span class="batch-qty" v-if="pallet.partNo && pallet.receiveDate">
| 接收日期: {{ pallet.receiveDate }}
</span>
</div>
<div class="item-status">
<i class="el-icon-check" v-if="isSelected(pallet)"></i>
</div>
</div>
</el-col>
</el-row>
</el-form>
</div>
</div>
</div>
<!-- 选择区域和站点弹窗 - rqrq -->
<el-dialog
title="选择目标位置"
:visible.sync="locationModalVisible"
width="90%"
:close-on-click-modal="false"
:show-close="false"
:modal="true"
:modal-append-to-body="true"
:append-to-body="true"
>
<div class="location-selection">
<!-- 选择区域 - 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>
</div>
<div slot="footer" class="dialog-footer" style="display: flex; gap: 8px;">
<button class="action-btn secondary" @click="locationModalVisible=false" style="flex: 1;">
取消
</button>
<button
class="action-btn primary"
@click="handleConfirmLocation"
:disabled="submitLoading || !selectedArea"
style="flex: 1;">
{{ submitLoading ? '处理中...' : '确认' }}
</button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
getShopOrderFromIFSWithOrderNo,
getPalletList
} from '../../../api/haianAutoWarehouse/callOut'
import {
getAreaOptionsForChange,
getStationsByArea
} from '../../../api/haianAutoWarehouse/palletChangeStation'
import {
callOutToStation
} from '../../../api/haianAutoWarehouse/callOutToStation'
export default {
name: 'haianCallOutToStation',
data() {
return {
username: localStorage.getItem('username'),
// - rqrq
formData: {
palletId: '',
partNo: '',
partDesc: '',
batchNo: '',
site: this.$store.state.user.site
},
// - rqrq
palletList: [],
selectedPallet: null, // - rqrq
// - rqrq
locationModalVisible: false,
selectedArea: '',
selectedStation: '',
areaOptions: [],
stationOptions: [],
// - rqrq
loading: false,
submitLoading: false
};
},
computed: {
// sitestore - rqrq
site() {
return this.$store.state.user.site
}
},
methods: {
// - rqrq
handleBack() {
// keep-alive - rqrq
this.resetPage(false);
this.$router.back();
},
// Call退 - rqrq
resetPage(needFocus = true) {
this.formData = {
palletId: '',
partNo: '',
partDesc: '',
batchNo: '',
site: this.site
};
this.palletList = [];
this.selectedPallet = null;
this.locationModalVisible = false;
this.selectedArea = '';
this.selectedStation = '';
this.areaOptions = [];
this.stationOptions = [];
this.loading = false;
this.submitLoading = false;
if (needFocus) {
this.$nextTick(() => {
if (this.$refs.partNoInput) {
this.$refs.partNoInput.focus();
}
});
}
},
// - rqrq
async handlePartNoBlur() {
const partNo = this.formData.partNo;
if (!partNo) {
this.formData.partDesc = '';
return;
}
this.loading = true;
getShopOrderFromIFSWithOrderNo({
site: this.formData.site,
partNo: partNo
}).then(({ data }) => {
this.loading = false;
if (data.code === 0) {
let rows = data.rows
if (rows.length > 0) {
this.formData.partDesc = rows[0].description || '';
} else {
this.formData.partDesc = '';
this.$alert('没有找到该物料编码', '错误', {
confirmButtonText: '确定',
})
}
} else {
this.formData.partDesc = '';
this.$alert(data.msg, '错误', {
confirmButtonText: '确定',
})
}
})
},
// - rqrq
confirmDo() {
if ((!this.formData.partNo || this.formData.partNo === '') &&
(!this.formData.palletId || this.formData.palletId === '')) {
this.$alert('请输入物料编码或栈板编码', '提示', {
confirmButtonText: '确定'
});
return;
}
if (!this.site) {
this.$alert('当前用户缺少site,无法查询', '提示', {
confirmButtonText: '确定'
});
return;
}
const queryParams = {
site: this.site
};
if (this.formData.palletId && this.formData.palletId.trim()) {
queryParams.palletId = this.formData.palletId.trim();
}
if (this.formData.partNo && this.formData.partNo.trim()) {
queryParams.partNo = this.formData.partNo.trim();
}
if (this.formData.batchNo && this.formData.batchNo.trim()) {
queryParams.batchNo = this.formData.batchNo.trim();
}
getPalletList(queryParams).then(({ data }) => {
if (data && data.code === 0) {
this.palletList = data.rows || [];
if (this.palletList.length === 0) {
this.$message.warning('未找到满足条件的栈板');
} else {
this.$message.success(`找到 ${this.palletList.length} 个栈板`);
}
this.selectedPallet = null; // - rqrq
} else {
this.$alert(data.msg || '查询失败', '错误', {
confirmButtonText: '确定'
});
this.palletList = [];
this.selectedPallet = null;
}
}).catch(error => {
console.error('查询栈板列表失败:', error);
this.$alert(error.message || '查询失败', '错误', {
confirmButtonText: '确定'
});
this.palletList = [];
this.selectedPallet = null;
});
},
// - rqrq
selectPallet(pallet) {
if (this.selectedPallet && this.selectedPallet.palletId === pallet.palletId) {
// - rqrq
this.selectedPallet = null;
this.$message.success('已取消选择');
} else {
// - rqrq
this.selectedPallet = {
site: pallet.site,
palletId: pallet.palletId,
partNo: pallet.partNo || '',
qty: pallet.qty || 0,
batchNo: pallet.batchNo || this.formData.batchNo || ''
};
this.$message.success(`已选择栈板: ${pallet.palletId}`);
}
},
// - rqrq
isSelected(pallet) {
return this.selectedPallet && this.selectedPallet.palletId === pallet.palletId;
},
// - rqrq
handleTransportPallet() {
if (!this.selectedPallet) {
this.$alert('请选择一个栈板', '提示', {
confirmButtonText: '确定'
});
return;
}
// - rqrq
this.loadAreaOptions();
this.locationModalVisible = true;
},
// - rqrq
loadAreaOptions() {
getAreaOptionsForChange({
site: this.site
}).then(({ data }) => {
if (data.code === 0) {
// Z199CallZ199 - rqrq
const allOptions = data.rows || [];
this.areaOptions = allOptions.filter(area => area.areaId !== 'Z199');
} else {
this.areaOptions = [];
this.$alert('获取区域选项失败', '错误', {
confirmButtonText: '确定'
});
}
}).catch(error => {
console.error('获取区域选项失败:', error);
this.areaOptions = [];
});
},
// - rqrq
handleAreaChange(areaId) {
this.selectedStation = '';
this.stationOptions = [];
if (!areaId) {
return;
}
getStationsByArea({
site: this.site,
areaId: areaId
}).then(({ data }) => {
if (data.code === 0) {
this.stationOptions = data.rows || [];
} else {
this.stationOptions = [];
this.$alert('获取站点选项失败', '错误', {
confirmButtonText: '确定'
});
}
}).catch(error => {
console.error('获取站点选项失败:', error);
this.stationOptions = [];
});
},
// - rqrq
handleConfirmLocation() {
if (!this.selectedArea) {
this.$alert('请选择目标区域', '提示', {
confirmButtonText: '确定'
});
return;
}
// - rqrq
this.$confirm('确定要叫料并运输到指定位置?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.submitLoading = true;
const params = {
site: this.site,
palletId: this.selectedPallet.palletId,
partNo: this.selectedPallet.partNo,
qty: this.selectedPallet.qty,
batchNo: this.selectedPallet.batchNo,
targetArea: this.selectedArea,
targetStation: this.selectedStation || '', // - rqrq
username: this.username
};
// - rqrq
callOutToStation(params).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success('任务下达成功');
this.locationModalVisible = false;
this.cleanData();
} else {
this.$alert(data.msg || '任务下达失败', '错误', {
confirmButtonText: '确定'
});
}
}).catch(error => {
console.error('任务下达失败:', error);
this.$alert(error.message || '任务下达失败', '错误', {
confirmButtonText: '确定'
});
}).finally(() => {
this.submitLoading = false;
});
}).catch(() => {
// - rqrq
});
},
// - rqrq
cleanData() {
// 退 - rqrq
this.resetPage(true);
}
},
// keep-alive - rqrq
activated() {
this.resetPage(true);
},
// - rqrq
beforeRouteLeave(to, from, next) {
this.resetPage(false);
next();
},
mounted() {
this.resetPage(true);
}
};
</script>
<style scoped>
/* 按钮禁用状态样式 - rqrq */
.action-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
background-color: #ccc !important;
border-color: #ccc !important;
}
/* 位置选择区域样式 - rqrq */
.location-selection {
padding: 10px 0;
}
.dialog-footer {
text-align: center;
}
/* 修复模态框层级问题 - rqrq */
::v-deep .el-dialog__wrapper {
z-index: 2000 !important;
}
::v-deep .el-overlay {
z-index: 2000 !important;
}
</style>

1216
src/views/modules/haianAutoWarehouse/haianPalletPacking.vue
File diff suppressed because it is too large
View File

601
src/views/modules/haianAutoWarehouse/haianPalletSearch.vue

@ -0,0 +1,601 @@
<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="table-body" style="max-height: 500px; 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="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="flex: 0.25; margin: 0; white-space: nowrap;"
@click="refreshTable"
>
刷新
</button>
</div>
</div>
</div>
<!-- 栈板明细表格 (扫描栈板后显示) - rqrq -->
<div v-if="palletScanned" class="rma-list">
<div class="list-title-row" style="display: flex; gap: 8px; align-items: center; padding: 0;">
<div class="list-title" style="flex: 1; margin: 0; display: flex; align-items: center; flex-wrap: wrap; gap: 5px;">
<button class="action-btn primary" style="margin: 0;" @click="showDetailModal" >
{{ '浏览明细' }}
</button>
<label style="margin-left: 5px;">条码数:{{detailList.length}}</label>
<!-- 预留清单按钮 - rqrq -->
<button
class="action-btn"
:class="reserveCount > 0 ? 'warning' : 'secondary'"
style="margin: 0; margin-left: 10px;"
@click="showReserveModal">
预留清单({{ reserveCount }})
</button>
</div>
</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>
<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>
</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="'预留清单 (共'+reserveCount+'条)'"
:visible.sync="reserveModalVisible"
width="95%"
: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: 350px; overflow-y: auto;">
<div class="detail-table">
<div class="table-header reserve-header">
<div class="col-serial-reserve">标签号</div>
<div class="col-ref">申请单号</div>
<div class="col-ref">订单号</div>
</div>
<div
v-for="(item, index) in reservedLabels"
:key="index"
class="table-row"
>
<div class="col-serial-reserve">{{ item.serialNo || '-' }}</div>
<div class="col-ref">{{ item.reserveOrderRef1 || '-' }}</div>
<div class="col-ref">{{ item.reserveOrderRef3 || '-' }}</div>
</div>
<!-- 暂无数据提示 -->
<div v-if="reservedLabels.length === 0" class="table-row empty-row">
<div class="empty-hint">暂无预留标签</div>
</div>
</div>
</div>
<div slot="footer" class="dialog-footer" style="display: flex; gap: 10px; justify-content: center;">
<button class="action-btn secondary" @click="reserveModalVisible=false" :disabled="cancelReserveLoading">关闭</button>
<button
class="action-btn danger"
@click="handleBatchCancelReserve"
:disabled="cancelReserveLoading || reservedLabels.length === 0 || locationCode === '1101'"
v-if="reservedLabels.length > 0"
>
{{ cancelReserveLoading ? '取消中...' : '一键取消预留' }}
</button>
</div>
<!-- 库位1101提示 - rqrq -->
<div v-if="locationCode === '1101'" class="reserve-warning">
<i class="el-icon-warning"></i> 栈板在立库异常位上不允许取消预留
</div>
</el-dialog>
</div>
</template>
<script>
import {
getPalletInfoSimple,
getPalletDetails,
getPalletReservedLabels,
batchCancelReserve
} from '../../../api/haianAutoWarehouse/palletPacking'
export default {
name: 'haianPalletSearch',
data() {
return {
site: this.$store.state.user.site,
palletCode: '',
palletScanned: false,
detailModalVisible: false,
// - rqrq
selectedPosition: '',
positionOptions: [],
// - rqrq
detailList: [],
// - rqrq
locationCode: '',
// - rqrq
reserveModalVisible: false,
reservedLabels: [],
reserveCount: 0,
cancelReserveLoading: false
};
},
methods: {
// - rqrq
handleBack() {
// keep-alive - rqrq
this.resetPage(false)
this.$router.back();
},
// - rqrq
resetPage(needFocus = true) {
this.site = this.$store.state.user.site;
this.palletCode = '';
this.palletScanned = false;
this.selectedPosition = '';
this.positionOptions = [];
this.detailList = [];
this.detailModalVisible = false;
this.locationCode = '';
this.reserveModalVisible = false;
this.reservedLabels = [];
this.reserveCount = 0;
this.cancelReserveLoading = false;
// - rqrq
if (needFocus) {
this.$nextTick(() => {
if (this.$refs.palletInput) {
this.$refs.palletInput.focus();
}
});
}
},
// 使- rqrq
handlePalletScan() {
if (!this.site) {
this.$alert('当前用户缺少site,无法执行海安托盘查询', '提示', {
confirmButtonText: '确定'
});
return;
}
if (!this.palletCode.trim()) {
this.$alert('请输入栈板编码', '提示', {
confirmButtonText: '确定'
});
return;
}
getPalletInfoSimple({
site: this.site,
palletId: this.palletCode
}).then(({ data }) => {
if (data.code === 0) {
this.palletCode = data.palletId;
this.palletScanned = true;
this.positionOptions = data.positions || [];
this.locationCode = data.locationCode || '';
this.refreshTable();
this.loadReservedLabels(); // - rqrq
} else {
let errorMsg = data.msg || '栈板不存在';
if (errorMsg.length > 100) {
errorMsg = errorMsg.substring(0, 100) + '...';
}
this.$alert(errorMsg, '错误', {
confirmButtonText: '确定',
callback: () => {
this.palletCode = '';
this.$nextTick(() => {
if (this.$refs.palletInput) {
this.$refs.palletInput.focus();
}
});
}
});
}
}).catch(error => {
console.error('查询栈板失败:', error);
let errorMsg = error.message || '查询栈板失败';
if (errorMsg.length > 100) {
errorMsg = errorMsg.substring(0, 100) + '...';
}
this.$alert(errorMsg, '错误', {
confirmButtonText: '确定',
callback: () => {
this.palletCode = '';
this.$nextTick(() => {
if (this.$refs.palletInput) {
this.$refs.palletInput.focus();
}
});
}
});
});
},
// - rqrq
refreshTable() {
getPalletDetails({
site: this.site,
palletId: this.palletCode,
position: this.selectedPosition,
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
showReserveModal() {
this.loadReservedLabels();
this.reserveModalVisible = true;
},
// - rqrq
loadReservedLabels() {
getPalletReservedLabels({
site: this.site,
palletId: this.palletCode
}).then(({ data }) => {
if (data.code === 0 && data.data) {
this.reservedLabels = data.data.reservedLabels || [];
this.reserveCount = data.data.reserveCount || 0;
this.locationCode = data.data.locationCode || '';
} else {
this.reservedLabels = [];
this.reserveCount = 0;
}
}).catch(error => {
console.error('获取预留标签列表失败:', error);
this.reservedLabels = [];
this.reserveCount = 0;
});
},
// - rqrq
handleBatchCancelReserve() {
if (this.locationCode === '1101') {
this.$alert('栈板在库位1101上,不允许取消预留', '错误', { confirmButtonText: '确定' });
return;
}
this.$confirm('确定要取消所有预留标签吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.doBatchCancelReserve();
}).catch(() => {
//
});
},
// - rqrq
doBatchCancelReserve() {
this.cancelReserveLoading = true;
batchCancelReserve({
site: this.site,
palletId: this.palletCode
}).then(({ data }) => {
if (data.code === 0) {
this.$message.success('取消预留成功');
this.reserveModalVisible = false;
// - rqrq
this.loadReservedLabels();
} else {
this.$alert(data.msg || '取消预留失败', '错误', { confirmButtonText: '确定' });
}
}).catch(error => {
console.error('批量取消预留失败:', error);
this.$alert('取消预留异常', '错误', { confirmButtonText: '确定' });
}).finally(() => {
this.cancelReserveLoading = false;
});
}
},
// keep-alive退 - rqrq
activated() {
this.resetPage(true);
},
// - rqrq
beforeRouteLeave(to, from, next) {
this.resetPage(false);
next();
},
mounted() {
this.resetPage(true);
}
};
</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: 4;
text-align: center;
word-break: break-all;
}
/* 空数据提示 */
.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%;
}
/* 预留清单相关样式 - rqrq */
.action-btn.warning {
background: #E6A23C;
color: white;
border: none;
}
.action-btn.warning:hover {
background: #d99429;
}
.action-btn.danger {
background: #F56C6C;
color: white;
border: none;
}
.action-btn.danger:hover:not(:disabled) {
background: #e45656;
}
.action-btn.danger:disabled {
background: #ccc;
cursor: not-allowed;
opacity: 0.6;
}
.reserve-header {
font-size: 12px;
}
.col-serial-reserve {
flex: 2;
text-align: center;
word-break: break-all;
font-size: 12px;
}
.col-ref {
flex: 1.5;
text-align: center;
word-break: break-all;
font-size: 12px;
}
.reserve-warning {
text-align: center;
color: #E6A23C;
padding: 10px;
font-size: 14px;
background: #fdf6ec;
border-radius: 4px;
margin-top: 10px;
}
.reserve-warning i {
margin-right: 5px;
}
</style>

1064
src/views/modules/haianAutoWarehouse/haianPalletSorting.vue
File diff suppressed because it is too large
View File

Loading…
Cancel
Save