<template>
|
<view class="sockpage">
|
<view class="column">
|
<view class="form-card">
|
<view class="form-row">
|
<view class="label">
|
<text class="required">*</text>托盘编码:
|
</view>
|
<view class="picker-wrap" hover-class="picker-hover">
|
<view class="input-box">
|
<input
|
id="pdacode"
|
type="text"
|
ref="barcodeInput"
|
v-model="barcode"
|
placeholder="请扫码(12位以下为托盘码)"
|
:focus="focusState"
|
@focus="focusFn"
|
@blur="focusState = false"
|
/>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 箱型栏(对应后端boxType) -->
|
<view class="form-card">
|
<view class="form-row">
|
<view class="label">
|
<text class="required">*</text>箱 型:
|
</view>
|
<view class="picker-wrap" hover-class="picker-hover">
|
<picker @change="modePickerChange" :value="index_mode" :range="mode">
|
<view class="input-box">
|
<text class="input-placeholder" v-if="!mode.length || !mode[index_mode]">请选择箱型</text>
|
<text class="input-value" v-else>{{mode[index_mode]}}</text>
|
</view>
|
</picker>
|
</view>
|
</view>
|
</view>
|
|
<!-- 物料信息输入栏(对应后端MatList) -->
|
<view class="form-card material-card">
|
<view class="card-title">物料信息</view>
|
<view class="material-grid">
|
<view class="material-item">
|
<text class="material-label"><text class="required">*</text>卷号:</text>
|
<input
|
class="material-input"
|
type="text"
|
v-model="matList.model"
|
placeholder="请扫码或输入卷号"
|
placeholder-class="input-placeholder"
|
ref="modelInput"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label"><text class="required">*</text>箱号:</text>
|
<input
|
class="material-input"
|
type="text"
|
v-model="matList.batch"
|
placeholder="请扫码或输入箱号"
|
placeholder-class="input-placeholder"
|
ref="batchInput"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">规格:</text>
|
<input
|
class="material-input"
|
type="text"
|
v-model="matList.matnr"
|
placeholder="请输入规格"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">长度:</text>
|
<input
|
class="material-input"
|
type="number"
|
v-model="matList.rollExtent"
|
placeholder="请输入长度"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">净重:</text>
|
<input
|
class="material-input"
|
type="number"
|
v-model="matList.weight"
|
placeholder="请输入净重"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">毛重:</text>
|
<input
|
class="material-input"
|
type="number"
|
v-model="matList.roughWeight"
|
placeholder="请输入毛重"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">接头:</text>
|
<input
|
class="material-input"
|
type="number"
|
v-model="matList.joint"
|
placeholder="请输入接头数"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
</view>
|
</view>
|
|
<!-- 操作按钮组 -->
|
<view class="btn-group">
|
<button class="operate-btn scan-btn" @click="startScan">开始扫码</button>
|
<button class="operate-btn submit-btn" @click="submit">成品入库</button>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import { onLoad } from '../../uni_modules/uview-ui/libs/mixin/mixin'
|
|
export default {
|
onLoad(){
|
// 先读取缓存,再执行请求
|
this.baseUrl = uni.getStorageSync('baseUrl');
|
this.token = uni.getStorageSync('token');
|
// 页面加载时 mode 为空,调用接口后才填充数据
|
this.POSTinfo();
|
},
|
|
mounted() {
|
this.setupScanListener();
|
},
|
|
beforeDestroy() {
|
this.removeScanListener();
|
},
|
|
data() {
|
return {
|
focusState: false,
|
baseUrl: '',
|
barcodeNum:'',
|
barcode: '', // 托盘码
|
palletizingNo: '1', // 码垛位编号
|
boxType: '', // 木箱类型
|
matList: {
|
matnr: '', // 规格
|
maktx: '', // 物料名称
|
batch: '', // 木箱编号
|
model: '', // 卷编号
|
position: '1', // 木箱码垛位置
|
weight: '', // 净重
|
roughWeight: '', // 毛重
|
anfme: 1.0, // 默认值1.0
|
rollExtent: '', // 卷长度
|
joint: 0, // 接头
|
cutting: 2,
|
qualified: 0,
|
modelFront: '', // 分切前箱编号
|
batchFront: '' ,// 分切前卷号
|
},
|
// 初始化 mode 为空数组 → 页面加载时箱型无数据
|
mode: [],
|
index_mode: 0,
|
index_num: 0,
|
submitData: {} ,// 最终提交给后端的数据
|
scanBuffer: '', // 添加扫码缓冲区
|
scanTimeout: null, // 扫码超时定时器
|
isScanning: false, // 扫码状态标志
|
scanMode: 'tray', // 扫码模式: tray-托盘码, material-物料码
|
lastFillTarget: null // 记录上次填充的目标
|
}
|
},
|
methods: {
|
POSTinfo(){
|
uni.request({
|
url: this.baseUrl + '/mobile/box/type/complete/auth/v2',
|
method:'POST',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success:(res)=>{
|
// 接口返回后才填充箱型数据
|
this.mode = res.data.data.map(item => item.boxSpecs || '').filter(item => item);
|
console.log('提取的箱型数据:', this.mode);
|
},
|
fail:(err)=>{
|
console.error('获取箱型失败:', err)
|
}
|
})
|
},
|
|
// 设置扫码监听
|
setupScanListener() {
|
// 移除之前的监听
|
this.removeScanListener();
|
|
// 监听键盘输入事件
|
document.addEventListener('keydown', this.handleKeyDown);
|
},
|
|
// 移除监听
|
removeScanListener() {
|
document.removeEventListener('keydown', this.handleKeyDown);
|
if (this.scanTimeout) {
|
clearTimeout(this.scanTimeout);
|
}
|
},
|
|
// 键盘事件处理
|
handleKeyDown(e) {
|
// 排除功能键(F1-F12等)
|
if (e.key.length > 1 && !['Enter', 'Tab'].includes(e.key)) {
|
return;
|
}
|
|
// PDA扫码通常以回车结束
|
if (e.key === 'Enter') {
|
e.preventDefault(); // 阻止默认行为
|
this.processScanCode();
|
} else {
|
// 累积扫码字符(排除Shift等修饰键)
|
if (!e.ctrlKey && !e.altKey && !e.metaKey && e.key.length === 1) {
|
this.scanBuffer += e.key;
|
|
// 重置超时定时器
|
if (this.scanTimeout) {
|
clearTimeout(this.scanTimeout);
|
}
|
|
// 设置超时(假设扫码间隔超过200ms表示一次扫码完成)
|
this.scanTimeout = setTimeout(() => {
|
this.processScanCode();
|
}, 200);
|
}
|
}
|
},
|
|
// 处理扫码结果
|
processScanCode() {
|
if (!this.scanBuffer) return;
|
|
const scanResult = this.scanBuffer.trim();
|
this.scanBuffer = '';
|
|
// 判断扫码长度决定填充位置
|
if (scanResult.length <= 12) {
|
// 12位以下填充到托盘编码
|
this.barcode = scanResult;
|
this.lastFillTarget = 'tray';
|
uni.showToast({
|
title: '托盘码已填充',
|
icon: 'success',
|
duration: 1000
|
});
|
} else {
|
// 12位以上填充到物料信息
|
this.autoFillMaterialInfo(scanResult);
|
this.lastFillTarget = 'material';
|
uni.showToast({
|
title: '物料码已填充',
|
icon: 'success',
|
duration: 1000
|
});
|
}
|
|
// 清除定时器
|
if (this.scanTimeout) {
|
clearTimeout(this.scanTimeout);
|
this.scanTimeout = null;
|
}
|
|
// 自动失焦
|
setTimeout(() => {
|
this.focusState = false;
|
}, 100);
|
},
|
|
// 自动填充物料信息
|
autoFillMaterialInfo(code) {
|
// 尝试解析二维码内容
|
if (code.includes('卷号:') && code.includes('箱号:')) {
|
// 如果是带格式的二维码
|
const parseResult = this.parseQrCodeText(code);
|
this.matList = { ...this.matList, ...parseResult };
|
console.log('解析后的物料信息:', parseResult);
|
} else {
|
// 如果是纯数字/条码,智能填充
|
this.smartFillMaterialFields(code);
|
}
|
},
|
|
// 智能填充物料字段
|
smartFillMaterialFields(code) {
|
// 根据业务逻辑判断,这里假设长条码可能是卷号或箱号
|
// 如果卷号为空,优先填充卷号
|
if (!this.matList.model) {
|
this.matList.model = code;
|
}
|
// 如果卷号已有值但箱号为空,填充箱号
|
else if (!this.matList.batch) {
|
this.matList.batch = code;
|
}
|
// 如果两者都有值,提示用户
|
else {
|
uni.showModal({
|
title: '提示',
|
content: `扫描到长条码: ${code}\n请选择填充位置:`,
|
showCancel: true,
|
cancelText: '卷号',
|
confirmText: '箱号',
|
success: (res) => {
|
if (res.confirm) {
|
this.matList.batch = code;
|
} else if (res.cancel) {
|
this.matList.model = code;
|
}
|
}
|
});
|
}
|
},
|
|
// 解析二维码文本(用于扫货物码功能)
|
parseQrCodeText(qrText) {
|
const result = {};
|
const lines = qrText.split('\n');
|
|
lines.forEach(line => {
|
if (line.includes('卷号:')) {
|
result.model = line.split('卷号:')[1]?.trim() || '';
|
}
|
if (line.includes('箱号:')) {
|
result.batch = line.split('箱号:')[1]?.trim() || '';
|
}
|
if (line.includes('规格:')) {
|
result.matnr = line.split('规格:')[1]?.trim() || '';
|
}
|
// 可以根据需要添加更多字段的解析
|
});
|
|
return result;
|
},
|
|
// 手动开始扫码
|
startScan() {
|
// 清空当前值并聚焦
|
this.scanBuffer = '';
|
|
this.$nextTick(() => {
|
this.focusState = true;
|
|
// 延迟确保input已聚焦
|
setTimeout(() => {
|
const input = document.getElementById('pdacode');
|
if (input) {
|
input.focus();
|
input.select();
|
}
|
}, 100);
|
});
|
},
|
|
// 修改focusFn
|
focusFn() {
|
this.focusState = true;
|
this.scanBuffer = ''; // 聚焦时清空缓冲区
|
},
|
|
// 保留原有的扫货物码功能
|
scantwo() {
|
uni.scanCode({
|
autoDecodeCharSet: true,
|
scanType: ['qrCode', 'barCode'],
|
success: (res) => {
|
const qrResult = res.result.trim();
|
this.autoFillMaterialInfo(qrResult);
|
|
uni.showToast({
|
title: '物料信息扫码成功',
|
icon: 'success',
|
duration: 2000
|
});
|
},
|
fail: (err) => {
|
console.log('扫码失败:', err);
|
uni.showToast({
|
title: '扫码失败或取消',
|
icon: 'none'
|
});
|
}
|
});
|
},
|
|
modePickerChange(e) {
|
this.index_mode = e.detail.value;
|
this.boxType = this.mode[this.index_mode]; // 同步到boxType
|
},
|
|
numPickerChange(e) {
|
this.index_num = e.detail.value;
|
},
|
|
// 修改重置方法
|
resetForm() {
|
this.barcodeNum = '';
|
this.barcode = '';
|
this.boxType = '';
|
this.index_mode = 0;
|
this.index_num = 0;
|
this.submitData = {};
|
this.mode = [];
|
this.lastFillTarget = null;
|
this.scanBuffer = '';
|
|
// 重置物料信息
|
this.matList = {
|
matnr: '',
|
maktx: '',
|
batch: '',
|
model: '',
|
position: '1',
|
weight: '',
|
roughWeight: '',
|
anfme: 1.0,
|
rollExtent: '',
|
joint: 0,
|
cutting: 2,
|
qualified: 0,
|
modelFront: '',
|
batchFront: ''
|
};
|
},
|
|
submit() {
|
// 校验必填项
|
if (!this.barcode) {
|
uni.showToast({title: '请扫描托盘编码', icon: 'none'});
|
return;
|
}
|
|
if (!this.boxType) {
|
uni.showToast({title: '请选择箱型', icon: 'none'});
|
return;
|
}
|
|
if (!this.matList.model || !this.matList.batch) {
|
uni.showToast({title: '请填写卷号和箱号', icon: 'none'});
|
return;
|
}
|
|
// 数据类型转换
|
const matItem = {
|
...this.matList,
|
weight: this.matList.weight ? Number(this.matList.weight) : null,
|
roughWeight: this.matList.roughWeight ? Number(this.matList.roughWeight) : null,
|
rollExtent: this.matList.rollExtent ? Number(this.matList.rollExtent) : null,
|
joint: this.matList.joint ? Number(this.matList.joint) : 0,
|
anfme: 1.0,
|
cutting: 2,
|
qualified: 0
|
};
|
|
// 组装提交数据
|
this.submitData = {
|
barcode: this.barcode,
|
palletizingNo: this.palletizingNo,
|
boxType: this.boxType,
|
matList: [matItem]
|
};
|
|
console.log('提交数据:', this.submitData);
|
|
// 提交请求
|
uni.request({
|
url: this.baseUrl + '/mobile/truss/comd/auth/v2',
|
method: 'POST',
|
header: {'Content-Type': 'application/json'},
|
data: this.submitData,
|
success: (res) => {
|
console.log('后端返回:', res);
|
|
if (res.data && res.data.code === 200) {
|
uni.showToast({title: '提交成功', icon: 'success'});
|
this.resetForm();
|
} else {
|
uni.showToast({title: res.data.message || '提交失败', icon: 'none'});
|
}
|
},
|
fail: (err) => {
|
console.error('请求失败详情:', err);
|
uni.showToast({title: '网络请求失败', icon: 'none'});
|
}
|
});
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
/* 全局样式 */
|
.sockpage {
|
background-color: #f5f7fa;
|
padding: 24rpx;
|
min-height: 100vh;
|
}
|
|
/* 表单列容器 */
|
.column {
|
display: flex;
|
flex-direction: column;
|
gap: 24rpx;
|
}
|
|
/* 表单卡片 */
|
.form-card {
|
background: #ffffff;
|
border-radius: 12rpx;
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
padding: 24rpx;
|
transition: all 0.2s ease;
|
}
|
|
/* 物料信息卡片特殊样式 */
|
.material-card {
|
padding: 0;
|
}
|
|
.card-title {
|
font-size: 30rpx;
|
font-weight: 500;
|
color: #1f2937;
|
padding: 24rpx 24rpx 16rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
/* 表单行 */
|
.form-row {
|
display: flex;
|
flex-direction: row;
|
align-items: center;
|
gap: 16rpx;
|
}
|
|
/* 标签样式 */
|
.label {
|
font-size: 28rpx;
|
color: #374151;
|
font-weight: 500;
|
min-width: 140rpx;
|
}
|
|
/* 必填项标红 */
|
.required {
|
color: #ef4444;
|
margin-right: 4rpx;
|
}
|
|
/* 选择器容器 */
|
.picker-wrap {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
}
|
|
/* 选择器hover态 */
|
.picker-hover {
|
background-color: #f9fafb;
|
border-radius: 8rpx;
|
}
|
|
/* 输入框容器 */
|
.input-box {
|
flex: 1;
|
font-size: 28rpx;
|
padding: 16rpx 12rpx;
|
border: 1rpx solid #e5e7eb;
|
border-radius: 8rpx;
|
transition: border-color 0.2s ease;
|
}
|
|
.input-box:focus-within {
|
border-color: #f97316;
|
}
|
|
/* 输入值样式 */
|
.input-value {
|
color: #1f2937;
|
}
|
|
/* 扫码图标 */
|
.scan-icon {
|
font-size: 24rpx;
|
margin-left: 8rpx;
|
color: #6b7280;
|
}
|
|
/* 物料信息网格布局 */
|
.material-grid {
|
display: grid;
|
grid-template-columns: repeat(2, 1fr);
|
gap: 20rpx;
|
padding: 24rpx;
|
}
|
|
/* 物料信息项 */
|
.material-item {
|
display: flex;
|
flex-direction: column;
|
gap: 8rpx;
|
}
|
|
/* 物料标签 */
|
.material-label {
|
font-size: 26rpx;
|
color: #4b5563;
|
}
|
|
/* 物料输入框 */
|
.material-input {
|
font-size: 28rpx;
|
color: #1f2937;
|
padding: 16rpx 12rpx;
|
border: 1rpx solid #e5e7eb;
|
border-radius: 8rpx;
|
background-color: #ffffff;
|
transition: border-color 0.2s ease;
|
}
|
|
.material-input:focus {
|
border-color: #f97316;
|
outline: none;
|
}
|
|
/* 按钮组 */
|
.btn-group {
|
display: flex;
|
gap: 20rpx;
|
justify-content: center;
|
margin-top: 16rpx;
|
padding: 8rpx 0;
|
}
|
|
/* 操作按钮通用样式 */
|
.operate-btn {
|
flex: 1;
|
max-width: 200rpx;
|
height: 80rpx;
|
line-height: 80rpx;
|
font-size: 28rpx;
|
font-weight: 500;
|
border-radius: 12rpx;
|
border: none;
|
transition: all 0.2s ease;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
/* 扫码按钮 */
|
.scan-btn {
|
background-color: #3b82f6;
|
color: #ffffff;
|
}
|
|
.scan-btn:active {
|
background-color: #2563eb;
|
transform: scale(0.98);
|
}
|
|
/* 提交按钮 */
|
.submit-btn {
|
background-color: #f97316;
|
color: #ffffff;
|
}
|
|
.submit-btn:active {
|
background-color: #ea580c;
|
transform: scale(0.98);
|
}
|
|
/* 适配小屏幕 */
|
@media (max-width: 375px) {
|
.material-grid {
|
grid-template-columns: 1fr;
|
}
|
|
.operate-btn {
|
max-width: 160rpx;
|
height: 72rpx;
|
line-height: 72rpx;
|
font-size: 26rpx;
|
}
|
}
|
</style>
|