Smart_Canteen_Handheld_Devi.../pages/enterAndExit/exit/add.vue

706 lines
21 KiB
Vue
Raw Normal View History

2025-08-11 16:45:01 +08:00
<template>
<page-meta :page-font-size="fontValue+'px'" :root-font-size="fontValue+'px'"></page-meta>
<view class="health-form">
<Navbar title="新增出库" :showRightText="false" :isBack="true" />
2025-08-21 15:29:01 +08:00
<scroll-view style="width: 100%;height: calc(100vh - 80px);" scroll-y="true">
2025-08-11 16:45:01 +08:00
<u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" style="margin-left: 20rpx;">
2025-08-21 15:29:01 +08:00
<u-form-item label="出库单号:" labelWidth="180rpx" style="height: 6vh">
2025-08-11 16:45:01 +08:00
<u--input
v-model.number="form.outCode"
placeholder="自动生成"
:disabled="true"
type="number"
></u--input>
</u-form-item>
2025-08-21 15:29:01 +08:00
<u-form-item label="所属区域" prop="areaId" required labelWidth="180rpx" style="height: 6vh">
2025-08-11 16:45:01 +08:00
<uni-data-select
v-model="form.areaId"
:localdata="selectors.areaId.options"
placeholder="请选择所属区域"
style="text-align: left;"
@change="changeWarehouse"
></uni-data-select>
</u-form-item>
2025-08-21 15:29:01 +08:00
<u-form-item label="货品仓库" prop="warehouseId" required labelWidth="180rpx" style="height: 6vh">
2025-08-11 16:45:01 +08:00
<uni-data-select
v-model="form.warehouseId"
:localdata="selectors.warehouseId.options"
placeholder="请选择货品仓库"
style="text-align: left;"
></uni-data-select>
</u-form-item>
2025-08-21 15:29:01 +08:00
<u-form-item label="出库类型" prop="outType" required labelWidth="180rpx" style="height: 6vh">
2025-08-11 16:45:01 +08:00
<uni-data-select
v-model="form.outType"
:localdata="selectors.outType.options"
placeholder="请选择入库类型"
style="text-align: left;"
></uni-data-select>
</u-form-item>
2025-08-21 15:29:01 +08:00
<u-form-item label="领料人" prop="fetchUserId" required labelWidth="180rpx" style="height: 6vh">
2025-08-11 16:45:01 +08:00
<uni-data-select
v-model="form.fetchUserId"
:localdata="selectors.fetchUserId.options"
placeholder="请选择入库人"
style="text-align: left;"
></uni-data-select>
</u-form-item>
2025-08-21 15:29:01 +08:00
<u-form-item label="备注说明" prop="remark" labelWidth="180rpx" style="height: 200rpx">
2025-08-11 16:45:01 +08:00
<uni-easyinput type="textarea" v-model="form.remark" placeholder="请输入备注" maxlength="100" />
</u-form-item>
2025-08-21 15:29:01 +08:00
<u-form-item style="width: 100%; padding: 20rpx 0;">
<view class="button-group">
<view @click="selectGoods" class="action-button" style="background: linear-gradient( 270deg, #7D97FF 0%, #4367F5 100%);width: 200rpx;">
<image src="/static/images/handheld/ic_select_goods.png" class="button-icon"></image>
<text class="button-text">选择货品</text>
</view>
<view @click="selectDocument" class="action-button" style="margin-left: 20rpx;background: linear-gradient( 270deg, #FFB679 0%, #EF882E 100%);width: 200rpx;">
<image src="/static/images/handheld/ic_select_document.png" class="button-icon"></image>
<text class="button-text">选择领料单</text>
</view>
2025-08-11 16:45:01 +08:00
</view>
</u-form-item>
<scroll-view class="chronic-science" scroll-y="true">
<view class="scroll-view-item" v-for="(item,index) in imsOutInventoryDetailAddList" :key="index">
<view class="scroll-view-item_content">
<view
style="width: 100%;height: 90%;display: flex;flex-direction: column;justify-content: space-between;padding: 15px;">
<view
style="width: 100%;font-size:26rpx;color: black;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;height: 35px;display: flex">
<checkbox-group style="width: 30px;height: 30px" @change="checkClick(item)">
<checkbox :checked="item.checked" />
</checkbox-group>
<view
style="width: 100%;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;height: 25px;display: flex;font-size:32rpx;font-weight: 600;color: #FF6816">
<view style="width:90%;">
<text style="margin-left: 10px;">{{ item.materialName }}</text>
</view>
<view style="width:10%;display: flex;align-items: center;justify-content: center">{{ index + 1 }}
</view>
</view>
</view>
<view style="width: 100%;display:flex;height: 30px">
<view style="width: 50%;display: flex;align-items: center">
<view class="scroll_title">计量单位</view>
<view class="scroll_content">{{ item.unitName }}</view>
</view>
<view style="width: 50%;display: flex;align-items: center">
<view class="scroll_title">库存数量</view>
<view class="scroll_content">{{ item.materialNum }}</view>
</view>
</view>
<view style="width: 100%;display:flex;height: 50px">
<view style="width: 100%;display: flex;align-items: center">
2025-08-21 15:29:01 +08:00
<view class="scroll_title_input"><i style="color:red;">*</i>领取数量</view>
2025-08-11 16:45:01 +08:00
<view class="scroll_content_input">
2025-08-21 15:29:01 +08:00
<uni-easyinput placeholder="输入数量" type="number" v-model="item.fetchNum"
@blur="calculateTotal(item)"></uni-easyinput>
2025-08-11 16:45:01 +08:00
</view>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</u--form>
</scroll-view>
<view class="submit-btn">
2025-08-21 15:29:01 +08:00
<view class="checked">
2025-08-11 16:45:01 +08:00
<checkbox-group @tap="checkAll">
<checkbox :checked="allChecked" />
</checkbox-group>
2025-08-21 15:29:01 +08:00
<text class="check-all-text">全选</text>
2025-08-11 16:45:01 +08:00
</view>
2025-08-21 15:29:01 +08:00
<view class="total-info">
<view class="total-item">
<text class="total-label">总数量</text>
<text class="total-value">{{ totalNum }}</text>
2025-08-11 16:45:01 +08:00
</view>
</view>
2025-08-21 15:29:01 +08:00
<u-button class="action-btn delete-btn" text="删除" @click="del"></u-button>
<u-button class="action-btn save-btn" text="保存" @click="handleSubmit"></u-button>
2025-08-11 16:45:01 +08:00
</view>
<u-action-sheet
v-if="currentSelector"
:show="selectorVisible"
:actions="getSelectorOptions(currentSelector)"
:title="getSelectorTitle(currentSelector)"
@close="hideSelector"
style="max-height: 400px"
@select="handleSelectorSelect"></u-action-sheet>
</view>
</template>
<script>
import {
addEnterRecord,
addOutRecord,
getAreaApi,
getPersonApi,
getSupplierApi,
getWarehouseApi
} from '@/api/enterExit'
import UButton from '@/uni_modules/uview-ui/components/u-button/u-button.vue'
import URow from '@/uni_modules/uview-ui/components/u-row/u-row.vue'
export default {
components: { URow, UButton },
data() {
return {
fontValue: uni.getStorageSync('fontSize') || 8,
selectorVisible: false,
currentSelector: null,
allChecked: false,
totalMoney: 0.00,
totalNum: 0.00,
selectors: {
areaId: { options: [], title: '请选择所属区域' },
warehouseId: { options: [], title: '请选择所属仓库' },
fetchUserId: { options: [], title: '请选择领料人' },
supplierId: { options: [], title: '请选择供应商' },
2025-08-21 15:29:01 +08:00
outType: {
options: [
2025-08-11 16:45:01 +08:00
{ name: '领取出库', text: '领取出库', value: '1' },
{ name: '报损出库', text: '报损出库', value: '2' },
{ name: '退货出库', text: '退货出库', value: '3' },
2025-08-21 15:29:01 +08:00
{ name: '调拨出库', text: '调拨出库', value: '4' }
2025-08-11 16:45:01 +08:00
], title: '请选择出库类型'
}
},
imsOutInventoryDetailAddList: [],
form: {
areaName: null,
areaId: null,
warehouseId: null,
warehouseName: null,
outType: null,
remark: null,
fetchUserId: null,
supplierId: null,
status: 2,
totalAmount: 0,
totalNum: 0,
outDate: null
},//详情
showProductCalendar: false,
showExpireCalendar: false,
dateValue: new Date(),
dateValue1: new Date(),
selectedItem: {
supplierId: null,
supplierName: null
},
2025-08-21 15:29:01 +08:00
currentDateOption: -1,
isUploading: false,
2025-08-11 16:45:01 +08:00
}
},
onLoad(options) {
if (options.selectList) {
this.imsOutInventoryDetailAddList = JSON.parse(decodeURIComponent(options.selectList))
console.log('选中的货品列表:', this.imsOutInventoryDetailAddList)
this.imsOutInventoryDetailAddList.forEach(item => {
item.checked = false // 初始化为未选中状态
})
this.form = options.form ? JSON.parse(decodeURIComponent(options.form)) : this.form
2025-08-21 15:29:01 +08:00
console.log('form------',this.form)
2025-08-11 16:45:01 +08:00
this.areaControlName = this.getDisplayName('areaId', this.form.areaId)
this.calculateTotal()
}
this.getAreaControlList()
this.getWarehouseControlList()
this.getFetchUserIdControlList()
this.getSupplierControlList()
},
methods: {
async getAreaControlList() {
const res = await getAreaApi()
this.selectors.areaId.options = res.data[0].children.map(item => ({
name: item.label,
text: item.label,
value: item.id
}))
console.log(res, '区域列表')
},
async getWarehouseControlList() {
const res = await getWarehouseApi(this.form.areaId)
this.selectors.warehouseId.options = res.rows.map(item => ({
name: item.warehouseName,
text: item.warehouseName,
value: item.warehouseId
}))
console.log(res, '仓库列表')
},
async getFetchUserIdControlList() {
// 假设有一个获取入库人列表的API
const res = await getPersonApi(124) // 这里可以替换为实际的API
this.selectors.fetchUserId.options = res.rows.map(item => ({
name: item.userName,
text: item.userName,
value: item.userId
}))
console.log(res, '入库人列表')
},
async getSupplierControlList() {
// 假设有一个获取供应商列表的API
const res = await getSupplierApi() // 这里可以替换为实际的API
this.selectors.supplierId.options = res.rows.map(item => ({
name: item.supplierName,
text: item.supplierName,
value: item.supplierId
}))
console.log(res, '供应商列表')
},
showSelector(selector) {
this.currentSelector = selector
this.selectorVisible = true
},
hideSelector() {
this.currentSelector = null
this.selectorVisible = false
},
getSelectorOptions(selector) {
return this.selectors[selector]?.options || []
},
getSelectorTitle(selector) {
return this.selectors[selector]?.title || ''
},
handleSelectorSelect(e) {
this.form[this.currentSelector] = e.value
this.hideSelector()
},
changeWarehouse() {
this.form.warehouseId = null
this.getWarehouseControlList()
},
getDisplayName(selector, value) {
const options = this.selectors[selector]?.options || []
const selectedOption = options.find(option => option.value == value)
return selectedOption ? selectedOption.name : ''
},
// 单个商品的选择
checkClick(item) {
item.checked = !item.checked
if (!item.checked) {
this.allChecked = false
} else {
// 判断每一个商品是否是被选择的状态
const goods = this.imsOutInventoryDetailAddList.every(item => {
return item.checked === true
})
if (goods) {
this.allChecked = true
} else {
this.allChecked = false
}
}
},
checkAll() {
this.allChecked = !this.allChecked
if (this.allChecked) {
this.imsOutInventoryDetailAddList.map(item => {
item.checked = true
})
} else {
this.imsOutInventoryDetailAddList.map(item => {
item.checked = false
})
}
},
hideKeyboard() {
uni.hideKeyboard()
},
selectGoods() {
if (!this.form.areaId) {
uni.showToast({
title: '请先选择所属区域',
icon: 'none'
})
return
}
2025-08-21 15:29:01 +08:00
if (!this.form.warehouseId) {
uni.showToast({
title: '请先选择所属仓库',
icon: 'none'
})
return
}
2025-08-11 16:45:01 +08:00
uni.navigateTo({
url: '/pages/enterAndExit/exit/selectGoods?form=' + JSON.stringify(this.form)
})
},
selectDocument() {
2025-08-21 15:29:01 +08:00
if (!this.form.areaId) {
uni.showToast({
title: '请先选择所属区域',
icon: 'none'
})
return
}
if (!this.form.warehouseId) {
uni.showToast({
title: '请先选择所属仓库',
icon: 'none'
})
return
}
2025-08-11 16:45:01 +08:00
uni.navigateTo({
url: '/pages/enterAndExit/exit/selectDocument?form=' + JSON.stringify(this.form)
})
},
del() {
this.imsOutInventoryDetailAddList = this.imsOutInventoryDetailAddList.filter(item => !item.checked)
this.allChecked = false
this.calculateTotal()
},
handleSubmit() {
2025-08-21 15:29:01 +08:00
if (this.isUploading) return
this.isUploading = true
2025-08-11 16:45:01 +08:00
if (this.checkIsExist(this.form.areaId)) {
2025-08-21 15:29:01 +08:00
this.isUploading = false
2025-08-11 16:45:01 +08:00
uni.showToast({
title: '请选择所属区域',
icon: 'none'
})
return
} else if (this.checkIsExist(this.form.warehouseId)) {
2025-08-21 15:29:01 +08:00
this.isUploading = false
2025-08-11 16:45:01 +08:00
uni.showToast({
title: '请选择货品仓库',
icon: 'none'
})
return
} else if (this.checkIsExist(this.form.outType)) {
2025-08-21 15:29:01 +08:00
this.isUploading = false
2025-08-11 16:45:01 +08:00
uni.showToast({
title: '请选择出库类型',
icon: 'none'
})
return
} else if (this.checkIsExist(this.form.fetchUserId)) {
2025-08-21 15:29:01 +08:00
this.isUploading = false
2025-08-11 16:45:01 +08:00
uni.showToast({
title: '请选择领料人',
icon: 'none'
})
return
} else if (this.imsOutInventoryDetailAddList.length === 0) {
2025-08-21 15:29:01 +08:00
this.isUploading = false
2025-08-11 16:45:01 +08:00
uni.showToast({
title: '请选择出库货品',
icon: 'none'
})
return
}
var tf = false
this.imsOutInventoryDetailAddList.forEach(item => {
if (tf) {
2025-08-21 15:29:01 +08:00
this.isUploading = false
2025-08-11 16:45:01 +08:00
return
}
if (this.checkIsExist(item.fetchNum)) {
2025-08-21 15:29:01 +08:00
this.isUploading = false
2025-08-11 16:45:01 +08:00
uni.showToast({
title: '请输入货品:【' + item.materialName + '】的数量',
icon: 'none'
})
tf = true
return
}
if (item.materialNum && item.materialNum > 0 && item.fetchNum > item.materialNum) {
2025-08-21 15:29:01 +08:00
this.isUploading = false
2025-08-11 16:45:01 +08:00
uni.showToast({
2025-08-21 15:29:01 +08:00
title: '货品:【' + item.materialName + '】的出库数量不能大于库存数量【' + item.materialNum + '】',
2025-08-11 16:45:01 +08:00
icon: 'none'
})
tf = true
}
})
if (!tf) {
this.uploadDate()
}
},
async uploadDate() {
2025-08-21 15:29:01 +08:00
var list = this.imsOutInventoryDetailAddList
const now = new Date()
const dateTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`
2025-08-11 16:45:01 +08:00
let param = {
...this.form,
imsOutInventoryDetailAddList: list,
totalNum: this.totalNum,
outDate: dateTime
}
const res = await addOutRecord(param)
console.log(res)
if (res.code == 200) {
uni.$u.toast('出库成功')
setTimeout(() => {
this.$tab.reLaunch('/pages/enterAndExit/exit/index')
}, 1000)
2025-08-21 15:29:01 +08:00
} else {
this.isUploading = false
uni.$u.toast('出库失败,请稍后再试')
2025-08-11 16:45:01 +08:00
}
},
checkIsExist(param) {
return param == null || param === '' || param === undefined
},
2025-08-21 15:29:01 +08:00
calculateTotal(e) {
if (!e || typeof e.fetchNum === 'undefined') {
this.totalNum = 0
}else if(e.fetchNum && e.fetchNum < 0) {
uni.showToast({
title: '领取数量不能小于0',
icon: 'none'
})
e.fetchNum = undefined
}
2025-08-11 16:45:01 +08:00
this.totalNum = this.imsOutInventoryDetailAddList.reduce((sum, item) => {
2025-08-21 15:29:01 +08:00
return sum + (item.fetchNum ? parseFloat(item.fetchNum) : 0)
}, 0)
}
2025-08-11 16:45:01 +08:00
}
}
</script>
<style scoped lang="scss">
page {
//从上到下渐变
min-height: 100vh;
background-size: 100% 100%;
}
2025-08-21 15:29:01 +08:00
.u-form-item {
min-height: 80rpx !important;
padding: 20rpx 0 !important;
}
.button-group {
display: flex;
justify-content: space-around;
width: 100%;
}
.action-button {
width: 48%;
height: 110rpx;
border-radius: 8rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
2025-08-11 16:45:01 +08:00
2025-08-21 15:29:01 +08:00
.button-icon {
width: 40rpx;
height: 40rpx;
margin-bottom: 10rpx;
}
.button-text {
color: #FFFFFF;
font-size: 28rpx;
}
2025-08-11 16:45:01 +08:00
.health-form {
padding: 20rpx;
height: 100vh;
background-color: #F7F7F7;
2025-08-21 15:29:01 +08:00
overflow-y: hidden;
2025-08-11 16:45:01 +08:00
.chronic-diseases {
margin-top: 20rpx;
&__label {
font-size: 28rpx;
color: $u-main-color;
margin-bottom: 20rpx;
display: block;
}
}
2025-08-21 15:29:01 +08:00
}
2025-08-11 16:45:01 +08:00
2025-08-21 15:29:01 +08:00
.submit-btn {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
background: #fff;
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.checked {
display: flex;
align-items: center;
width: 20%;
}
.check-all-text {
margin-left: 10rpx;
font-size: 26rpx;
}
.total-info {
width: 30%;
}
.total-item {
display: flex;
align-items: center;
}
.total-label {
font-size: 20rpx;
color: #A69F9A;
}
.total-value {
font-size: 28rpx;
color: #FF6816;
font-weight: bold;
margin-left: 10rpx;
2025-08-11 16:45:01 +08:00
}
2025-08-21 15:29:01 +08:00
.action-btn {
width: 150rpx !important;
height: 70rpx !important;
border-radius: 8rpx !important;
margin-left: 20rpx !important;
}
.delete-btn {
background: linear-gradient(270deg, #F87665 0%, #E43D26 100%) !important;
color: white !important;
}
.save-btn {
background: linear-gradient(270deg, #FFB679 0%, #EF882E 100%) !important;
color: white !important;
}
2025-08-11 16:45:01 +08:00
.searchInput {
width: 80%;
height: 40px;
margin-left: 10px;
font-size: 16px;
}
.chronic-science {
width: 100%;
height: 35vh;
.scroll-view-item {
width: 96%;
background: #fff;
margin-top: 10px;
border-radius: 23rpx;
2025-08-21 15:29:01 +08:00
2025-08-11 16:45:01 +08:00
.scroll-view-item_content {
width: 100%;
display: flex;
align-items: center;
height: fit-content;
justify-content: space-between;
border: 0.1rpx solid #ececec;
border-radius: 20rpx;
box-shadow: 0rpx 6rpx 10rpx 0rpx rgba(87, 87, 87, 0.14);
.scroll_title {
width: 50%;
font-size: 28rpx;
color: #0F274B;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-family: PingFang SC-Medium;
}
.scroll_title_input {
width: 30%;
font-size: 28rpx;
color: #0F274B;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-family: PingFang SC-Medium;
}
.scroll_content {
width: 50%;
font-size: 28rpx;
color: #86817B;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-family: PingFang SC-Regular;
}
.scroll_content_input {
width: 70%;
font-size: 28rpx;
color: #86817B;
white-space: nowrap;
text-overflow: ellipsis;
font-family: PingFang SC-Regular;
}
}
}
}
2025-08-21 15:29:01 +08:00
::v-deep .uni-scroll-view-content {
max-height: 16vh !important;
2025-08-11 16:45:01 +08:00
}
2025-08-21 15:29:01 +08:00
2025-08-11 16:45:01 +08:00
::v-deep .u-form-item {
min-height: 100rpx;
&__body__right__content__slot {
text-align: right;
}
}
::v-deep .u-checkbox {
margin-bottom: 16rpx;
}
/deep/ uni-checkbox .uni-checkbox-input {
width: 25px;
height: 25px;
border-radius: 15px;
}
/deep/ uni-checkbox .uni-checkbox-input.uni-checkbox-input-checked {
border-color: #ddd;
color: #fff !important;
background-color: #3E34FF !important;
}
/deep/ uni-checkbox .uni-checkbox-input {
border-color: #ddd;
}
/deep/ uni-checkbox .uni-checkbox-input:hover {
border-color: #ddd;
}
.date-input {
flex: 1;
width: 75%;
.date-placeholder {
color: #999999;
}
.selected-date {
color: #333333;
}
}
</style>