fourPayProject/51uni/components/three-level-linkage/linkage.nvue
2025-03-31 10:23:28 +08:00

492 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="linkage" v-if="showPopup" @touchmove.stop.prevent="clear">
<!-- 遮罩层 -->
<view class="linkage-mask" @touchmove.stop.prevent="clear" v-if="maskClick"
:class="[ani+'-mask', animation ? 'mask-ani' : '']" :style="{
'background-color': maskBgColor
}" @tap="hideMask(true)"></view>
<view class="linkage-content linkage--fixed" :class="[type,ani+'-content', animation ? 'content-ani' : '']">
<view class="top-pop">
<view style="width: 30px; height: 10px;"></view>
<view class="">选择地址</view>
<view class="" @click="pickerCancel">
<u-icon name="close" size="18"></u-icon>
</view>
</view>
<!-- <view class="linkage__header">
<view class="linkage__header-btn-box" @click="pickerCancel">
<text class="linkage__header-text">取消</text>
</view>
<view class="linkage__header-btn-box" @click="pickerConfirm">
<text class="linkage__header-text" :style="{color:themeColor}">确定</text>
</view>
</view> -->
<view class="linkage__box">
<picker-view indicator-style="height: 70rpx;" class="linkage-view" :value="pickerValue"
@change="pickerChange">
<picker-view-column>
<!-- #ifndef APP-NVUE -->
<view class="picker-item" v-for="(item,index) in firstLevel" :key="index">{{getItemText(item)}}
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<text class="picker-item" v-for="(item,index) in firstLevel"
:key="index">{{getItemText(item)}}</text>
<!-- #endif -->
</picker-view-column>
<picker-view-column v-if="secondShow">
<!-- #ifndef APP-NVUE -->
<view class="picker-item" v-for="(item,index) in secondLevel" :key="index">{{getItemText(item)}}
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<text class="picker-item" v-for="(item,index) in secondLevel"
:key="index">{{getItemText(item)}}</text>
<!-- #endif -->
</picker-view-column>
<picker-view-column v-if="thirdShow">
<!-- #ifndef APP-NVUE -->
<view class="picker-item" v-for="(item,index) in thirdLevel" :key="index">{{getItemText(item)}}
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<text class="picker-item" v-for="(item,index) in thirdLevel"
:key="index">{{getItemText(item)}}</text>
<!-- #endif -->
</picker-view-column>
</picker-view>
<view class="anniu" @click="pickerConfirm">
确认
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "levelLinkage",
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
/* 弹出层类型,可选值;
bottom底部弹出层
*/
type: {
type: String,
default: 'bottom'
},
// maskClick
maskClick: {
type: Boolean,
default: true
},
show: {
type: Boolean,
default: true
},
maskBgColor: {
type: String,
default: 'rgba(0, 0, 0, 0.4)', //背景颜色 rgba(0, 0, 0, 0.4) 为空则调用 uni.scss
},
themeColor: {
type: String,
default: '', // 主题色
},
/* 默认值 */
pickerValueDefault: {
type: Array,
default () {
return [0, 0, 0]
}
},
keyName: {
type: String,
default: 'name',
},
valueName: {
type: String,
default: 'code',
},
},
data() {
return {
allData: [],
secondShow: false,
thirdShow: false,
ani: '',
showPopup: false,
pickerValue: [0, 0, 0],
firstLevel: [],
secondLevel: [],
thirdLevel: [],
emptyList: [{
}]
}
},
watch: {
show(newValue) {
if (newValue) {
this.open()
} else {
this.close()
}
},
// pickerValueDefault() {
// this.init();
// }
},
// created() {
// this.init()
// },
methods: {
// 获取item需要显示的文字判别为对象还是文本
getItemText(item) {
if (uni.$u.test.object(item)) {
return item[this.keyName]
} else {
return item
}
},
init(data) {
this.allData = data
this.handPickValueDefault(); // 对 pickerValueDefault 做兼容处理
this.firstLevel = this.allData;
this.secondShow = this.pickerValueDefault[1] >= 0 ? true : false;
this.thirdShow = this.pickerValueDefault[2] >= 0 ? true : false;;
if (this.secondShow) {
this.secondLevel = this.firstLevel[this.pickerValueDefault[0]].inferior.length == 0 ?
this.emptyList : this.firstLevel[this.pickerValueDefault[0]].inferior;
} else {
this.thirdShow = false;
}
if (this.thirdShow) {
this.thirdLevel = this.secondLevel[this.pickerValueDefault[1]].inferior.length == 0 ?
this.emptyList : this.secondLevel[this.pickerValueDefault[1]].inferior;
}
this.pickerValue = this.pickerValueDefault;
},
handPickValueDefault() {
if (this.pickerValueDefault !== [0, 0, 0]) {
if (this.pickerValueDefault[0] > this.allData.length - 1) {
this.pickerValueDefault[0] = this.allData.length - 1;
}
if (this.secondShow && this.pickerValueDefault[1] > this.allData[this.pickerValueDefault[0]].inferior
.length - 1) {
this.pickerValueDefault[1] = this.allData[this.pickerValueDefault[0]].inferior.length - 1;
}
if (this.thirdShow &&
this.pickerValueDefault[2] >
this.allData[this.pickerValueDefault[0]].inferior[this.pickerValueDefault[1]].inferior.length - 1
) {
this.pickerValueDefault[2] = this.allData[this.pickerValueDefault[0]].inferior[this
.pickerValueDefault[1]].inferior.length - 1;
}
}
},
pickerChange(e) {
let changePickerValue = e.detail.value;
if (this.pickerValue[0] !== changePickerValue[0]) {
// 第一级发生滚动
if (this.secondShow) {
this.secondLevel = this.firstLevel[changePickerValue[0]].inferior.length == 0 ?
this.emptyList : this.firstLevel[changePickerValue[0]].inferior;
changePickerValue[1] = 0;
}
if (this.thirdShow) {
this.thirdLevel = this.secondLevel[0].inferior.length == 0 ?
this.emptyList : this.secondLevel[0].inferior;
changePickerValue[2] = 0;
}
} else if (this.pickerValue[1] !== changePickerValue[1]) {
// 第二级滚动
if (this.thirdShow) {
this.thirdLevel = this.secondLevel[changePickerValue[1]].inferior == 0 ?
this.emptyList : this.secondLevel[changePickerValue[1]].inferior;
changePickerValue[2] = 0;
}
}
this.pickerValue = changePickerValue;
this._$emit('onChange');
},
_$emit(emitName) {
// 自定义选中项,选中内容
let firstPick = {};
let secondPick = {};
let thirdPick = {};
firstPick[this.keyName] = this.getItemText(this._getFirst())
firstPick[this.valueName] = this._getFirst()[this.valueName]
if (this.secondShow) {
secondPick[this.keyName] = this.getItemText(this._getSecond())
secondPick[this.valueName] = this._getSecond()[this.valueName]
}
if (this.thirdShow) {
thirdPick[this.keyName] = this.getItemText(this._getThird())
thirdPick[this.valueName] = this._getThird()[this.valueName]
}
let pickObj = {
value: this.pickerValue,
secondPick: secondPick,
thirdPick: thirdPick,
firstPick: firstPick
};
pickObj[this.keyName] = this._getLabel()
this.$emit(emitName, pickObj);
},
_getLabel() {
let pcikerLabel =
this.firstLevel[this.pickerValue[0]][this.keyName];
if (this.secondShow) {
pcikerLabel = pcikerLabel + '-' +
this.secondLevel[this.pickerValue[1]][this.keyName]
}
if (this.thirdShow) {
pcikerLabel = pcikerLabel + '-' +
this.thirdLevel[this.pickerValue[2]][this.keyName];
}
return pcikerLabel;
},
_getSecond() {
if (this.secondShow) {
return this.secondLevel[this.pickerValue[1]];
}
return this.emptyList;
},
_getFirst() {
return this.firstLevel[this.pickerValue[0]];
},
_getThird() {
if (this.thirdShow) {
return this.thirdLevel[this.pickerValue[2]];
}
return this.emptyList;
},
clear() {
},
hideMask() {
this._$emit('onCancel');
this.close();
},
pickerCancel() {
this._$emit('onCancel');
this.close();
},
pickerConfirm() {
this._$emit('onConfirm');
this.close();
},
open() {
this.showPopup = true
this.$nextTick(() => {
setTimeout(() => {
this.ani = 'linkage-c-' + this.type
}, 100)
})
},
close(type) {
if (!this.maskClick && type) return;
this.ani = ''
this.$nextTick(() => {
setTimeout(() => {
this.showPopup = false
}, 300)
})
}
}
}
</script>
<style lang="scss" scoped>
.linkage {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.linkage-mask {
position: fixed;
bottom: 0;
top: 0;
left: 0;
right: 0;
transition-property: opacity;
transition-duration: 0.3s;
opacity: 0;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.mask-ani {
transition-property: opacity;
transition-duration: 0.2s;
}
.linkage-c-bottom-mask {
opacity: 1;
}
.linkage-c-center-mask {
opacity: 1;
}
.linkage--fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
transition-property: transform;
transition-duration: 0.3s;
transform: translateY(460rpx);
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.linkage-content {
background-color: #FFFFFF;
}
.linkage-c-content-bottom {
bottom: 0;
left: 0;
right: 0;
transform: translateY(500rpx);
}
.content-ani {
transition-property: transform, opacity;
transition-duration: 0.2s;
}
.linkage-c-bottom-content {
transform: translateY(0);
}
.linkage-c-center-content {
transform: scale(1);
opacity: 1;
}
.linkage__header {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
border-bottom-color: #f2f2f2;
border-bottom-style: solid;
border-bottom-width: 1rpx;
}
.linkage--fixed-top {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
border-top-color: $uni-border-color;
border-top-style: solid;
border-top-width: 1rpx;
}
.linkage__header-btn-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
height: 70rpx;
}
.linkage__header-text {
text-align: center;
font-size: $uni-font-size-base;
color: #1aad19;
line-height: 70rpx;
padding-left: 40rpx;
padding-right: 40rpx;
}
.linkage__box {
position: relative;
}
.linkage-view {
position: relative;
bottom: 0;
left: 0;
/* #ifndef APP-NVUE */
width: 100%;
/* #endif */
/* #ifdef APP-NVUE */
width: 750rpx;
/* #endif */
height: 408rpx;
background-color: rgba(255, 255, 255, 1);
}
.picker-item {
text-align: center;
line-height: 70rpx;
text-overflow: ellipsis;
font-size: 28rpx;
}
.anniu {
width: 90%;
height: 35px;
background: #069647;
display: flex;
align-items: center;
justify-content: center;
color: white;
border-radius: 4px;
margin: 0px auto;
margin-bottom: 20px;
}
.top-pop {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 0px 10px;
margin-top: 10px;
}
</style>