<template>
|
<view class="page-container">
|
<!-- 顶部导航栏 -->
|
<view class="nav-header">
|
<uni-segmented-control
|
:current="current"
|
:values="items"
|
@clickItem="onClickItem"
|
class="segmented-control"
|
>
|
</uni-segmented-control>
|
</view>
|
|
<!-- 主内容区 -->
|
<view class="main-content">
|
<!-- 组盘模块 -->
|
<view v-if="current === 0" class="card-container">
|
<!-- 组盘表单卡片 -->
|
<view class="form-card">
|
<uni-forms class="form-wrapper" label-width="80px">
|
<uni-forms-item label="托盘条码:" class="form-item">
|
<uni-easyinput
|
type="text"
|
placeholder="请扫描托盘条码"
|
:focus="barcodeFocus"
|
v-model="barcode"
|
@confirm="onBarcodeConfirm"
|
class="input-field"
|
:disabled="isSubmitting"
|
/>
|
</uni-forms-item>
|
|
<uni-forms-item label="内箱标签:" class="form-item">
|
<uni-easyinput
|
type="text"
|
placeholder="请扫描内箱标签"
|
:focus="materSnFocus"
|
v-model="materSn"
|
@confirm="onMaterSnConfirm"
|
class="input-field"
|
:disabled="isSubmitting"
|
/>
|
</uni-forms-item>
|
|
<uni-forms-item :label="Testlabel" v-if="Test" class="form-item">
|
<uni-easyinput
|
type="text"
|
:placeholder="Testplaceholder"
|
v-model="Initiallife"
|
class="input-field"
|
:disabled="isSubmitting"
|
/>
|
</uni-forms-item>
|
|
<view class="form-actions">
|
<button
|
@click="submit"
|
type="primary"
|
class="btn-primary"
|
:disabled="isSubmitting"
|
>
|
<uni-icons type="refresh" size="16" v-if="isSubmitting"></uni-icons>
|
{{isSubmitting ? '组盘中...' : '组盘'}}
|
</button>
|
</view>
|
</uni-forms>
|
</view>
|
|
<!-- 物料信息列表 -->
|
<view class="list-card" v-if="matInfos.length > 0">
|
<view class="list-header">
|
<text class="list-title">物料信息</text>
|
<text class="count-badge">1</text>
|
</view>
|
|
<uni-list class="material-list">
|
<uni-list-item
|
direction="column"
|
v-for="(item,index) in matInfos"
|
:key="index"
|
class="list-item"
|
>
|
<template v-slot:body>
|
<view class="list-item-content">
|
<uni-icons
|
type="trash"
|
size="20"
|
class="delete-icon"
|
@click="deleteList(index)"
|
:disabled="isSubmitting"
|
>
|
</uni-icons>
|
|
<view class="info-grid">
|
<view class="info-row">
|
<text class="label">采购单号:</text>
|
<text class="value">{{item.purchaseOrderNo}}</text>
|
</view>
|
<view class="info-row">
|
<text class="label">物料编码:</text>
|
<text class="value">{{item.materielCode}}</text>
|
</view>
|
<view class="info-row">
|
<text class="label">批次号:</text>
|
<text class="value">{{item.lotNo}}</text>
|
</view>
|
<view class="info-row">
|
<text class="label">数量:</text>
|
<text class="value">{{item.quantity}}</text>
|
</view>
|
<view class="info-row">
|
<text class="label">生产日期:</text>
|
<text class="value">{{item.productionDate}}</text>
|
</view>
|
<view class="info-row">
|
<text class="label">有效期:</text>
|
<text class="value">{{item.effectiveDate}}</text>
|
</view>
|
<view class="info-row">
|
<text class="label">物料长度:</text>
|
<text class="value">{{item.materielLength}}</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
</uni-list-item>
|
</uni-list>
|
</view>
|
|
<!-- 空状态提示 -->
|
<view class="empty-state" v-if="matInfos.length === 0 && barcode">
|
<uni-icons type="empty" size="60" color="#ccc"></uni-icons>
|
<text class="empty-text">暂无物料信息,请扫描内箱标签</text>
|
</view>
|
</view>
|
|
<!-- 入库模块(保持不变) -->
|
<view v-if="current === 1" class="card-container">
|
<view class="form-card">
|
<uni-forms class="form-wrapper" label-width="80px">
|
<uni-forms-item label="托盘条码:" class="form-item">
|
<uni-easyinput
|
type="text"
|
placeholder="请扫描托盘条码"
|
:focus="!addressFocus"
|
v-model="inboundBarcode"
|
@confirm="inputChangebarcode"
|
class="input-field"
|
:disabled="isInboundSubmitting"
|
/>
|
</uni-forms-item>
|
|
<uni-forms-item label="地址条码:" class="form-item">
|
<uni-easyinput
|
type="text"
|
placeholder="请扫描地址条码"
|
:focus="addressFocus"
|
v-model="address"
|
class="input-field"
|
:disabled="addressdisabled || isInboundSubmitting"
|
/>
|
</uni-forms-item>
|
|
<view class="form-actions">
|
<button
|
@click="inbound"
|
type="primary"
|
class="btn-primary"
|
:disabled="isInboundSubmitting"
|
>
|
<uni-icons type="refresh" size="16" v-if="isInboundSubmitting"></uni-icons>
|
{{isInboundSubmitting ? '入库中...' : '入库确认'}}
|
</button>
|
</view>
|
</uni-forms>
|
</view>
|
|
<view class="list-card" v-if="inboundBarcode">
|
<view class="summary-card" v-if="Summmary > 0">
|
<text class="summary-label">组盘总数量:</text>
|
<text class="summary-value">{{Summmary}}</text>
|
</view>
|
|
<uni-list class="material-list" v-if="stockInfoDetail.length > 0">
|
<uni-list-item direction="column" v-for="(item,index) in stockInfoDetail" :key="index">
|
<template v-slot:body>
|
<view class="list-item-content">
|
<view class="info-grid">
|
<view class="info-row"><text class="label">物料编号:</text><text class="value">{{item.materielCode}}</text></view>
|
<view class="info-row"><text class="label">物料名称:</text><text class="value">{{item.materielName}}</text></view>
|
<view class="info-row"><text class="label">物料批次:</text><text class="value">{{item.batchNo}}</text></view>
|
<view class="info-row"><text class="label">组盘数量:</text><text class="value">{{item.stockQuantity}}</text></view>
|
<view class="info-row"><text class="label">生产日期:</text><text class="value">{{item.productionDate}}</text></view>
|
<view class="info-row"><text class="label">有效期:</text><text class="value">{{item.effectiveDate}}</text></view>
|
</view>
|
</view>
|
</template>
|
</uni-list-item>
|
</uni-list>
|
</view>
|
</view>
|
</view>
|
|
<u-toast ref="uToast" />
|
</view>
|
</template>
|
|
<script>
|
const innerAudioContext = uni.createInnerAudioContext();
|
export default {
|
data() {
|
return {
|
items: ['组盘', '入库'],
|
current: 0,
|
// 组盘模块数据
|
matInfos: [],
|
orderNo: "",
|
barcode: "",
|
materSn: "",
|
Initiallife: 1000,
|
sns: [],
|
// 组盘焦点控制
|
barcodeFocus: true, // 托盘条码初始获得焦点
|
materSnFocus: false, // 内箱标签焦点
|
// 入库模块数据
|
addressFocus: false,
|
inboundBarcode: "",
|
address: "",
|
warehouseId: "",
|
Test: false,
|
Testlabel: "",
|
Testplaceholder: "",
|
Testcheck: false,
|
Summmary: 0,
|
stockInfoDetail: [],
|
addressdisabled: false,
|
isSubmitting: false,
|
isInboundSubmitting: false
|
}
|
},
|
onLoad(res) {
|
this.orderNo = res.orderNo;
|
this.warehouseId = res.warehouseId;
|
|
if (this.warehouseId == 6) {
|
this.Test = true;
|
this.Testlabel = "初始寿命:";
|
this.Testplaceholder = "请输入初始寿命";
|
} else if (this.warehouseId == 2) {
|
this.Test = true;
|
this.Testlabel = "数量:";
|
this.Testplaceholder = "请输入数量";
|
this.Initiallife = 16;
|
} else if (this.warehouseId == 3) {
|
this.address = "1011";
|
this.addressdisabled = true;
|
}
|
|
// 确保初始焦点在托盘条码
|
this.barcodeFocus = true;
|
this.materSnFocus = false;
|
},
|
methods: {
|
getData() {},
|
onClickItem(e) {
|
this.current = e.currentIndex;
|
// 切换选项卡时重置焦点
|
if (this.current === 0) {
|
this.barcodeFocus = true;
|
this.materSnFocus = false;
|
} else {
|
this.addressFocus = false;
|
}
|
},
|
|
// ==================== 组盘模块焦点跳转 ====================
|
/**
|
* 托盘条码扫描确认
|
* 扫描后自动跳转到内箱标签输入框
|
*/
|
onBarcodeConfirm() {
|
if (!this.barcode || this.barcode.trim() === '') {
|
this.$refs.uToast.show({
|
title: "请扫描托盘条码",
|
type: 'error'
|
});
|
// 保持焦点在托盘条码框
|
this.barcodeFocus = true;
|
this.materSnFocus = false;
|
return;
|
}
|
// 托盘码有效,跳转到内箱标签
|
this.barcodeFocus = false;
|
this.materSnFocus = true;
|
},
|
|
/**
|
* 内箱标签扫描确认
|
* 自动解析内箱码,清空输入框,焦点保留在内箱标签框
|
*/
|
onMaterSnConfirm() {
|
if (!this.materSn || this.materSn.trim() === '') {
|
this.$refs.uToast.show({
|
title: "请扫描内箱标签",
|
type: 'error'
|
});
|
return;
|
}
|
|
// 特殊处理:仓库11时去掉后缀
|
let snToProcess = this.materSn;
|
if (this.warehouseId == 11) {
|
snToProcess = snToProcess.replace(/,SC.*/, '');
|
}
|
|
// 内箱码格式校验(必须包含7个字段,以逗号分隔)
|
if (snToProcess.split(',').length != 7) {
|
this.$refs.uToast.show({
|
title: "内箱码格式错误,请重新扫描",
|
type: 'error'
|
});
|
// 清空输入框,便于重新扫描
|
this.materSn = "";
|
// 焦点不动(materSnFocus 已是 true)
|
return;
|
}
|
|
// 发起后端解析请求
|
this.$u.post('/api/MaterielInfo/PPPKCodeAnalysis?serNum=' + snToProcess, {})
|
.then(res => {
|
if (res.status) {
|
// 解析成功:替换为最新的内箱码(只保留一个)
|
this.sns = [res.data.serialNumber];
|
this.matInfos = [res.data];
|
|
this.$refs.uToast.show({
|
title: "内箱码已更新",
|
type: "success",
|
duration: 1500
|
});
|
// 清空输入框,为下一次扫描做准备(焦点仍在内箱码框)
|
this.materSn = "";
|
// 焦点不动,保持在内箱码框(materSnFocus 已是 true)
|
} else {
|
this.$refs.uToast.show({
|
title: res.message,
|
type: "error"
|
});
|
// 解析失败,清空输入框,让用户重新扫描
|
this.materSn = "";
|
}
|
})
|
.catch(err => {
|
this.$refs.uToast.show({
|
title: err.message || "解析失败",
|
type: "error"
|
});
|
this.materSn = "";
|
});
|
},
|
|
// 删除内箱码(清空)
|
deleteList() {
|
if (this.isSubmitting) return;
|
this.matInfos = [];
|
this.sns = [];
|
this.$refs.uToast.show({
|
title: "内箱码已清空",
|
type: "info"
|
});
|
// 焦点保留在内箱码框
|
},
|
|
// ==================== 组盘提交 ====================
|
submit() {
|
if (this.isSubmitting) return;
|
if (!this.barcode) {
|
this.$refs.uToast.show({ title: "请扫描托盘条码", type: 'error' });
|
this.resetFocusToBarcode();
|
return;
|
}
|
if (this.matInfos.length === 0) {
|
this.$refs.uToast.show({ title: "请扫描内箱标签", type: 'error' });
|
this.resetFocusToMaterSn();
|
return;
|
}
|
if (this.Test && !this.Testcheck) {
|
this.Testcheck = true;
|
this.$refs.uToast.show({
|
title: this.warehouseId == 2 ? "请确认数量" : "请确认初始寿命",
|
type: 'error'
|
});
|
return;
|
}
|
|
if (this.warehouseId == 2) {
|
let sn = this.sns[0];
|
this.sns = Array(this.Initiallife).fill(sn);
|
}
|
|
this.isSubmitting = true;
|
let url = `palletCode=${this.barcode}&initiallife=${this.Initiallife}&warehouseId=${this.warehouseId}`;
|
|
this.$u.post('/api/InboundOrder/PPPKManualMaterielGroup?' + url, this.sns)
|
.then(res => {
|
if (res.status) {
|
this.$refs.uToast.show({ title: "组盘成功", type: "success" });
|
// 重置表单
|
this.barcode = "";
|
this.matInfos = [];
|
this.sns = [];
|
// 重置焦点:回到托盘条码框,开始新的一轮
|
this.resetFocusToBarcode();
|
} else {
|
this.$refs.uToast.show({ title: res.message, type: "error" });
|
}
|
})
|
.finally(() => {
|
this.isSubmitting = false;
|
});
|
},
|
|
// ==================== 焦点重置辅助 ====================
|
resetFocusToBarcode() {
|
this.barcodeFocus = true;
|
this.materSnFocus = false;
|
},
|
resetFocusToMaterSn() {
|
this.barcodeFocus = false;
|
this.materSnFocus = true;
|
},
|
|
// ==================== 入库模块(保持原逻辑) ====================
|
inputChangebarcode() {
|
this.addressFocus = false;
|
this.$nextTick(() => {
|
if (!this.inboundBarcode) return;
|
this.addressFocus = true;
|
this.$u.post('/api/StockInfo/StockQueryData', {
|
MainData: { barcode: this.inboundBarcode, warehouseId: this.warehouseId }
|
}).then(res => {
|
this.stockInfoDetail = [];
|
this.Summmary = 0;
|
if (res.status) {
|
this.stockInfoDetail = res.data.details;
|
this.stockInfoDetail.forEach(item => {
|
this.Summmary += item.stockQuantity;
|
});
|
} else {
|
this.$refs.uToast.show({ title: res.message, type: "error" });
|
}
|
})
|
})
|
},
|
|
inbound() {
|
if (this.isInboundSubmitting) return;
|
if (!this.inboundBarcode) {
|
this.$refs.uToast.show({ title: "请扫描托盘条码", type: "error" });
|
return;
|
}
|
if (!this.address) {
|
this.$refs.uToast.show({ title: "请扫描地址条码", type: "error" });
|
return;
|
}
|
|
this.isInboundSubmitting = true;
|
this.$u.post('/api/Task/PPPKRequestInboundTask', {
|
MainData: {
|
barcode: this.inboundBarcode,
|
startPoint: this.address,
|
warehouseId: this.warehouseId
|
}
|
}).then(res => {
|
if (res.status) {
|
this.inboundBarcode = "";
|
if (this.warehouseId != 3) this.address = "";
|
this.stockInfoDetail = [];
|
this.Summmary = 0;
|
this.$refs.uToast.show({ title: "入库成功", type: "success" });
|
} else {
|
this.$refs.uToast.show({ title: res.message, type: "error" });
|
}
|
}).finally(() => {
|
this.isInboundSubmitting = false;
|
});
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss">
|
@import '@/common/uni-ui.scss';
|
page { background-color: #f5f7fa; font-size: 14px; color: #333; }
|
.page-container { min-height: 100vh; display: flex; flex-direction: column; }
|
.nav-header { background: #fff; padding: 12px 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
|
.segmented-control { border-radius: 8px; --uni-segmented-control-height: 40px; }
|
.main-content { flex: 1; padding: 16px; }
|
.card-container { display: flex; flex-direction: column; gap: 16px; }
|
.form-card { background: #fff; border-radius: 12px; padding: 20px; box-shadow: 0 2px 12px rgba(0,0,0,0.04); }
|
.form-item { margin-bottom: 16px; }
|
.input-field { border-radius: 8px; height: 44px; }
|
.form-actions { margin-top: 10px; }
|
.btn-primary { width: 100%; height: 48px; border-radius: 8px; }
|
.list-card { background: #fff; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 12px rgba(0,0,0,0.04); }
|
.list-header { padding: 16px; border-bottom: 1px solid #f0f0f0; display: flex; justify-content: space-between; }
|
.count-badge { background: #e6f4ff; color: #165dff; padding: 2px 8px; border-radius: 20px; font-size: 12px; }
|
.list-item-content { position: relative; padding: 16px; }
|
.delete-icon { position: absolute; right: 16px; top: 50%; transform: translateY(-50%); color: #ef4444; }
|
.info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
|
.info-row { display: flex; flex-direction: column; }
|
.label { font-size: 12px; color: #6b7280; }
|
.value { font-size: 14px; color: #222; font-weight: 500; }
|
.summary-card { padding: 16px; background: #e6f4ff; font-size: 15px; }
|
.summary-value { font-weight: bold; color: #165dff; margin-left: 6px; }
|
.empty-state { padding: 50px 20px; text-align: center; color: #999; }
|
</style>
|