Files
FT542-WMS/RuoYi-App-master/pages/in/backIn.vue
2025-12-03 16:09:29 +08:00

448 lines
9.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<view class="input-group">
<text class="input-label">{{ $t('inbound.backIn.rackCode') }}</text>
<uni-easyinput
v-model="rackCode"
:placeholder="$t('inbound.backIn.rackCodePlaceholder')"
:clearable="true"
@input="handleInput"
@clear="handleClear"
ref="rackCodeInput">
<template #right>
<text class="scan-icon" @click="handleScan">📷</text>
</template>
</uni-easyinput>
</view>
<view class="loading-container" v-if="loading">
<uni-load-more status="loading" :content-text="{contentdown: $t('inbound.backIn.loading'),contentrefresh: $t('inbound.backIn.loading'),contentnomore: $t('common.noData')}"></uni-load-more>
</view>
<view class="card-container" v-if="materialList.length > 0">
<uni-card v-for="(item, index) in materialList" :key="index" class="material-card">
<view class="card-content">
<view class="info-row">
<text class="label">{{ $t('inbound.backIn.materialCode') }}</text>
<text class="value">{{ item.productId }}</text>
</view>
<view class="info-row">
<text class="label">{{ $t('inbound.backIn.materialName') }}</text>
<text class="value">{{ item.productName }}</text>
</view>
<view class="info-row">
<text class="label">{{ $t('inbound.backIn.quantity') }}</text>
<uni-easyinput
v-model="item.editQuantity"
type="number"
:placeholder="String(item.quantity)"
class="quantity-input"
@input="handleQuantityChange(index)"
/>
</view>
</view>
</uni-card>
</view>
<view class="empty-state" v-if="!loading && materialList.length === 0 && rackCode">
<text>{{ $t('inbound.backIn.noMaterialInfo') }}</text>
</view>
<view class="button-container" v-if="materialList.length > 0">
<button class="submit-button" @click="handleSubmit">{{ $t('inbound.backIn.submit') }}</button>
</view>
<!-- 仓库选择弹窗 -->
<uni-popup ref="warehousePopup" type="center">
<view class="popup-content">
<view class="popup-title">{{ $t('inbound.backIn.selectWarehouse') }}</view>
<view class="popup-body">
<uni-data-select
v-model="selectedWarehouseId"
:localdata="warehouseList"
:clear="false"
:placeholder="$t('inbound.backIn.warehousePlaceholder')"
/>
</view>
<view class="popup-footer">
<button class="cancel-button" @click="closeWarehousePopup">{{ $t('inbound.backIn.cancel') }}</button>
<button class="confirm-button" @click="confirmSubmit">{{ $t('inbound.backIn.confirm') }}</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { getContainerDetails, agvRequest } from '@/api/in/order.js'
import { getBasWarehouList } from '@/api/bas/bas.js'
export default {
data() {
return {
rackCode: '',
materialList: [],
loading: false,
submitting: false,
warehouseList: [],
selectedWarehouseId: '',
preparedSubmitData: null
}
},
onReady() {
setTimeout(() => {
this.$nextTick(() => {
this.$refs.rackCodeInput.onFocus()
})
}, 100)
// 获取仓库列表
this.getWarehouseList()
},
methods: {
// 获取仓库列表
async getWarehouseList() {
try {
const response = await getBasWarehouList({
pageNum: 1,
pageSize: 100,
typeData: ['2']
})
if (response.code === 200) {
this.warehouseList = response.rows.map(item => ({
value: item.warehouseId,
text: item.warehouseName,
type: item.warehouseType
}))
}
} catch (error) {
console.error('获取仓库列表失败:', error)
uni.showToast({
title: this.$t('inbound.backIn.getWarehouseListFailed'),
icon: 'none'
})
}
},
// 处理输入事件
handleInput(value) {
if (value) {
this.fetchRackInfo(value)
}
},
// 处理清除事件
handleClear() {
this.materialList = []
},
// 处理扫码事件
handleScan() {
uni.scanCode({
success: (res) => {
this.rackCode = res.result
this.fetchRackInfo(res.result)
}
})
},
// 获取料架信息
async fetchRackInfo(rackCode) {
this.loading = true
try {
const response = await getContainerDetails({
"containerId":rackCode,
"pageNum":1,
"pageSize":100
})
if (response.code === 200) {
if (response.rows && response.rows.length > 0) {
this.materialList = response.rows.map(item => {
return {
...item,
editQuantity: String(item.quantity)
}
})
} else {
this.materialList = []
uni.showToast({
title: this.$t('inbound.backIn.noMaterialInfo'),
icon: 'none'
})
}
} else {
this.materialList = []
uni.showToast({
title: response.msg || this.$t('inbound.backIn.getRackInfoFailed'),
icon: 'none'
})
}
} catch (error) {
this.materialList = []
uni.showToast({
title: this.$t('inbound.backIn.getRackInfoFailed'),
icon: 'none'
})
} finally {
this.loading = false
}
},
// 处理数量变更
handleQuantityChange(index) {
// 确保输入的是有效数字
const value = this.materialList[index].editQuantity
if (value === '' || isNaN(Number(value))) {
this.materialList[index].editQuantity = '0'
}
},
// 打开仓库选择弹窗
openWarehousePopup() {
this.$refs.warehousePopup.open()
},
// 关闭仓库选择弹窗
closeWarehousePopup() {
this.$refs.warehousePopup.close()
this.submitting = false
},
// 处理提交
async handleSubmit() {
if (this.submitting) return
if (this.materialList.length === 0) {
uni.showToast({
title: this.$t('inbound.backIn.noSubmitMaterial'),
icon: 'none'
})
return
}
if(!this.rackCode){
uni.showToast({
title: this.$t('inbound.backIn.enterRackCode'),
icon: 'none'
})
return
}
// 验证输入
let isValid = true
this.materialList.forEach(item => {
if (item.editQuantity === '' || isNaN(Number(item.editQuantity)) || Number(item.editQuantity) < 0) {
isValid = false
}
})
if (!isValid) {
uni.showToast({
title: this.$t('inbound.backIn.enterValidQuantity'),
icon: 'none'
})
return
}
this.submitting = true
// 准备提交数据
const submitData = this.materialList.map(item => {
return {
id: item.id,
productId: item.productId,
quantity: Number(item.editQuantity)
}
})
// 检查是否有数量不为0的物料
const hasNonZeroQuantity = submitData.some(item => item.quantity > 0)
if (hasNonZeroQuantity) {
// 保存提交数据,打开仓库选择弹窗
this.preparedSubmitData = submitData
this.openWarehousePopup()
} else {
// 直接提交
await this.submitData(submitData)
}
},
// 确认提交(选择仓库后)
async confirmSubmit() {
if (!this.selectedWarehouseId) {
uni.showToast({
title: this.$t('inbound.backIn.selectWarehouse'),
icon: 'none'
})
return
}
this.closeWarehousePopup()
await this.submitData(this.preparedSubmitData, this.selectedWarehouseId)
},
// 提交数据
async submitData(submitData, warehouseId = null) {
try {
const requestData = {
"details": submitData,
"containerId": this.rackCode
}
// 如果有仓库ID,添加到请求数据中
if (warehouseId) {
requestData.spare1 = warehouseId
}
const response = await agvRequest(requestData)
if (response.code === 200) {
uni.showToast({
title: this.$t('inbound.backIn.submitSuccess'),
icon: 'success'
})
// 更新本地数据
this.materialList.forEach(item => {
item.quantity = Number(item.editQuantity)
})
} else {
uni.showToast({
title: response.msg || this.$t('inbound.backIn.submitFailed'),
icon: 'none'
})
}
} catch (error) {
uni.showToast({
title: this.$t('inbound.backIn.submitFailed'),
icon: 'none'
})
console.error(error)
} finally {
this.submitting = false
}
}
}
}
</script>
<style lang="scss">
.container {
padding: 20rpx;
background-color: #f8f9fc;
}
.input-group {
margin-bottom: 20rpx;
display: flex;
align-items: center;
}
.input-label {
width: 180rpx;
font-size: 28rpx;
}
.scan-icon {
font-size: 40rpx;
padding: 0 20rpx;
}
.card-container {
margin-top: 30rpx;
}
.material-card {
margin-bottom: 20rpx;
}
.card-content {
padding: 10rpx;
}
.info-row {
display: flex;
margin-bottom: 15rpx;
}
.label {
width: 180rpx;
font-size: 28rpx;
color: #666;
}
.value {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.empty-state {
margin-top: 100rpx;
display: flex;
justify-content: center;
align-items: center;
color: #999;
font-size: 28rpx;
}
.loading-container {
margin-top: 50rpx;
display: flex;
justify-content: center;
}
.quantity-input {
flex: 1;
margin-left: 10rpx;
}
.button-container {
margin-top: 50rpx;
padding: 0 30rpx;
}
.submit-button {
background-color: #007aff;
color: #fff;
border-radius: 8rpx;
font-size: 32rpx;
height: 80rpx;
line-height: 80rpx;
}
/* 弹窗样式 */
.popup-content {
width: 600rpx;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
}
.popup-title {
font-size: 32rpx;
font-weight: bold;
padding: 30rpx;
text-align: center;
border-bottom: 1rpx solid #eee;
}
.popup-body {
padding: 30rpx;
}
.popup-footer {
display: flex;
border-top: 1rpx solid #eee;
}
.cancel-button, .confirm-button {
flex: 1;
height: 80rpx;
line-height: 80rpx;
text-align: center;
font-size: 28rpx;
}
.cancel-button {
background-color: #f2f2f2;
color: #666;
}
.confirm-button {
background-color: #007aff;
color: #fff;
}
</style>