Browse Source

合托功能

master
常熟吴彦祖 1 month ago
parent
commit
920c3695c7
  1. 3
      src/api/automatedWarehouse/callOut.js
  2. 1
      src/router/index.js
  3. 6
      src/views/main.vue
  4. 567
      src/views/modules/automatedWarehouse/callOutForHetuo.vue

3
src/api/automatedWarehouse/callOut.js

@ -7,3 +7,6 @@ export const callPalletFromWcs = data => createAPI(`/wcsIntegration/callPalletFr
// 【新方法】直接Call栈板(不使用定时任务方式) - rqrq // 【新方法】直接Call栈板(不使用定时任务方式) - rqrq
export const callPalletFromWcsNew = data => createAPI(`/wcsIntegration/callPalletFromWcsNew`,'post',data) export const callPalletFromWcsNew = data => createAPI(`/wcsIntegration/callPalletFromWcsNew`,'post',data)
// 【新方法】扫描托盘并直接Call料出库(用于合托Call料页面简化操作)- rqrq
export const scanAndCallPalletForHetuo = data => createAPI(`/wcsIntegration/scanAndCallPalletForHetuo`,'post',data)

1
src/router/index.js

@ -141,6 +141,7 @@ const globalRoutes = [
{path: "/callOutToStation",name: "callOutToStation", component: resolve => require(["@/views/modules/automatedWarehouse/callOutToStation.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}}, {path: "/callOutToStation",name: "callOutToStation", component: resolve => require(["@/views/modules/automatedWarehouse/callOutToStation.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/palletSortingNoAgv",name: "palletSortingNoAgv", component: resolve => require(["@/views/modules/automatedWarehouse/palletSortingNoAgv.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}}, {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: "/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}},
] ]

6
src/views/main.vue

@ -211,6 +211,12 @@
</div> </div>
<div class="menu-text">无AGV分拣组盘</div> <div class="menu-text">无AGV分拣组盘</div>
</div> </div>
<div class="menu-item" @click="navigateWithWarehouseCheck('callOutForHetuo')">
<div class="menu-icon purchase">
<van-icon name="shopping-cart-o" size="24" />
</div>
<div class="menu-text">Call栈板手工合托</div>
</div>
</div> </div>
</div> </div>
<!-- 库内管理 --> <!-- 库内管理 -->

567
src/views/modules/automatedWarehouse/callOutForHetuo.vue

@ -0,0 +1,567 @@
<template>
<div>
<div class="pda-container">
<!-- 头部栏 -->
<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="search-container">-->
<!-- -->
<!-- </div>-->
<div class="table-body" style="max-height: 500px; overflow-y: auto;">
<div class="main-content form-section">
<!-- 表单区域 -->
<!-- @blur="handlePartNoBlur"-->
<!-- 栈板编码搜索框 - rqrq -->
<div class="input-group">
<label class="input-label">栈板编码扫描后自动下达</label>
<el-input
v-model="formData.palletId"
placeholder="请扫描或输入栈板编码"
class="form-input"
clearable
ref="palletInput"
@keyup.enter.native="handleScanAndCall"
:disabled="scanLoading"
/>
</div>
<!-- 下达状态提示 - rqrq -->
<div v-if="scanLoading" class="status-tip loading">
<i class="el-icon-loading"></i> 正在下达中...
</div>
<div class="bottom-actions" style="display: flex; gap: 10px; flex-wrap: nowrap;">
<button
class="action-btn primary"
@click="handleScanAndCall"
:disabled="scanLoading || !formData.palletId"
style="flex: 2;"
>
{{ scanLoading ? '下达中...' : '扫描下达' }}
</button>
<button class="action-btn secondary" @click="cleanData" :disabled="scanLoading" style="flex: 1;">
清空
</button>
</div>
<!-- 下达记录列表 - rqrq -->
<div v-if="callHistory.length > 0" class="history-section">
<div class="list-title">本次下达记录{{ callHistory.length }}</div>
<div v-for="(record, index) in callHistory" :key="index" class="history-item" :class="record.success ? 'success' : 'error'">
<span class="history-pallet">{{ record.palletId }}</span>
<span class="history-status">{{ record.success ? '✓ 成功' : '✗ ' + record.reason }}</span>
<span class="history-time">{{ record.time }}</span>
</div>
</div>
</div>
<!-- 栈板列表保留用于手动模式- rqrq -->
<div v-if="palletList.length > 0" class="rma-list">
<!-- Call车按钮 - 当有选中栈板时显示 -->
<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.wdr">
| WDR: {{ pallet.wdr }}
</span>
<span class="batch-qty" v-if="pallet.partNo && pallet.expiredDate">
| 失效日期: {{ pallet.expiredDate }}
</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>
</div>
</template>
<script>
import {
saveTransportTask,
getShopOrderFromIFSWithOrderNo,
getPalletList,
callPalletFromWcs,
callPalletFromWcsNew,
scanAndCallPalletForHetuo
} from '../../../api/automatedWarehouse/callOut'
export default {
data() {
return {
scanRma: "",
rmaList: [],
returnList: [], // 退
selectedDetail: null, // RMA
processType: "inbound", //
site:localStorage.getItem('site'),
loading: false, // loading
lastPartNo: '', //
formData: {
palletId: '', // - rqrq
partNo: '',
partDesc: '',
batchNo: '',
rollNo: '',
site:localStorage.getItem('site'),
},
palletList: [], //
selectedPallet: null, //
selectedPallets: [], //
callLoading: false, // Callloading - rqrq
scanLoading: false, // loading - rqrq
callHistory: [], // - rqrq
};
},
computed: {
},
methods: {
handleBack() {
this.$router.back();
},
//
async handlePartNoBlur() {
const partNo = this.formData.partNo;
if (!partNo) {
this.formData.partDesc = '';
return;
}
//
// if (this.lastPartNo === partNo) {
// 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() {
// - rqrq
if((!this.formData.partNo || this.formData.partNo === '') &&
(!this.formData.palletId || this.formData.palletId === '')){
this.$alert('请输入物料编码或栈板编码', '提示', {
confirmButtonText: '确定'
});
return;
}
// - rqrq
const queryParams = {
site: this.formData.site
};
// - rqrq
if (this.formData.palletId && this.formData.palletId.trim()) {
queryParams.palletId = this.formData.palletId.trim();
}
// - rqrq
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 || [];
//batchNo
if (this.palletList.length === 0) {
this.$message.warning('未找到满足条件的栈板');
} else {
this.$message.success(`找到 ${this.palletList.length} 个栈板`);
}
//
this.selectedPallet = null;
this.selectedPallets = []; //
} else {
this.$alert(data.msg || '查询失败', '错误', {
confirmButtonText: '确定'
});
this.palletList = [];
this.selectedPallet = null;
this.selectedPallets = []; //
}
}).catch(error => {
console.error('查询栈板列表失败:', error);
this.$alert(error.message || '查询失败', '错误', {
confirmButtonText: '确定'
});
this.palletList = [];
this.selectedPallet = null;
this.selectedPallets = []; //
});
},
// - rqrq ID
selectPallet(pallet) {
const palletId = pallet.palletId;
const index = this.selectedPallets.findIndex(item => item.palletId === palletId);
if (index > -1) {
// - rqrq
this.selectedPallets.splice(index, 1);
this.$message.success('已取消选择栈板');
} else {
// Call- rqrq
this.selectedPallets.push({
site: pallet.site,
palletId: pallet.palletId,
partNo: pallet.partNo || '', //
qty: pallet.qty || 0,
batchNo: pallet.batchNo || this.formData.batchNo || ''
});
this.$message.success(`已选择栈板: ${palletId}`);
}
},
// - rqrq
isSelected(pallet) {
return this.selectedPallets.some(item => item.palletId === pallet.palletId);
},
// Call - rqrq
handleCall() {
if (this.selectedPallets.length === 0) {
this.$alert('请至少选择一个栈板', '提示', {
confirmButtonText: '确定'
});
return;
}
this.$confirm(`确定Call ${this.selectedPallets.length} 个栈板出库?`, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// loading - rqrq
this.callLoading = true;
// - rqrq
callPalletFromWcsNew(this.selectedPallets).then(({ data }) => {
if (data && data.code === 0) {
const failedCount = data.failedCount || 0;
const successCount = data.successCount || 0;
// - rqrq
if (failedCount === 0) {
// - rqrq
this.$message.success(`成功Call ${successCount} 个栈板出库!`);
this.cleanData();
} else {
// - rqrq
const failedPalletIds = data.failedPalletIds || [];
const failedReasons = data.failedReasons || [];
// - rqrq
let errorMsg = `成功:${successCount}个,失败:${failedCount}\n\n失败栈板:\n`;
failedPalletIds.forEach((palletId, index) => {
errorMsg += `${index + 1}. ${palletId}${failedReasons[index] || '未知错误'}\n`;
});
// - rqrq
this.$alert(errorMsg, `Call车结果`, {
confirmButtonText: '确定',
type: 'warning',
callback: () => {
// - rqrq
this.cleanData();
}
});
}
} else {
this.$alert(data.msg || 'Call车失败', '错误', {
confirmButtonText: '确定'
});
}
}).catch(error => {
console.error('Call车失败:', error);
this.$alert(error.message || 'Call车失败', '错误', {
confirmButtonText: '确定'
});
}).finally(() => {
// - rqrq
this.callLoading = false;
});
}).catch(() => {
// - rqrq
});
},
cleanData(){
// - rqrq
this.formData = {
palletId: '', // - rqrq
partNo: '',
partDesc: '',
batchNo: '',
rollNo: '',
site:localStorage.getItem('site'),
};
//
this.palletList = [];
this.selectedPallet = null;
this.selectedPallets = []; //
// - rqrq
this.callHistory = [];
// - rqrq
this.focusInput();
},
// - rqrq
focusInput() {
this.$nextTick(() => {
if (this.$refs.palletInput) {
this.$refs.palletInput.focus();
}
});
},
// - rqrq
getCurrentTime() {
const now = new Date();
return now.getHours().toString().padStart(2, '0') + ':' +
now.getMinutes().toString().padStart(2, '0') + ':' +
now.getSeconds().toString().padStart(2, '0');
},
// - rqrq
handleScanAndCall() {
const palletId = this.formData.palletId ? this.formData.palletId.trim() : '';
if (!palletId) {
this.$message.warning('请输入或扫描栈板编码');
this.focusInput();
return;
}
// loading - rqrq
this.scanLoading = true;
// - rqrq
scanAndCallPalletForHetuo({
site: this.formData.site,
palletId: palletId
}).then(({ data }) => {
if (data && data.code === 0) {
const failedCount = data.failedCount || 0;
const successCount = data.successCount || 0;
if (failedCount === 0 && successCount > 0) {
// - rqrq
this.$message.success('栈板【' + palletId + '】下达成功!');
// - rqrq
this.callHistory.unshift({
palletId: palletId,
success: true,
reason: '',
time: this.getCurrentTime()
});
} else if (failedCount > 0) {
// - rqrq
const failedReasons = data.failedReasons || [];
const errorMsg = failedReasons.length > 0 ? failedReasons[0] : '未知错误';
this.$message.error('下达失败:' + errorMsg);
// - rqrq
this.callHistory.unshift({
palletId: palletId,
success: false,
reason: errorMsg,
time: this.getCurrentTime()
});
}
} else {
// - rqrq
const errorMsg = data.msg || '下达失败';
this.$message.error(errorMsg);
// - rqrq
this.callHistory.unshift({
palletId: palletId,
success: false,
reason: errorMsg,
time: this.getCurrentTime()
});
}
}).catch(error => {
console.error('扫描下达失败:', error);
const errorMsg = error.message || '下达失败';
this.$message.error(errorMsg);
// - rqrq
this.callHistory.unshift({
palletId: palletId,
success: false,
reason: errorMsg,
time: this.getCurrentTime()
});
}).finally(() => {
// - rqrq
this.scanLoading = false;
// - rqrq
this.formData.palletId = '';
this.focusInput();
// 20 - rqrq
if (this.callHistory.length > 20) {
this.callHistory = this.callHistory.slice(0, 20);
}
});
},
},
mounted() {
// - rqrq
this.focusInput();
}
};
</script>
<style scoped>
/* 按钮禁用状态样式 - rqrq */
.action-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
background-color: #ccc !important;
border-color: #ccc !important;
}
/* 主要按钮样式 - rqrq */
.action-btn.primary {
background-color: #409EFF;
border-color: #409EFF;
color: #fff;
}
.action-btn.primary:hover:not(:disabled) {
background-color: #66b1ff;
border-color: #66b1ff;
}
/* 状态提示样式 - rqrq */
.status-tip {
padding: 10px;
margin: 10px 0;
border-radius: 4px;
text-align: center;
font-size: 14px;
}
.status-tip.loading {
background-color: #e6f7ff;
color: #1890ff;
border: 1px solid #91d5ff;
}
/* 下达记录区域样式 - rqrq */
.history-section {
margin-top: 15px;
border-top: 1px solid #eee;
padding-top: 10px;
}
.history-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 10px;
margin: 5px 0;
border-radius: 4px;
font-size: 13px;
}
.history-item.success {
background-color: #f0f9eb;
border-left: 3px solid #67c23a;
}
.history-item.error {
background-color: #fef0f0;
border-left: 3px solid #f56c6c;
}
.history-pallet {
font-weight: bold;
color: #333;
flex: 1;
}
.history-status {
flex: 2;
text-align: center;
}
.history-item.success .history-status {
color: #67c23a;
}
.history-item.error .history-status {
color: #f56c6c;
font-size: 12px;
}
.history-time {
color: #999;
font-size: 12px;
flex: 0.5;
text-align: right;
}
</style>
Loading…
Cancel
Save