163 lines
3.3 KiB
Vue
163 lines
3.3 KiB
Vue
<template>
|
|
<u-popup v-model="visible" mode="bottom" height="80%">
|
|
<view class="project-select">
|
|
<view class="project-select-btns">
|
|
<u-button size="mini" type="info" @click="handleCancel">取消</u-button>
|
|
<text></text>
|
|
<u-button size="mini" type="primary" @click="handleConfirm">确定</u-button>
|
|
</view>
|
|
<view class="project-select-filter">
|
|
<u-search placeholder="请输入项目名称" height="60" v-model="searchKey" :show-action="false"
|
|
@change="handleSearchKey"></u-search>
|
|
</view>
|
|
<scroll-view scroll-y="true" class="project-select-inner">
|
|
<view class="project-select-inner-wrap">
|
|
<view class="li" v-for="(item,idx) in filteredList" :key="idx"
|
|
:class="selectObj && selectObj[props.valueKey] == item[props.valueKey] ? 'active' : ''"
|
|
@click="handerChangList(item)"
|
|
>
|
|
{{ item[props.labelKey] }}
|
|
</view>
|
|
<view v-if="filteredList.length === 0" class="empty-tip">暂无匹配项目</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</u-popup>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {
|
|
ref,
|
|
watch,
|
|
computed
|
|
} from 'vue';
|
|
|
|
const props = defineProps({
|
|
modelValue: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
searchKey: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
list: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
labelKey: {
|
|
type: String,
|
|
default: 'label'
|
|
},
|
|
valueKey: {
|
|
type: String,
|
|
default: 'value'
|
|
},
|
|
selectId: {
|
|
type: String,
|
|
default: ''
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['update:modelValue', 'cancel', 'confirm', 'searchChange'])
|
|
|
|
const visible = ref(false)
|
|
const searchKey = ref("")
|
|
|
|
const selectObj = ref(null)
|
|
|
|
// 过滤后的列表
|
|
const filteredList = computed(() => {
|
|
if (!props.searchKey) return props.list
|
|
return props.list.filter(item =>
|
|
item[props.labelKey]?.includes(props.searchKey)
|
|
)
|
|
})
|
|
|
|
watch(() => props.modelValue, (val) => {
|
|
visible.value = val
|
|
if(val){
|
|
const selectedItem = props.list.find(item => item[props.valueKey] === props.selectId)
|
|
if (selectedItem) {
|
|
selectObj.value = selectedItem
|
|
} else {
|
|
selectObj.value = null
|
|
}
|
|
}
|
|
})
|
|
|
|
watch(visible, (val) => {
|
|
emit('update:modelValue', val)
|
|
})
|
|
const handerChangList = (item)=>{
|
|
selectObj.value = item
|
|
}
|
|
// 点击取消
|
|
const handleCancel = () => {
|
|
emit('update:modelValue', false)
|
|
}
|
|
// 点击确认
|
|
const handleConfirm = () => {
|
|
emit("confirm", selectObj.value)
|
|
}
|
|
// 搜索
|
|
const handleSearchKey = (val) => {
|
|
emit('searchChange', val)
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.project-select {
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: #fff;
|
|
border-radius: 24rpx 24rpx 0 0;
|
|
|
|
.project-select-btns {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 24rpx 32rpx;
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
}
|
|
|
|
.project-select-filter {
|
|
padding: 16rpx 32rpx;
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
}
|
|
|
|
.project-select-inner {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
|
|
.project-select-inner-wrap {
|
|
padding: 0 32rpx 32rpx;
|
|
|
|
.li {
|
|
padding: 28rpx 0;
|
|
border-bottom: 1rpx solid #f5f6f8;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
transition: all 0.2s;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
&.active {
|
|
color: $u-type-primary;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
|
|
.empty-tip {
|
|
text-align: center;
|
|
padding: 80rpx 0;
|
|
color: #999;
|
|
font-size: 26rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style> |