<template name="aui-picker"> <view class="aui-picker" v-if="SHOW" :class="{ 'aui-picker-in': FADE==1, 'aui-picker-out': FADE==0}"> <view class="aui-picker-main"> <view class="aui-mask" @click.stop="close"></view> <view class="aui-picker-header"> <view @click.stop="close" class="aui-picker-close">取消</view> <view class="aui-picker-title" v-if="title">{{title}}</view> <!-- <view class="aui-picker-close iconfont iconclose" ></view> --> <!-- <view class="aui-picker-sure" @click.stop="getSure" v-if="titflag">确定</view> --> <view class="aui-picker-sure" @click.stop="getSure">确定</view> </view> <view class="aui-picker-nav"> <view class="aui-picker-navitem" v-if="nav.length>0" v-for="(item, index) in nav" :key="index" :data-index="index" :class="[index==navCurrentIndex ? 'active' : '', 'aui-picker-navitem-'+index]" @click.stop="_changeNav($event)">{{item.label}}</view> <!-- :style="{margin: nav.length>2 ? '0 10px 0 0' : '0 30px 0 0'}" --> <view class="aui-picker-navitem" :key="nav.length" :data-index="nav.length" :class="[nav.length==navCurrentIndex ? 'active' : '', 'aui-picker-navitem-'+nav.length]" @click.stop="_changeNav($event)">请选择</view> <!-- :style="{margin: nav.length>2 ? '0 10px 0 0' : '0 30px 0 0'}" --> <view class="aui-picker-navborder" :style="{left: navBorderLeft+'px'}"></view> </view> <view class="aui-picker-content"> <view class="aui-picker-lists"> <view class="aui-picker-list" v-for="(list, index) in queryItems.length + 1" :key="index" :data-index="index" :class="[index==navCurrentIndex ? 'active' : '']"> <view class="aui-picker-list-warp" v-if="index == 0"> <view class="aui-picker-item" v-for="(item, key) in items" :key="key" :data-pindex="index" :data-index="key" :data-id="item.id" :data-label="item.label" :class="{'active': result.length>index && result[index].id==item.id}" :style="{'background': touchConfig.index==key && touchConfig.pindex==index ? touchConfig.style.background : ''}" @click.stop="_chooseItem($event)" @touchstart="_btnTouchStart($event)" @touchmove="_btnTouchEnd($event)" @touchend="_btnTouchEnd($event)">{{item.label}}</view> </view> <view class="aui-picker-list-warp" v-else> <view class="aui-picker-item" v-for="(item, key) in queryItems[index-1]" :key="key" :data-pindex="index" :data-index="key" :data-id="item.id" :data-label="item.label" :class="{'active': result.length>index && result[index].id==item.id}" :style="{'background': touchConfig.index==key && touchConfig.pindex==index ? touchConfig.style.background : ''}" @click.stop="_chooseItem($event)" @touchstart="_btnTouchStart($event)" @touchmove="_btnTouchEnd($event)" @touchend="_btnTouchEnd($event)">{{item.label}}</view> </view> </view> </view> </view> </view> </view> </template> <script> export default { label: 'aui-picker', props: { title: { //标题 type: String, default: '' }, titflag: { type: Boolean, default: false, }, layer: { //控制几级联动,默认无限级(跟随数据有无下级) type: Number, default: null }, data: { //数据 如:[{id: '', label: '', children: [{id: '', label: ''}]}] type: Array, default () { return [ // [{id: '', label: '', children: [{id: '', label: ''}]}] ] } } }, data() { return { SHOW: false, FADE: -1, nav: [], items: [], queryItems: [], navCurrentIndex: 0, navBorderLeft: 25, result: [], touchConfig: { index: -1, pindex: -1, style: { color: '#197DE0', background: '#EFEFEF' } }, loadflag: false } }, created() { const _this = this; }, watch: { data() { const _this = this; const data = _this.data; // _this.items = _this._flatten(data, '0') _this.items = data } }, mounted() { }, methods: { // 打开 open(e) { const _this = this; if (e == 1) { _this.reset(); //打开时重置picker } return new Promise(function(resolve, reject) { _this.SHOW = true; _this.FADE = 1; resolve(); }); }, // 关闭 close() { const _this = this; return new Promise(function(resolve, reject) { _this.FADE = 0; const _hidetimer = setTimeout(() => { _this.SHOW = false; _this.FADE = -1; clearTimeout(_hidetimer); resolve(); }, 100) }); }, //重置 reset() { const _this = this; _this.queryItems = []; _this.nav = []; _this.navBorderLeft = 25; _this.navCurrentIndex = 0; _this.result = []; }, //导航栏切换 _changeNav(e) { const _this = this; const index = Number(e.currentTarget.dataset.index); _this.navCurrentIndex = index; const _el = uni.createSelectorQuery().in(this).select(".aui-picker-navitem-" + index); _el.boundingClientRect(data => { _this.navBorderLeft = data.left + 15; }).exec(); }, //数据选择 _chooseItem(e) { // 加载的时候禁止点击 // if (this.loadflag) { // return // } // this.loadflag = true; const _this = this; const id = e.currentTarget.dataset.id; const label = e.currentTarget.dataset.label; // const deptId = e.currentTarget.dataset.deptId; const _arr = []; // 获取新数据 // _this.result[_this.navCurrentIndex] = {id: id, label: label, deptId: deptId}; // _this.$http.post('boman-system/chinaArea/treeSelect',{deptId: id}).then(res=>{ // this.loadflag=false; // if(res.data.length>0){ // if(_this.navCurrentIndex == _this.queryItems.length) // { //选择数据 // _this.queryItems.push(res.data); // _this.nav.push({label: label}); // } // else // { //重新选择数据 // _this.queryItems.splice(_this.navCurrentIndex+1); // _this.nav.splice(_this.navCurrentIndex+1); // _this.queryItems.splice(_this.navCurrentIndex, 1, res.data); // _this.nav.splice(_this.navCurrentIndex, 1, {label: label}); // //清空后面的选择 // _this.result.splice(Number(_this.navCurrentIndex+1)) // } // _this.navCurrentIndex = _this.navCurrentIndex + 1; // const _el = uni.createSelectorQuery().in(this).select(".aui-picker-navitem-"+_this.navCurrentIndex); // setTimeout(()=>{ // _el.boundingClientRect(data => { // _this.navBorderLeft = data.left + 15; // }).exec(); // },100) // }else{ // //无下级数据 // _this.close().then(()=>{ // _this.$emit("callback", {status: 0, data: _this.result}); // }); // } // }) _this.result.splice(Number(_this.navCurrentIndex+1)) _this.result[_this.navCurrentIndex] = { id: id, label: label, }; // console.log(id) // console.log(_this._deepQuery(_this.data, id),7) if ( (!_this._isDefine(_this.layer) && _this._isDefine(_this._deepQuery(_this.data, id).children)) || (_this.navCurrentIndex < (Number(_this.layer) - 1) && _this._isDefine(_this._deepQuery(_this.data, id).children)) ) { //有下级数据 _this._deepQuery(_this.data, id).children.forEach(function(item, index) { _arr.push({ id: item.id, label: item.label, }); }); if (_this.navCurrentIndex == _this.queryItems.length) { //选择数据 _this.queryItems.push(_arr); _this.nav.push({ label: label }); } else { //重新选择数据 _this.queryItems.splice(_this.navCurrentIndex + 1, 1); _this.nav.splice(_this.navCurrentIndex + 1, 1); _this.queryItems.splice(_this.navCurrentIndex, 1, _arr); _this.nav.splice(_this.navCurrentIndex, 1, { label: label }); } _this.navCurrentIndex = _this.navCurrentIndex + 1; const _el = uni.createSelectorQuery().in(this).select(".aui-picker-navitem-" + _this.navCurrentIndex); setTimeout(() => { _el.boundingClientRect(data => { _this.navBorderLeft = data.left + 20; }).exec(); }, 100) } else { //无下级数据 _this.close().then(() => { _this.$emit("callback", { status: 0, data: _this.result }); }); } }, getSure() { this.close().then(() => { this.$emit("callback", { status: 0, data: this.result }); }); }, //递归遍历——将树形结构数据转化为数组格式 _flatten(tree, deptId) { return tree.reduce((arr, { id, label, children = [] }) => arr.concat([{ id, label, }], this._flatten(id)), []) }, //根据id查询对应的数据(如查询id=10100对应的对象) _deepQuery(tree, id) { let isGet = false; let retNode = null; function deepSearch(tree, id) { for (let i = 0; i < tree.length; i++) { if (tree[i].children && tree[i].children.length > 0) { deepSearch(tree[i].children, id); } if (id == tree[i].id || isGet) { isGet || (retNode = tree[i]); isGet = true; break; } } } deepSearch(tree, id); return retNode; }, /***判断字符串是否为空 @param {string} str 变量 @example: aui.isDefine("变量"); */ _isDefine(str) { if (str == null || str == "" || str == "undefined" || str == undefined || str == "null" || str == "(null)" || str == 'NULL' || typeof(str) == 'undefined') { return false; } else { str = str + ""; str = str.replace(/\s/g, ""); if (str == "") { return false; } return true; } }, _btnTouchStart(e) { const _this = this, index = Number(e.currentTarget.dataset.index), pindex = Number(e.currentTarget.dataset.pindex); _this.touchConfig.index = index; _this.touchConfig.pindex = pindex; }, _btnTouchEnd(e) { const _this = this, index = Number(e.currentTarget.dataset.index), pindex = Number(e.currentTarget.dataset.pindex); _this.touchConfig.index = -1; _this.touchConfig.pindex = -1; }, } } </script> <style scoped> /* ==================== 多级联动弹窗 =====================*/ .aui-picker { width: 100vw; height: 100vh; /* opacity: 0; */ position: fixed; top: 0; left: 0; z-index: 1200; background: rgba(0, 0, 0, 0.5); /* display: none; */ } .aui-picker.aui-picker-in { -moz-animation: aui-fade-in .1s ease-out forwards; -ms-animation: aui-fade-in .1s ease-out forwards; -webkit-animation: aui-fade-in .1s ease-out forwards; animation: aui-fade-in .1s ease-out forwards; } .aui-picker.aui-picker-out { -moz-animation: aui-fade-out .1s ease-out forwards; -ms-animation: aui-fade-out .1s ease-out forwards; -webkit-animation: aui-fade-out .1s ease-out forwards; animation: aui-fade-out .1s ease-out forwards; } .aui-picker-main { width: 100vw; height: 50vh; background: #FFF; border-radius: 15px 15px 0 0; position: absolute; left: 0px; /* bottom: -50vh; */ bottom: 0vh; z-index: 999; } .aui-picker.aui-picker-in .aui-picker-main { -moz-animation: aui-slide-up-screen .2s ease-out forwards; -ms-animation: aui-slide-up-screen .2s ease-out forwards; -webkit-animation: aui-slide-up-screen .2s ease-out forwards; animation: aui-slide-up-screen .2s ease-out forwards; } .aui-picker.aui-picker-out .aui-picker-main { -moz-animation: aui-slide-down-screen .2s ease-out forwards; -ms-animation: aui-slide-down-screen .2s ease-out forwards; -webkit-animation: aui-slide-down-screen .2s ease-out forwards; animation: aui-slide-down-screen .2s ease-out forwards; } .aui-picker-header { width: 100%; height: 50px; position: relative; z-index: 999; background: #F2F2F2; border-radius: 15px 15px 0 0; display: flex; align-items: center; } .aui-picker-header::after { content: ''; width: 100%; height: 1px; background: rgba(100, 100, 100, .3); -moz-transform: scaleY(.3); -ms-transform: scaleY(.3); -webkit-transform: scaleY(.3); transform: scaleY(.3); position: absolute; left: 0; bottom: 0; z-index: 999; } .aui-picker-title { line-height: 20px; text-align: center; font-size: 17px; color: #333; padding: 15px; box-sizing: border-box; flex: 1; text-align: center; /* position: absolute; left: 50px; right: 50px; top: 0; */ } .aui-picker-close { font-size: 15px; color: #333333; flex: 0 0 auto; height: 50px; width: 60px; text-align: center; line-height: 50px; } .aui-picker-sure { flex: 0 0 auto; font-size: 15px; color: #197DE0; height: 50px; width: 60px; text-align: center; line-height: 50px; } /* .aui-picker-close.iconfont{ width: 50px; height: 50px; line-height: 50px; text-align: center; font-size: 20px; color: #aaa; border-radius: 0 10px 0 0; position: absolute; right: 0; top: 0; } */ .aui-picker-content { width: 100%; height: -webkit-calc(100% - 100px); height: calc(100% - 100px); } .aui-picker-nav { width: 100%; height: 50px; text-align: left; padding: 0 20rpx; margin: 0 0 1px 0; justify-content: flex-start; white-space: nowrap; box-sizing: border-box; position: relative; display: flex; align-items: center; } .aui-picker-nav::after { content: ''; width: 100%; height: 1px; background: rgba(100, 100, 100, .3); -moz-transform: scaleY(.3); -ms-transform: scaleY(.3); -webkit-transform: scaleY(.3); transform: scaleY(.3); position: absolute; left: 0; bottom: 0; z-index: 999; } .aui-picker-navitem { flex: 1; max-width: 70px; /* width: 80px; */ line-height: 50px; font-size: 16px; text-align: center; display: inline-block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .aui-picker-navitem.active { color: #197DE0; } .aui-picker-navborder { width: 40px; height: 3px; background: #197DE0; border-radius: 5px; transition: left .15s; position: absolute; left: 25px; bottom: 0; } .aui-picker-lists { width: 100%; height: 100%; justify-content: space-around; white-space: nowrap; } .aui-picker-list { width: 100%; height: 100%; overflow: hidden; overflow-y: scroll; display: none; vertical-align: top; } .aui-picker-list.active { display: inline-block; } .aui-picker-list-warp { width: 100%; height: auto; box-sizing: border-box; padding: 15px 0; display: inline-block; } .aui-picker-item { width: 100%; height: 50px; line-height: 50px; padding: 0 15px; box-sizing: border-box; font-size: 15px; color: #333; position: relative; } .aui-picker-item.active { color: #197DE0; } .aui-picker-item.active::after { content: '✔'; font-size: 15px; color: #197DE0; position: absolute; top: 0px; right: 10px; } </style>