TabCards.nvue 6.58 KB
<template>
  <view class="body-view" :style="`height:${swiperHeight}px`">
    <scroll-view class="scroll-tab" scroll-x="true" scroll-with-animation :scroll-left="scrollLeft">
      <view style="display: flex;flex-direction: row;height: 44px;">
        <view class="menu-topic-view" v-for="(item,index) in cards" :key="index" @click="swichMenu(index)" :style="`width:${scrollWidth}`">
          <view class="menu-topic">
            <text class="menu-topic-text" :style="`font-size: ${props.textSize}`"
              :class="{'act-menu-topic-text': currentIndex === index}">{{t(item.name)}}</text>
            <image src="@/static/common/tab-act.png" v-if="currentIndex === index" style="width: 32rpx; height: 10rpx;"
              mode=""></image>
            <view class="tab-block" v-else style="width: 32rpx;height: 10rpx">
            </view>
          </view>
        </view>
      </view>
    </scroll-view>
    <swiper class="swiper-box-list" :style="`height:${swiperHeight-44}px`" :current="currentIndex"
      @change="swiperChange">
      <swiper-item class="swiper-topic-list" v-for="(item,index) in cards" :key="index">
        <scroll-view scroll-y="true" class="scroll-swiper-item" :style="`height:${swiperHeight-44}px`">
          <!-- 微信小程序是静态语言,不支持动态组件component,所以这里使用静态组件 -->
          <!-- 客流页组件 -->
          <Flow v-if="(currentIndex === index || loadedComponents.includes(index))&& item.component === 'Flow'" :index="currentIndex"  v-bind="item.props || {}"></Flow>
          <IosStoreHeatMapNvue v-if="(currentIndex === index || loadedComponents.includes(index))&& item.component === 'IosStoreHeatMapNvue'" :index="currentIndex"  v-bind="item.props || {}"></IosStoreHeatMapNvue>
          <!-- #ifndef MP-WEIXIN -->
          <StoreHeatMap v-if="(currentIndex === index || loadedComponents.includes(index))&& item.component === 'StoreHeatMap'" :index="currentIndex"  v-bind="item.props || {}"></StoreHeatMap>
          <AreaStatistic v-if="(currentIndex === index || loadedComponents.includes(index))&& item.component === 'AreaStatistic'" :index="currentIndex"  v-bind="item.props || {}"></AreaStatistic>
          <!-- #endif -->
        
          <!-- 巡店页组件 -->
          <StoreList v-if="(currentIndex === index || loadedComponents.includes(index))&& item.component === 'StoreList'" :index="currentIndex"  v-bind="item.props || {}"></StoreList>
          <Organization v-if="(currentIndex === index || loadedComponents.includes(index))&& item.component === 'Organization'" :index="currentIndex"  v-bind="item.props || {}"></Organization>
          <MarkStore v-if="(currentIndex === index || loadedComponents.includes(index))&& item.component === 'MarkStore'" :index="currentIndex"  v-bind="item.props || {}"></MarkStore>
          <TagStoreVue v-if="(currentIndex === index || loadedComponents.includes(index))&& item.component === 'TagStoreVue'" :index="currentIndex"  v-bind="item.props || {}"></TagStoreVue>
          <!-- <component v-if="currentIndex === index || loadedComponents.includes(index)" :is="item.component" :index="currentIndex" v-bind="item.props || {}"></component> -->
        </scroll-view>
      </swiper-item>
    </swiper>
  </view>
</template>
<script setup>
  // 客流页组件
  import Flow from '../pages/flow/FlowDetail.nvue'
  import AreaStatistic from '../pages/flow/AreaStatistic.nvue'
  import IosStoreHeatMapNvue from '../pages/flow/IosStoreHeatMap.nvue';
  import StoreHeatMap from '@/subPackages/accountGroup/pages/store-analysis/store-heatmap/index.nvue'
  
  // 巡店页组件
  import StoreList from '../pages/inspection/indexStore.vue';
  import Organization from '../pages/inspection/Organization.nvue'
  import MarkStore from '../pages/inspection/MarkStore.vue';
  import TagStoreVue from '../pages/inspection/TagStore.vue';
  import {
    t
  } from '@/plugins/index.js'
  
  import {
    ref,
    watch,
    onMounted,
    computed
  } from 'vue'

  const scrollLeft = ref(0)
  const props = defineProps({
    cards: {
      type: Array,
      default: () => []
    },
    textSize: {
      type: String,
      default: '32rpx'
    },
    top: {
      type: Number,
      default: 0
    }
  })
  const scrollWidth = computed(()=>{
    const cardsLength = props.cards.length
    return cardsLength === 0? '750rpx':cardsLength>=4 ?'187rpx' : (750/cardsLength).toFixed(0)+'rpx'
  })

  const currentIndex = ref(0)
  const loadedComponents = ref([0])

  const setActive = (index)=>{
    currentIndex.value = 0
    loadedComponents.value = [index]
  }
  const emit = defineEmits(['indexChange'])
  watch(currentIndex, (newIndex) => {
    if (!loadedComponents.value.includes(newIndex)) {
      loadedComponents.value.push(newIndex)
    }
    emit('indexChange',newIndex)
  })

  const swiperHeight = ref(0)

  onMounted(() => {
    const systemInfo = uni.getSystemInfoSync()
    swiperHeight.value = systemInfo.windowHeight - props.top
  })

  function swichMenu(index) {
    currentIndex.value = index
    // 滑动swiper后,每个选项距离其父元素最左侧的距离
    scrollLeft.value = 0;
    if (props.cards.length > 4) {
      for (let i = 0; i < index; i++) {
        scrollLeft.value += 60
      };
    }
  }

  function swiperChange(e) {
    let index = e.detail.current
    swichMenu(index)
  }
  defineExpose({
    setActive
  })
</script>

<style lang="scss">
  .body-view {
    width: 750rpx;
    /* #ifdef APP-NVUE */
    flex: 1;
    /* #endif */
    /* #ifndef APP-NVUE */
    display: flex;
    flex-direction: column;
    /* #endif */
    /* #ifdef H5 */
    height: calc(100vh - 104px);
    /* #endif */
    background-color: #F2f3f6;
  }

  .scroll-tab,
  .scroll-tab-vue {
    width: 750rpx;
    height: 44px;
    padding-top: 12rpx;
    background-color: #3277FB;
    display: flex;
    flex-direction: row;

    .menu-topic-view {
      /* #ifndef APP-NVUE */
      min-width: 187rpx;
      /* #endif */

      .menu-topic {
        /* #ifndef APP-NVUE */
        display: flex;
        flex-direction: column;
        /* #endif */
        flex: 1;
        /* #ifndef APP-NVUE */
        display: flex;
        flex-direction: column;
        /* #endif */
        align-items: center;

        .menu-topic-text {
          color: #fff;
          padding-bottom: 6rpx;
        }

        .act-menu-topic-text {
          font-weight: 700;
        }
      }
    }
  }


  .swiper-box-list {
    flex: 1;
    /* #ifndef APP-NVUE */
    min-height: 0;
    /* #endif */
    width: 750rpx;
  }

  /* #ifndef APP-NVUE */
  .scroll-swiper-item,
  .swiper-topic-list {
    // flex: 1;
    min-height: 0;
  }

  .content-scroll {
    flex: 1;
  }

  /* #endif */
</style>