<template>
|
<view class="page-container">
|
<!-- 头部导航 -->
|
<u-navbar
|
:title="$t('container.orderComb')"
|
:fixed="true"
|
:placeholder="true"
|
bgColor="#ffffff"
|
titleStyle="font-weight: 600; color: #303133; font-size: 32rpx;"
|
autoBack
|
></u-navbar>
|
|
<!-- 表单区域 -->
|
<view class="panel-section">
|
<view class="panel form-panel">
|
<u--form
|
labelPosition="left"
|
labelWidth="auto"
|
>
|
<u-form-item borderBottom>
|
<template slot="label">
|
<view class="form-label">
|
<u-icon
|
name="account"
|
color="#409eff"
|
customStyle="margin-right: 10rpx;"
|
></u-icon>
|
<text class="label-text">
|
{{ $t('container.orderNo') }}
|
</text>
|
</view>
|
</template>
|
<view class="input-wrap">
|
<u--input
|
v-model="orderNo"
|
:placeholder="$t('container.scanOrder')"
|
clearable
|
border="none"
|
:focus="orderNoFocus"
|
disabled
|
></u--input>
|
</view>
|
</u-form-item>
|
<u-form-item :borderBottom="orderReviewRequired">
|
<template slot="label">
|
<view class="form-label">
|
<u-icon
|
name="scan"
|
color="#409eff"
|
customStyle="margin-right: 10rpx;"
|
></u-icon>
|
<text class="label-text">
|
{{ $t('container.palletCode') }}
|
</text>
|
</view>
|
</template>
|
<view class="input-wrap">
|
<u--input
|
v-model="barcode"
|
:placeholder="$t('container.scanPallet')"
|
clearable
|
border="none"
|
:focus="barcodeFocus"
|
@change="barcodeInput"
|
></u--input>
|
</view>
|
</u-form-item>
|
<u-form-item v-if="orderReviewRequired">
|
<template slot="label">
|
<view class="form-label">
|
<u-icon
|
name="list"
|
color="#409eff"
|
customStyle="margin-right: 10rpx;"
|
></u-icon>
|
<text class="label-text">
|
{{ $t('container.matCode') }}
|
</text>
|
</view>
|
</template>
|
<view class="input-wrap">
|
<u--input
|
v-model="matnr"
|
:placeholder="$t('container.scanMatReview')"
|
clearable
|
border="none"
|
:focus="matFocus"
|
@change="findMat"
|
></u--input>
|
</view>
|
</u-form-item>
|
</u--form>
|
</view>
|
</view>
|
|
<!-- 列表区域 -->
|
<view class="list-section">
|
<view
|
class="list-header"
|
style="justify-content: space-between"
|
>
|
<view style="display: flex; align-items: center">
|
<view class="title-indicator"></view>
|
<text class="header-title">
|
{{ $t('container.matList') }} ({{ dataList.length }})
|
</text>
|
</view>
|
<view class="review-status">
|
<text v-if="orderReviewRequired">
|
{{ $t('container.reviewed') }}: {{ reviewedCount }} /
|
{{ dataList.length }}
|
</text>
|
<text v-else>
|
{{ $t('container.noReviewReq', '无需复核') }}
|
</text>
|
</view>
|
</view>
|
|
<view class="list-container">
|
<view
|
class="panel mat-card"
|
v-for="(item, i) in dataList"
|
:key="i"
|
>
|
<view class="card-top">
|
<view style="display: flex; align-items: center">
|
<view class="card-index">{{ i + 1 }}</view>
|
<text class="mat-code">{{ item.matnr }}</text>
|
</view>
|
<view
|
v-if="orderReviewRequired"
|
class="review-badge"
|
:class="
|
item.review === 'reviewed'
|
? 'reviewed'
|
: 'unreviewed'
|
"
|
>
|
<text class="badge-text">
|
{{
|
item.review === 'reviewed'
|
? $t('container.reviewed')
|
: $t('container.unreviewed')
|
}}
|
</text>
|
</view>
|
</view>
|
|
<view class="card-content">
|
<view class="info-row">
|
<text class="info-label">
|
{{ $t('container.matName') }}
|
</text>
|
<text class="info-value">
|
{{ item.maktx || '-' }}
|
</text>
|
</view>
|
<view class="info-row">
|
<view class="info-col">
|
<text class="info-label">
|
{{ $t('container.matSpec') }}
|
</text>
|
<text class="info-value">
|
{{ item.specs || '-' }}
|
</text>
|
</view>
|
<view class="info-col">
|
<text class="info-label">
|
{{ $t('container.matBatch') }}
|
</text>
|
<text class="info-value highlight">
|
{{ item.batch || '-' }}
|
</text>
|
</view>
|
</view>
|
<view class="info-row">
|
<view class="info-col">
|
<text class="info-label">
|
{{ $t('container.matQty') }}
|
</text>
|
<text class="info-value qty">
|
{{ item.anfme }}
|
</text>
|
</view>
|
</view>
|
</view>
|
|
<view class="card-actions">
|
<u-button
|
type="primary"
|
size="small"
|
plain
|
:text="$t('container.modify')"
|
@click="revise(item, i)"
|
customStyle="width: 140rpx; margin: 0;"
|
></u-button>
|
<view style="width: 20rpx"></view>
|
<u-button
|
type="error"
|
size="small"
|
plain
|
:text="$t('container.remove')"
|
@click="remove(item, i)"
|
customStyle="width: 140rpx; margin: 0;"
|
></u-button>
|
</view>
|
</view>
|
|
<u-empty
|
v-if="dataList.length === 0"
|
mode="list"
|
:text="$t('container.emptyMat')"
|
marginTop="40"
|
></u-empty>
|
</view>
|
</view>
|
|
<!-- 底部操作按钮 -->
|
<view class="bottom-bar">
|
<view class="btn-wrap">
|
<u-button
|
type="info"
|
:text="$t('container.reset')"
|
@click="resetConfirmBtn"
|
></u-button>
|
</view>
|
<view
|
class="btn-wrap"
|
style="flex: 2; margin-left: 20rpx"
|
>
|
<u-button
|
type="primary"
|
:text="$t('container.confirmComb')"
|
@click="combConfirmBtn"
|
:disabled="isDisabled || dataList.length === 0"
|
:throttleTime="1500"
|
></u-button>
|
</view>
|
</view>
|
|
<!-- 修改数量弹窗 -->
|
<u-popup
|
:show="showRevise"
|
mode="center"
|
round="12"
|
@close="showRevise = false"
|
>
|
<view class="popup-card">
|
<view class="popup-header">
|
<text>{{ $t('container.modifyInfo') }}</text>
|
</view>
|
<view class="popup-body">
|
<u--form
|
labelWidth="80"
|
labelPosition="left"
|
>
|
<u-form-item :label="$t('container.code')">
|
<text class="popup-text-val">{{ editMatnr }}</text>
|
</u-form-item>
|
<u-form-item :label="$t('container.matBatch')">
|
<u--input
|
v-model="batch"
|
:placeholder="$t('matSelected.inputBatch')"
|
border="surround"
|
></u--input>
|
</u-form-item>
|
<u-form-item :label="$t('container.matQty')">
|
<u-number-box
|
v-model="count"
|
:step="0.01"
|
:max="9999999"
|
@change="changeValue"
|
></u-number-box>
|
</u-form-item>
|
</u--form>
|
</view>
|
<view class="popup-footer">
|
<u-button
|
:text="$t('common.cancel')"
|
@click="showRevise = false"
|
customStyle="margin-right: 20rpx; flex: 1;"
|
></u-button>
|
<u-button
|
type="primary"
|
:text="$t('common.confirm')"
|
@click="reviseConfirm"
|
customStyle="flex: 1;"
|
></u-button>
|
</view>
|
</view>
|
</u-popup>
|
|
<!-- 模态框 -->
|
<u-modal
|
:show="showRemove"
|
:title="$t('container.confirmRemove')"
|
:content="$t('container.removeMsg')"
|
showCancelButton
|
@confirm="removeConfirm"
|
@cancel="showRemove = false"
|
></u-modal>
|
<u-modal
|
:show="showComb"
|
:title="$t('container.confirmComb')"
|
:content="$t('container.combMsg')"
|
showCancelButton
|
@confirm="comb"
|
@cancel="showComb = false"
|
></u-modal>
|
<u-modal
|
:show="showReset"
|
:title="$t('container.confirmReset')"
|
:content="$t('container.resetMsg')"
|
showCancelButton
|
@confirm="resetConfirm"
|
@cancel="showReset = false"
|
></u-modal>
|
<u-toast ref="uToast"></u-toast>
|
</view>
|
</template>
|
|
<script>
|
import { combOrder } from './api.js'
|
|
export default {
|
data() {
|
return {
|
barcode: '',
|
orderNo: '',
|
dataList: [],
|
count: 0,
|
rowNum: '',
|
matnr: '',
|
editMatnr: '',
|
batch: '',
|
weight: '',
|
orderNoFocus: false,
|
barcodeFocus: true,
|
matFocus: false,
|
removeNum: 0,
|
isDisabled: false,
|
|
showRevise: false,
|
showRemove: false,
|
showComb: false,
|
showReset: false,
|
orderReviewRequired: false,
|
orderCombNeedSplit: true,
|
orderCombSeparator: ';',
|
orderCombArrayIndex: 0,
|
orderCombStartPos: 3
|
}
|
},
|
computed: {
|
// 已复核数量
|
reviewedCount() {
|
return this.dataList.filter((item) => item.review === 'reviewed')
|
.length
|
}
|
},
|
onLoad() {
|
let that = this
|
const eventChannel = this.getOpenerEventChannel()
|
if (eventChannel) {
|
eventChannel.on('orderItem', function (data) {
|
if (data.items && data.items.length > 0) {
|
that.orderNo = data.items[0].orderNo
|
data.items.forEach((item) => {
|
that.checkMat(item)
|
})
|
} else if (data.item) {
|
that.orderNo = data.item.orderNo
|
that.checkMat(data.item)
|
}
|
})
|
}
|
},
|
onShow() {
|
// 获取开多选设置
|
let settings = uni.getStorageSync('appSettings')
|
if (settings) {
|
this.orderReviewRequired = !!settings.orderReviewRequired
|
this.orderCombNeedSplit = settings.orderCombNeedSplit !== false
|
this.orderCombSeparator = settings.orderCombSeparator || ';'
|
this.orderCombArrayIndex = settings.orderCombArrayIndex !== undefined ? Number(settings.orderCombArrayIndex) : 0
|
this.orderCombStartPos = settings.orderCombStartPos !== undefined ? Number(settings.orderCombStartPos) : 3
|
} else {
|
this.orderReviewRequired = false
|
this.orderCombNeedSplit = true
|
this.orderCombSeparator = ';'
|
this.orderCombArrayIndex = 0
|
this.orderCombStartPos = 3
|
}
|
},
|
methods: {
|
barcodeInput(val) {
|
setTimeout(() => {
|
var len = this.barcode.length
|
this.focuss()
|
}, 200)
|
},
|
barcodeFocuss() {
|
this.barcodeFocus = false
|
setTimeout(() => {
|
this.barcode = ''
|
this.barcodeFocus = true
|
}, 100)
|
},
|
focuss() {
|
this.matFocus = false
|
setTimeout(() => {
|
this.matnr = ''
|
this.matFocus = true
|
}, 100)
|
},
|
// 搜索物料 - 扫码复核
|
findMat(val) {
|
if (!this.matnr) return
|
let matnr1 = this.matnr
|
if (this.orderCombNeedSplit) {
|
let m = this.matnr.split(this.orderCombSeparator)
|
// Ensure index is within bounds to avoid undefined errors
|
let targetChunk = m[this.orderCombArrayIndex] || m[0]
|
matnr1 = targetChunk.slice(this.orderCombStartPos)
|
}
|
let found = false
|
for (var i = 0; i < this.dataList.length; i++) {
|
if (this.dataList[i].matnr === matnr1) {
|
this.dataList[i].review = 'reviewed'
|
found = true
|
}
|
}
|
if (found) {
|
this.$showToast({
|
type: 'success',
|
message: this.$t('toast.reviewSuccess')
|
})
|
} else {
|
this.$showToast({
|
type: 'error',
|
message: this.$t('toast.reviewFail')
|
})
|
}
|
setTimeout(() => {
|
this.matnr = ''
|
}, 100)
|
},
|
checkMat(mat) {
|
mat.review = 'unreviewed'
|
mat.anfme = mat.enableQty
|
var len = this.dataList.length
|
var add = true,
|
sameItem = false
|
for (var i = 0; i < len; i++) {
|
if (mat.matnr == this.dataList[i].matnr) {
|
for (var j = 0; j < len; j++) {
|
if (mat.batch == this.dataList[j].batch) {
|
sameItem = true
|
}
|
}
|
if (mat.batch != this.dataList[i].batch) {
|
if (sameItem) {
|
add = false
|
} else {
|
add = true
|
}
|
} else {
|
this.dataList[i].anfme += mat.anfme
|
add = false
|
}
|
}
|
}
|
if (add) {
|
this.dataList.unshift(mat)
|
}
|
},
|
revise(item, i) {
|
this.editMatnr = this.dataList[i].matnr
|
this.count = this.dataList[i].anfme
|
this.batch = this.dataList[i].batch
|
this.weight = this.dataList[i].weight
|
this.rowNum = i
|
this.showRevise = true
|
},
|
changeValue(e) {
|
this.count = e.value
|
},
|
reviseConfirm() {
|
this.dataList[this.rowNum].anfme = this.count
|
this.dataList[this.rowNum].batch = this.batch
|
this.dataList[this.rowNum].weight = this.weight
|
this.editMatnr = ''
|
this.$showToast({
|
type: 'success',
|
message: this.$t('toast.modifySuccess')
|
})
|
this.showRevise = false
|
},
|
remove(item, i) {
|
this.removeNum = i
|
this.showRemove = true
|
},
|
removeConfirm() {
|
this.dataList.splice(this.removeNum, 1)
|
this.$showToast({
|
type: 'success',
|
message: this.$t('toast.removeSuccess')
|
})
|
this.showRemove = false
|
},
|
combConfirmBtn() {
|
if (this.isDisabled || this.dataList.length === 0) return
|
this.showComb = true
|
},
|
async comb() {
|
let that = this
|
that.isDisabled = true
|
|
if (that.orderNo === '') {
|
this.$showToast({
|
type: 'error',
|
message: this.$t('toast.inputOrderNo')
|
})
|
that.isDisabled = false
|
this.showComb = false
|
return
|
}
|
if (that.barcode === '') {
|
this.$showToast({
|
type: 'error',
|
message: this.$t('toast.scanPalletCode')
|
})
|
that.isDisabled = false
|
this.showComb = false
|
return
|
}
|
if (that.dataList.length === 0) {
|
this.$showToast({
|
type: 'error',
|
message: this.$t('toast.emptyMat')
|
})
|
that.isDisabled = false
|
this.showComb = false
|
return
|
}
|
|
this.showComb = false
|
uni.vibrateShort()
|
|
try {
|
const { code, msg } = await combOrder(
|
{
|
orderNo: this.orderNo,
|
barcode: this.barcode,
|
combMats: this.dataList
|
},
|
{ custom: { catch: true } }
|
)
|
|
if (code === 200) {
|
this.resst()
|
this.$showToast({
|
type: 'success',
|
message: this.$t('toast.combSuccess')
|
})
|
const innerAudioContext = uni.createInnerAudioContext()
|
innerAudioContext.src = '/static/music/pakinOk.mp3'
|
innerAudioContext.play()
|
setTimeout(() => {
|
uni.navigateBack()
|
}, 1500)
|
} else if (code === 403) {
|
this.$showToast({ type: 'error', message: msg })
|
setTimeout(() => {
|
uni.reLaunch({ url: '/pages/login/login' })
|
}, 1000)
|
} else {
|
this.$showToast({
|
type: 'error',
|
message: msg || this.$t('toast.combFail')
|
})
|
}
|
} catch (err) {
|
} finally {
|
that.isDisabled = false
|
}
|
},
|
resetConfirmBtn() {
|
this.showReset = true
|
},
|
resetConfirm() {
|
this.dataList = []
|
this.barcode = ''
|
this.$showToast({
|
type: 'success',
|
message: this.$t('toast.resetComplete')
|
})
|
this.showReset = false
|
},
|
resst() {
|
this.orderNo = ''
|
this.dataList = []
|
this.barcode = ''
|
this.orderNoFocus = false
|
setTimeout(() => {
|
this.orderNo = ''
|
this.orderNoFocus = true
|
}, 100)
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
page {
|
background-color: #f0f2f5;
|
}
|
|
.page-container {
|
min-height: 100vh;
|
background-color: #f0f2f5;
|
padding-bottom: 140rpx;
|
}
|
|
/* 面板区域 */
|
.panel-section {
|
padding: 24rpx;
|
}
|
|
.panel {
|
background-color: #ffffff;
|
border-radius: 12rpx;
|
padding: 24rpx;
|
box-shadow: 0 2rpx 12rpx 0 rgba(0, 0, 0, 0.05);
|
margin-bottom: 24rpx;
|
}
|
|
.form-panel {
|
padding: 10rpx 24rpx;
|
}
|
|
.form-label {
|
display: flex;
|
align-items: center;
|
height: 100%;
|
padding-right: 20rpx;
|
}
|
|
.label-text {
|
font-size: 28rpx;
|
color: #606266;
|
white-space: nowrap;
|
line-height: 1;
|
}
|
|
.input-wrap {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
height: 100%;
|
}
|
|
::v-deep .u-form-item__body {
|
align-items: center !important;
|
padding: 10rpx 0 !important;
|
}
|
::v-deep .u-form-item__body__left {
|
align-items: center !important;
|
margin-bottom: 0 !important;
|
}
|
|
/* 列表区域 */
|
.list-section {
|
padding: 0 24rpx;
|
}
|
|
.list-header {
|
display: flex;
|
align-items: center;
|
margin-bottom: 24rpx;
|
}
|
|
.title-indicator {
|
width: 6rpx;
|
height: 30rpx;
|
background-color: #409eff;
|
border-radius: 4rpx;
|
margin-right: 16rpx;
|
}
|
|
.header-title {
|
font-size: 30rpx;
|
color: #303133;
|
font-weight: 600;
|
}
|
|
.review-status {
|
font-size: 24rpx;
|
color: #909399;
|
}
|
|
/* 卡片样式 */
|
.mat-card {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.card-top {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
border-bottom: 1px solid #ebeef5;
|
padding-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
}
|
|
.card-index {
|
background-color: #409eff;
|
color: #fff;
|
width: 40rpx;
|
height: 40rpx;
|
border-radius: 50%;
|
text-align: center;
|
line-height: 40rpx;
|
font-size: 24rpx;
|
margin-right: 16rpx;
|
}
|
|
.mat-code {
|
font-size: 32rpx;
|
font-weight: 600;
|
color: #303133;
|
}
|
|
.review-badge {
|
padding: 4rpx 12rpx;
|
border-radius: 16rpx;
|
}
|
|
.reviewed {
|
background: #67c23a;
|
}
|
|
.unreviewed {
|
background: #909399;
|
}
|
|
.badge-text {
|
font-size: 22rpx;
|
color: #ffffff;
|
}
|
|
.card-content {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.info-row {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 12rpx;
|
}
|
|
.info-col {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
}
|
|
.info-label {
|
color: #909399;
|
font-size: 26rpx;
|
width: 80rpx;
|
}
|
|
.info-value {
|
color: #303133;
|
font-size: 28rpx;
|
}
|
|
.highlight {
|
color: #e6a23c;
|
}
|
|
.qty {
|
color: #f56c6c;
|
font-weight: bold;
|
}
|
|
.card-actions {
|
display: flex;
|
justify-content: flex-end;
|
margin-top: 10rpx;
|
border-top: 1px dashed #ebeef5;
|
padding-top: 20rpx;
|
}
|
|
/* 底部操作条 */
|
.bottom-bar {
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
background-color: #fff;
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
display: flex;
|
padding: 20rpx 24rpx;
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
z-index: 99;
|
}
|
|
.btn-wrap {
|
display: flex;
|
flex: 1;
|
}
|
|
/* 弹窗样式 */
|
.popup-card {
|
width: 600rpx;
|
background-color: #fff;
|
border-radius: 12rpx;
|
padding: 40rpx 30rpx;
|
}
|
|
.popup-header {
|
text-align: center;
|
font-size: 32rpx;
|
font-weight: bold;
|
color: #303133;
|
margin-bottom: 30rpx;
|
}
|
|
.popup-text-val {
|
font-size: 28rpx;
|
color: #606266;
|
}
|
|
.popup-footer {
|
display: flex;
|
margin-top: 40rpx;
|
}
|
</style>
|