| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 | <template>  <su-fixed alway :bgStyles="{ background: '#fff' }" :val="0" noNav opacity :placeholder="false">    <su-status-bar />    <view      class="ui-bar ss-flex ss-col-center ss-row-between ss-p-x-20"      :style="[{ height: sys_navBar - sys_statusBar + 'px' }]"    >      <!-- 左 -->      <view class="icon-box ss-flex">        <view class="icon-button icon-button-left ss-flex ss-row-center" @tap="onClickLeft">          <text class="sicon-back" v-if="hasHistory" />          <text class="sicon-home" v-else />        </view>        <view class="line"></view>        <view class="icon-button icon-button-right ss-flex ss-row-center" @tap="onClickRight">          <text class="sicon-more" />        </view>      </view>      <!-- 中 -->      <view class="detail-tab-card ss-flex-1" :style="[{ opacity: state.tabOpacityVal }]">        <view class="tab-box ss-flex ss-col-center ss-row-around">          <view            class="tab-item ss-flex-1 ss-flex ss-row-center ss-col-center"            v-for="item in state.tabList"            :key="item.value"            @tap="onTab(item)"          >            <view class="tab-title" :class="state.curTab === item.value ? 'cur-tab-title' : ''">              {{ item.label }}            </view>            <view v-show="state.curTab === item.value" class="tab-line"></view>          </view>        </view>      </view>      <!-- #ifdef MP -->      <view :style="[capsuleStyle]"></view>      <!-- #endif -->    </view>  </su-fixed></template><script setup>  import { reactive } from 'vue';  import { onPageScroll } from '@dcloudio/uni-app';  import sheep from '@/sheep';  import throttle from '@/sheep/helper/throttle.js';  import { showMenuTools, closeMenuTools } from '@/sheep/hooks/useModal';  const sys_statusBar = sheep.$platform.device.statusBarHeight;  const sys_navBar = sheep.$platform.navbar;  const capsuleStyle = {    width: sheep.$platform.capsule.width + 'px',    height: sheep.$platform.capsule.height + 'px',  };  const state = reactive({    tabOpacityVal: 0,    curTab: 'goods',    tabList: [      {        label: '商品',        value: 'goods',        to: 'detail-swiper-selector',      },      {        label: '评价',        value: 'comment',        to: 'detail-comment-selector',      },      {        label: '详情',        value: 'detail',        to: 'detail-content-selector',      },    ],  });  const emits = defineEmits(['clickLeft']);  const hasHistory = sheep.$router.hasHistory();  function onClickLeft() {    if (hasHistory) {      sheep.$router.back();    } else {      sheep.$router.go('/pages/index/index');    }    emits('clickLeft');  }  function onClickRight() {    showMenuTools();  }  let commentCard = {    top: 0,    bottom: 0,  };  function getCommentCardNode() {    return new Promise((res, rej) => {      uni.createSelectorQuery()        .select('.detail-comment-selector')        .boundingClientRect((data) => {          if (data) {            commentCard.top = data.top;            commentCard.bottom = data.top + data.height;            res(data);          } else {            res(null);          }        })        .exec();    });  }  function onTab(tab) {    let scrollTop = 0;    if (tab.value === 'comment') {      scrollTop = commentCard.top - sys_navBar + 1;    } else if (tab.value === 'detail') {      scrollTop = commentCard.bottom - sys_navBar + 1;    }    uni.pageScrollTo({      scrollTop,      duration: 200,    });  }  onPageScroll((e) => {    state.tabOpacityVal = e.scrollTop > sheep.$platform.navbar ? 1 : e.scrollTop * 0.01;    if (commentCard.top === 0) {      throttle(() => {        getCommentCardNode();      }, 50);    }    if (e.scrollTop < commentCard.top - sys_navBar) {      state.curTab = 'goods';    } else if (      e.scrollTop >= commentCard.top - sys_navBar &&      e.scrollTop <= commentCard.bottom - sys_navBar    ) {      state.curTab = 'comment';    } else {      state.curTab = 'detail';    }  });</script><style lang="scss" scoped>  .icon-box {    box-shadow: 0px 0px 4rpx rgba(51, 51, 51, 0.08), 0px 4rpx 6rpx 2rpx rgba(102, 102, 102, 0.12);    border-radius: 30rpx;    width: 134rpx;    height: 56rpx;    margin-left: 8rpx;    border: 1px solid rgba(#fff, 0.4);    .line {      width: 2rpx;      height: 24rpx;      background: #e5e5e7;    }    .sicon-back {      font-size: 32rpx;      color: #000;    }    .sicon-home {      font-size: 32rpx;      color: #000;    }    .sicon-more {      font-size: 32rpx;      color: #000;    }    .icon-button {      width: 67rpx;      height: 56rpx;      &-left:hover {        background: rgba(0, 0, 0, 0.16);        border-radius: 30rpx 0px 0px 30rpx;      }      &-right:hover {        background: rgba(0, 0, 0, 0.16);        border-radius: 0px 30rpx 30rpx 0px;      }    }  }  .left-box {    position: relative;    width: 60rpx;    height: 60rpx;    display: flex;    justify-content: center;    align-items: center;    .circle {      position: absolute;      left: 0;      top: 0;      width: 60rpx;      height: 60rpx;      background: rgba(#fff, 0.6);      border: 1rpx solid #ebebeb;      border-radius: 50%;      box-sizing: border-box;      z-index: -1;    }  }  .right {    position: relative;    width: 60rpx;    height: 60rpx;    display: flex;    justify-content: center;    align-items: center;    .circle {      position: absolute;      left: 0;      top: 0;      width: 60rpx;      height: 60rpx;      background: rgba(#ffffff, 0.6);      border: 1rpx solid #ebebeb;      box-sizing: border-box;      border-radius: 50%;      z-index: -1;    }  }  .detail-tab-card {    width: 50%;    .tab-item {      height: 80rpx;      position: relative;      z-index: 11;      .tab-title {        font-size: 30rpx;      }      .cur-tab-title {        font-weight: $font-weight-bold;      }      .tab-line {        width: 60rpx;        height: 6rpx;        border-radius: 6rpx;        position: absolute;        left: 50%;        transform: translateX(-50%);        bottom: 10rpx;        background-color: var(--ui-BG-Main);        z-index: 12;      }    }  }</style>
 |