392 lines
8.2 KiB
Vue
392 lines
8.2 KiB
Vue
<template>
|
||
<view class="container">
|
||
<view class="header">
|
||
<button class="back" @click="back"><i class="icon icon-arrow_back"
|
||
style="color:#05DCEF;font-size:36rpx"></i></button>
|
||
<text class="title">手动码盘入库</text>
|
||
</view>
|
||
|
||
<view class="content">
|
||
<!-- 顶部提示 -->
|
||
<view class="tip">
|
||
<view class="tip-icon"><i class="icon icon-info" style="color:#05DCEF"></i></view>
|
||
<text class="tip-text">请先扫描载具号,然后添加物料信息进行码盘入库</text>
|
||
</view>
|
||
|
||
<!-- 载具条码 -->
|
||
<view class="field">
|
||
<text class="label">载具号</text>
|
||
<view class="input-wrap">
|
||
<i class="left-icon icon icon-qr_code_2" style="font-size:36rpx"></i>
|
||
<input class="input" placeholder="请扫描或输入载具号" v-model="vehicleCode" @blur="resolveVehicle" />
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 物料条码 -->
|
||
<view class="field">
|
||
<text class="label">物料条码</text>
|
||
<view class="input-wrap">
|
||
<i class="left-icon icon icon-qr_code_2" style="font-size:36rpx"></i>
|
||
<input class="input" placeholder="请扫描物料二维码" v-model="goodsCode" @blur="resolveCode" />
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 操作按钮组 -->
|
||
<view class="button-row">
|
||
<button class="btn" @click="addGoods"><i class="icon icon-add"
|
||
style="margin-right:8rpx"></i>添加物料</button>
|
||
<button class="btn" @click="finish"><i class="icon icon-task_alt"
|
||
style="margin-right:8rpx"></i>码盘完成</button>
|
||
</view>
|
||
|
||
<!-- 列表统计 -->
|
||
<view class="list-header"><text>已添加物料 ({{ packageData.length }})</text></view>
|
||
|
||
<!-- 物料卡片列表:尽量还原 RN 的布局与字段 -->
|
||
<view class="list">
|
||
<view v-for="item in packageData" :key="item.id" class="card">
|
||
<view class="card-header">
|
||
<view class="card-header-left">
|
||
<text class="card-header-text">批次:{{ item.batch }}</text>
|
||
<text class="card-header-text">物料:{{ item.segment1 }}</text>
|
||
</view>
|
||
<view class="card-actions">
|
||
<button class="card-action-button" @click="editItem(item)"><i
|
||
class="icon icon-edit"></i></button>
|
||
<button class="card-action-button" @click="deleteItem(item.id)"><i
|
||
class="icon icon-delete"></i></button>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="card-content">
|
||
<view class="card-row">
|
||
<view class="card-field">
|
||
<text class="card-label">物料编码</text>
|
||
<text class="card-value">{{ item.segment1 }}</text>
|
||
</view>
|
||
<view class="card-field">
|
||
<text class="card-label">物料ID</text>
|
||
<text class="card-value">{{ item.itemId }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="card-row">
|
||
<view class="card-field">
|
||
<text class="card-label">数量</text>
|
||
<view class="editable-value">
|
||
<input class="num-input" type="number" v-model="item.quantity" />
|
||
</view>
|
||
</view>
|
||
<view class="card-field">
|
||
<text class="card-label">重量(kg)</text>
|
||
<view class="editable-value">
|
||
<input class="num-input" type="number" v-model="item.weight" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="card-row">
|
||
<view class="card-field">
|
||
<text class="card-label">产品数据</text>
|
||
<text class="card-value">{{ item.productData }}</text>
|
||
</view>
|
||
<view class="card-field">
|
||
<text class="card-label">区域/库位</text>
|
||
<text class="card-value">{{ item.area || '-' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { DialogUtils } from '@/utils/dialog.js';
|
||
let nextId = 1
|
||
export default {
|
||
data() {
|
||
return {
|
||
vehicleCode: '',
|
||
goodsCode: '',
|
||
packageData: []
|
||
}
|
||
},
|
||
methods: {
|
||
back() {
|
||
uni.navigateBack()
|
||
},
|
||
resolveVehicle() {
|
||
const code = (this.vehicleCode || '').trim()
|
||
if (!code) return
|
||
if (code.length === 15) {
|
||
DialogUtils.showSuccessMessage('扫描成功', `车辆码: ${code}`)
|
||
} else {
|
||
DialogUtils.showErrorMessage('校验失败', '无效的车辆码长度')
|
||
}
|
||
},
|
||
resolveCode() {
|
||
const code = (this.goodsCode || '').trim()
|
||
if (!code) return
|
||
const parts = code.split(',')
|
||
if (![6, 7, 8].includes(parts.length)) {
|
||
DialogUtils.showWarningMessage('提示', '物料条码格式不正确')
|
||
return
|
||
}
|
||
const p = parts.slice(0, 6)
|
||
const item = {
|
||
id: String(nextId++),
|
||
segment1: p[0],
|
||
itemId: p[1],
|
||
batch: p[2],
|
||
quantity: p[3],
|
||
weight: p[4],
|
||
productData: p[5],
|
||
area: ''
|
||
}
|
||
if (this.packageData.some(x => x.batch === item.batch)) {
|
||
DialogUtils.showWarningMessage('重复', '该物料已在列表中')
|
||
} else {
|
||
this.packageData.push(item)
|
||
}
|
||
this.goodsCode = ''
|
||
},
|
||
addGoods() {
|
||
this.resolveCode()
|
||
},
|
||
deleteItem(id) {
|
||
this.packageData = this.packageData.filter(x => x.id !== id)
|
||
},
|
||
editItem(item) {
|
||
DialogUtils.toast('可编辑数量与重量')
|
||
},
|
||
finish() {
|
||
DialogUtils.toast('码盘完成')
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.header {
|
||
position: relative;
|
||
height: 120rpx;
|
||
padding: 0;
|
||
background: linear-gradient(90deg, var(--grad-primary-start), var(--grad-primary-mid));
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.container {
|
||
min-height: 100vh;
|
||
background: #F5F5F5;
|
||
}
|
||
|
||
|
||
.title {
|
||
color: #fff;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.content {
|
||
padding: 24rpx;
|
||
}
|
||
|
||
.tip {
|
||
flex-direction: row;
|
||
display: flex;
|
||
align-items: center;
|
||
background: #f2fdff;
|
||
border-radius: 12rpx;
|
||
padding: 24rpx;
|
||
color: #333;
|
||
margin-bottom: 28rpx;
|
||
}
|
||
|
||
.tip-icon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
border-radius: 20rpx;
|
||
background: #e6f7ff;
|
||
text-align: center;
|
||
line-height: 40rpx;
|
||
margin-right: 12rpx;
|
||
font-weight: 600;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.tip-text {
|
||
color: #333;
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.field {
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.label {
|
||
color: #333;
|
||
font-size: 30rpx;
|
||
margin-bottom: 12rpx;
|
||
display: block;
|
||
}
|
||
|
||
.input-wrap {
|
||
height: 96rpx;
|
||
border-radius: 12rpx;
|
||
border: 1px solid #e6e6e6;
|
||
background: #fff;
|
||
padding: 0 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.left-icon {
|
||
color: #05DCEF;
|
||
font-size: 36rpx;
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
.input {
|
||
flex: 1;
|
||
height: 100%;
|
||
font-size: 30rpx;
|
||
}
|
||
|
||
.button-row {
|
||
display: flex;
|
||
gap: 24rpx;
|
||
margin: 24rpx 0;
|
||
}
|
||
|
||
.btn {
|
||
flex: 1;
|
||
height: 92rpx;
|
||
border: none;
|
||
color: #fff;
|
||
border-radius: 46rpx;
|
||
background: linear-gradient(90deg, var(--grad-primary-start), var(--grad-primary-mid));
|
||
font-size: 30rpx;
|
||
box-shadow: 0 8rpx 22rpx rgba(5, 220, 239, .25);
|
||
text-align: center;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.list-header {
|
||
margin-top: 8rpx;
|
||
color: #333;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.card {
|
||
background: #fff;
|
||
border-radius: 12rpx;
|
||
padding: 0;
|
||
margin-top: 16rpx;
|
||
overflow: hidden;
|
||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, .06)
|
||
}
|
||
|
||
.card-header {
|
||
flex-direction: row;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 16rpx;
|
||
border-bottom: 1px solid rgba(0, 0, 0, .08);
|
||
background: linear-gradient(90deg, var(--grad-primary-start), var(--grad-primary-mid));
|
||
}
|
||
|
||
.card-header-left {
|
||
flex: 1
|
||
}
|
||
|
||
.card-header-text {
|
||
color: #fff;
|
||
font-size: 24rpx;
|
||
margin-right: 16rpx
|
||
}
|
||
|
||
.card-actions {
|
||
display: flex;
|
||
gap: 8rpx
|
||
}
|
||
|
||
.card-action-button {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
border: none;
|
||
border-radius: 8rpx;
|
||
background: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.card-content {
|
||
padding: 16rpx;
|
||
background: #fff
|
||
}
|
||
|
||
.card-row {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
margin-bottom: 12rpx
|
||
}
|
||
|
||
.card-field {
|
||
flex: 1
|
||
}
|
||
|
||
.card-label {
|
||
color: #888;
|
||
font-size: 24rpx;
|
||
margin-bottom: 4rpx;
|
||
display: block
|
||
}
|
||
|
||
.card-value {
|
||
color: #333;
|
||
font-size: 28rpx
|
||
}
|
||
|
||
.editable-value {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8rpx
|
||
}
|
||
|
||
.num-input {
|
||
width: 220rpx;
|
||
height: 64rpx;
|
||
border: 1px solid #e6e6e6;
|
||
border-radius: 8rpx;
|
||
padding: 0 12rpx;
|
||
font-size: 28rpx
|
||
}
|
||
|
||
.back {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 80rpx;
|
||
height: 64rpx;
|
||
line-height: 64rpx;
|
||
border: none;
|
||
color: #05DCEF;
|
||
background: #fff;
|
||
border-radius: 12rpx;
|
||
text-align: center;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
</style> |