Files
FTC25009/pda/pages/warehouse/outbound/emptyTray.vue

417 lines
10 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="page-container">
<view class="form-section">
<text class="form-title">空托盘出库</text>
<view class="form-item">
<text class="form-label">仓库</text>
<picker class="form-picker" mode="selector" :range="warehouseOptions" range-key="warehouseName"
:value="warehouseIndex" @change="handleWarehouseChange">
<view class="picker-value" :class="{ placeholder: !warehouseId }">
{{ selectedWarehouseName || '请选择仓库' }}
</view>
</picker>
</view>
<view class="type-section" v-if="warehouseId">
<view class="type-header">
<text class="type-title">库内空托盘类型</text>
<text class="type-total">合计 {{ totalEmptyTrayCount }}</text>
</view>
<view class="type-empty" v-if="emptyTrayTypes.length === 0">
<text class="empty-text">当前仓库暂无可出库空托盘</text>
</view>
<view
class="type-card"
:class="{ active: selectedTrayType && selectedTrayType.barcodePrefix === item.barcodePrefix }"
v-for="(item, index) in emptyTrayTypes"
:key="item.barcodePrefix || index"
@click="selectTrayType(index)"
>
<view class="type-main">
<text class="type-name">{{ item.formatName || '托盘条码' }}</text>
<text class="type-prefix">{{ item.barcodePrefix }}</text>
</view>
<view class="type-count">
<text class="type-count-value">{{ item.quantity }}</text>
<text class="type-count-unit">个</text>
</view>
</view>
</view>
<view class="form-item">
<text class="form-label">出库数量</text>
<input class="form-input" v-model="quantity" type="number" placeholder="请输入出库数量" />
</view>
</view>
<view class="summary-section">
<view class="summary-row">
<text class="summary-label">作业类型</text>
<text class="summary-value">空容器出库</text>
</view>
<view class="summary-row">
<text class="summary-label">托盘类型</text>
<text class="summary-value">{{ selectedTrayTypeName || '未选择' }}</text>
</view>
<view class="summary-row">
<text class="summary-label">下发方式</text>
<text class="summary-value muted">生成后自动下发 WCS</text>
</view>
</view>
<view class="btn-section">
<button class="btn btn-primary" :disabled="!canSubmit || submitting" @click="submitEmptyTray">
{{ submitting ? '提交中...' : '生成空托出库作业' }}
</button>
<button class="btn btn-default" @click="resetQuantity">重置数量</button>
</view>
</view>
</template>
<script>
import { getWarehouseOptions } from '@/api/warehouse/inbound'
import { getEmptyTrayOutboundTypes, submitEmptyTrayOutbound } from '@/api/warehouse/outbound'
export default {
data() {
return {
warehouseOptions: [],
warehouseIndex: 0,
warehouseId: '',
warehouseName: '',
emptyTrayTypes: [],
trayTypeIndex: -1,
quantity: '',
submitting: false
}
},
computed: {
selectedWarehouseName() {
if (this.warehouseName) return this.warehouseName
var selected = this.warehouseOptions[this.warehouseIndex]
return selected && selected.warehouseId === this.warehouseId ? selected.warehouseName : ''
},
selectedTrayType() {
if (this.trayTypeIndex < 0) return null
return this.emptyTrayTypes[this.trayTypeIndex] || null
},
selectedTrayTypeName() {
var type = this.selectedTrayType
if (!type) return ''
return (type.formatName || '托盘条码') + '(' + type.barcodePrefix + ')'
},
selectedAvailableCount() {
var type = this.selectedTrayType
return type ? Number(type.quantity || 0) : 0
},
totalEmptyTrayCount() {
return this.emptyTrayTypes.reduce(function(total, item) {
return total + (Number(item.quantity) || 0)
}, 0)
},
canSubmit() {
var qty = Number(this.quantity)
return !!this.warehouseId && !!this.selectedTrayType && qty > 0 && qty <= this.selectedAvailableCount
}
},
onLoad() {
this.loadWarehouseOptions()
},
methods: {
loadWarehouseOptions() {
var that = this
getWarehouseOptions().then(function(res) {
that.warehouseOptions = res.data || res.rows || []
}).catch(function() {
that.warehouseOptions = []
})
},
handleWarehouseChange(e) {
var index = Number(e.detail.value)
var selected = this.warehouseOptions[index]
if (!selected) return
this.warehouseIndex = index
this.warehouseId = selected.warehouseId
this.warehouseName = selected.warehouseName
this.quantity = ''
this.resetTrayType()
this.loadEmptyTrayCount()
},
loadEmptyTrayCount() {
var that = this
if (!this.warehouseId) {
this.emptyTrayTypes = []
this.resetTrayType()
return
}
getEmptyTrayOutboundTypes(this.warehouseId).then(function(res) {
var list = Array.isArray(res.data) ? res.data : []
that.emptyTrayTypes = list.map(function(item) {
return {
formatId: item.formatId,
formatName: item.formatName,
barcodePrefix: item.barcodePrefix,
quantity: Number(item.quantity || 0)
}
})
that.resetTrayType()
if (that.emptyTrayTypes.length === 1) {
that.selectTrayType(0)
}
}).catch(function() {
that.emptyTrayTypes = []
that.resetTrayType()
})
},
selectTrayType(index) {
var selected = this.emptyTrayTypes[index]
if (!selected) return
this.trayTypeIndex = index
this.quantity = ''
},
resetTrayType() {
this.trayTypeIndex = -1
},
submitEmptyTray() {
var qty = Number(this.quantity)
if (!this.warehouseId) {
this.$modal.msg('请选择仓库')
return
}
if (!this.selectedTrayType) {
this.$modal.msg('请选择空托盘类型')
return
}
if (!qty || qty <= 0) {
this.$modal.msg('请输入有效的出库数量')
return
}
if (qty > this.selectedAvailableCount) {
this.$modal.msg('出库数量不能大于当前类型空托盘数量')
return
}
var that = this
var data = {
warehouseId: this.warehouseId,
barcodePrefix: this.selectedTrayType.barcodePrefix,
quantity: qty
}
this.$modal.confirm('是否确认生成空托出库作业并下发 WCS?').then(function() {
that.submitting = true
return submitEmptyTrayOutbound(data)
}).then(function(res) {
that.$modal.msgSuccess(res.msg || '空托出库作业生成成功')
that.quantity = ''
that.loadEmptyTrayCount()
}).catch(function() {}).finally(function() {
that.submitting = false
})
},
resetQuantity() {
this.quantity = ''
}
}
}
</script>
<style lang="scss" scoped>
page {
background-color: #f5f7fa;
min-height: 100%;
}
.page-container {
padding: 24rpx;
padding-bottom: 60rpx;
}
.form-section,
.summary-section {
background: #fff;
border-radius: 16rpx;
padding: 28rpx;
margin-bottom: 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
}
.form-title {
display: block;
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 24rpx;
padding-bottom: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.form-item {
display: flex;
align-items: center;
padding: 16rpx 0;
}
.form-label {
width: 160rpx;
flex-shrink: 0;
font-size: 28rpx;
color: #666;
}
.form-input,
.form-picker {
flex: 1;
width: 0;
min-width: 0;
box-sizing: border-box;
}
.form-input,
.picker-value {
width: 100%;
min-height: 72rpx;
padding: 16rpx;
border: 1rpx solid #e8e8e8;
border-radius: 8rpx;
background: #fff;
font-size: 28rpx;
color: #333;
box-sizing: border-box;
}
.picker-value.placeholder {
color: #c0c4cc;
}
.type-section {
margin: 18rpx 0;
}
.type-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 14rpx;
}
.type-title {
font-size: 26rpx;
color: #666;
}
.type-total {
font-size: 26rpx;
color: #1890ff;
}
.type-empty {
padding: 30rpx 0;
border: 1rpx dashed #d9d9d9;
border-radius: 12rpx;
display: flex;
justify-content: center;
}
.empty-text {
font-size: 26rpx;
color: #999;
}
.type-card {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 22rpx;
margin-bottom: 16rpx;
border: 1rpx solid #e8e8e8;
border-radius: 12rpx;
background: #fff;
}
.type-card.active {
border-color: #1890ff;
background: #e6f7ff;
}
.type-main {
flex: 1;
min-width: 0;
}
.type-name {
display: block;
font-size: 28rpx;
color: #333;
margin-bottom: 8rpx;
}
.type-prefix {
font-size: 24rpx;
color: #1890ff;
}
.type-count {
display: flex;
align-items: baseline;
margin-left: 20rpx;
}
.type-count-value {
font-size: 40rpx;
font-weight: 600;
color: #096dd9;
}
.type-count-unit {
margin-left: 4rpx;
font-size: 24rpx;
color: #666;
}
.summary-row {
display: flex;
justify-content: space-between;
padding: 12rpx 0;
}
.summary-label {
font-size: 26rpx;
color: #999;
}
.summary-value {
font-size: 26rpx;
color: #333;
}
.summary-value.muted {
color: #52c41a;
}
.btn-section {
padding: 8rpx 0 24rpx;
}
.btn {
font-size: 30rpx;
border-radius: 12rpx;
margin-bottom: 20rpx;
}
.btn-primary {
background: #1890ff;
color: #fff;
}
.btn-primary[disabled] {
background: #b0d4f5;
color: #fff;
}
.btn-default {
background: #fff;
color: #666;
border: 1rpx solid #d9d9d9;
}
</style>