一、最终效果
1、默认样式(默认选择第一条数据)
2、点击后默认展示10条数据
3、支持模糊查询
4、选择项目确认后
二、代码实现过程
<template>
<view class="layout">
<!-- #ifndef MP-TOUTIAO -->
<custom-nav-bar title="物品出库" withBack @backPage="backSpace"></custom-nav-bar>
<!-- #endif -->
<view class="inner">
<view class="content">
<view class="goodsInfo">
<view class="top">
<view class="img">
<u--image :src="baseUrl + info.goodsImages" width="80px" height="80px" radius="4"></u--image>
</view>
<view class="text">
<u--text :text="info.goodsName" bold lines="1" size="20px"></u--text>
<view style="margin-top: 10rpx;">
<u--text :text="info.goodsCode" lines="1" size="14px" color="#999"></u--text>
</view>
</view>
</view>
<view class="goodsDesc">
<view class="row">
<view class="left">
仓库名
</view>
<view class="right">
{{info.wareHouseName}}
</view>
</view>
<view class="row">
<view class="left">
库位号
</view>
<view class="right">
{{info.wareStorageCode}}
</view>
</view>
<view class="row">
<view class="left">
规格
</view>
<view class="right">
{{info.goodsSize==null ? '暂无' :info.goodsSize}}
</view>
</view>
<view class="row">
<view class="left">
单位
</view>
<view class="right">
{{info.goodsUnit}}
</view>
</view>
<view class="row">
<view class="left">
类别
</view>
<view class="right">
{{info.goodsCategory }}
</view>
</view>
<view class="row">
<view class="left">
库存数量
</view>
<view class="right">
{{info.goodsInventoryNum}}
</view>
</view>
</view>
</view>
</view>
<view class="intoNum">
<u-form
labelWidth="180rpx"
:model="formData"
:rules="rules"
ref="form"
>
<u-form-item
label="出库数量"
prop="outNum"
>
<u--input
v-model="formData.outNum"
type="number"
border="none"
placeholder="请输入数量"
/>
</u-form-item>
<!-- 下拉选择框-->
<view class="project" v-if="projectFlag">
<u-form-item
label="关联项目"
prop="projectName"
>
<view class="put" @click="isNation=!isNation">
<u--input
v-model="formData.projectName"
type="text"
border="none"
disabled
placeholder="请选择关联项目"
/>
</view>
</u-form-item>
</view>
</u-form>
</view>
<view class="remark">
<view class="text">
备注信息
</view>
<u--textarea v-model="remarkText" placeholder="请输入备注信息" border="null"></u--textarea>
</view>
<view class="upLoadImg" >
<view class="img">
<text>出库照片</text>
</view>
<u-upload
class="upload"
:fileList="fileList1"
@afterRead="afterRead"
@delete="deletePic"
name="1"
multiple
:maxCount="9"
></u-upload>
</view>
<view class="footer">
<view class="certain" @click="certain">
<btn title="添加出库单"></btn>
</view>
</view>
</view>
<!-- 下拉选择框底部弹出框 -->
<view class="date-background" v-show="isNation">
<view class='date-gray-background' @click="hiddeDatePicker"></view>
<view class='date-container'>
<view class="transparent">
<view class='date-confirm'>
<view @click="hiddeDatePicker" class="pickerCancel">取消</view>
<!-- 输入框 -->
<u-search style="width: 70%;" placeholder="请输入项目名称" @clear="clearSearch" @change='searchChange'
:show-action='false' v-model="searchValue" shape="round" clearabled></u-search>
<view @click="confirm1" class="pickerConfirm">确认</view>
</view>
<picker-view :immediate-change='true' indicator-class="indicator" :value="setValues"
@change="bindChange" mask-style="height:100rpx;"
style="width: 100%; height: 80%;position:absolute;bottom:0rpx;text-align:center;background:white">
<picker-view-column class="pickViewColumn">
<view v-for="item in array" :key="item.id" class="u-column-item"
style="height: 68rpx;overflow: hidden;">{{item.projectName}}
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</view>
</view>
</template>
<script>
import config from '@/config'
import { getToken } from '@/utils/auth'
import {onLoad,onReady} from "@dcloudio/uni-app"
import {apiGetGoodsInfo,apiFdProject} from "@/api/home.js"
import {mounted,watch} from "vue"
export default {
data(){
return{
projectFlag:false,
baseUrl:config.baseUrl,
pageNum:1,
pageSize:10,
projectCode:'',
//搜索下拉框
proIndex:0,
setValues:[0],
array: [],
searchValue:'',
isNation:false,
baseUrl:config.baseUrl,
wareHouseName:'',
info:{},
remarkText:'',
operationType:2,
files:'',
fileList1:[],
lastList:[],
//表单验证
goodsNum:0,
formData: {
outNum: '', // 初始化为空字符串
projectName:''
},
rules: {
outNum: [
{
required: true,
message: "请输入出库数量",
trigger: ['blur', 'change']
},
{
type: 'number',
message: '请输入数字',
trigger: ['blur', 'change']
},
{
validator: (rule, value, callback) => {
console.log(this.goodsNum)
console.log(value)
if (value > this.goodsNum) {
callback(new Error(`出库数量不能大于库存数量 ${this.goodsNum}`));
} else if (value <= 0) {
// 修正:判断小于等于 0
callback(new Error('出库数量必须大于 0'));
} else {
callback();
}
},
trigger: ['blur','change']
}
],
},
}
},
methods:{
setValueInit(){
this.$nextTick(()=>{
this.setValues=[0]
this.formData.projectName=this.array[0].projectName
this.projectCode = this.array[0].projectCode;
})
},
backSpace(){
// 返回上个页面,此处使用navigateBack避免页面栈爆掉
uni.navigateBack({
url:"/pages/home/outBill/outBill"
})
},
//隐藏底部弹出框
clearSearch() {
//清空搜索内容
this.searchValue = ''
},
hiddeDatePicker(){
this.isNation=false
},
bindChange(e) {
const proIndex = e.detail.value[0]; // 获取选中项目的索引
this.formData.projectName = this.array[proIndex].projectName;
this.projectCode = this.array[proIndex].projectCode;
console.log(e)
// 获取选择得项目的索引
// let proIndex = e.detail.value.toString()
// this.array.forEach((item,index)=>{
// if(proIndex==index){
// this.$nextTick(()=>{
// this.formData.projectName=item.projectName
// this.projectCode = item.projectCode
// })
// }
// })
},
// 确认关闭
confirm1(e) {
console.log(this.array)
this.setValues=[0]
this.isNation=false
},
// 查询项目
searchChange(e){
this.searchValue=e
this.getPro()
this.setValueInit()
},
// 获取物品信息
getGoodsInfo(id){
apiGetGoodsInfo(id).then(res=>{
this.info=res.data
// 判断物品是否需要关联项目
if(this.info.goodsCategoryCode==='3'||this.info.goodsCategoryCode==='5'){
this.projectFlag=true
}
this.goodsNum=res.data.goodsInventoryNum
})
},
// 获取项目数据
getPro(){
apiFdProject({pageNum:this.pageNum,pageSize:this.pageSize,projectName:this.searchValue}).then(res=>{
this.array=[...res.rows]
})
},
//删除图片
deletePic(event) {
this[`fileList${event.name}`].splice(event.index, 1)
this.lastList.splice(event.index,1)
this.files=this.lastList.join(',')
},
// 新增图片
async afterRead(event) {
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file)
let fileListLen = this[`fileList${event.name}`].length
lists.map((item) => {
this[`fileList${event.name}`].push({
...item,
status: 'uploading',
message: '上传中'
})
})
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url)
let item = this[`fileList${event.name}`][fileListLen]
this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '',
url: result
}))
fileListLen++
}
},
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
let a = uni.uploadFile({
url: this.baseUrl + '/common/upload',
filePath: url,
name: 'file',
formData: {},
header: {
Authorization: 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
success: (res) => {
this.lastList.push(JSON.parse(res.data).fileName)
this.files=this.lastList.join(',')
setTimeout(() => {
resolve(res.data.data)
}, 500)
}
});
})
},
certain(){
if(this.formData.outNum<=0){
uni.showModal({
title:'提示',
content:'请正确填写出库数量',
showCancel:false,
confirmText:"去填写",
success: (res) => {
if(res.confirm){
// 用户点击确定,但因为没有填写数量,所以不需要跳转到其他页面或提交数据
}
}
})
return
}
if(this.projectFlag){
if(!this.formData.projectName){
uni.showModal({
title:'提示',
content:'没有关联项目',
showCancel:false,
confirmText:"去关联",
success: (res) => {
if(res.confirm){
// 用户点击确定,但因为没有填写数量,所以不需要跳转到其他页面或提交数据
}
}
})
return
}
}
//设置info对象的数据
this.info.operationNum=Number(this.formData.outNum)
this.info.remark=this.remarkText
this.info.operationType = this.operationType
this.info.projectCode = this.projectCode
this.info.projectName = this.formData.projectName
if(this.files!==''&&this.files){
this.info.operationImage = this.files
}else{
this.info.operationImage = ''
}
this.$store.dispatch('addToOutCart',this.info).then(()=>{
})
.catch((err)=>{
console.log('添加购物车失败',err)
})
}
},
onReady() {
//如果需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则。
this.$refs.form.setRules(this.rules)
},
// 与vue中的mounted作用类似,但是执行时间更早
onLoad(options) {
let id = options.id
this.wareHouseName = options.wareHouseName
this.getGoodsInfo(id)
this.getPro()
},
watch:{
array:function (newVal,oldVal) {
console.log(newVal)
this.formData.projectName = newVal[0].projectName;
this.projectCode = newVal[0].projectCode;
}
},
mounted(){
this.setValueInit()
}
}
</script>
<style lang="scss" scoped>
.layout{
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 30rpx;
padding-bottom: 140rpx;
background-color: #f2f4f8;
.inner{
height: 1240rpx;
overflow: hidden;
overflow-y: auto;
.content{
box-sizing: border-box;
padding:20rpx 30rpx;
background-color: #fff;
border-radius: 20rpx;
.top{
height: 240rpx;
box-sizing: border-box;
background-color: #f2f4f8;
padding: 20rpx;
border-radius: 20rpx;
position: relative;
.img{
position: absolute;
top:20%;
left: 60rpx;
}
.text{
position: absolute;
top:30%;
left: 40%;
}
}
.goodsDesc{
margin-top: 40rpx;
.row{
margin-bottom: 15rpx;
display: flex;
justify-content: space-between;
.left{
color:#999;
font-size: 14px;
}
.right{
color:#333;
font-size: 14px;
}
}
}
}
.intoNum,.remark,.upLoadImg{
margin-top: 20rpx;
box-sizing: border-box;
padding:20rpx 30rpx;
background-color: #fff;
border-radius: 15rpx;
display: flex;
}
.intoNum{
align-items: center;
justify-content: start;
.put{
display: flex;
align-items: center;
}
}
.remark{
align-items: start;
.text{
margin-top: 15rpx;
}
}
.upLoadImg{
align-items: center;
justify-content: space-between;
.upload{
margin-left: 40rpx;
}
}
.footer{
padding: 0 20rpx;
position: fixed;
bottom: 0;
left: 0;
height: 160rpx;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
border-radius: 25rpx;
}
}
//底部弹出框样式
.date-background {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 1111;
}
.date-gray-background {
position: absolute;
width: 100%;
top: 0rpx;
background: rgba(0, 0, 0, .5);
height: calc(100% - 500rpx);
}
.date-container {
position: absolute;
width: 100%;
height: 60%;
overflow: hidden;
background: #fff;
bottom: 0;
z-index: 1000;
}
.date-confirm {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
font-size: 34rpx;
line-height: 100rpx;
z-index: 2;
}
.pickViewColumn {
height: 60%;
}
.indicator {
height: 40rpx;
}
.pickerCancel {
font-size: 30rpx;
color: #606266;
box-sizing: border-box;
text-align: center;
text-decoration: none;
padding: 0rpx 8rpx;
}
.pickerConfirm {
font-size: 30rpx;
color: #2979ff;
box-sizing: border-box;
text-align: center;
text-decoration: none;
padding: 0rpx 8rpx;
}
.u-column-item {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
font-size: 30rpx;
color: #303133;
padding: 0 8rpx;
}
}
</style>
上述代码为实现过程