<template name="cascade-picker">
  <view class="aui-picker" v-if="SHOW" :class="{'aui-picker-in': FADE==1,'aui-picker-out': FADE==0}">
    <view class="aui-mask" @click.stop="close"></view>
    <view class="aui-picker-main">
      <view class="aui-picker-header">
        <view class="aui-picker-header-icon" @click.stop="close">取消</view>
        <view class="aui-picker-title" v-if="title">{{ title }}</view>
        <view class="aui-picker-header-icon aui-picker-confirm" @click.stop="_confirm">确认</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]"
              :style="{margin: nav.length>2 ? '0 25rpx 0 0' : '0 45rpx 0 0'}"
              @click.stop="_changeNav($event)"
        >{{ item.name }}
        </view>
        <view class="aui-picker-navitem"
              :key="nav.length"
              :data-index="nav.length"
              :class="[nav.length==navCurrentIndex ? 'active' : '', 'aui-picker-navitem-'+nav.length]"
              :style="{margin: nav.length>2 ? '0 25rpx 0 0' : '0 45rpx 0 0'}"
              @click.stop="_changeNav($event)">请选择
        </view>
        <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"
                    v-if="item.pid=='0'"
                    :key="key"
                    :data-pindex="index"
                    :data-index="key"
                    :data-id="item.id"
                    :data-pid="item.pid"
                    :data-name="item.name"
                    :data-type="item.type"
                    :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.name }}
              </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-pid="item.pid"
                    :data-name="item.name"
                    :data-type="item.type"
                    :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.name }}
              </view>
            </view>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: 'cascade-picker',
  props: {
    title: { //标题
      type: String,
      default: ''
    },
    layer: { //控制几级联动,默认无限级(跟随数据有无下级)
      type: Number,
      default: null
    },
    data: { //数据 如：[{id: '', name: '', children: [{id: '', name: ''}]}]
      type: Array,
      default() {
        return [
          // [{id: '', name: '', children: [{id: '', name: ''}]}]
        ]
      }
    }
  },
  data() {
    return {
      SHOW: false,
      FADE: -1,
      nav: [],
      items: [], // 第一级数据列表
      queryItems: [], // 各级数据列表
      navCurrentIndex: 0, // 当前选中的导航项索引
      navBorderLeft: 26, // 导航栏的边框左侧位置
      result: [],
      touchConfig: {
        index: -1,
        pindex: -1,
        style: {
          color: '#214579',
          background: '#EFEFEF'
        }
      },
      selectedData: [] // 用于回显数据的属性
    }
  },
  watch: {
    data() {
      const _this = this;
      const data = _this.data;
      _this.items = _this._flatten(data, '0')
      console.log(_this.items,"_this.items")
    }
  },
  methods: {
    // 打开
    open() {
      const _this = this;
      _this.reset(); //打开时重置picker
    //   _this._restoreSelectedData()
      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 = 26;
      _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 + 10;
      }).exec();
    },
    //数据选择
    _chooseItem(e) {
      const _this = this;
      const id = e.currentTarget.dataset.id;
      const name = e.currentTarget.dataset.name;
      const pid = e.currentTarget.dataset.pid;
      const type = e.currentTarget.dataset.type;
      const _arr = [];
      _this.result[_this.navCurrentIndex] = {id: id, name: name, pid: pid, type: type};
      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, name: item.name, pid: id, type: item.type});
        });
        if (_this.navCurrentIndex == _this.queryItems.length) { //选择数据
          _this.queryItems.push(_arr);
          _this.nav.push({name: name});
        } 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, {name: name});
        }
        _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 + 10;
          }).exec();
        }, 100)
      } else { //无下级数据且最后一级数据的type为1时，则可以确认关闭
    //   console.log(_this.result,type,"typetypetypetypetype",e.currentTarget.dataset)
        _this._confirm();
      }
    },
    _confirm() {
      const _this = this;
      const lastItem = _this.result[_this.result.length - 1];
      console.log(lastItem)
      console.log(_this.result)
      if (lastItem && lastItem.type === 1) {
        _this.close().then(() => {
            _this.selectedData = [..._this.result]; // 保存选择的数据
          _this.$emit("callback", {status: 0, data: _this.result});
        });
      } else {
        uni.$u.toast('请选择最后一级分类')
      }
    },
    //递归遍历——将树形结构数据转化为数组格式
    _flatten(tree, pid) {
      return tree.reduce((arr, {id, name, type, children = []}) =>
        arr.concat([{id, name, pid, type}], this._flatten(children, 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;
    },
     // 恢复选择的数据
    _restoreSelectedData() {
      const _this = this;
      console.log(_this.selectedData, "selectedData")
      if (_this.selectedData.length > 0) {
        _this.result = [..._this.selectedData];
        _this.queryItems = [];
        _this.nav = [];
        _this.navCurrentIndex = 0;
        _this.selectedData.forEach((item, index) => {
          _this.result[index] = item;
          if (index > 0) {
            const parent = _this._deepQuery(_this.data, item.pid);
            if (parent && parent.children) {
              _this.queryItems[index - 1] = parent.children.map(child => ({
                id: child.id,
                name: child.name,
                pid: child.pid,
                type: child.type
              }));
              _this.nav[index - 1] = {name: parent.name};
            }
          }
        });
        _this.navCurrentIndex = _this.selectedData.length - 1;
        const lastItem = _this.selectedData[_this.selectedData.length - 1];
        if (lastItem) {
          const _el = uni.createSelectorQuery().in(_this).select(".aui-picker-navitem-" + _this.navCurrentIndex);
        setTimeout(() => {
              _el.boundingClientRect(data => {
            // _this.navBorderLeft = data?.left + 10;
            console.log(data, "data")
          }).exec();
        },50)
            _this.$emit("callback", {status: 1, data: _this.result});
        }
      }
    
    },
  }
}
</script>

<style lang="scss" scoped>
$custom-content-color: #1f7cff;
/* ====================
  多级联动弹窗
 =====================*/
.aui-picker {
  width: 100vw;
  height: 100vh;
  //opacity: 0;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  /* display: none; */
}

// 遮罩层
.aui-mask {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, .3);
  position: absolute;
  left: 0;
  top: 0;
  z-index: 999;
}

.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;
  position: absolute;
  left: 0rpx;
  bottom: 0;
  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%;
  min-height: 70rpx;
  position: relative;
  z-index: 999;
  display: flex;
  justify-content: space-between;
  align-items: center;

  &-icon {
    font-size: 26rpx;
    color: #aaa;
    padding: 0 26rpx;
  }

  .aui-picker-confirm {
    height: 70rpx;
    line-height: 70rpx;
    text-align: center;
    font-size: 26rpx;
    color: $custom-content-color;
    padding: 0 25rpx;
  }
}

.aui-picker-header::after {
  content: '';
  width: 100%;
  height:2rpx;
  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: 45rpx;
  text-align: center;
  font-size: 26rpx;
  color: #333;
  padding: 15rpx;
  font-weight: bold;
  box-sizing: border-box;
  position: absolute;
  left: 60rpx;
  right: 60rpx;
  top: 0;
}

.aui-picker-content {
  width: 100%;
  height: -webkit-calc(100% - 110rpx);
  height: calc(100% - 110rpx);
}

.aui-picker-nav {
  width: 100%;
  height: 60rpx;
  text-align: left;
  padding: 0 26rpx;
  margin: 0 0 2rpx 0;
  justify-content: flex-start;
  white-space: nowrap;
  box-sizing: border-box;
  position: relative;
  overflow-x: scroll;
  overflow-y: hidden;
}

.aui-picker-nav::after {
  content: '';
  width: 100%;
  height: 2rpx;
  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 {
  width: 110rpx;
  line-height: 50rpx;
  font-size: 25rpx;
  margin: 0 70rpx 0 0;
  text-align: center;
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.aui-picker-navitem.active {
  color: $custom-content-color;
}

.aui-picker-navborder {
  width: 90rpx;
  height: 6rpx;
  background: $custom-content-color;
  border-radius: 10rpx;
  transition: left .15s;
  position: absolute;
  left: 60rpx;
  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: 20rpx 0;
  display: inline-block;
}

.aui-picker-item {
  width: 100%;
  height: 70rpx;
  line-height: 70rpx;
  padding: 0 30rpx;
  box-sizing: border-box;
  font-size: 25rpx;
  color: #333;
  position: relative;
}

.aui-picker-item.active {
  color: $custom-content-color;
}

.aui-picker-item.active::after {
  content: '✔';
  font-size: 25rpx;
  color: $custom-content-color;
  position: absolute;
  top: 0rpx;
  right: 20rpx;
}

</style>
