<template>
<view class="u-select">
<u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto"
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex" border-radius="4.4">
<view class="u-select" v-if="value">
<view class="u-select__header__my">
<view class="u-select__header__cancel u-select__bottom__btn__cancle" :style="{ color: cancelColor }" hover-class="u-hover-class"
:hover-stay-time="150" @tap="getResult('cancel')">{{cancelText}}</view>
<view class="header__title">{{handerTitle}}</view>
<view class="u-select__header__confirm u-select__bottom__btn__ok" :style="{ color: moving ? cancelColor : confirmColor }"
hover-class="u-hover-class" :hover-stay-time="150" @touchmove.stop @tap.stop="getResult('confirm')">{{confirmText}}</view>
</view>
<view class="u-select__body">
<picker-view @change="columnChange" class="u-select__body__picker-view" :value="defaultSelector" @pickstart="pickstart"
@pickend="pickend">
<picker-view-column v-for="(item, index) in columnData" :key="index">
<view class="u-select__body__picker-view__item" v-for="(item1, index1) in item" :key="index1">
<view class="u-line-1" :class="index === 0 && fontWeight[0] === index1 ? 'font__weight': index === 1 && fontWeight[1] === index1 ? 'font__weight': index === 2 && fontWeight[2] === index1 ? 'font__weight': ''">{{ item1[labelName] }}</view>
</view>
</picker-view-column>
</picker-view>
<view class="dim__top"></view>
<view class="dim__bottom"></view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
props: {
list: {
type: Array,
default () {
return []
},
},
border: {
type: Boolean,
default: true,
},
value: {
type: Boolean,
default: false,
},
cancelColor: {
type: String,
default: '#000',
},
confirmColor: {
type: String,
default: '#fff',
},
confirmText: {
type: String,
default: '确认'
},
cancelText: {
type: String,
default: '取消'
},
zIndex: {
type: [String, Number],
default: 0,
},
safeAreaInsetBottom: {
type: Boolean,
default: false,
},
maskCloseAble: {
type: Boolean,
default: true,
},
defaultValue: {
type: Array,
default () {
return [0]
},
},
mode: {
type: String,
default: 'single-column',
},
valueName: {
type: String,
default: 'value',
},
labelName: {
type: String,
default: 'label',
},
childName: {
type: String,
default: 'children',
},
title: {
type: String,
default: '',
},
handerTitle: {
type: String,
default: '自定义标题',
},
cancelImg: {
type: String,
default: '',
},
},
data() {
return {
defaultSelector: [0],
columnData: [],
selectValue: [],
lastSelectIndex: [],
columnNum: 0,
moving: false,
fontWeight: '',
}
},
watch: {
value: {
immediate: true,
handler(val) {
if (val) setTimeout(() => this.init(), 10)
},
},
},
computed: {
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.popup
},
},
methods: {
pickstart() {
this.moving = true
},
pickend() {
this.moving = false
},
init() {
this.setColumnNum()
this.setDefaultSelector()
this.setColumnData()
this.setSelectValue()
},
setDefaultSelector() {
this.defaultSelector =
this.defaultValue.length == this.columnNum ?
this.defaultValue :
Array(this.columnNum).fill(0)
this.lastSelectIndex = this.$u.deepClone(this.defaultSelector)
this.fontWeight = this.lastSelectIndex
},
setColumnNum() {
if (this.mode == 'single-column') this.columnNum = 1
else if (this.mode == 'mutil-column') this.columnNum = this.list.length
else if (this.mode == 'mutil-column-auto') {
let num = 1
let column = this.list
while (column[0][this.childName]) {
column = column[0] ? column[0][this.childName] : {}
num++
}
this.columnNum = num
}
},
setColumnData() {
let data = []
this.selectValue = []
if (this.mode == 'mutil-column-auto') {
let column = this.list[
this.defaultSelector.length ? this.defaultSelector[0] : 0
]
for (let i = 0; i < this.columnNum; i++) {
if (i == 0) {
data[i] = this.list
column = column[this.childName]
} else {
data[i] = column
column = column[this.defaultSelector[i]][this.childName]
}
}
} else if (this.mode == 'single-column') {
data[0] = this.list
} else {
data = this.list
}
this.columnData = data
},
setSelectValue() {
let tmp = null
for (let i = 0; i < this.columnNum; i++) {
tmp = this.columnData[i][this.defaultSelector[i]]
let data = {
value: tmp ? tmp[this.valueName] : null,
label: tmp ? tmp[this.labelName] : null,
}
if (tmp && tmp.extra) data.extra = tmp.extra
this.selectValue.push(data)
}
},
columnChange(e) {
let index = null
let columnIndex = e.detail.value
this.fontWeight = e.detail.value
this.selectValue = []
if (this.mode == 'mutil-column-auto') {
this.lastSelectIndex.map((val, idx) => {
if (val != columnIndex[idx]) index = idx
})
this.defaultSelector = columnIndex
for (let i = index + 1; i < this.columnNum; i++) {
this.columnData[i] = this.columnData[i - 1][
i - 1 == index ? columnIndex[index] : 0
][this.childName]
this.defaultSelector[i] = 0
}
columnIndex.map((item, index) => {
let data = this.columnData[index][columnIndex[index]]
let tmp = {
value: data ? data[this.valueName] : null,
label: data ? data[this.labelName] : null,
}
if (data && data.extra) tmp.extra = data.extra
this.selectValue.push(tmp)
})
this.lastSelectIndex = columnIndex
} else if (this.mode == 'single-column') {
let data = this.columnData[0][columnIndex[0]]
let tmp = {
value: data ? data[this.valueName] : null,
label: data ? data[this.labelName] : null,
}
if (data && data.extra) tmp.extra = data.extra
this.selectValue.push(tmp)
} else if (this.mode == 'mutil-column') {
columnIndex.map((item, index) => {
let data = this.columnData[index][columnIndex[index]]
let tmp = {
value: data ? data[this.valueName] : null,
label: data ? data[this.labelName] : null,
}
if (data && data.extra) tmp.extra = data.extra
this.selectValue.push(tmp)
})
}
},
close() {
this.$emit('input', false)
},
getResult(event = null) {
if (this.moving) return
if (event) this.$emit(event, this.selectValue)
this.close()
},
selectHandler() {
this.$emit('click')
},
},
}
</script>
<style scoped lang="scss">
@import '../../libs/css/style.components.scss';
.u-select {
/deep/ .uni-picker-view-mask {
background:rgba(226,226,226,1);
}
.u-select__header__my {
display: flex;
font-size: 16px;
width: 100%;
height: 38.46rpx;
line-height: 38.46rpx;
justify-content: space-between;
background: linear-gradient(180deg,
rgba(248, 248, 248, 1) 0%,
rgba(218, 218, 218, 1) 52%,
rgba(208, 208, 208, 1) 100%);
padding: 0 11rpx;
align-items: center;
border-bottom: 0.5px solid rgba(161, 161, 161, 1);
.header-icon {
border: 1px solid rgba(135, 135, 135, 1);
border-radius: 50%;
padding: 5px 5px;
background: linear-gradient(180deg,
rgba(254, 254, 255, 1) 0%,
rgba(209, 211, 216, 1) 100%);
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 1);
font-weight: bold;
}
.header__title {
font-weight: bold;
font-size: 14.83rpx;
color: rgba(0, 0, 0, 1);
font-family: SourceHanSansCN-Medium, SourceHanSansCN;
}
.header-icon:active {
background: #ccc;
}
.header-img {
width: 12.08rpx;
height: 12.08rpx;
}
.placeholder {
width: 20rpx;
height: 10px;
}
}
.u-select__bottom {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 51.37rpx;
margin-bottom: 18.13rpx;
padding: 0 24px;
background: rgba(225, 225, 225, 1);
}
.u-select__bottom__btn__cancle,
.u-select__bottom__btn__ok {
font-size: 12.36rpx;
width: 82.41rpx;
height: 27.47rpx;
font-weight: bold;
display: flex;
justify-content: center;
align-items: center;
}
.u-select__bottom__btn__cancle {
background: linear-gradient(180deg,
rgba(247, 247, 247, 1) 0%,
rgba(184, 184, 184, 1) 100%);
text-align: center;
border-radius: 3.84rpx;
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 1);
border: 0.5px solid rgba(139, 139, 139, 1);
text-shadow: 0px 0.5px 0px rgba(255, 255, 255, 1);
}
.u-select__bottom__btn__ok {
background: linear-gradient(180deg,
rgba(123, 186, 255, 1) 0%,
rgba(0, 114, 238, 1) 73%,
rgba(0, 122, 255, 1) 100%);
border-radius: 3.84rpx;
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 1);
border: 0.5px solid rgba(27, 99, 179, 1);
text-shadow: 0px 0.5px 0px rgba(0, 0, 0, 0.5);
}
/deep/ .uni-picker-view-indicator {
height: 35rpx;
}
/deep/ .uni-picker-view-content {
z-index: 999;
}
/deep/ .uni-picker-view-indicator:before {
border-top: 1px solid #979797;
}
/deep/ .uni-picker-view-indicator:after {
border-bottom: 1px solid #979797;
}
&__action {
position: relative;
line-height: 70rpx;
height: 70rpx;
&__icon {
position: absolute;
right: 10rpx;
top: 50%;
transition: transform 0.4s;
transform: translateY(-50%);
z-index: 1;
&--reverse {
transform: rotate(-180deg) translateY(50%);
}
}
}
&__hader {
&__title {
color: #606266;
}
}
&--border {
border-radius: 6rpx;
border-radius: 4px;
border: 1px solid #dcdfe6;
}
&__header {
display: flex;
align-items: center;
justify-content: space-between;
height: 40rpx;
padding: 0 20rpx;
}
&__body {
width: 100%;
height: 170rpx;
overflow: hidden;
position: relative;
.font__weight {
font-weight: bold;
font-size: 14.83rpx;
}
&__picker-view {
height: 100%;
box-sizing: border-box;
&__item {
display: flex;
align-items: center;
justify-content: center;
font-size: 16rpx;
color:#303133;
padding: 0 4rpx;
font-size: 12.36rpx;
}
}
}
}
</style>