You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
438 lines
9.4 KiB
438 lines
9.4 KiB
<template> |
|
<ifrm ref="ifrm"> |
|
<!-- <view class="header"> |
|
<button v-if="activeBox" @click="handleResetBox" class="header-btn"> |
|
换箱 |
|
</button> |
|
</view> --> |
|
<uni-forms ref="wrForm" class="formBox" label-position="top"> |
|
<uni-forms-item label="物料箱条码:" label-width="100px"> |
|
<view class="bottom-input-row"> |
|
<view class="weight-input-wrapper"> |
|
<view class="input-box"> |
|
<input |
|
type="text" |
|
v-model="boxCode" |
|
@confirm="handleBoxConfirm" |
|
placeholder="物料箱条码" |
|
class="uni-input-border" |
|
confirm-type="done" |
|
:focus="boxInputFocus" |
|
/> |
|
</view> |
|
</view> |
|
<button class="submit-btn" :disabled="!canSubmit" @tap="handleSubmit"> |
|
装箱 |
|
</button> |
|
</view> |
|
<view v-if="activeBox" class="box-stats"> |
|
<view class="stats-left"> |
|
<text class="stats-label">当前物料箱</text> |
|
<text class="stats-value-box">{{ activeBox }}</text> |
|
</view> |
|
<view class="stats-right"> |
|
<view class="stats-item"> |
|
<text class="stats-label">总数量</text> |
|
<text class="stats-value">{{ totalCount }} 单</text> |
|
</view> |
|
<view class="stats-item"> |
|
<text class="stats-label">总重量</text> |
|
<text class="stats-value-weight">{{ totalWeight }} g</text> |
|
</view> |
|
</view> |
|
</view> |
|
</uni-forms-item> |
|
<uni-forms-item label="扫描流程卡(装箱):" label-width="200px"> |
|
<input |
|
type="text" |
|
v-model="cardCode" |
|
@confirm="handleCardConfirm" |
|
:disabled="!activeBox" |
|
placeholder="流程卡号" |
|
class="uni-input-border" |
|
:class="{ 'input-disabled': !activeBox }" |
|
confirm-type="done" |
|
:focus="cardInputFocus" |
|
/> |
|
</uni-forms-item> |
|
</uni-forms> |
|
<scroll-view class="orders-scroll" scroll-y> |
|
<view class="orders-header"> |
|
<text class="orders-icon"></text> |
|
<text class="orders-title" |
|
>箱内明细 ({{ |
|
boxInfo.yieldOrderList ? boxInfo.yieldOrderList.length : 0 |
|
}})</text |
|
> |
|
</view> |
|
|
|
<view v-if="boxInfo.yieldOrderList.length === 0" class="empty-tip"> |
|
<text>{{ |
|
activeBox ? "暂无明细,请扫描流程卡装箱" : "请先扫描物料箱" |
|
}}</text> |
|
</view> |
|
|
|
<view v-else class="orders-list"> |
|
<view |
|
v-for="(order, index) in boxInfo.yieldOrderList" |
|
:key="order.id" |
|
class="order-card" |
|
:class="{ 'order-latest': index === 0 }" |
|
> |
|
<view v-if="index === 0" class="latest-badge">最新</view> |
|
<view class="order-header"> |
|
<text class="order-no">{{ order.woOrder }}订单号</text> |
|
<text class="order-no">{{ order.cardNo }}</text> |
|
</view> |
|
<view class="order-footer"> |
|
<text class="order-part">{{ order.partCode }}</text> |
|
<text class="order-weight">{{ order.actualWeighing }} g</text> |
|
</view> |
|
</view> |
|
</view> |
|
</scroll-view> |
|
</ifrm> |
|
</template> |
|
|
|
<script> |
|
import ifrm from "@/pages/index/ifrm"; |
|
export default { |
|
components: { |
|
ifrm, |
|
}, |
|
data() { |
|
return { |
|
boxInfo: { |
|
yieldOrderList: [], |
|
}, |
|
boxCode: "", |
|
cardCode: "", |
|
activeBox: null, |
|
orders: [], |
|
boxInputFocus: true, |
|
cardInputFocus: false, |
|
}; |
|
}, |
|
computed: { |
|
canSubmit() { |
|
return this.boxInfo.yieldOrderList.length > 0; |
|
}, |
|
totalCount() { |
|
return this.boxInfo.yieldOrderList.length; |
|
}, |
|
totalWeight() { |
|
if ( |
|
!this.boxInfo.yieldOrderList || |
|
this.boxInfo.yieldOrderList.length === 0 |
|
) { |
|
return 0; |
|
} |
|
return this.boxInfo.yieldOrderList.reduce((sum, o) => { |
|
return sum + (Number(o.actualWeighing) || 0); |
|
}, 0); |
|
}, |
|
}, |
|
methods: { |
|
// 扫描物料箱条码 |
|
handleBoxConfirm() { |
|
const code = this.boxCode.trim(); |
|
if (!code) return; |
|
this.$u.api |
|
.boxbarcodeDetails({ boxBarcode: this.boxCode }) |
|
.then((res) => { |
|
this.boxInfo = res.data; |
|
}); |
|
this.activeBox = code; |
|
// 加载已有数据,如果没有则为空箱 |
|
uni.showToast({ |
|
title: `物料箱 ${code} 已就绪`, |
|
icon: "success", |
|
}); |
|
this.boxCode = ""; |
|
this.boxInputFocus = false; |
|
this.cardInputFocus = true; |
|
}, |
|
|
|
handleCardConfirm() { |
|
const code = this.cardCode.trim(); |
|
if (!code) return; |
|
|
|
if (!this.activeBox) { |
|
uni.showToast({ |
|
title: "请先扫描物料箱条码", |
|
icon: "none", |
|
}); |
|
this.boxInputFocus = true; |
|
return; |
|
} |
|
if (this.boxInfo.yieldOrderList.some((o) => o.cardNo === this.cardCode)) { |
|
uni.showToast({ |
|
title: `订单 ${this.cardCode} 已在该箱中!`, |
|
icon: "none", |
|
}); |
|
this.cardCode = ""; |
|
return; |
|
} |
|
this.$u.api.queryCardNo({ cardNo: this.cardCode }).then((res) => { |
|
this.boxInfo.yieldOrderList.push(res.data); |
|
if (!res.data.cardNo) { |
|
uni.showToast({ |
|
title: `流程卡 ${code} 不存在或未称重`, |
|
icon: "none", |
|
}); |
|
this.cardCode = ""; |
|
return; |
|
} |
|
uni.showToast({ |
|
title: `流程卡 ${code} 装箱成功`, |
|
icon: "success", |
|
}); |
|
this.cardCode = ""; |
|
}); |
|
}, |
|
|
|
handleResetBox() { |
|
this.activeBox = null; |
|
this.boxCode = ""; |
|
this.orders = []; |
|
this.boxInputFocus = true; |
|
this.cardInputFocus = false; |
|
}, |
|
// 装箱确认 |
|
handleSubmit() { |
|
this.$u.api |
|
.boxBinding({ |
|
boxBarcode: this.activeBox, //箱条码 |
|
orderIdList: this.boxInfo.yieldOrderList.map((o) => o.cardNo), |
|
}) |
|
.then((res) => { |
|
uni.showToast({ |
|
title: `装箱成功`, |
|
icon: "success", |
|
}); |
|
this.cardCode = ""; |
|
this.boxInfo.yieldOrderList = []; |
|
}); |
|
}, |
|
}, |
|
}; |
|
</script> |
|
|
|
<style scoped> |
|
.formBox { |
|
border-bottom: 4rpx solid #cbd5e1; |
|
} |
|
|
|
.box-stats { |
|
margin-top: 16rpx; |
|
display: flex; |
|
align-items: center; |
|
justify-content: space-between; |
|
background-color: #eff6ff; |
|
border: 2rpx solid #bfdbfe; |
|
padding: 16rpx; |
|
border-radius: 4rpx; |
|
} |
|
|
|
.stats-left { |
|
display: flex; |
|
flex-direction: column; |
|
} |
|
|
|
.stats-label { |
|
color: #475569; |
|
font-size: 22rpx; |
|
} |
|
|
|
.stats-value-box { |
|
font-weight: bold; |
|
color: #1e40af; |
|
font-size: 26rpx; |
|
} |
|
|
|
.stats-right { |
|
display: flex; |
|
gap: 24rpx; |
|
text-align: right; |
|
} |
|
|
|
.stats-item { |
|
display: flex; |
|
flex-direction: column; |
|
} |
|
|
|
.stats-value { |
|
font-weight: bold; |
|
color: #0f172a; |
|
font-size: 26rpx; |
|
} |
|
|
|
.stats-value-weight { |
|
font-weight: bold; |
|
color: #059669; |
|
font-size: 26rpx; |
|
} |
|
|
|
.orders-scroll { |
|
flex: 1; |
|
padding: 16rpx; |
|
background-color: #f8fafc; |
|
} |
|
|
|
.orders-header { |
|
display: flex; |
|
align-items: center; |
|
color: #334155; |
|
font-weight: bold; |
|
margin-bottom: 16rpx; |
|
padding: 0 8rpx; |
|
} |
|
|
|
.orders-icon { |
|
font-size: 32rpx; |
|
margin-right: 8rpx; |
|
} |
|
|
|
.orders-title { |
|
font-size: 26rpx; |
|
} |
|
|
|
.empty-tip { |
|
text-align: center; |
|
padding: 48rpx 0; |
|
color: #94a3b8; |
|
font-weight: 500; |
|
font-size: 24rpx; |
|
} |
|
|
|
.orders-list { |
|
display: flex; |
|
flex-direction: column; |
|
gap: 16rpx; |
|
} |
|
|
|
.order-card { |
|
background-color: #ffffff; |
|
padding: 16rpx; |
|
border: 4rpx solid #cbd5e1; |
|
border-radius: 4rpx; |
|
display: flex; |
|
flex-direction: column; |
|
position: relative; |
|
} |
|
|
|
.order-latest { |
|
border-color: #fb923c; |
|
box-shadow: 0 0 0 2rpx rgba(251, 146, 60, 0.2); |
|
} |
|
|
|
.latest-badge { |
|
position: absolute; |
|
top: -8rpx; |
|
right: -4rpx; |
|
background-color: #f97316; |
|
color: #ffffff; |
|
font-size: 18rpx; |
|
font-weight: bold; |
|
padding: 4rpx 12rpx; |
|
border-radius: 4rpx; |
|
} |
|
|
|
.order-header { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
border-bottom: 2rpx solid #f1f5f9; |
|
padding-bottom: 8rpx; |
|
margin-bottom: 8rpx; |
|
} |
|
|
|
.order-no { |
|
font-weight: bold; |
|
color: #0f172a; |
|
font-size: 28rpx; |
|
} |
|
|
|
.order-weight { |
|
font-weight: bold; |
|
color: #059669; |
|
} |
|
|
|
.order-footer { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
} |
|
|
|
.order-label { |
|
color: #475569; |
|
font-weight: 500; |
|
} |
|
|
|
.order-part { |
|
font-weight: bold; |
|
color: #1e293b; |
|
} |
|
|
|
.help-tip { |
|
position: absolute; |
|
top: 40%; |
|
left: 0; |
|
width: 100%; |
|
display: flex; |
|
justify-content: center; |
|
pointer-events: none; |
|
opacity: 0.5; |
|
z-index: 10; |
|
} |
|
|
|
.tip-content { |
|
background-color: #1e293b; |
|
color: #ffffff; |
|
font-size: 20rpx; |
|
padding: 8rpx 16rpx; |
|
border-radius: 4rpx; |
|
display: flex; |
|
align-items: center; |
|
} |
|
|
|
.tip-icon { |
|
margin-right: 8rpx; |
|
font-size: 24rpx; |
|
} |
|
|
|
.tip-text { |
|
font-size: 20rpx; |
|
} |
|
.bottom-input-row { |
|
display: flex; |
|
gap: 10px; |
|
margin-bottom: 12px; |
|
} |
|
|
|
.weight-input-wrapper { |
|
flex: 1; |
|
} |
|
|
|
.submit-btn { |
|
width: 88px; |
|
height: 50px; |
|
background-color: #155dfc; |
|
border-radius: 10px; |
|
color: #ffffff; |
|
font-size: 16px; |
|
font-weight: 500; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.1), |
|
0px 1px 2px 0px rgba(0, 0, 0, 0.1); |
|
border: none; |
|
padding: 0; |
|
line-height: 50px; |
|
} |
|
|
|
.submit-btn.disabled { |
|
opacity: 0.5; |
|
} |
|
</style>
|
|
|