| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 | <template>  <view class="ui-fixed">    <view      class="ui-fixed-box"      :id="`fixed-${uuid}`"      :class="[{ fixed: state.fixed }]"      :style="[        {          left: sticky ? 'auto' : '0px',          top: state.fixed && !bottom ? (noNav ? val : val + sys_navBar) + 'px' : 'auto',          bottom: insetHeight,          zIndex: index + sheep.$zIndex.navbar,        },        !alway ? { opacity: state.opacityVal } : '',      ]"    >      <view        class="ui-fixed-content"        @tap="toTop"        :style="[{ zIndex: index + sheep.$zIndex.navbar }]"      >        <slot></slot>        <view          v-if="safeAreaInsets.bottom && bottom && isInset"          class="inset-bottom"          :style="[{ height: safeAreaInsets.bottom + 'px' }]"        ></view>      </view>      <view class="ui-fixed-bottom" :class="[bg]" v-if="bottom"></view>      <view        class="ui-fixed-bg"        :class="[ui, bg]"        :style="[          { zIndex: index + sheep.$zIndex.navbar - 1 },          bgStyles,          opacity ? { opacity: state.opacityVal } : '',        ]"      ></view>    </view>    <view      class="skeleton"      :style="[{ height: state.content.height + 'px', width: width + 'px' }]"      v-if="sticky ? state.fixed : placeholder && state.fixed"    ></view>  </view></template><script setup>  import { onPageScroll } from '@dcloudio/uni-app';  import { getCurrentInstance, unref, onMounted, reactive, nextTick, computed } from 'vue';  import sheep from '@/sheep';  const { safeAreaInsets } = sheep.$platform.device;  const vm = getCurrentInstance();  const uuid = sheep.$helper.guid();  const sys_navBar = sheep.$platform.navbar;  const state = reactive({    content: {},    fixed: true,    scrollTop: 0,    opacityVal: 0,  });  const insetHeight = computed(() => {    if (state.fixed && props.bottom) {      if (props.isInset) {        return props.val + 'px';      } else {        return props.val + safeAreaInsets.bottom + 'px';      }    } else {      return 'auto';    }  });  const props = defineProps({    noNav: {      type: Boolean,      default: false,    },    bottom: {      type: Boolean,      default: false,    },    bg: {      type: String,      default: '',    },    bgStyles: {      type: Object,      default() {},    },    val: {      type: Number,      default: 0,    },    width: {      type: [String, Number],      default: 0,    },    alway: {      type: Boolean,      default: true,    },    opacity: {      type: Boolean,      default: false,    },    index: {      type: [Number, String],      default: 0,    },    placeholder: {      type: [Boolean],      default: false,    },    sticky: {      type: [Boolean],      default: false,    },    noFixed: {      type: Boolean,      default: false,    },    ui: {      type: String,      default: '',    },    clickTo: {      type: Boolean,      default: false,    },    //是否需要安全区    isInset: {      type: Boolean,      default: true,    },  });  state.fixed = !unref(props.sticky);  onPageScroll((e) => {    let top = e.scrollTop;    state.scrollTop = top;    state.opacityVal = top > sheep.$platform.navbar ? 1 : top * 0.01;  });  onMounted(() => {    nextTick(() => {      computedQuery();    });  });  const computedQuery = () => {    uni.createSelectorQuery()      .in(vm)      .select(`#fixed-${uuid}`)      .boundingClientRect((data) => {        if (data != null) {          state.content = data;          if (unref(props.sticky)) {            setFixed(state.scrollTop);          }        }      })      .exec();  };  const setFixed = (value) => {    if (unref(props.bottom)) {      state.fixed =        value >=        state.content.bottom -          sheep.$platform.device.windowHeight +          state.content.height +          unref(props.val);    } else {      state.fixed =        value >=        state.content.top -          (unref(props.noNav) ? unref(props.val) : unref(props.val) + sheep.$platform.navbar);    }  };  const toTop = () => {    if (props.hasToTop) {      uni.pageScrollTo({        scrollTop: state.content.top,        duration: 100,      });    }  };</script><style lang="scss">  .ui-fixed {    .ui-fixed-box {      position: relative;      width: 100%;      &.fixed {        position: fixed;      }      .ui-fixed-content {        position: relative;      }      .ui-fixed-bg {        position: absolute;        width: 100%;        height: 100%;        top: 0;        z-index: 1;        pointer-events: none;      }    }  }  .inset-bottom {    background: #fff;  }</style>
 |