<template>
<div class="vant_select_wrapper">
<div class="vant_select" @click="open_popup" :class="{'error_select': props.error,'disabled_select': props.disabled,}">
<span :disabled="props.disabled" :class="{ 'notDataTitle':data.notDataTitle}" class="vant_select_cont">{{ data.notDataTitle?'请选择':data.title }}</span>
<IconC v-if="props.modelValue && !props.disabled" class="icon-shanchu input_del" @click.stop="clearInputValue"></IconC>
<IconC class="select_icon" :class="data.selectChoseIcon ? 'icon-shangjiantou' : 'icon-xiajiantou'"></IconC>
</div>
<van-popup v-model:show="data.popupShow" :close-on-click-overlay="false" :overlay-style="{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }" :style="{ minHeight:props.selectList.length>0?'':'30%',maxHeight:'80%' }" position="bottom">
<div class="popup_top">
<span class="popup_top_title">{{ props.title }}</span>
<IconC class="icon-guanbi-9 popup_close_icon" @click="popup_close"></IconC>
</div>
<div class="popup_nav">
<div class="popup_have_data" v-if="props.selectList.length>0">
<div class="select_List" @click="select_onclick(item)" v-for="item in props.selectList" :key="item.optId" ><span :class="{ 'select_selected': item.selected }" class="select_List_li">{{item.optName}}</span><IconC v-if="item.selected" class="icon-duigou popup_nav_chose"></IconC></div>
</div>
<div class="popup_not_data" v-else>
<span class="popup_not_data_icon"></span>
<span class="popup_not_data_title">暂无数据</span>
</div>
</div>
</van-popup>
</div>
</template>
<script setup lang="ts">
import {ref, reactive, watch} from 'vue';
interface iObj {
popupShow:boolean //弹框的展示隐藏
selectChoseIcon:boolean
notDataTitle:boolean
title:string
[key: string]: any
}
//props
interface iProps {
placeholder: string
disabled?: boolean
title:string
error?:boolean
modelValue?: string | number
selectList?:iList[]
[key: string]: any
}
interface iList {
optName: string;
optId:string | number;
selected?: boolean; // 添加一个选中状态
}
//emit
interface iEmit {
(e: 'click', value: string): void
(e: 'input', value: string): void
(e: 'change', value: string | number): void
(e: 'update:modelValue', value: string | number): void //更新v-model
}
const emit = defineEmits<iEmit>();
const props = withDefaults(defineProps<iProps>(), {
selectList:() =>[], //定义数组需要一个箭头函数
})
const data:iObj = reactive({
popupShow:false, //遮罩收起或者展开的状态
selectChoseIcon:false, //下拉框展开或者收起状态
notDataTitle:false, //输入框里面无数据
title:''
})
watch(()=>props.modelValue,(newVal)=>{
props.selectList.forEach((listItem) => {
listItem.selected = false;
if(newVal){
data.notDataTitle = false
if(listItem.optId == newVal){
listItem.selected = true;
data.title = listItem.optName
}
}else{
data.notDataTitle = true
}
});
},{
immediate: true,
deep:true
})
function clearInputValue() {
emit('update:modelValue','')
emit('change','')
}
function open_popup() {
if(!props.disabled){
data.popupShow = true
data.selectChoseIcon = true
}
}
function popup_close() {
data.notDataTitle = false
data.popupShow = false
data.selectChoseIcon = false
}
function select_onclick(item:iList){
props.selectList.forEach((listItem) => {
listItem.selected = false;
});
item.selected = true;
data.popupShow = false
data.notDataTitle = false
data.selectChoseIcon = false
data.title = item.optName
emit('update:modelValue', item.optId);
console.log(3333323,item.optId)
emit('change', item.optId);
}
</script>
<style scoped lang="less">
.vant_select{
position: relative;
border-radius: 5px;
height: 40px;
line-height: 40px;
border: 1px solid #DDE0E8;
color:rgba(0,0,0,0.9);
font-weight: 400;
font-size: 14px;
padding:0 54px 0 8px;
}
.vant_select_cont{
display: block;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: left;
}
.disabled_select{
background: #F0F2F4;
border: 1px solid #DDE0E8;
}
.error_select{
box-shadow: 0px 0px 4px 0px rgba(244,78,78,0.5);
border: 1px solid #F44E4E;
}
.notDataTitle{
color:rgba(0,0,0,0.35);
font-weight: 400;
font-size: 14px;
}
.input_del{
display: block;
position: absolute;
right: 30px;
top:0;
font-size: 14px;
color:#95979C;
}
.select_icon{
display: block;
position: absolute;
right: 10px;
top:0;
font-size: 8px;
color:#5E6575;
}
//.vant_select:focus{
// border: 1px solid #0162E2;
// box-shadow: 0 0 4px 0 rgba(1,98,226,0.5);
//}
.disabled_select:active{
border: 1px solid #DDE0E8 !important;
box-shadow:none !important;
}
.error_select:active{
box-shadow: 0px 0px 4px 0px rgba(244,78,78,0.5) !important;
border: 1px solid #F44E4E !important;
}
.vant_select:active{
border: 1px solid #0162E2;
box-shadow: 0 0 4px 0 rgba(1,98,226,0.5);
}
//popup
/deep/.van-popup{
width: calc(100% - 39px);
padding: 18px 19px 0 20px;
.popup_top{
.popup_top_title{
font-weight: 400;
font-size: 20px;
color: #141F2B;
text-align: center;
line-height: 20px;
}
.popup_close_icon{
margin-top: 2px;
display: block;
float: right;
font-size: 14px;
color:#383A3F;
}
}
.popup_nav{
.popup_have_data{
margin-top: 6px;
.select_List{
height: 47px;
line-height: 47px;
font-weight: 400;
font-size: 16px;
color: #141F2B;
border-bottom: 1px solid #EAECEF;
text-align: left;
.select_List_li{
width: calc(100% - 36px);
display: block;
float: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select_selected{
color: #006EFF;
}
.popup_nav_chose{
margin-left: 18px;
display: block;
float: right;
width: 16px;
height: 11px;
color: #006EFF;
}
}
.select_List:last-child{
border-bottom: transparent;
}
}
.popup_not_data{
.popup_not_data_icon{
margin: 24px auto 0;
display: block;
width: 64px;
height: 64px;
background: url("./src/assets/img/zanwushuju.png") no-repeat center center;
background-size: 64px 64px;
}
.popup_not_data_title{
display: inline-block;
font-weight: 400;
font-size: 15px;
color: #101F2C;
//margin-top: 15px;
margin:15px auto 0;
margin-left: -5px;
text-align: center;
}
}
}
}
</style>
01-11
1215
12-08
2721
01-10
1725
05-21
2710
04-23
435
06-16
8258