pda-uni-app-perkins/pages/stock-in/manual.vue

392 lines
8.2 KiB
Vue
Raw Normal View History

2025-10-31 22:49:51 +08:00
<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>