You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
5.7 KiB

1 year ago
<template>
<view class="wz-select-input">
<view class="select-input" @click="changePopup">
<view class="content">
<view v-if="isValueEmpty " class="value">
{{showNames}}
</view>
<view v-else class="placeholder">{{placeholder}}</view>
</view>
<view :class="showPop ?'right-icon-rotate':'right-icon'">
<uni-icons class="bottom-icon" color="#808080" type="bottom" size="22"></uni-icons>
</view>
</view>
<wz-select-popup ref="wzSelectPopup" @select="selectValue" @close="showPop=false" />
</view>
</template>
<script>
/**
* input弹层选择器
* @property {String | Number | Array} value v-model绑定值
* @property {String} placeholder 占位文字
*
* @property {Object} popupConfig 弹出层配置
* @property {String} popupConfig.mode 选择模式radio单选 | checkbox多选 默认是radio
* @property {String | Array} popupConfig.selected 已选中的value,单选传字符串多选传数组
*
* @property {Array} dataList 如果dataList传入了数组则直接使用传入的数组渲染无需再配置proxyConfig
*
* @property {Object} popupConfig.proxyConfig 组件内部代理请求数据配置
* @property {Function} proxyConfig.reqFun 请求数据的方法
* @property {Boolean} proxyConfig.localPaging 是否本地分页
*
* @property {Object} popupConfig.search //搜索相关参数
* @property {String} search.type = local组件内部排序搜索 | remote请求接口会把输入的搜索文字传入proxyConfig.reqFun
*
* @property {Object} popupConfig.page 分页的页码参数
* @property {Number} page.pageIndex 当前页
* @property {Number} page.pageSize 页大小
*
* @property {Object} popupConfig.fields 传入选项数据的key value
* @property {String} fields.label 用于显示文字的key
* @property {String} fields.value 用于取值的key
*/
export default {
name: 'wz-select-input',
props: {
value: {
type: [String, Number, Array],
default: ''
},
//radio checkbox 单选、多选
mode: {
type: String,
default: 'radio'
},
//如果dataList传入了数组则直接使用传入的数组渲染,无需再配置proxyConfig
dataList: {
default: null
},
//组件内部代理请求数据配置
proxyConfig: {
type: Object,
default: () => {
return {
reqFun: function() {}, //请求方法
localPaging: false //前端本地分页,如果使用的是dataList默认是本地分页
}
}
},
//如果是组件内部代理请求会把page的值加入到请求参数里
page: {
type: Object,
default: () => {
return {
pageIndex: 1, //当前页
pageSize: 20 //页大小
}
}
},
//搜索的类型,local本地搜索, remote向服务器请求。只有使用proxyConfig.reqFun请求才能配置为remote
searchType: {
type: String,
default: 'local'
},
//显示的key,value
fields: {
type: Object,
default: () => {
return {
label: 'name',
value: 'code'
}
}
},
placeholder: {
type: String,
default: '请选择'
},
},
data() {
return {
showPop: false,
dataForm: {
name: '',
}
}
},
computed: {
isValueEmpty() {
if (this.mode === 'checkbox' && typeof this.dataForm.name == 'object') {
return this.dataForm.name && this.dataForm.name.length != 0
}
const nameText = this.dataList ? this.value : this.dataForm.name
return nameText != '' && nameText != null && nameText != undefined
},
showNames() {
if (this.dataList && this.dataList instanceof Array) {
if (this.mode == 'radio') {
const item = this.dataList.find(v => v[this.fields.value] == this.value)
return item ? item[this.fields.label] : this.dataForm.name
} else {
const items = this.dataList.filter(v => this.value.includes(v[this.fields.value]))
const names = items.map(v => v[this.fields.label])
return names?.join(',')
}
} else if (this.dataForm.name instanceof Array) {
return this.dataForm.name.join(',')
}
return this.dataForm.name
}
},
mounted() {
},
methods: {
selectValue(mode, data) {
if (mode == 'radio') {
this.dataForm.name = data[this.fields.label]
this.$emit('input', data[this.fields.value])
} else {
const {
names,
values,
origin
} = data
this.dataForm.name = names
this.$emit('input', values)
}
this.$emit('select', mode, data)
},
changePopup() {
this.$refs.wzSelectPopup.open({
mode: this.mode, //radio checkbox 单选、多选
selected: this.value, //已选中的
dataList: this.dataList, //如果dataList传入了数组则直接使用传入的数组渲染,无需再配置proxyConfig
proxyConfig: this.proxyConfig, //组件内部代理请求数据配置
page: this.page, //如果是组件内部代理请求会把page的值加入到请求参数里
search: { //搜索的类型,local本地搜索, remote向服务器请求。只有使用proxyConfig.reqFun请求才能配置为remote
type: this.searchType,
},
fields: this.fields
})
this.showPop = true
},
setName(data) {
this.dataForm.name = data
}
}
}
</script>
<style scoped lang="scss">
.wz-select-input {
width: 100%;
.select-input {
display: flex;
align-items: center;
padding: 8px;
border: 1px solid $uni-border-color;
border-radius: $uni-border-radius-base;
.content {
flex: 1;
.value {
color: $uni-text-color;
}
.placeholder {
color: $uni-text-color-placeholder;
}
}
.right-icon {
transition: all .3s;
}
.right-icon-rotate {
@extend .right-icon;
transform: rotate(180deg);
}
}
}
</style>