LiveAttention.vue 11.9 KB
<template>
  <div>
    <template v-for="(game_list, i) in cacheDate">
      <transition name="slideInRight" v-if="game_list" :key="game_list">
        <PullRefresh v-show="i == attentionIndex" v-model="is_Refresh" @refresh="getAttentionList">
          <List id="liveAttention" ref="liveAttention" :loading="is_loading" :finished="is_finished" finished-text="没有更多了"
            :style="{ 'min-height': minHigeht + 'px' }">
            <template v-for="(item, index) in game_list" :key="item">
              <div v-if="item.status == 8 && (game_list[index - 1] && game_list[index - 1].status != 8 || !game_list[index - 1])" class="separator">
                ———&nbsp;&nbsp;&nbsp;已结束&nbsp;&nbsp;&nbsp;———
              </div>
              <Match v-if="matchShow(i, index)" class="match-box" :data="item" :note="matchNote(item.id)" :otherData="matchOtherData(item.id)"
                @domHeight="changeCacheHeight" @showMore="changeShowMore" :isShow="showMore == item.id">
              </Match>
              <div v-else-if="cacheHeight[item.id]" :style="{ height: cacheHeight[item.id] + 'px' }"></div>
              <div v-else></div>
            </template>
          </List>
        </PullRefresh>
      </transition>
    </template>
  </div>
</template>

<script lang="ts">export default { name: 'LiveAttention' };</script>
<script lang="ts" setup>
import { ref, toRef, watch, computed, onBeforeMount, onActivated, onDeactivated, defineProps } from 'vue';
import { useStore } from 'vuex';
import { default as _ } from 'lodash';
import { List, PullRefresh } from 'vant';
import Match from './component/Match.vue';
import moment from 'moment';
import { nm_match_attention_list } from '@/api/live_api';

const store: any = useStore();
const is_first = ref(true);
const is_loading = ref(false);
const is_Refresh = ref(false);
const is_finished = ref(false);
const defaultTimeDay = moment(store.state.server_time).format('YYYY-MM-DD');

// 过滤
const props: any = defineProps({
  attentionIndex: {
    type: Number,
    required: true,
    default: () => { return 4; }
  }
});
const attentionIndex: any = toRef(props, 'attentionIndex');

const getAttentionList = async () => {
  if (is_first.value) is_loading.value = true;
  else is_Refresh.value = true;
  is_finished.value = false;
  try {
    let matchListAttention = _.clone(store.state.match_list_attention) || {};
    let match_date: any = moment(defaultTimeDay).add(attentionIndex.value - 4, 'days').format('YYYY-MM-DD');
    let data: any = await nm_match_attention_list({ match_date });
    if (data.data.data.nm_match_attention_list.Result) {
      matchListAttention[match_date] = data.data.data.nm_match_attention_list.Result;
      store.commit('updateMatchListAttention', matchListAttention);
    }
    if (is_first.value) is_loading.value = false;
    else is_Refresh.value = false;
    is_finished.value = true;
    is_first.value = false;
  } catch (error) {
    if (is_first.value) is_loading.value = false;
    else is_Refresh.value = false;
    is_finished.value = true;
    is_first.value = false;
  }
};

watch(() => attentionIndex.value, (newVal: any) => {
  let key: any = moment(defaultTimeDay).add(attentionIndex.value - 4, 'd').format('YYYY-MM-DD');
  if (!store.state.match_list_attention[key]) {
    getAttentionList();
  }
});

const isUnusual = (data: any) => { // 是否异常
  let updateWsTime = store.state.updateWsTime || null;
  let status = data?.status || null;
  let isError = false;
  if (!updateWsTime || !status) return isError;
  // 已到比赛时间但状态未开始 || 进行中的比赛不存在ws数据
  if (updateWsTime > data.match_time && status < 2 || ([2, 3, 4, 5, 6, 7].includes(status) && !store.state.nm_live_message[data.id])) {
    isError = true;
  }
  return isError;
};
const gameSort = (arr: any) => {
  const order_end: any = { 8: 1, 9: 2, 10: 3, 11: 4, 12: 5, 13: 6, 0: 7 };
  return arr.sort((a: any, b: any) => {
    const aSortIndex = order_end[a.status] || 0;
    const bSortIndex = order_end[b.status] || 0;
    return aSortIndex - bSortIndex || a.match_time - b.match_time;
  });
};
const match_list_attention = computed(() => { return _.clone(store.state.match_list_attention); });
const high_light = computed(() => { return store.state.high_light; });
const set_config = computed(() => { return store.state.set_config; });
const cacheDate = computed(() => {
  let arr: any = [[], [], [], [], []];
  for (let a = 0; a < arr.length; a++) {
    let key = moment(defaultTimeDay).add(a - 4, 'days').format('YYYY-MM-DD');
    let list = match_list_attention.value[key] || [];
    for (let i = 0; i < list.length; i++) {
      let item = list[i];
      if (item && !isUnusual(item)) {
        if (set_config.value.type == 'all' || set_config.value.type == 'jz' && item.is_jingcai) {
          if (high_light.value['score'][item.id] && set_config.value.goal) {
            item.is_hl = true;
            item.ranksBackground = high_light.value['score'][item.id].ranksBackground;
          } else if (high_light.value['red'][item.id] && set_config.value.red) {
            item.is_hl = true;
            item.ranksBackground = high_light.value['red'][item.id].ranksBackground;
          } else if (high_light.value['yellow'][item.id] && set_config.value.yellow) {
            item.is_hl = true;
            item.ranksBackground = high_light.value['yellow'][item.id].ranksBackground;
          } else {
            item.is_hl = false;
          }
        }
      }
    }
    arr[a] = gameSort(list);
  }
  return arr;
});

// 即时数据
const nm_live_message = computed(() => {
  return store.state.nm_live_message;
});
// 优化
const current = ref([0, 25]);
const c_m_h: any = ref({
  header: 0,
  top: 0,
  center: 0,
  bottom: 0,
  more: 0,
  note: 0,
  paddingBottom: 0,
  finishedText: 0
});
const item_h: any = computed(() => {
  return c_m_h.value.top + c_m_h.value.center + c_m_h.value.bottom + c_m_h.value.paddingBottom;
});
const oldScrollTop: any = ref(0);
const leaveScrollTop: any = ref(0);
const cacheHeight: any = ref({});
const changeCacheHeight: any = (id: any, domHeight: any) => {
  if (cacheHeight.value[id] === domHeight || domHeight < 1) return;
  cacheHeight.value[id] = domHeight;
};
const get_c_m_h = async () => {
  if (c_m_h.value.header < 1) {
    let header: any = document.getElementsByClassName('reserve-box')[0];
    if (header?.offsetHeight > 0) c_m_h.value.header = header?.offsetHeight;
  }
  if (c_m_h.value.top < 1) {
    let top: any = document.getElementsByClassName('match-top')[0];
    if (top?.offsetHeight > 0) c_m_h.value.top = top?.offsetHeight;
  }
  if (c_m_h.value.top < 1) {
    let top: any = document.getElementsByClassName('match-top')[0];
    if (top?.offsetHeight > 0) c_m_h.value.top = top?.offsetHeight;
  }
  if (c_m_h.value.center < 1) {
    let center: any = document.getElementsByClassName('match-center')[0];
    if (center?.offsetHeight > 0) c_m_h.value.center = center?.offsetHeight;
  }
  if (c_m_h.value.bottom < 1) {
    let bottom: any = document.getElementsByClassName('match-bottom')[0];
    if (bottom?.offsetHeight > 0) c_m_h.value.bottom = bottom?.offsetHeight;
  }
  if (c_m_h.value.more < 1) {
    let more: any = document.getElementsByClassName('match-more')[0];
    if (more?.offsetHeight > 0) c_m_h.value.more = more?.offsetHeight;
  }
  if (c_m_h.value.note < 1) {
    let note: any = document.getElementsByClassName('match-note')[0];
    if (note?.offsetHeight > 0) c_m_h.value.note = note?.offsetHeight;
  }
  if (c_m_h.value.finishedText < 1) {
    let finishedText: any = document.getElementsByClassName('van-list__finished-text')[0];
    if (finishedText?.offsetHeight > 0) c_m_h.value.finishedText = finishedText?.offsetHeight;
  }
  if (c_m_h.value.paddingBottom < 1) {
    let item_dom: any = document.getElementsByClassName('match-box')[0];
    if (item_dom && (window as any)?.getComputedStyle(item_dom)?.paddingBottom) {
      c_m_h.value.paddingBottom = Number(window.getComputedStyle(item_dom).paddingBottom.split('px')[0]);
    }
  }
};
const getCurrentIndex = (scrollTop: any) => {
  let list = _.clone(cacheDate.value[attentionIndex.value]);
  let scrollBottom = scrollTop + window.innerHeight;
  if (scrollTop + 200 < window.innerHeight) return [0, 25];
  if (scrollBottom + 200 >= document.body.clientHeight) return [list.length - 25, list.length];
  let top = c_m_h.value.header, topIndex = { isEnd: false, index: current.value[0] };
  let bottom = c_m_h.value.header, bottomIndex = { isEnd: false, index: current.value[1] };
  list.forEach((item: any, index: any) => {
    if (top < scrollTop) {
      top += cacheHeight[item.id] || item_h.value;
    } else if (!topIndex.isEnd) {
      topIndex.index = (index - 10) < 0 ? 0 : index - 10;
      topIndex.isEnd = true;
    }
    if (bottom < scrollBottom) {
      bottom += cacheHeight[item.id] || item_h.value;
    } else if (!bottomIndex.isEnd) {
      bottomIndex.index = (index + 10) > list.length ? list.length : index + 10;
      bottomIndex.isEnd = true;
    }
    if (topIndex.isEnd && bottomIndex.isEnd) return;
  });
  let indexTop = topIndex.index > (list.length - 25) ? list.length - 25 : topIndex.index;
  let indexBottom = bottomIndex.index < 25 ? 25 : bottomIndex.index;
  return [indexTop, indexBottom];
};
const attentionScrollEvent = () => {
  let scrollTop: any = document.documentElement.scrollTop;
  if (oldScrollTop.value > 0 && Math.abs(oldScrollTop.value - scrollTop) < 80) return;
  oldScrollTop.value = scrollTop;
  get_c_m_h();
  current.value = getCurrentIndex(scrollTop);
};
const attentionScrollInit = async () => { // 重置
  c_m_h.value = {
    header: 0,
    top: 0,
    center: 0,
    bottom: 0,
    more: 0,
    note: 0,
    paddingBottom: 0,
    finishedText: 0
  };
  cacheHeight.value = {};
  oldScrollTop.value = 0;
};
// match组件传参
const matchShow = (i: any, index: any) => {
  return i == attentionIndex.value && index >= current.value[0] && index < current.value[1];
};
const matchOtherData = (id: any) => {
  return nm_live_message.value[id]?.stats;
};
const matchNote = (id: any) => {
  return nm_live_message.value[id]?.score[5];
};
const showMore: any = ref(null);
const changeShowMore: any = (id: any, is: any) => {
  if (!showMore.value || showMore.value != id) {
    showMore.value = id;
  } else {
    showMore.value = null;
  }
};

// 列表最小高度(下拉刷新优化)
const minHigeht = computed(() => {
  return window.innerHeight - c_m_h.value.header;
});

// loading显示方式
watch(() => store.state.init, (newVal: any) => {
  if (newVal) {
    if (is_first.value) is_loading.value = false;
    else is_Refresh.value = false;
    is_finished.value = true;
    is_first.value = false;
  } else {
    if (is_first.value) is_loading.value = true;
    else is_Refresh.value = true;
    is_finished.value = false;
  }
});

// 页面创建前
onBeforeMount(async () => {
  let key: any = moment(defaultTimeDay).add(attentionIndex.value - 4, 'd').format('YYYY-MM-DD');
  if (!store.state.match_list_attention[key]) {
    await getAttentionList();
  } else {
    if (is_first.value) is_loading.value = false;
    else is_Refresh.value = false;
    is_finished.value = true;
    is_first.value = false;
  }
});
// 页面显示
onActivated(() => {
  oldScrollTop.value = 0;
  window.addEventListener('scroll', attentionScrollEvent);
  window.addEventListener('resize', attentionScrollInit);
  // 滚动条复位:设置延迟,避免动画效果影响
  let timer: any = setTimeout(() => {
    window.scrollTo({ top: leaveScrollTop.value });
    clearTimeout(timer);
    timer = null;
  }, 300);
});
// 页面隐藏
onDeactivated(() => {
  window.removeEventListener('scroll', attentionScrollEvent);
  window.removeEventListener('resize', attentionScrollInit);
  leaveScrollTop.value = document.documentElement.scrollTop;
});
</script>

<style lang="scss" scoped>
#liveAttention {
  padding: 5px 2px 0 2px;

  >div {
    padding-bottom: 5px;
    min-height: 103px;
  }

  .separator {
    color: #969799;
    font-size: 14px;
    height: 35px;
    min-height: 35px;
    line-height: 35px;
    padding-bottom: 5px;
  }
}
</style>