Files
2025-11-06 17:42:14 +08:00

464 lines
12 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="content">
<view class="title-box">
<!-- <span class="title-text">拼箱拆箱入库</span> -->
<view class="warehoseInfo-box">
<view>
仓库编号{{ warehouseInfo.warehouse + ' ' + warehouseInfo.location }}
<span></span>
</view>
<view class="row">
<view class="col">层号{{ warehouseInfo.layer }}</view>
<view class="col">货架{{ warehouseInfo.shelf }}</view>
</view>
<view class="row">
<span class="col">总货物数{{ quantityTotal }}</span>
<span class="col">总箱数{{ newMaterialList.length }}</span>
</view>
<view>
<view v-if="searchType === 1" class="color1 aciton-box">请扫仓库码</view>
<view v-if="searchType === 2" class="color2 aciton-box">请扫箱码</view>
<!-- 扫描操作 -->
<view class="pda-search-box">
<PdaScanInput @getInfo="handleGetInfo" :type="searchType" :warehouseInfo="warehouseInfo"></PdaScanInput>
</view>
</view>
</view>
</view>
<!-- 上次批次号 -->
<view class="last-batch-info">
<view class="scroll-view-last" v-if="newMaterialList.length > 1">上次批次号{{ newMaterialList[newMaterialList.length - 2].patchCode }}</view>
<view class="scroll-view-last" v-if="newMaterialList.length <= 1">上次批次号</view>
</view>
<!-- 货物列表 -->
<view class="scroll-view-box">
<view class="scroll-view-title">入库清单</view>
<view class="scroll-view-content">
<!-- 优化后的packageCard组件使用 -->
<packageCard v-for="(item, index) in newMaterialList" :packageInfo="item" :key="item.originalCode" @delete="handleDeleteItem"></packageCard>
</view>
</view>
<!-- 底部按钮 -->
<view class="button-box">
<u-button style="width: 40%" type="error" @click="clear" :disabled="loading" :loading="loading">全部重置</u-button>
<u-button style="width: 40%" type="success" @click="handlerSubmit" :disabled="loading" :loading="loading">入库</u-button>
</view>
</view>
</template>
<script>
import materialItem from '@/components/material-item/material-item.vue';
import packageCard from '@/components/package-card/package-card.vue';
import * as WarehoseApi from '@/api/warehouse/warehose.js';
import { showOperationConfirm, isRepeatPackage, isChangeBatch, clearRepeatPackages, debounce } from './utils.js';
// 入库
export default {
components: {
materialItem,
packageCard
},
data() {
return {
// 入库模式true严格追溯 false不严格不追溯
isStrict: false,
loading: false,
clearData: {},
// 仓库信息
warehouseInfo: {
id: '',
warehouse: '',
warehouse_num: '',
location: '',
shelf: '',
layer: '',
number: 0
},
// 货物信息
lastPackageInfo: {
// 工单号
workoderID: '',
// 批次号(工单号+箱号+班组)
patchCode: '',
// 零件号
partNumner: '',
// 描述
productionDescribe: '',
// 出厂日期/生产日期
productionTime: '',
// 此箱数量
quantity: 0
},
// 库位历史信息
oldMaterialList: [],
// 库位新录入货物信息
newMaterialList: [],
// 1-仓库扫码 2-货物扫码
searchType: 1
};
},
watch: {},
onLoad(e) {
if (e.isStrict === 'true') {
this.isStrict = true;
} else {
this.isStrict = false;
}
},
created() {
this.init();
},
computed: {
quantityTotal() {
let num = 0;
for (let index = 0; index < this.newMaterialList.length; index++) {
num += this.newMaterialList[index].quantity * 1;
}
return num;
}
},
methods: {
init() {
// 需要展示的参数:【零件号[物料号](35233201041) 描述(鲨鱼鳍) 箱号+班组(BNW240312023_18B1) 数量 时间 】
// 初始化,并且清空数据
this.clearData.warehouseInfo = JSON.parse(JSON.stringify(this.warehouseInfo));
this.clearData.oldMaterialList = JSON.parse(JSON.stringify(this.oldMaterialList));
this.clearData.newMaterialList = JSON.parse(JSON.stringify(this.newMaterialList));
this.searchType = 1;
},
clear() {
uni.showModal({
title: '确认重置',
content: '确定要重置所有数据吗?',
showCancel: true,
cancelText: '取消',
confirmText: '确认',
success: (res) => {
if (res.confirm) {
this.warehouseInfo = JSON.parse(JSON.stringify(this.clearData.warehouseInfo));
this.oldMaterialList = JSON.parse(JSON.stringify(this.clearData.oldMaterialList));
this.newMaterialList = JSON.parse(JSON.stringify(this.clearData.newMaterialList));
this.searchType = 1;
}
}
});
},
handleGetInfo(data, type) {
if (type === 1) {
// 仓库扫完后是箱号
this.searchType = 2;
this.warehouseInfo = data?.warehoseInfo;
this.newMaterialList = [];
this.loading = false;
} else if (type === 2) {
if (this.loading) {
showOperationConfirm('提示', '请等待加载完成!', false);
return;
}
// 此时扫描的是箱号
// 当前录入的箱号是否在同一批次录入过
// 曾经是否扫过
if (this.newMaterialList.length > 0) {
// 检查是否为重复箱
if (isRepeatPackage(this.newMaterialList, data.patchCode)) {
showOperationConfirm('提示', '此货物已录入过!', false);
this.loading = false;
return;
}
// 检查是否更换了批次
if (isChangeBatch(this.newMaterialList, data.productionTime)) {
showOperationConfirm('提示', '已更换入库批次!', false);
}
}
const checkData = {
production_packcode: data.originalCode,
location: this.warehouseInfo.location,
//严格模式
isStrict: this.isStrict
};
this.loading = true;
// 使用Promise包装API调用避免setTimeout可能带来的问题
const checkWarehousingPromise = WarehoseApi.checkWarehousing(checkData);
const timeoutPromise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('timeout')), 10000);
});
Promise.race([checkWarehousingPromise, timeoutPromise])
.then((res) => {
if (res.code === 200 && res.data) {
this.newMaterialList.push(data);
} else {
uni.showModal({
title: '提示',
content: '不可入库:' + res.msg,
showCancel: false,
confirmText: '确定'
});
}
})
.catch((error) => {
if (error.message === 'timeout') {
uni.showModal({
title: '提示',
content: '请求超时,请重试!',
showCancel: false,
confirmText: '确定'
});
} else {
uni.showModal({
title: '提示',
content: '请求异常,请重试!',
showCancel: false,
confirmText: '确定'
});
}
})
.finally(() => {
this.loading = false;
});
}
},
// 删除货物项
handleDeleteItem(item) {
showOperationConfirm('删除提示', '是否从列表中删除此货物?', true).then((res) => {
if (res.confirm) {
const index = this.newMaterialList.findIndex((i) => i.originalCode === item.originalCode);
if (index > -1) {
this.newMaterialList.splice(index, 1);
}
}
});
},
// 入库提交
handlerSubmit() {
if (this.newMaterialList.length === 0) {
showOperationConfirm('提示', '无入库货物!', false);
return;
}
// 箱重复提醒 this.isPackageRepeat()
if (this.isPackageRepeat()) {
showOperationConfirm('重复箱校验', '检测到存在重复箱,是否自动清除?', true).then((res) => {
if (res.confirm) {
this.clearRepeatPackage();
}
});
return;
}
showOperationConfirm('入库操作', '是否确认入库?', true).then((res) => {
if (res.confirm) {
this.loading = true;
let list = [];
for (let item of this.newMaterialList) {
list.push(item.originalCode);
}
const data = {
location: this.warehouseInfo.location,
packagelist: list
};
// 优化防抖处理机制,使用更可靠的防抖函数
const debouncedSubmit = (() => {
let timeoutId;
return () => {
// 清除之前的定时器
if (timeoutId) {
clearTimeout(timeoutId);
}
// 设置新的定时器执行入库操作
timeoutId = setTimeout(() => {
WarehoseApi.IntoProductwarehouseNoU8(data)
.then((res) => {
if (res.code === 200) {
if (res.data === 0 || !res.data) {
showOperationConfirm('提示', '入库失败:' + res.msg, false);
this.loading = false;
return;
}
uni.showToast({
icon: 'none',
title: '入库成功!' + res.msg
});
this.loading = false;
this.oldMaterialList = JSON.parse(JSON.stringify(this.clearData.oldMaterialList));
this.newMaterialList = JSON.parse(JSON.stringify(this.clearData.newMaterialList));
} else {
showOperationConfirm('提示', '入库失败!', false);
this.loading = false;
}
})
.catch((error) => {
// 处理请求失败的情况确保loading状态被重置
//console.error('入库请求失败:', error);
//showOperationConfirm('提示', '请求失败,请重试!', false);
this.loading = false;
});
}, 1000); // 1秒防抖延迟
};
})();
// 调用防抖函数
debouncedSubmit();
} else {
this.loading = false;
}
});
},
// 入库箱去重校验,数据是否有重复
// 统一重复检查逻辑使用Map提高查找效率
isPackageRepeat() {
let oldList = this.newMaterialList;
let seen = new Map();
for (let item of oldList) {
if (seen.has(item.originalCode)) {
return true;
}
seen.set(item.originalCode, true);
}
return false;
},
// 自动清除重复箱
clearRepeatPackage() {
let oldArray = this.newMaterialList;
let newArray = [];
let seen = new Map();
let repeatPackage = [];
oldArray.forEach((item) => {
// 统一重复检查逻辑使用originalCode作为唯一标识
if (!seen.has(item.originalCode)) {
seen.set(item.originalCode, true);
newArray.push(item);
} else {
repeatPackage.push(item.patchCode);
}
});
this.newMaterialList = newArray;
// 增强用户交互提示信息
showOperationConfirm(
'重复箱清除',
`检测到${repeatPackage.length}个重复箱,已自动清除。原箱数:${oldArray.length} 现箱数:${newArray.length} 重复箱:${repeatPackage.join(', ')}`,
false
);
}
}
};
</script>
<style scoped>
.content {
display: flex;
flex-direction: column;
min-height: 100vh;
padding: 10px 0;
box-sizing: border-box;
}
.title-box {
font-size: 26px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.warehoseInfo-box {
font-size: 20px;
width: 94%;
margin: 5px auto;
padding: 5px;
background-color: aliceblue;
border-radius: 10px;
display: flex;
flex-direction: column;
gap: 5px;
}
.warehoseInfo-box .row {
display: flex;
flex-direction: row;
}
.warehoseInfo-box .row .col {
width: 50%;
}
.aciton-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.color1 {
color: brown;
}
.color2 {
color: orange;
}
.pda-search-box {
margin-bottom: 5px;
}
.list-box {
width: 100%;
}
.scroll-view-title {
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
color: #151515;
margin-bottom: 10px;
}
.scroll-view-box {
width: 94%;
margin: 20px auto;
padding: 10px;
background-color: rgba(179, 179, 179, 0.7);
border-radius: 5px;
overflow-y: auto;
flex: 1;
min-height: 300px;
}
.scroll-view-content {
/* 确保内容高度超过容器时可以滚动 */
}
.last-batch-info {
width: 94%;
margin: 10px auto;
padding: 5px;
background-color: #f5f5f5;
border-radius: 5px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
.scroll-view-last {
width: 100%;
font-size: 18px;
color: rgba(0, 9, 0, 0.7);
display: flex;
flex-direction: column;
justify-content: center;
padding: 8px;
border-radius: 5px;
background-color: white;
min-height: 30px;
}
.button-box {
width: 90%;
margin: 20px auto;
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
}
</style>