lxf
2025-07-16 f96f952d95930e1295051c1bfe348dd324ebf878
src/views/cryptos/index.vue
@@ -4,7 +4,7 @@
    <!-- <ioe-swiper /> -->
    <!-- <div class="py-10"> -->
    <!-- <van-notice-bar class="font-26 textColor" left-icon="" :scrollable="false" background="transparent">
      <div slot="left-icon" class=" flex items-center more-img"><img class="w-20 h-20  more-img"
          src="../../assets/Horn.png" alt="">
@@ -17,7 +17,7 @@
          class="w-20 h-20 more-img" src="../../assets/more.png" alt="">
      </div>
    </van-notice-bar> -->
  <!-- </div> -->
    <!-- </div> -->
    <!-- <cry-nav /> -->
    <!-- <div class="quickly">
      <div class="quickBox chongbi" :class="THEME == 'dark' ? 'dark' : 'white'"
@@ -42,13 +42,13 @@
      </div>
    </div> -->
    <!-- <ex-hot :listData="hList"></ex-hot> -->
    <list-quatation :listData="qList" @onfetchQList="fetchQList"/>
    <list-quatation :listData="qList" :hList="filteredHList" @onfetchQList="fetchQList" />
    <van-popup v-model:show="item.showPopUp" style="border-radius:10px;" :close-on-click-overlay="false"
      v-for="item in popupNewsList" :key="item.id">
      <div class="w-350 p-20 box-border">
        <div class="font-700 text-center font-28 textColor">{{ item.title }}</div>
        <div class="flex justify-center mt-30" v-if="item.imgUrl"><img
            :src="`${item.imgUrl}`" class="w-200 h-200" alt="" /></div>
        <div class="flex justify-center mt-30" v-if="item.imgUrl"><img :src="`${item.imgUrl}`" class="w-200 h-200"
            alt="" /></div>
        <div class="py-10 textColor   content-title" v-html="item.content"></div>
        <van-button color="#1194F7" class="w-full h-40 rounded-full" type="info" @click="closePopNotice(item)">
          {{ $t('我知道了') }}
@@ -62,7 +62,7 @@
import IoeSwiper from "@/components/Transform/ioe-swiper/index.vue";
import ListQuatation from "@/components/Transform/list-quotation/index.vue";
import { mapGetters, mapActions } from "vuex";
import { TIME_OUT } from "@/config";
import { TIME_OUT, QUOTE_POLLING_INTERVAL, CACHE_EXPIRE } from "@/config";
import { SET_COIN_LIST } from '@/store/const.store'
import { _getHomeList } from '@/service/cryptos.api'
import ExHeader from "@/components/Transform/ex-header/index.vue";
@@ -73,7 +73,7 @@
import { _getUnreadMsg } from '@/service/im.api'
import { _getNewsList1, _getPopupNews } from '@/service/user.api'
import { BASE_URL } from "@/config";
import { _getCoinList } from '@/service/quotes.api';
import { _getCoinList } from '@/service/quotes.api';
const THEME = 'dark'
export default {
  name: "HomePage",
@@ -87,6 +87,14 @@
    [Swipe.name]: Swipe,
    [SwipeItem.name]: SwipeItem,
  },
  watch: {
    hotArr(newVal) {
      // 当热门币种列表更新时重新计算hList
      if (this.qList && newVal.length) {
        this.hList = this.qList.filter(item => newVal.includes(item.symbol)).slice(0, 3);
      }
    }
  },
  async created() {
    this.init();
    this.checkingMesk();
@@ -94,6 +102,17 @@
    await this.fetchQList()
  },
  computed: {
    // 优化:使用计算属性高效生成热门列表
    filteredHList() {
      const result = [];
      for (const item of this.qList) {
        if (this.hotArr.includes(item.symbol)) {
          result.push(item);
          if (result.length >= 3) break;
        }
      }
      return result;
    },
    ...mapGetters({
      coinList: 'home/coinList',
      currency: 'home/currency',
@@ -103,19 +122,20 @@
    }),
  },
  data() {
    const arr = [] // 初始化数据
    for (let i = 0; i < 10; i++) {
      arr.push({ id: i })
    }
    // 优先从localStorage加载缓存数据
    const cachedData = getStorage('qoutes');
    const now = Date.now();
    const isCacheValid = cachedData && cachedData.timestamp && (now - cachedData.timestamp < CACHE_EXPIRE);
    return {
      BASE_URL,
      THEME,
      account: "",
      hList: arr.slice(0, 3), // 热门
      qList: arr, // 行情列表
      qList: isCacheValid ? cachedData.data : [], // 行情列表 - 优先使用缓存
      active: 0,
      timeout: null,
      loading: true,
      loading: !isCacheValid, // 有缓存数据时不显示加载状态
      announceTitle: '',
      announceId: '',
      announceList: [],
@@ -135,61 +155,79 @@
      })
    },
    async fetchQList(v) { // 获取行情
      let coninArr = ''
      // if (v) { this.getVal = v }
      let arr = getStorage('qoutes')
      // 优化:使用缓存数据快速展示,同时后台更新
      const cachedQuotes = getStorage('quotes');
      if (cachedQuotes && cachedQuotes.data && Date.now() - cachedQuotes.timestamp < CACHE_EXPIRE) {
        this.qList = cachedQuotes.data;
        this.hList = cachedQuotes.data.filter(item => this.hotArr.includes(item.symbol)).slice(0, 3);
        this.loading = false;
        return;
      }
      // 优先用本地缓存的 coins
      let coins = (arr && arr.coins && arr.coins.length) ? arr.coins : arr
      // 优化:变量名修正与符号拼接
      let coinArr = '';
      const arr = getStorage('quotes');
      const coins = (arr && arr.coins && arr.coins.length) ? arr.coins : arr;
      if (coins && coins.length) {
        // 如果本地有 coins,优先用本地
        coins.forEach(item => {
          coninArr += item.symbol + ','
        })
        // 优化:使用map和join提升性能
        coinArr = coins.map(item => item.symbol).join(',');
      } else {
        // 如果本地没有 coins,拉取接口
        const quotesData = await _getCoinList()
        if (quotesData && quotesData.coins && quotesData.coins.length) {
          quotesData.coins.forEach(item => {
            coninArr += item.symbol + ','
          })
        const quotesData = await _getCoinList().catch(err => {
          console.error('获取币种列表失败:', err);
          this.loading = false; // 错误状态处理
          return null;
        });
        if (quotesData?.coins?.length) {
          coinArr = quotesData.coins.map(item => item.symbol).join(',');
        }
      }
      console.log('fetchQList', v, coninArr)
      // if()
      const list = await _getHomeList(coninArr).catch(() => {
        //请求失败时,1秒后重试
        this.timeout = setTimeout(() => {
          this.fetchQList()
        }, 1000)
      })
      if (!(list instanceof Array)) {
        return
      }
      // console.log('接口:_getHomeList 热门:',list)
      this.loading = false
      // this.qList = list.slice(0,10);
      this.qList = list;
      const list = await _getHomeList(coinArr).catch(err => {
        console.error('获取行情列表失败:', err);
        this.loading = false;
        return [];
      });
      //请求失败时,1秒后重试
      this.timeout = setTimeout(() => {
        this.fetchQList();
      }, 1000);
      this.hList = list.filter(item => this.hotArr.includes(item.symbol));
      if (this.hList.length == 4) {
        this.hList.pop()
      // console.log('接口:_getHomeList 热门:',list)
      this.loading = false;
      // 优化:仅在获取有效数据时更新
      if (list.length) {
        // 冻结数据减少响应式开销提升性能
        this.qList = Object.freeze(list);
        setStorage('quotes', { data: list, timestamp: Date.now() });
      }
      console.log(this.hList)
      if (this.timeout) {
        clearTimeout(this.timeout)
      }
      // 检查缓存是否有效
      const cacheData = getStorage('quotes');
      const now = Date.now();
      const isCacheValid = cacheData && cacheData.timestamp && (now - cacheData.timestamp < CACHE_EXPIRE);
      this.timeout = setTimeout(async () => {
        await this.fetchQList()
      }, TIME_OUT)
        // 如果缓存有效则直接使用缓存数据
        // if (isCacheValid) {
        //   this.qList = cacheData.data;
        //   this.hList = cacheData.data.filter(item => this.hotArr.includes(item.symbol));
        //   if (this.hList.length === 4) this.hList.pop();
        // } else {
        await this.fetchQList();
        // }
      }, QUOTE_POLLING_INTERVAL);
    },
    getNews() {
      _getNewsList1({
        language: this.$i18n.locale,
      }).then(res => {
        this.announceList = res
      })
        this.announceList = res;
      });
    },
    getPopupNews() {
      _getPopupNews({
@@ -200,62 +238,70 @@
          if (!getStorage('popNotice')) {
            let list = res
            list.forEach(item => {
              item.showPopUp = true
            })
              item.showPopUp = true;
            });
            this.popupNewsList = list
          }
        }
      })
    },
    closePopNotice(item) {
      item.showPopUp = false
      setStorage('popNotice', true)
      item.showPopUp = false;
      setStorage('popNotice', true);
    },
    toAnnounceDetail(announceId) {
      if (announceId) {
        this.$router.push({ path: '/cryptos/AnnounceDetail', query: { id: announceId } })
        this.$router.push({ path: '/cryptos/AnnounceDetail', query: { id: announceId } });
      }
    },
    onClickLeft() { },
    onClickRight() { },
    startTimeout() {
      this.clearTimeout()
      this.fetchQList()
      this.clearTimeout();
      this.fetchQList();
    },
    clearTimeout() {
      if (this.timeout) {
        clearTimeout(this.timeout)
        this.timeout = null
        clearTimeout(this.timeout);
        this.timeout = null;
      }
    }
  },
  async created() {
    this.getNews();
    this.getPopupNews()
    await this.SET_COIN_LIST('cryptos')
    this.startTimeout()
    this.getPopupNews();
    this.startTimeout(); // 优先执行缓存加载
    await this.SET_COIN_LIST('cryptos');
    // 缓存已加载,重新计算hList
    if (this.qList && this.qList.length) {
      this.hList = this.qList.filter(item => this.hotArr.includes(item.symbol)).slice(0, 3);
    }
  },
  async activated() {
    this.getNews()
    this.getPopupNews()
    await this.SET_COIN_LIST('cryptos')
    this.startTimeout()
    this.getNews();
    this.getPopupNews();
    this.startTimeout(); // 优先执行缓存加载
    await this.SET_COIN_LIST('cryptos');
    // 缓存已加载,重新计算hList
    if (this.qList && this.qList.length) {
      this.hList = this.qList.filter(item => this.hotArr.includes(item.symbol)).slice(0, 3);
    }
    if (this.userInfo.token) {
      this.fetchUnread()
      this.unreadMsg_timer = setInterval(() => { this.fetchUnread() }, 5000);
      this.fetchUnread();
      this.unreadMsg_timer = setInterval(() => { this.fetchUnread(); }, 5000);
    } else {
      this.unreadMsg_num = ''
      this.unreadMsg_num = '';
    }
  },
  deactivated() {
    this.clearTimeout()
    this.clearTimeout();
    if (this.unreadMsg_timer) {
      clearInterval(this.unreadMsg_timer);
      this.unreadMsg_timer = null;
    }
  },
  beforeUnmount() {
    this.clearTimeout()
    this.clearTimeout();
    if (this.unreadMsg_timer) {
      clearInterval(this.unreadMsg_timer);
      this.unreadMsg_timer = null;
@@ -336,7 +382,8 @@
    }
    span {
      color: $text_color1;;
      color: $text_color1;
      ;
      font-size: 22px;
      line-height: 30px;
    }
@@ -485,7 +532,8 @@
  height: 40px !important;
  margin-top: 8px;
}
.content-title{
  font-size: 28px;
.content-title {
  font-size: 28px;
}
</style>