<template>
  <view class="me-tabs" :class="{ 'tabs-fixed': fixed, isDouble }" :style="{ height: tabHeightVal, top: topFixed, 'margin-top': topMargin }">
    <scroll-view v-if="tabs.length" :id="viewId" :scroll-left="scrollLeft" scroll-x scroll-with-animation :scroll-animation-duration="300">
      <view class="tabs-item" :class="{ 'tabs-flex': !isScroll, 'tabs-scroll': isScroll }">
        <!-- tab -->
        <view
          class="tab-item"
          :style="{ width: tabWidthVal, height: tabHeightVal, 'line-height': tabHeightVal }"
          v-for="(tab, i) in tabs"
          :class="{ active: modelValue === i }"
          :key="i"
          @click="tabClick(i)"
        >
          {{ getTabName(tab) }}
        </view>
        <!-- 下划线 -->
        <view class="tabs-line" :style="{ left: lineLeft }"></view>
      </view>
    </scroll-view>
  </view>
</template>

<script>
export default {
  props: {
    tabs: {
      type: Array,
      default() {
        return []
      }
    },
    nameKey: {
      // 取name的字段
      type: String,
      default: 'name'
    },
    modelValue: {
      // 当前显示的下标 (使用v-model语法糖: 1.props需为modelValue; 2.需回调input事件)
      type: [String, Number],
      default: 0
    },
    fixed: Boolean, // 是否悬浮,默认false
    tabWidth: Number, // 每个tab的宽度,默认不设置值,为flex平均分配; 如果指定宽度,则不使用flex,每个tab居左,超过则水平滑动(单位默认rpx)
    height: {
      // 高度,单位rpx
      type: Number,
      default: 80
    },
    top: {
      // 顶部偏移的距离,默认单位rpx (当fixed=true时,已加上windowTop)
      type: Number,
      default: 0
    },
    // 是否是第二层选项卡
    isDouble: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      viewId: 'id_' + Math.random().toString(36).substr(2, 16),
      scrollLeft: 0,
      windowWidth: 0,
      windowTop: 0
    }
  },
  computed: {
    isScroll() {
      return this.tabWidth && this.tabs.length // 指定了tabWidth的宽度,则支持水平滑动
    },
    tabHeightPx() {
      return uni.upx2px(this.height)
    },
    tabHeightVal() {
      return this.tabHeightPx + 'px'
    },
    tabWidthPx() {
      return uni.upx2px(this.tabWidth)
    },
    tabWidthVal() {
      return this.isScroll ? this.tabWidthPx + 'px' : ''
    },
    lineLeft() {
      if (this.isScroll) {
        return this.tabWidthPx * this.modelValue + this.tabWidthPx / 2 + 'px' // 需转为px (用rpx的话iOS真机显示有误差)
      } else {
        return (100 / this.tabs.length) * (this.modelValue + 1) - 100 / (this.tabs.length * 2) + '%'
      }
    },
    topFixed() {
      return this.fixed ? this.windowTop + uni.upx2px(this.top) + 'px' : 0
    },
    topMargin() {
      return this.fixed ? 0 : this.top + 'rpx'
    }
  },
  watch: {
    tabs() {
      // 水平滚动到中间
      this.initWarpRect(() => {
        this.scrollCenter()
      })
    },
    //modelValue() {
    //  this.scrollCenter() // 水平滚动到中间
    //}
    modelValue: {
      handler(val) {
        this.scrollCenter() // 水平滚动到中间
      },
      deep: true,
      immediate: true
    }
  },
  created() {
    let sys = uni.getSystemInfoSync()
    this.windowWidth = sys.windowWidth
    this.windowTop = sys.windowTop
  },
  mounted() {
    // 滚动到当前下标
    this.initWarpRect(() => {
      this.scrollCenter()
    })
  },
  methods: {
    getTabName(tab) {
      return typeof tab === 'object' ? tab[this.nameKey] : tab
    },
    tabClick(i) {
      if (this.modelValue != i) {
        this.$emit('update:modelValue', i)
        this.$emit('change', i)
      }
    },
    scrollCenter() {
      if (!this.isScroll) return
      let tabLeft = this.tabWidthPx * this.modelValue + this.tabWidthPx / 2 // 当前tab中心点到左边的距离
      let diff = tabLeft - this.warpWidth / 2 // 如果超过tabs容器的一半,则滚动差值
      this.scrollLeft = diff
    },
    initWarpRect(success) {
      setTimeout(() => {
        // 延时确保dom已渲染, 不使用$nextclick
        let query = uni.createSelectorQuery().in(this)
        query
          .select('#' + this.viewId)
          .boundingClientRect((rect) => {
            this.warpWidth = rect ? rect.width : this.windowWidth // 某些情况下取不到宽度,暂时取屏幕宽度
            success()
          })
          .exec()
      }, 20)
    }
  }
}
</script>

<style lang="scss">
.me-tabs.isDouble {
  padding-top: 10px !important;
  background-color: #f8f8f8 !important;
  border: none !important;
  .tabs-flex {
    justify-content: center !important;
  }
  .tabs-line {
    display: none !important;
  }
  .tabs-item {
    .tab-item {
      flex: unset !important;
      width: 43% !important;
      border-radius: 10rpx !important;
      font-size: 24rpx !important;
      background-color: #fff !important;  
      height: 30px !important;
      line-height: 30px !important;
      margin: 0 10px;
      &.active {
        background-color: #00c1ab !important;
        color: #fff !important;
      }
    }
  }
}
.me-tabs {
  position: relative;
  font-size: 28rpx;
  background-color: #fff;
  border-bottom: 1rpx solid #eee;
  box-sizing: border-box;
  overflow-y: hidden;
  background-color: #fff;
  &.tabs-fixed {
    z-index: 990;
    position: fixed;
    left: 0;
    width: 100%;
  }

  .tabs-item {
    position: relative;
    white-space: nowrap;
    padding-bottom: 30rpx; // 撑开高度,再配合me-tabs的overflow-y: hidden,以达到隐藏滚动条的目的
    box-sizing: border-box;
    .tab-item {
      position: relative;
      text-align: center;
      box-sizing: border-box;
      font-size: 28rpx;
      &.active {
        font-weight: 600;
        color: #00c1ab;
        font-size: 28rpx;
      }
    }
  }

  // 平分的方式显示item
  .tabs-flex {
    display: flex;
    .tab-item {
      flex: 1;
    }
  }
  // 居左显示item,支持水平滑动
  .tabs-scroll {
    .tab-item {
      display: inline-block;
    }
  }

  // 选中tab的线
  .tabs-line {
    z-index: 1;
    position: absolute;
    bottom: 30rpx; // 至少与.tabs-item的padding-bottom一致,才能保证在底部边缘
    width: 50rpx;
    height: 6rpx;
    transform: translateX(-50%);
    border-radius: 4rpx;
    transition: left 0.3s;
    background: #00c1ab;
  }
}
</style>
