智慧教务系统
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.
 
 
 
 
 
 

195 lines
4.8 KiB

<template>
<view class="single-picker">
<fui-picker
:layer="1"
:options="formattedOptions"
:show="show"
@change="onChange"
@cancel="onCancel"
:title="title"
></fui-picker>
</view>
</template>
<script>
/**
* 通用单选选择器组件
* @description 基于FirstUI的fui-picker组件封装的通用单选选择器,支持灵活配置
*/
export default {
name: "single-picker",
props: {
/**
* 是否显示选择器
* @property {Boolean} show - 控制选择器的显示与隐藏
* @default false
*/
show: {
type: Boolean,
default: false
},
/**
* 数据源
* @property {Array} data - 选择器数据数组
* @default []
*/
data: {
type: Array,
default() {
return []
},
validator(value) {
// 允许空数组或非空数组
return Array.isArray(value)
}
},
/**
* 值字段名
* @property {String} valueKey - 用作选项值的字段名
* @default 'value'
*/
valueKey: {
type: String,
default: 'value'
},
/**
* 文本字段名
* @property {String|Array} textKey - 用作显示文本的字段名,支持字符串或数组
* @default 'text'
*/
textKey: {
type: [String, Array],
default: 'text'
},
/**
* 文本分隔符
* @property {String} textSeparator - 当textKey为数组时,各字段之间的分隔符
* @default '-'
*/
textSeparator: {
type: String,
default: '-'
},
/**
* 选择器标题
* @property {String} title - 选择器顶部显示的标题
* @default '请选择'
*/
title: {
type: String,
default: '请选择'
},
/**
* 默认占位文本
* @property {String} placeholder - 当字段为空时显示的占位文本
* @default '未命名'
*/
placeholder: {
type: String,
default: '未命名'
}
},
computed: {
/**
* 格式化后的选项数据,适配fui-picker组件
*/
formattedOptions() {
// 确保data是数组且不为空
if (!this.data || !Array.isArray(this.data) || this.data.length === 0) {
return []
}
return this.data.map(item => {
return this.getDisplayText(item)
})
}
},
methods: {
/**
* 获取显示文本
* @param {Object} item - 数据项
* @returns {String} 显示文本
*/
getDisplayText(item) {
if (!item || typeof item !== 'object') {
return this.placeholder
}
if (Array.isArray(this.textKey)) {
// 如果textKey是数组,组合多个字段
const textParts = this.textKey.map(key => {
return item[key] || this.placeholder
})
return textParts.join(this.textSeparator)
} else {
// 如果textKey是字符串,直接取对应字段
return item[this.textKey] || this.placeholder
}
},
/**
* 获取选项值
* @param {Object} item - 数据项
* @returns {*} 选项值
*/
getDisplayValue(item) {
if (!item || typeof item !== 'object') {
return null
}
return item[this.valueKey]
},
/**
* 选择器确认事件处理
* @param {Object} e - 选择器返回的数据对象
* @emits update:show - 更新show属性
* @emits change - 选择完成事件
*/
onChange(e) {
// 隐藏选择器
this.$emit('update:show', false)
// 获取选中的索引
const index = e.index && e.index[0]
// 如果没有选中任何项或没有数据,返回
if (index === undefined || !this.data || !Array.isArray(this.data) || this.data.length === 0 || index >= this.data.length) {
return
}
// 获取选中的数据项
const selectedItem = this.data[index]
// 如果选中的项不存在,返回
if (!selectedItem) {
return
}
// 将选择结果传递给父组件
this.$emit('change', {
text: this.getDisplayText(selectedItem),
value: this.getDisplayValue(selectedItem),
index: index,
item: selectedItem
})
},
/**
* 选择器取消事件处理
* @emits update:show - 更新show属性
* @emits cancel - 取消选择事件
*/
onCancel() {
// 隐藏选择器
this.$emit('update:show', false)
// 通知父组件取消选择
this.$emit('cancel')
}
}
}
</script>
<style scoped>
.single-picker {
/* 可以根据需要添加自定义样式 */
}
</style>