13 changed files with 494 additions and 144 deletions
@ -0,0 +1,195 @@ |
|||
<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> |
|||
Loading…
Reference in new issue