256 lines
6.6 KiB
Vue
256 lines
6.6 KiB
Vue
|
<template>
|
||
|
<view :class="['lb-picker', inline ? 'lb-picker-inline' : '']">
|
||
|
<view class="lb-picker-mask"
|
||
|
v-show="visible && !inline"
|
||
|
:style="{ 'background-color': maskColor }"
|
||
|
@tap.stop="handleMaskTap"
|
||
|
@touchmove.stop.prevent="moveHandle">
|
||
|
</view>
|
||
|
<view :class="['lb-picker-container', visible ? 'lb-picker-toggle' : '']"
|
||
|
:style="{ borderRadius: `${radius} ${radius} 0 0` }">
|
||
|
<view v-if="showHeader"
|
||
|
class="lb-picker-header"
|
||
|
:style="{
|
||
|
height: pickerHeaderHeight,
|
||
|
'line-height': pickerHeaderHeight
|
||
|
}">
|
||
|
<view class="lb-picker-action lb-picker-left">
|
||
|
<view class="lb-picker-action-cancel"
|
||
|
@tap.stop="handleCancel">
|
||
|
<slot v-if="$slots['cancel-text']"
|
||
|
name="cancel-text"> </slot>
|
||
|
<view v-else
|
||
|
class="action-cancel-text"
|
||
|
:style="{ color: cancelColor }">
|
||
|
{{ cancelText }}
|
||
|
</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
|
||
|
<view class="lb-picker-action lb-picker-center"
|
||
|
v-if="$slots['action-center']">
|
||
|
<slot name="action-center"></slot>
|
||
|
</view>
|
||
|
|
||
|
<view class="lb-picker-action lb-picker-right">
|
||
|
<view class="lb-picker-action-confirm"
|
||
|
@tap.stop="handleConfirm">
|
||
|
<slot v-if="$slots['confirm-text']"
|
||
|
name="confirm-text"> </slot>
|
||
|
<view v-else
|
||
|
class="action-confirm-text"
|
||
|
:style="{ color: confirmColor }">
|
||
|
{{ confirmText }}
|
||
|
</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
<view class="lb-picker-content"
|
||
|
:style="{ height: pickerContentHeight }">
|
||
|
<!-- loading -->
|
||
|
<view v-if="loading"
|
||
|
class="lb-picker-loading">
|
||
|
<slot name="loading">
|
||
|
<view class="lb-picker-loading-img"></view>
|
||
|
</slot>
|
||
|
</view>
|
||
|
|
||
|
<!-- 暂无数据 -->
|
||
|
<view v-if="isEmpty && !loading"
|
||
|
class="lb-picker-empty">
|
||
|
<slot name="empty">
|
||
|
<text class="lb-picker-empty-text"
|
||
|
:style="{ color: emptyColor }">
|
||
|
{{ emptyText }}
|
||
|
</text>
|
||
|
</slot>
|
||
|
</view>
|
||
|
|
||
|
<!-- 单选 -->
|
||
|
<selector-picker v-if="mode === 'selector' && !loading && !isEmpty"
|
||
|
:value="value"
|
||
|
:list="list"
|
||
|
:props="pickerProps"
|
||
|
:height="pickerContentHeight"
|
||
|
:inline="inline"
|
||
|
@change="handleChange">
|
||
|
</selector-picker>
|
||
|
|
||
|
<!-- 多列联动 -->
|
||
|
<multi-selector-picker v-if="mode === 'multiSelector' && !loading && !isEmpty"
|
||
|
:value="value"
|
||
|
:list="list"
|
||
|
:level="level"
|
||
|
:visible="visible"
|
||
|
:props="pickerProps"
|
||
|
:height="pickerContentHeight"
|
||
|
:inline="inline"
|
||
|
@change="handleChange">
|
||
|
</multi-selector-picker>
|
||
|
|
||
|
<!-- 非联动选择 -->
|
||
|
<unlinked-selector-picker v-if="mode === 'unlinkedSelector' && !loading && !isEmpty"
|
||
|
:value="value"
|
||
|
:list="list"
|
||
|
:visible="visible"
|
||
|
:props="pickerProps"
|
||
|
:height="pickerContentHeight"
|
||
|
:inline="inline"
|
||
|
@change="handleChange">
|
||
|
</unlinked-selector-picker>
|
||
|
</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
const defaultProps = {
|
||
|
label: 'label',
|
||
|
value: 'value',
|
||
|
children: 'children'
|
||
|
}
|
||
|
import { getIndicatorHeight } from './utils'
|
||
|
import SelectorPicker from './pickers/selector-picker'
|
||
|
import MultiSelectorPicker from './pickers/multi-selector-picker'
|
||
|
import UnlinkedSelectorPicker from './pickers/unlinked-selector-picker'
|
||
|
const indicatorHeight = getIndicatorHeight()
|
||
|
export default {
|
||
|
components: {
|
||
|
SelectorPicker,
|
||
|
MultiSelectorPicker,
|
||
|
UnlinkedSelectorPicker
|
||
|
},
|
||
|
props: {
|
||
|
value: [String, Number, Array],
|
||
|
list: Array,
|
||
|
mode: {
|
||
|
type: String,
|
||
|
default: 'selector'
|
||
|
},
|
||
|
level: {
|
||
|
type: Number,
|
||
|
default: 1
|
||
|
},
|
||
|
props: {
|
||
|
type: Object
|
||
|
},
|
||
|
cancelText: {
|
||
|
type: String,
|
||
|
default: '取消'
|
||
|
},
|
||
|
cancelColor: String,
|
||
|
confirmText: {
|
||
|
type: String,
|
||
|
default: '确定'
|
||
|
},
|
||
|
confirmColor: String,
|
||
|
canHide: {
|
||
|
type: Boolean,
|
||
|
default: true
|
||
|
},
|
||
|
emptyColor: String,
|
||
|
emptyText: {
|
||
|
type: String,
|
||
|
default: '暂无数据'
|
||
|
},
|
||
|
radius: String,
|
||
|
columnNum: {
|
||
|
type: Number,
|
||
|
default: 5
|
||
|
},
|
||
|
loading: Boolean,
|
||
|
closeOnClickMask: {
|
||
|
type: Boolean,
|
||
|
default: true
|
||
|
},
|
||
|
maskColor: {
|
||
|
type: String,
|
||
|
default: 'rgba(0, 0, 0, 0.4)'
|
||
|
},
|
||
|
dataset: Object,
|
||
|
inline: Boolean,
|
||
|
showHeader: {
|
||
|
type: Boolean,
|
||
|
default: true
|
||
|
}
|
||
|
},
|
||
|
data () {
|
||
|
return {
|
||
|
visible: false,
|
||
|
myValue: this.value,
|
||
|
picker: {},
|
||
|
pickerProps: Object.assign({}, defaultProps, this.props),
|
||
|
pickerHeaderHeight: '50px',
|
||
|
pickerContentHeight: '300px'
|
||
|
}
|
||
|
},
|
||
|
computed: {
|
||
|
isEmpty () {
|
||
|
if (!this.list) return true
|
||
|
if (this.list && !this.list.length) return true
|
||
|
return false
|
||
|
}
|
||
|
},
|
||
|
methods: {
|
||
|
show () {
|
||
|
if (this.inline) return
|
||
|
this.visible = true
|
||
|
},
|
||
|
hide () {
|
||
|
if (this.inline) return
|
||
|
this.visible = false
|
||
|
},
|
||
|
handleCancel () {
|
||
|
this.$emit('cancel', this.picker)
|
||
|
if (this.canHide && !this.inline) {
|
||
|
this.hide()
|
||
|
}
|
||
|
},
|
||
|
handleConfirm () {
|
||
|
if (this.isEmpty) {
|
||
|
this.$emit('confirm', null)
|
||
|
this.hide()
|
||
|
} else {
|
||
|
const picker = JSON.parse(JSON.stringify(this.picker))
|
||
|
this.myValue = picker.value
|
||
|
this.$emit('confirm', this.picker)
|
||
|
if (this.canHide) this.hide()
|
||
|
}
|
||
|
},
|
||
|
handleChange ({ value, item, index, change }) {
|
||
|
this.picker.value = value
|
||
|
this.picker.item = item
|
||
|
this.picker.index = index
|
||
|
this.picker.change = change
|
||
|
this.picker.dataset = this.dataset || {}
|
||
|
this.$emit('change', this.picker)
|
||
|
},
|
||
|
handleMaskTap () {
|
||
|
if (this.closeOnClickMask) {
|
||
|
this.visible = false
|
||
|
}
|
||
|
},
|
||
|
moveHandle () {}
|
||
|
},
|
||
|
watch: {
|
||
|
value (newVal) {
|
||
|
this.myValue = newVal
|
||
|
},
|
||
|
myValue (newVal) {
|
||
|
this.$emit('input', newVal)
|
||
|
},
|
||
|
visible (newVisible) {
|
||
|
if (newVisible) {
|
||
|
this.$emit('show')
|
||
|
} else {
|
||
|
this.$emit('hide')
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
@import "./style/picker.scss";
|
||
|
</style>
|