<template>
|
<div class="home">
|
<!-- <ex-header :unread_num="`${unreadMsg_num}`"></ex-header> -->
|
<!-- <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="">
|
</div>
|
<van-swipe vertical class="notice-swipe" :autoplay="2000" :show-indicators="false">
|
<van-swipe-item v-for="item in announceList" :key="item.id" @click="toAnnounceDetail(item.uuid)">{{ item.title }}
|
</van-swipe-item>
|
</van-swipe>
|
<div class="ml-20 flex items-center " slot="right-icon" @click.stop="$router.push('/cryptos/announce')"><img
|
class="w-20 h-20 more-img" src="../../assets/more.png" alt="">
|
</div>
|
</van-notice-bar> -->
|
<!-- </div> -->
|
<!-- <cry-nav /> -->
|
<!-- <div class="quickly">
|
<div class="quickBox chongbi" :class="THEME == 'dark' ? 'dark' : 'white'"
|
@click="$router.push('/cryptos/recharge/rechargeList')">
|
<div class="left">
|
<div class="leftBox"><img src="@/assets/theme/dark/image/chongicon.png" alt=""></div>
|
<div class="leftCont">
|
<p style="max-width:100px;">{{ $t("快捷充币") }}</p>
|
</div>
|
</div>
|
<div class="right"><img src="@/assets/theme/dark/image/goto.png" alt=""></div>
|
</div>
|
<div class="quickBox tibi ml-40" :class="THEME == 'dark' ? 'dark' : 'white'"
|
@click="$router.push('/cryptos/withdraw/withdrawPage')">
|
<div class="left">
|
<div class="leftBox"><img src="@/assets/theme/dark/image/tiicon.png" alt=""></div>
|
<div class="leftCont">
|
<p style="max-width:100px;">{{ $t("快速提币") }}</p>
|
</div>
|
</div>
|
<div class="right"><img src="@/assets/theme/dark/image/goto.png" alt=""></div>
|
</div>
|
</div> -->
|
<!-- <ex-hot :listData="hList"></ex-hot> -->
|
<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="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('我知道了') }}
|
</van-button>
|
</div>
|
</van-popup>
|
</div>
|
</template>
|
<script>
|
import { Popup, Swipe, SwipeItem } from "vant";
|
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, 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";
|
import CryNav from "@/components/Transform/cry-nav/index.vue";
|
import ExHot from "@/components/Transform/ex-hot/index.vue";
|
import Axios from '@/service/userCenter'
|
import { setStorage, getStorage } from '@/utils'
|
import { _getUnreadMsg } from '@/service/im.api'
|
import { _getNewsList1, _getPopupNews } from '@/service/user.api'
|
import { BASE_URL } from "@/config";
|
import { _getCoinList } from '@/service/quotes.api';
|
const THEME = 'dark'
|
export default {
|
name: "HomePage",
|
components: {
|
IoeSwiper,
|
ListQuatation,
|
ExHeader,
|
CryNav,
|
ExHot,
|
[Popup.name]: Popup,
|
[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();
|
this.connectWallet()
|
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',
|
coinArr: 'home/coinArr',
|
hotArr: 'home/hotArr',
|
userInfo: 'user/userInfo',
|
}),
|
},
|
data() {
|
// 优先从localStorage加载缓存数据
|
const cachedData = getStorage('qoutes');
|
const now = Date.now();
|
const isCacheValid = cachedData && cachedData.timestamp && (now - cachedData.timestamp < CACHE_EXPIRE);
|
|
return {
|
BASE_URL,
|
THEME,
|
account: "",
|
|
qList: isCacheValid ? cachedData.data : [], // 行情列表 - 优先使用缓存
|
active: 0,
|
timeout: null,
|
loading: !isCacheValid, // 有缓存数据时不显示加载状态
|
announceTitle: '',
|
announceId: '',
|
announceList: [],
|
socket: null,
|
unreadMsg_timer: null,
|
unreadMsg_num: '',
|
popupNewsList: [],
|
getVal: 1,
|
}
|
},
|
methods: {
|
...mapActions('home', [SET_COIN_LIST]),
|
fetchUnread() { // 获取未读
|
_getUnreadMsg().then(unread_num => {
|
this.unreadMsg_num = (unread_num * 1 > 0) ? unread_num * 1 : '';
|
//console.log('\n *** \n'+unread_num*1+'\n *** \n')
|
})
|
},
|
async fetchQList(v) { // 获取行情
|
// 优化:使用缓存数据快速展示,同时后台更新
|
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;
|
}
|
|
// 优化:变量名修正与符号拼接
|
let coinArr = '';
|
const arr = getStorage('quotes');
|
const coins = (arr && arr.coins && arr.coins.length) ? arr.coins : arr;
|
|
if (coins && coins.length) {
|
// 优化:使用map和join提升性能
|
coinArr = coins.map(item => item.symbol).join(',');
|
} else {
|
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(',');
|
}
|
}
|
// if()
|
const list = await _getHomeList(coinArr).catch(err => {
|
console.error('获取行情列表失败:', err);
|
this.loading = false;
|
return [];
|
});
|
//请求失败时,1秒后重试
|
this.timeout = setTimeout(() => {
|
this.fetchQList();
|
}, 1000);
|
|
// console.log('接口:_getHomeList 热门:',list)
|
this.loading = false;
|
|
// 优化:仅在获取有效数据时更新
|
if (list.length) {
|
// 冻结数据减少响应式开销提升性能
|
this.qList = Object.freeze(list);
|
setStorage('quotes', { data: list, timestamp: Date.now() });
|
}
|
|
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 () => {
|
// 如果缓存有效则直接使用缓存数据
|
// 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;
|
});
|
},
|
getPopupNews() {
|
_getPopupNews({
|
token: this.userInfo.token,
|
language: this.$i18n.locale,
|
}).then(res => {
|
if (res.length) {
|
if (!getStorage('popNotice')) {
|
let list = res
|
list.forEach(item => {
|
item.showPopUp = true;
|
});
|
this.popupNewsList = list
|
}
|
}
|
})
|
},
|
closePopNotice(item) {
|
item.showPopUp = false;
|
setStorage('popNotice', true);
|
},
|
toAnnounceDetail(announceId) {
|
if (announceId) {
|
this.$router.push({ path: '/cryptos/AnnounceDetail', query: { id: announceId } });
|
}
|
},
|
onClickLeft() { },
|
onClickRight() { },
|
startTimeout() {
|
this.clearTimeout();
|
this.fetchQList();
|
},
|
clearTimeout() {
|
if (this.timeout) {
|
clearTimeout(this.timeout);
|
this.timeout = null;
|
}
|
}
|
},
|
async created() {
|
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);
|
}
|
},
|
async activated() {
|
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);
|
} else {
|
this.unreadMsg_num = '';
|
}
|
},
|
deactivated() {
|
this.clearTimeout();
|
if (this.unreadMsg_timer) {
|
clearInterval(this.unreadMsg_timer);
|
this.unreadMsg_timer = null;
|
}
|
},
|
beforeUnmount() {
|
this.clearTimeout();
|
if (this.unreadMsg_timer) {
|
clearInterval(this.unreadMsg_timer);
|
this.unreadMsg_timer = null;
|
}
|
},
|
};
|
</script>
|
<style lang="scss" scoped>
|
:deep(.van-notice-bar__content) {
|
width: 100%;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.home {
|
width: 100%;
|
box-sizing: border-box;
|
padding: 16px 16px 108px;
|
}
|
|
.box {
|
width: 100px;
|
height: 100px;
|
background: red;
|
font-size: 25px;
|
}
|
|
.van-notice-bar {
|
padding: 0;
|
}
|
|
.notice-swipe {
|
flex: 1;
|
height: 82px;
|
line-height: 82px;
|
margin-top: 20px;
|
margin-left: 10px;
|
}
|
|
.buyBox {
|
background: $cont_background;
|
width: 100%;
|
height: 132px;
|
border-radius: 10px;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding-left: 43px;
|
padding-right: 40px;
|
margin-bottom: 44px;
|
box-sizing: border-box;
|
|
.left {
|
display: flex;
|
align-items: center;
|
flex: 1;
|
|
.leftBox {
|
width: 104px;
|
height: 88px;
|
|
img {
|
width: 100%;
|
height: 100%;
|
}
|
}
|
}
|
|
.leftCont {
|
margin-left: 40px;
|
|
p {
|
font-size: 30px;
|
color: #21262F;
|
font-weight: 600;
|
line-height: 36px;
|
}
|
|
span {
|
color: $text_color1;
|
;
|
font-size: 22px;
|
line-height: 30px;
|
}
|
}
|
|
.right {
|
width: 53px;
|
height: 53px;
|
|
img {
|
width: 100%;
|
height: 100%;
|
}
|
}
|
}
|
|
|
#cryptos .quickly {
|
width: 100%;
|
height: 144px;
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 32px;
|
|
.quickBox {
|
width: 360px;
|
height: 100%;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding-right: 40px;
|
padding-left: 16px;
|
|
.left {
|
display: flex;
|
align-items: center;
|
flex: 1;
|
|
.leftBox {
|
width: 100px;
|
height: 100px;
|
|
img {
|
width: 100%;
|
height: 100%;
|
}
|
}
|
}
|
|
.leftCont {
|
margin-left: 24px;
|
|
p {
|
font-size: 24px;
|
color: $text_color;
|
font-weight: 600;
|
line-height: 36px;
|
}
|
}
|
|
.right {
|
width: 48px;
|
height: 48px;
|
|
img {
|
width: 100%;
|
height: 100%;
|
}
|
}
|
}
|
|
.chongbi {
|
background: url('@/assets/theme/white/image/chongb.png');
|
background-size: cover;
|
|
&.dark {
|
background: url('@/assets/theme/dark/image/chongb.png');
|
background-size: cover;
|
}
|
}
|
|
.tibi {
|
background: url('@/assets/theme/white/image/tib.png');
|
background-size: cover;
|
|
&.dark {
|
background: url('@/assets/theme/dark/image/tib.png');
|
background-size: cover;
|
}
|
}
|
}
|
|
.addBox {
|
border-radius: 10px;
|
width: 540px;
|
height: 200px;
|
font-size: 15px;
|
background: $text_color;
|
position: fixed;
|
bottom: 70px;
|
left: 50%;
|
margin-left: -270px;
|
z-index: 1000;
|
|
.add {
|
padding: 30px;
|
box-sizing: border-box;
|
height: 100%;
|
position: relative;
|
color: $main_background;
|
|
.closeAdd {
|
position: absolute;
|
right: 10px;
|
top: 10px;
|
}
|
|
.jiao {
|
position: absolute;
|
bottom: -76px;
|
width: 0;
|
height: 0;
|
left: 240px;
|
border: 30px solid transparent;
|
border-top: 50px solid $text_color;
|
}
|
}
|
|
}
|
|
.van-notice-bar {
|
height: 60px;
|
}
|
|
.notice-swipe {
|
height: 60px;
|
line-height: 60px;
|
}
|
|
.van-swipe-item {
|
font-size: 30px;
|
}
|
|
.more-img {
|
width: 40px !important;
|
height: 40px !important;
|
margin-top: 8px;
|
}
|
|
.content-title {
|
font-size: 28px;
|
}
|
</style>
|