mand-mobile/components/tab-picker/index.vue

214 lines
4.8 KiB
Vue

<template>
<div class="md-tab-picker">
<md-popup
:value="value"
position="bottom"
:mask-closable="maskClosable"
@input="$_onInput"
@show="$emit('show')"
@hide="$emit('hide')"
>
<md-popup-title-bar
:title="title"
:describe="describe"
@cancel="$_onCancel"
>
<md-icon name="cross" size="lg" slot="cancel" />
</md-popup-title-bar>
<div class="md-tab-picker-content">
<md-tabs v-model="currentTab">
<md-tab-pane
v-for="(pane, index) in panes"
:key="pane.name"
:name="pane.name"
:label="pane.label"
>
<md-radio
isAcrossBorder
:value="pane.value"
:options="pane.options"
@input="$_onSelectPaneItem($event, index)"
v-if="$scopedSlots.item"
>
<template slot-scope="{ option }">
<slot name="item" :option="option"></slot>
</template>
</md-radio>
<md-radio
v-else
isAcrossBorder
:value="pane.value"
:options="pane.options"
@input="$_onSelectPaneItem($event, index)"
/>
</md-tab-pane>
</md-tabs>
</div>
</md-popup>
</div>
</template>
<script>
import Popup from '../popup'
import PopupTitlebar from '../popup/title-bar'
import Icon from '../icon'
import Tabs from '../tabs'
import TabPane from '../tab-pane'
import Radio from '../radio'
export default {
name: 'md-tab-picker',
components: {
[Popup.name]: Popup,
[PopupTitlebar.name]: PopupTitlebar,
[Icon.name]: Icon,
[Tabs.name]: Tabs,
[TabPane.name]: TabPane,
[Radio.name]: Radio,
},
props: {
value: {
type: Boolean,
default: false,
},
defaultValue: {
type: Array,
default: () => [],
},
title: {
type: String,
default: '',
},
describe: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '请选择',
},
maskClosable: {
type: Boolean,
default: true,
},
data: {
type: Object,
default: () => ({}),
},
},
data() {
return {
selected: [],
currentTab: '',
}
},
computed: {
panes() {
const panes = []
let target = this.data
let cursor = 0
while (target && target.name) {
const pane = {
name: target.name,
label: target.label || this.placeholder,
value: this.selected[cursor],
selected: null,
options: target.options,
}
let find = false
for (let i = 0, len = target.options.length; i < len; i++) {
if (target.options[i].value === this.selected[cursor]) {
pane.label = target.options[i].label
pane.selected = target.options[i]
target = target.options[i].children
find = true
cursor++
break
}
}
if (!find) {
target = null
}
panes.push(pane)
}
return panes
},
},
created() {
/* istanbul ignore else */
if (this.defaultValue) {
this.selected = this.defaultValue
}
/* istanbul ignore else */
if (this.data) {
this.currentTab = this.data.name
}
},
methods: {
// MARK: private events
$_onInput(val) {
this.$emit('input', val)
},
$_onCancel() {
this.$emit('input', false)
},
$_onSelectPaneItem(value, index) {
this.selected.splice(index, this.selected.length - index, value)
this.$emit('change', {
values: this.getSelectedValues(),
options: this.getSelectedOptions(),
})
this.$nextTick(function() {
const nextPane = this.panes[index + 1]
/* istanbul ignore else */
if (nextPane) {
this.currentTab = nextPane.name
}
})
},
// MARK: public methods
getSelectedValues() {
return this.selected
},
getSelectedOptions() {
if (this.panes && this.panes.length) {
return this.panes.filter(pane => pane.value).map(pane => pane.selected)
} else {
return []
}
},
},
}
</script>
<style lang="stylus">
.md-tab-picker
.md-tab-bar
margin-left tab-picker-h-gap
margin-right tab-picker-h-gap
padding-left 0
padding-right 0
background-color tab-picker-bg
hairline(bottom, color-border-base)
.md-tabs-content
height tab-picker-height
overflow auto
-webkit-overflow-scrolling touch
&::-webkit-scrollbar
display none
.md-tab-pane
padding-left tab-picker-h-gap
padding-right tab-picker-h-gap
.md-popup-cancel
width 90px !important
.md-tab-picker-content
background-color tab-picker-bg
</style>