| | |
| | | <template> |
| | | <div class="home_page"> |
| | | <div class="home_page textColor" style="background-color: #f6f5fa;"> |
| | | |
| | | <Head></Head> |
| | | <div class="home_logo flex justify-center"><img src="@/assets/imgs/home/home_logo.png" alt=""></div> |
| | | <div class="text-center font-bold mt-8 logo_text">{{ $t('复制财富,從此刻開始') }}</div> |
| | | <div class="text-center mt-2 logo_text_small">{{ $t('超6000種熱門交易類別,立即註冊领取5000USDT') }}!</div> |
| | | <Head @search="onSearch"></Head> |
| | | <!-- <div class="home_logo flex justify-center"><img src="@/assets/imgs/home/home_logo.png" alt=""></div> --> |
| | | <!-- <van-swipe class="home_logo" :autoplay="3000" indicator-color="white"> |
| | | <van-swipe-item><img src="@/assets/imgs/home/Slider-1.jpg" alt=""></van-swipe-item> |
| | | <van-swipe-item><img src="@/assets/imgs/home/Slider-2.jpg" alt=""></van-swipe-item> |
| | | <van-swipe-item><img src="@/assets/imgs/home/Slider-3.jpg" alt=""></van-swipe-item> |
| | | <van-swipe-item><img src="@/assets/imgs/home/Slider-4.jpg" alt=""></van-swipe-item> |
| | | </van-swipe> --> |
| | | <div class="flex flex-col items-center justify-center home-kyc-block" @click="toPage('/certificationCenter')"> |
| | | <img style="width: 100%;border-radius: 10px;" src="@/assets/imgs/new/kyc-reward.png" alt=""> |
| | | <!-- <div style="font-size: 25px;">{{ $t('kycLotteryBroadcast') }}</div> |
| | | <div style="font-size: 12px;">{{ $t('kycLotterySubtitle') }}</div> --> |
| | | </div> |
| | | <!-- <video autoplay loop muted playsinline class="home_logo"> --> |
| | | <!-- <source src="@/assets/video/home_1.mp4" type="video/mp4"> --> |
| | | <!-- </video> --> |
| | | |
| | | <!-- <div class="text-center font-bold mt-8 logo_text">{{ $t('复制财富,從此刻開始') }}</div> |
| | | <div class="text-center mt-2 logo_text_small">{{ $t('超6000種熱門交易類別,立即註冊领取5000USDT') }}!</div> --> |
| | | |
| | | |
| | | <div class="login_buts flex justify-between pl-10 pr-10 pt-10" |
| | |
| | | <div class="login_but_d text-center" @click="toPage('/login')">{{ $t('登录') }}</div> |
| | | </div> |
| | | |
| | | <div class="home_grid flex justify-between flex-wrap"> |
| | | <div class="grid_item pt-10" v-for="value in tabbers" :key="value.key" @click="toPage(value.path)"> |
| | | <!-- 轮播图:使用本地两张图片,带圆角 --> |
| | | <div class="home_banner mp-20"> |
| | | <van-swipe |
| | | class="home_banner_swipe" |
| | | :autoplay="4000" |
| | | :show-indicators="false" |
| | | @change="onBannerChange" |
| | | > |
| | | <van-swipe-item |
| | | v-for="(item, index) in bannerImages" |
| | | :key="index" |
| | | class="home_banner_item" |
| | | @click="onBannerClick(item)" |
| | | > |
| | | <img :src="item.img" :alt="item.alt" class="home_banner_img" /> |
| | | </van-swipe-item> |
| | | </van-swipe> |
| | | <div class="home_banner_indicator"> |
| | | <span |
| | | v-for="(_, i) in bannerImages" |
| | | :key="i" |
| | | class="home_banner_dot" |
| | | :class="{ active: currentBanner === i }" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div class="home_grid flex justify-start flex-wrap home_grid_bg mt-10 pt-8" style="height: 110px;"> |
| | | <div class="grid_item" v-for="value in tabbers" :key="value.key" @click="onGridClick(value)"> |
| | | <div class="grid_item_img flex justify-center"><img :src="value.icon" alt=""></div> |
| | | <div class="text-center mt-2">{{ value.name }}</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <van-notice-bar class="font-26 mt-10 index_notice" background="#fafbfc" :scrollable="false" wrapable |
| | | color="#333333"> |
| | | <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)"> |
| | | <div class="flex justify-start items-center"> |
| | | <img :src="item.imgUrl" alt="" class="notice_img mr-5"> |
| | | <div class="notice_content"> |
| | | <div>{{ item.startTime }}</div> |
| | | <div>{{ item.title }}</div> |
| | | </div> |
| | | </div> |
| | | </van-swipe-item> |
| | | </van-swipe> |
| | | </van-notice-bar> |
| | | |
| | | <!-- <div class="flex justify-between mt-10"> |
| | | <van-swipe class="home_swipe_1" :autoplay="2000"> |
| | | <van-swipe-item v-for="value in swipe1" :key="value.key" class="flex justify-center items-center"> |
| | |
| | | </div> |
| | | </div> --> |
| | | |
| | | <div id="cryptos" class="pt-10"> |
| | | <list-quatation :listData="qList" :tabShow="false" /> |
| | | <!-- 列表区:Favorites / Markets 切换 --> |
| | | <div id="cryptos" class="pt-10 home-list-section"> |
| | | <div class="home-list-tabs"> |
| | | <span class="home-list-tab" :class="{ active: listMode === 'favorites' }" @click="listMode = 'favorites'">{{ $t('favorites') }}</span> |
| | | <span class="home-list-tab" :class="{ active: listMode === 'markets' }" @click="listMode = 'markets'">{{ $t('markets') }}</span> |
| | | </div> |
| | | <list-quatation :listData="displayedList" :tabShow="false" :tabActive="2" /> |
| | | <div |
| | | v-if="!showMoreList && currentList.length > listInitialCount" |
| | | class="home-list-more" |
| | | @click="showMoreList = true" |
| | | > |
| | | {{ $t('展示更多') }} |
| | | </div> |
| | | |
| | | <!-- HOT COINS:横向滚动卡片 --> |
| | | <div class="home-hot-coins"> |
| | | <div class="home-hot-title">{{ $t('HOT COINS') }}</div> |
| | | <div class="home-hot-subtitle">{{ $t('The popular cryptocurrency') }}</div> |
| | | <div class="home-hot-scroll"> |
| | | <div |
| | | v-for="item in hotCoinsList" |
| | | :key="item.symbol_data" |
| | | class="home-hot-card" |
| | | @click="toQuote(item)" |
| | | > |
| | | <img :src="item.symbol ? `${HOST_URL}/symbol/${item.symbol_data}.png` : ''" alt="" class="home-hot-logo" /> |
| | | <div class="home-hot-symbol">{{ (item.symbol_data || '').toUpperCase() }}</div> |
| | | <div class="home-hot-pct" :class="(item.change_ratio || 0) >= 0 ? 'up' : 'down'"> |
| | | {{ (item.change_ratio || 0) >= 0 ? '↗' : '↘' }} {{ (item.change_ratio != null ? item.change_ratio : 0).toFixed(2) }}% |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- Trend / Follow / News / IPO 切换 --> |
| | | <div class="home-trend-tabs"> |
| | | <span class="home-trend-tab" :class="{ active: trendTab === 'trend' }" @click="trendTab = 'trend'">{{ $t('trend') }}</span> |
| | | <span class="home-trend-tab" :class="{ active: trendTab === 'follow' }" @click="trendTab = 'follow'">{{ $t('follow') }}</span> |
| | | <span class="home-trend-tab" :class="{ active: trendTab === 'news' }" @click="trendTab = 'news'">{{ $t('news') }}</span> |
| | | <span class="home-trend-tab" :class="{ active: trendTab === 'ipo' }" @click="trendTab = 'ipo'">{{ $t('ipo') }}</span> |
| | | </div> |
| | | <!-- Trend:riseBg.jpg 背景 + 3 条数据 --> |
| | | <div v-if="trendTab === 'trend'" class="home-trend-card home-trend-card--bg"> |
| | | <div class="home-trend-card-inner"> |
| | | <div class="home-trend-heading">{{ $t('trend') }}</div> |
| | | <div class="home-trend-subtitle">{{ $t('trendSubtitle') }}</div> |
| | | <div class="home-trend-list"> |
| | | <div |
| | | v-for="item in trendList" |
| | | :key="item.symbol_data" |
| | | class="home-trend-item" |
| | | @click="toQuote(item)" |
| | | > |
| | | <img :src="item.iconUrl || ''" alt="" class="home-trend-logo" /> |
| | | <div class="home-trend-info"> |
| | | <span class="home-trend-name">{{ item.symbol_data }}</span> |
| | | </div> |
| | | <div class="home-trend-right"> |
| | | <span class="home-trend-price">{{ (item.close || 0).toFixed(3) }}</span> |
| | | <span class="home-trend-pct up">↗ {{ (item.change_ratio != null ? item.change_ratio : 0).toFixed(2) }}%</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- News:news!getUsHeadNews.action --> |
| | | <div v-else-if="trendTab === 'news'" class="home-trend-card home-trend-card--news"> |
| | | <div class="home-trend-card-inner"> |
| | | <div class="home-trend-heading home-trend-heading--dark">{{ $t('news') }}</div> |
| | | <div v-if="newsLoading" class="home-trend-card--empty-inner"> |
| | | <van-loading type="spinner" size="24" /> |
| | | <div class="home-empty-text mt-8">{{ $t('加载中...') }}</div> |
| | | </div> |
| | | <div v-else-if="newsListForTab.length" class="home-news-list"> |
| | | <div |
| | | v-for="(item, index) in newsListForTab" |
| | | :key="(item.url || item.uuid) || index" |
| | | class="home-news-item" |
| | | @click="onNewsItemClick(item)" |
| | | > |
| | | <div v-if="item.urlToImage" class="home-news-thumb"> |
| | | <img :src="item.urlToImage" alt="" /> |
| | | </div> |
| | | <div class="home-news-body"> |
| | | <div class="home-news-title textColor">{{ item.title }}</div> |
| | | <div class="home-news-meta"> |
| | | <div class="home-news-date text-grey">{{ item.author }}</div> |
| | | <span class="home-news-detail text-grey">{{ $t('详情') }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-else class="home-trend-card--empty-inner"> |
| | | <img :src="emptyImg" alt="" class="home-empty-img" /> |
| | | <div class="home-empty-text">{{ $t('暂无数据') }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- Follow / IPO:empty.png 暂无数据 --> |
| | | <div v-else class="home-trend-card home-trend-card--empty"> |
| | | <img :src="emptyImg" alt="" class="home-empty-img" /> |
| | | <div class="home-empty-text">{{ $t('暂无数据') }}</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <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 popup_news"> |
| | | <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> |
| | | |
| | | <!-- 新闻详情弹层(站内展示,不跳外链) --> |
| | | <van-popup v-model:show="showNewsDetailPopup" round position="bottom" :style="{ height: '88%' }" class="news-detail-popup"> |
| | | <div class="news-detail-inner" v-if="selectedNewsDetail"> |
| | | <div class="news-detail-drag-bar" /> |
| | | <div class="news-detail-header"> |
| | | <span class="news-detail-source">{{ selectedNewsDetail.sourceName || '' }}</span> |
| | | </div> |
| | | <h2 class="news-detail-title textColor">{{ selectedNewsDetail.title }}</h2> |
| | | <div class="news-detail-img-wrap" v-if="selectedNewsDetail.urlToImage"> |
| | | <img :src="selectedNewsDetail.urlToImage" alt="" class="news-detail-img" /> |
| | | </div> |
| | | <div class="news-detail-content textColor"> |
| | | {{ selectedNewsDetail.description || selectedNewsDetail.content || '' }} |
| | | </div> |
| | | <van-button color="#1194F7" class="news-detail-close" block round @click="showNewsDetailPopup = false"> |
| | | {{ $t('关闭') }} |
| | | </van-button> |
| | | </div> |
| | | </van-popup> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Head from './components/head.vue' |
| | | import { useI18n } from "vue-i18n"; |
| | | import { ref, computed, onBeforeUnmount } from 'vue'; |
| | | import { ref, computed, onMounted, onBeforeUnmount } from 'vue'; |
| | | import { useRouter } from 'vue-router'; |
| | | import ListQuatation from "@/components/Transform/list-quotation/index.vue"; |
| | | import { _getHomeList } from '@/service/cryptos.api' |
| | | import { _getNewsList1, _getPopupNews } from '@/service/user.api' |
| | | import { _getNewsList1, _getPopupNews, _getUsHeadNews } from '@/service/user.api' |
| | | import { useStore } from "vuex"; |
| | | import { TIME_OUT } from "@/config"; |
| | | import { TIME_OUT, HOST_URL } from "@/config"; |
| | | import { useUserStore } from '@/store/user'; |
| | | import { showToast } from 'vant'; |
| | | import { setStorage, getStorage } from '@/utils/index.js'; |
| | | let catchSymbol = getStorage('symbol') |
| | | if (!catchSymbol) { |
| | | setStorage('symbol', 'btcusdt'); |
| | | } |
| | | const userStore = useUserStore() |
| | | |
| | | const { t } = useI18n() |
| | | const router = useRouter() |
| | | const store = useStore(); |
| | | |
| | | const tabbers = [ |
| | | // { key: 1, name: t('跟单'), icon: new URL('@/assets/imgs/home/home_1.png', import.meta.url) }, |
| | | // { key: 2, name: t('储值'), icon: new URL('@/assets/imgs/home/home_2.png', import.meta.url) }, |
| | | // { key: 3, name: `C2C ${t('交易')}`, icon: new URL('@/assets/imgs/home/home_3.png', import.meta.url) }, |
| | | // { key: 4, name: t('邀请好友'), icon: new URL('@/assets/imgs/home/home_4.png', import.meta.url) }, |
| | | { key: 5, name: t('合约'), icon: new URL('@/assets/imgs/home/home_5.png', import.meta.url), path: '/trade/index' }, |
| | | { key: 6, name: t('现货'), icon: new URL('@/assets/imgs/home/home_5.png', import.meta.url), path: '/cryptos/trade/btcusdt' }, |
| | | { key: 7, name: t('提现'), icon: new URL('@/assets/imgs/home/home_6.png', import.meta.url), path: '/exchange/withdraw-usdt' }, |
| | | // { key: 8, name: t('卡券中心'), icon: new URL('@/assets/imgs/home/home_7.png', import.meta.url) }, |
| | | { key: 9, name: t('闪兑'), icon: new URL('@/assets/imgs/home/home_8.png', import.meta.url), path: '/cryptos/exchangePage' }, |
| | | // { key: 10, name: t('更多'), icon: new URL('@/assets/imgs/home/home_9.png', import.meta.url) }, |
| | | { key: 2, name: t('recharge'), icon: new URL('@/assets/imgs/new/quick-function2.png', import.meta.url), path: '/cryptos/recharge/rechargeList?isForeign=true' }, |
| | | { key: 7, name: t('提现'), icon: new URL('@/assets/imgs/new/quick-function1.png', import.meta.url), path: '/cryptos/Withdraw/withdrawPage' }, |
| | | { key: 5, name: t('合约'), icon: new URL('@/assets/imgs/new/index-function5.png', import.meta.url), path: '/trade/index' }, |
| | | { key: 14, name: t('客服'), icon: new URL('@/assets/imgs/new/index-function3.png', import.meta.url), path: '/customerService' }, |
| | | ] |
| | | |
| | | // 获取公告数据 |
| | | // 交易区列表:外汇、股票、ETF(均带图标) |
| | | const tradingList = [ |
| | | { name: t('外汇'), icon: new URL('@/assets/theme/dark/image/nav/trade.png', import.meta.url), path: '/foreign/coinChart?symbol=USDSGD' }, |
| | | { name: t('股票'), icon: new URL('@/assets/theme/dark/image/nav/trade.png', import.meta.url), path: '/quotes/openTrade?tabActive=0&symbol=AAPL&type=US-stocks' }, |
| | | { name: t('ETF'), icon: new URL('@/assets/theme/dark/image/nav/contract.png', import.meta.url), path: '/quotes/openTrade?tabActive=0&symbol=GlobalETF500&type=indices' }, |
| | | ] |
| | | |
| | | // 轮播图:使用本地两张图片(swiper_1、swiper_2 放在 src/assets/imgs/new/ 下) |
| | | const bannerImages = [ |
| | | { img: new URL('@/assets/imgs/new/swiper_1.png', import.meta.url).href, alt: 'Banner 1' }, |
| | | { img: new URL('@/assets/imgs/new/swiper_2.png', import.meta.url).href, alt: 'Banner 2' }, |
| | | ] |
| | | const currentBanner = ref(0) |
| | | const onBannerChange = (index) => { |
| | | currentBanner.value = index |
| | | } |
| | | const onBannerClick = (item) => { |
| | | if (item.link) router.push(item.link) |
| | | } |
| | | |
| | | // 获取公告数据(用作轮播图) |
| | | const announceList = ref([]) |
| | | _getNewsList1({ |
| | | language: useI18n().locale.value, |
| | |
| | | announceList.value = res |
| | | }) |
| | | |
| | | // 获取弹出新闻 |
| | | const popupNewsList = ref([]) |
| | | _getPopupNews({ |
| | | language: useI18n().locale.value, |
| | | }).then(res => { |
| | | if (res && res.length > 0) { |
| | | let list = res |
| | | list.forEach(item => { |
| | | item.showPopUp = true |
| | | }) |
| | | popupNewsList.value = list |
| | | } |
| | | }) |
| | | // 关闭弹窗新闻 |
| | | const closePopNotice = (item) => { |
| | | item.showPopUp = false |
| | | } |
| | | |
| | | // 跳转公告详情 |
| | | const toAnnounceDetail = (announceId) => { |
| | | if (announceId) { |
| | | router.push({ path: '/cryptos/AnnounceDetail', query: { id: announceId } }) |
| | | router.push({ path: '/cryptos/announceDetail', query: { id: announceId } }) |
| | | } |
| | | } |
| | | |
| | | // 新闻项点击:站内弹层展示详情(不跳外链);公告项仍走公告详情页 |
| | | const onNewsItemClick = (item) => { |
| | | if (item && item.url) { |
| | | selectedNewsDetail.value = item |
| | | showNewsDetailPopup.value = true |
| | | } else if (item && item.uuid) { |
| | | toAnnounceDetail(item.uuid) |
| | | } |
| | | } |
| | | |
| | | // 新闻日期展示:ISO 取前 10 位 |
| | | const formatNewsDate = (publishedAt) => { |
| | | if (!publishedAt) return '' |
| | | return String(publishedAt).substring(0, 10) |
| | | } |
| | | |
| | | // 首页四个按钮点击:无 path 时提示暂未开放 |
| | | const onGridClick = (value) => { |
| | | if (!value.path) { |
| | | showToast(t('notOpenYet')); |
| | | return; |
| | | } |
| | | toPage(value.path); |
| | | }; |
| | | |
| | | // 跳转页面 |
| | | const toPage = (path) => { |
| | | if (!path) return |
| | | |
| | | // 如果路径包含 "http",则作为外链跳转 |
| | | if (path && (path.startsWith('http://') || path.startsWith('https://'))) { |
| | | window.open(path, '_blank'); |
| | | return; |
| | | } |
| | | |
| | | router.push(path) |
| | | } |
| | | |
| | |
| | | { key: 3, img: new URL('@/assets/imgs/home/home_3.png', import.meta.url) }, |
| | | ]) |
| | | |
| | | // 列表区:Favorites / Markets 切换 |
| | | const listMode = ref('markets') // 'favorites' | 'markets' |
| | | const listInitialCount = 8 // 竖列表默认展示条数,点击「展示更多」后显示全部 |
| | | const showMoreList = ref(false) |
| | | const favoritesList = ref([ |
| | | { symbol: 'btcusdt', symbol_data: 'BTC', name: 'BTC/USDT', close: 43250.5, change_ratio: 2.18, amount: 12345678 }, |
| | | { symbol: 'ethusdt', symbol_data: 'ETH', name: 'ETH/USDT', close: 2280.2, change_ratio: -0.85, amount: 8765432 }, |
| | | { symbol: 'xrpusdt', symbol_data: 'XRP', name: 'XRP/USDT', close: 0.62, change_ratio: 1.25, amount: 5678901 }, |
| | | ]) |
| | | |
| | | // HOT COINS / Trend 数据(HOT 用 qList 前几条,Trend 用 mock 3 条) |
| | | const hotCoinsList = ref([]) |
| | | // Trend 三条:使用本地图片 a-DOT / a-APT / a-FIL(放在 src/assets/imgs/new/ 下) |
| | | const trendList = ref([ |
| | | { symbol: 'dotusdt', symbol_data: 'DOT', iconUrl: new URL('@/assets/imgs/new/a-DOT.png', import.meta.url).href, name: 'DOT/USDT', close: 1.589, change_ratio: 25.51 }, |
| | | { symbol: 'aptusdt', symbol_data: 'APT', iconUrl: new URL('@/assets/imgs/new/a-APT.png', import.meta.url).href, name: 'APT/USDT', close: 0.958, change_ratio: 14.18 }, |
| | | { symbol: 'filusdt', symbol_data: 'FIL', iconUrl: new URL('@/assets/imgs/new/a-FIL.png', import.meta.url).href, name: 'FIL/USDT', close: 1.005, change_ratio: 12.54 }, |
| | | ]) |
| | | const trendTab = ref('trend') // 'trend' | 'follow' | 'news' | 'ipo' |
| | | const emptyImg = new URL('@/assets/imgs/new/empty.png', import.meta.url).href |
| | | // 新闻 tab:仅使用 news!getUsHeadNews.action 接口数据 |
| | | const newsApiList = ref([]) |
| | | const newsLoading = ref(false) |
| | | const newsListForTab = computed(() => { |
| | | const list = newsApiList.value || [] |
| | | if (list.length === 0) return [] |
| | | return list.map((a) => ({ |
| | | title: a.title || '', |
| | | author: a.author || '', |
| | | publishedAt: a.publishedAt || '', |
| | | url: a.url || '', |
| | | urlToImage: a.urlToImage || '', |
| | | description: a.description || '', |
| | | content: a.content || '', |
| | | sourceName: (a.source && a.source.name) ? a.source.name : '', |
| | | source: a.source, |
| | | })) |
| | | }) |
| | | |
| | | // 新闻详情弹层(站内展示,不跳外链) |
| | | const showNewsDetailPopup = ref(false) |
| | | const selectedNewsDetail = ref(null) |
| | | |
| | | // 首页新闻:在 onMounted 中请求,避免重复请求、便于统一管理 |
| | | function fetchUsHeadNews() { |
| | | if (newsLoading.value) return |
| | | newsLoading.value = true |
| | | _getUsHeadNews() |
| | | .then((list) => { newsApiList.value = list || [] }) |
| | | .finally(() => { newsLoading.value = false }) |
| | | } |
| | | |
| | | // 跳转行情/交易页 |
| | | const toQuote = (item) => { |
| | | if (item && item.symbol) router.push(`/cryptos/trade/${item.symbol}`) |
| | | } |
| | | |
| | | //#region 行情数据---------------------------------------- |
| | | let qList = ref([]) |
| | | let qListCope = ref([]) // 备份数据 |
| | | let key = ref('') // 搜索关键词 |
| | | let timeout = ref(null) |
| | | const coinArr = computed(() => store.getters['home/coinArr']); |
| | | |
| | | // 竖列表:当前数据源与展示条数(展示更多前只显示 5 条) |
| | | const currentList = computed(() => (listMode.value === 'markets' ? qList.value : favoritesList.value)) |
| | | const displayedList = computed(() => { |
| | | const list = currentList.value |
| | | return showMoreList.value ? list : (list || []).slice(0, listInitialCount) |
| | | }) |
| | | |
| | | const fetchQList = async () => { // 获取行情 |
| | | const list = await _getHomeList(coinArr.value.join(',')).catch(() => { |
| | |
| | | if (!(list instanceof Array)) { |
| | | return |
| | | } |
| | | qList.value = list; |
| | | |
| | | // 通过关键字进行筛选 |
| | | if (key.value) { |
| | | qList.value = list.filter(item => { |
| | | return item.symbol_data.toLowerCase().includes(key.value.toLowerCase()) || item.name.toLowerCase().includes(key.value.toLowerCase()) |
| | | }) |
| | | } else { |
| | | qList.value = list |
| | | } |
| | | qListCope.value = list; // 备份数据 |
| | | // HOT COINS 取前 8 条 |
| | | hotCoinsList.value = (list || []).slice(0, 8) |
| | | |
| | | if (timeout.value) { |
| | | clearTimeout(timeout.value) |
| | |
| | | } |
| | | fetchQList() |
| | | |
| | | // 搜索 |
| | | const onSearch = (val) => { |
| | | key.value = val |
| | | |
| | | if (!val) { |
| | | qList.value = qListCope.value |
| | | return |
| | | } |
| | | let newList = qListCope.value.filter(item => { |
| | | return item.symbol_data.toLowerCase().includes(val.toLowerCase()) || item.name.toLowerCase().includes(val.toLowerCase()) |
| | | }) |
| | | qList.value = newList |
| | | } |
| | | |
| | | onMounted(() => { |
| | | fetchUsHeadNews() |
| | | }) |
| | | onBeforeUnmount(() => { |
| | | if (timeout.value) { |
| | | clearInterval(timeout.value) |
| | | clearTimeout(timeout.value) |
| | | } |
| | | }) |
| | | //#endregion---------------------------------------------- |
| | |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | @import '@/assets/theme/index.scss'; |
| | | .mainBackground{ |
| | | background-color: #f6f5fa !important; |
| | | } |
| | | .home-kyc-block { |
| | | cursor: pointer; |
| | | width: 100%; |
| | | } |
| | | .home_page { |
| | | background: $white; |
| | | // background: $white; |
| | | min-height: 100vh; |
| | | width: 100%; |
| | | padding: 1rem 1rem 10rem 1rem; |
| | | // $log-c: #282828; |
| | | $tab-c: #343434; |
| | | $tab-c: #888; |
| | | $inp-c: #999; |
| | | $crd-b: #f7f7f7; |
| | | .popup_news{ |
| | | font-size: 1.8rem; |
| | | } |
| | | |
| | | .index_notice { |
| | | height: 100px; |
| | | border-radius: 10px; |
| | | /* 首页轮播图(BlueWhale 风格) */ |
| | | .home_banner { |
| | | position: relative; |
| | | width: 100%; |
| | | margin: 12px auto; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | background: $crd-b; |
| | | } |
| | | |
| | | .notice-swipe { |
| | | height: 82px; |
| | | } |
| | | .home_banner_swipe { |
| | | width: 100%; |
| | | border-radius: 12px; |
| | | } |
| | | |
| | | .notice_img { |
| | | height: 80px; |
| | | width: 100px; |
| | | // background-color: $icon-bg; |
| | | } |
| | | .home_banner_item { |
| | | width: 100%; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .notice_content { |
| | | &>div:first-child { |
| | | color: $text_color1; |
| | | } |
| | | } |
| | | .home_banner_img { |
| | | width: 100%; |
| | | height: auto; |
| | | display: block; |
| | | vertical-align: top; |
| | | border-radius: 12px; |
| | | } |
| | | |
| | | .home_banner_indicator { |
| | | position: absolute; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 12px; |
| | | display: flex; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | z-index: 2; |
| | | } |
| | | |
| | | .home_banner_dot { |
| | | width: 6px; |
| | | height: 6px; |
| | | border-radius: 3px; |
| | | background: rgba(255, 255, 255, 0.4); |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .home_banner_dot.active { |
| | | width: 16px; |
| | | border-radius: 3px; |
| | | background: #fff; |
| | | } |
| | | |
| | | .home_logo { |
| | | width: 100%; |
| | | width: 48rem; |
| | | margin: 2rem auto 1rem; |
| | | border-radius: 1rem; |
| | | |
| | | img { |
| | | width: 22.5rem; |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | .home_grid { |
| | | width: 100%; |
| | | background-size: 100% 100%; |
| | | background-repeat: no-repeat; |
| | | |
| | | &.home_grid_bg { |
| | | background-image: url('@/assets/imgs/new/index-funbg.png'); |
| | | } |
| | | |
| | | .grid_item { |
| | | width: 24%; |
| | | width: 25%; |
| | | color: $tab-c; |
| | | font-size: 1.6rem; |
| | | |
| | |
| | | width: 100%; |
| | | |
| | | img { |
| | | width: 6.3rem; |
| | | width: 5.8rem; |
| | | } |
| | | } |
| | | } |
| | |
| | | padding: 1.6rem 1.6rem 2rem 1.6rem; |
| | | font-size: 2rem; |
| | | } |
| | | |
| | | /* 列表区 Favorites / Markets 切换(与下方 Trend 等统一样式) */ |
| | | .home-list-section { |
| | | .home-list-tabs { |
| | | display: flex; |
| | | gap: 2.4rem; |
| | | margin-bottom: 1.2rem; |
| | | padding: 0 0.8rem; |
| | | .home-list-tab { |
| | | font-size: 1.8rem; |
| | | color: $tab-c; |
| | | padding: 0.6rem 1.4rem; |
| | | border-radius: 2rem; |
| | | &.active { |
| | | background: #fff; |
| | | color: #000; |
| | | font-weight: 600; |
| | | } |
| | | } |
| | | } |
| | | .home-list-more { |
| | | text-align: center; |
| | | padding: 1.2rem; |
| | | font-size: 2rem; |
| | | color: #1194F7; |
| | | margin-top: 0.8rem; |
| | | } |
| | | } |
| | | |
| | | /* HOT COINS 横向滚动卡片:一屏约 3 个,细体 + 色 #29155a */ |
| | | .home-hot-coins { |
| | | margin-top: 2.4rem; |
| | | .home-hot-title { |
| | | font-size: 2.1rem; |
| | | font-weight: 400; |
| | | color: #29155a; |
| | | margin-bottom: 0.4rem; |
| | | } |
| | | .home-hot-subtitle { |
| | | font-size: 1.5rem; |
| | | font-weight: 400; |
| | | color: #29155a; |
| | | margin-bottom: 1rem; |
| | | opacity: 0.75; |
| | | } |
| | | .home-hot-scroll { |
| | | display: flex; |
| | | gap: 1.4rem; |
| | | overflow-x: auto; |
| | | padding: 0.8rem 0 1.2rem 0; |
| | | -webkit-overflow-scrolling: touch; |
| | | &::-webkit-scrollbar { height: 6px; } |
| | | &::-webkit-scrollbar-thumb { background: #ddd; border-radius: 3px; } |
| | | } |
| | | .home-hot-card { |
| | | flex-shrink: 0; |
| | | width: calc((100vw ) / 3); |
| | | min-width: 10rem; |
| | | padding: 1.4rem 1rem; |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | box-shadow: 0 2px 8px rgba(0,0,0,0.06); |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 0.6rem; |
| | | } |
| | | .home-hot-logo { |
| | | width: 5rem; |
| | | height: 5rem; |
| | | border-radius: 50%; |
| | | } |
| | | .home-hot-symbol { |
| | | font-size: 1.7rem; |
| | | font-weight: 400; |
| | | color: #29155a; |
| | | } |
| | | .home-hot-pct { |
| | | font-size: 1.5rem; |
| | | font-weight: 400; |
| | | &.up { color: #0ecb81; } |
| | | &.down { color: #f6465d; } |
| | | } |
| | | } |
| | | |
| | | /* Trend / Follow / News / IPO 切换:左右内外边距加宽 */ |
| | | .home-trend-tabs { |
| | | display: flex; |
| | | gap: 3rem; |
| | | margin-top: 2.4rem; |
| | | margin-bottom: 1rem; |
| | | padding: 0 1.8rem; |
| | | .home-trend-tab { |
| | | font-size: 1.8rem; |
| | | color: $tab-c; |
| | | padding: 0.8rem 2.2rem; |
| | | border-radius: 2rem; |
| | | &.active { |
| | | background: #fff; |
| | | color: #000; |
| | | font-weight: 600; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .home-trend-card { |
| | | border-radius: 16px; |
| | | overflow: hidden; |
| | | min-height: 200px; |
| | | margin-top: 10px; |
| | | &.home-trend-card--bg { |
| | | background: url('@/assets/imgs/new/riseBg.jpg') no-repeat center/cover; |
| | | background-color: #fff; |
| | | background-size: 100% 100%; |
| | | .home-trend-card-inner { |
| | | padding: 1.6rem; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | .home-trend-heading { |
| | | font-size: 2.8rem; |
| | | color: #fff; |
| | | margin-bottom: 0.4rem; |
| | | margin-top: 30px; |
| | | padding: 0 2rem; |
| | | |
| | | } |
| | | .home-trend-subtitle { |
| | | padding: 0 2rem; |
| | | font-size: 1.5rem; |
| | | color: rgba(255,255,255,0.85); |
| | | margin-bottom: 1.2rem; |
| | | |
| | | } |
| | | .home-trend-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 1rem; |
| | | } |
| | | .home-trend-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1rem; |
| | | padding: 0rem 0rem; |
| | | margin: 0.5rem 2rem; |
| | | border-bottom: 1px solid hsla(0, 0%, 100%, .1); |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | .home-trend-logo { |
| | | width: 3.6rem; |
| | | height: 3.6rem; |
| | | border-radius: 50%; |
| | | } |
| | | .home-trend-info { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 0.2rem; |
| | | } |
| | | .home-trend-name { |
| | | font-size: 1.7rem; |
| | | font-weight: 600; |
| | | color: #fff; |
| | | } |
| | | .home-trend-right { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-end; |
| | | gap: 0.3rem; |
| | | } |
| | | .home-trend-price { |
| | | font-size: 1.5rem; |
| | | color: #fff; |
| | | } |
| | | .home-trend-pct { |
| | | font-size: 1.6rem; |
| | | font-weight: 600; |
| | | color: #0ecb81; |
| | | } |
| | | } |
| | | &.home-trend-card--empty { |
| | | background: #f7f7f7; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 2rem; |
| | | .home-empty-img { |
| | | width: 12rem; |
| | | height: auto; |
| | | margin-bottom: 1rem; |
| | | } |
| | | .home-empty-text { |
| | | font-size: 1.8rem; |
| | | color: $tab-c; |
| | | } |
| | | } |
| | | &.home-trend-card--news { |
| | | background: #fff; |
| | | .home-trend-card-inner { |
| | | padding: 1.6rem 1.8rem; |
| | | } |
| | | .home-trend-heading--dark { |
| | | color: #29155a; |
| | | font-size: 2.2rem; |
| | | margin-top: 0; |
| | | padding: 0; |
| | | } |
| | | .home-news-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 0; |
| | | } |
| | | .home-news-item { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | gap: 1rem; |
| | | padding: 1.2rem 0; |
| | | border-bottom: 1px solid #eee; |
| | | cursor: pointer; |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | .home-news-thumb { |
| | | flex-shrink: 0; |
| | | width: 7.2rem; |
| | | height: 7.2rem; |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | background: #f0f0f0; |
| | | img { |
| | | width: 100%; |
| | | height: 100%; |
| | | object-fit: cover; |
| | | } |
| | | } |
| | | .home-news-body { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | .home-news-title { |
| | | font-size: 1.5rem; |
| | | line-height: 1.4; |
| | | margin-bottom: 0.4rem; |
| | | display: -webkit-box; |
| | | -webkit-line-clamp: 2; |
| | | -webkit-box-orient: vertical; |
| | | overflow: hidden; |
| | | } |
| | | .home-news-meta { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | font-size: 1.2rem; |
| | | gap: 0.5rem; |
| | | } |
| | | .home-news-date { |
| | | flex: 1; |
| | | min-width: 0; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | color: #999; |
| | | } |
| | | .home-news-detail { |
| | | flex-shrink: 0; |
| | | color: #999; |
| | | } |
| | | .home-trend-card--empty-inner { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-height: 160px; |
| | | .home-empty-img { |
| | | width: 10rem; |
| | | height: 10rem; |
| | | } |
| | | .home-empty-text { |
| | | margin-top: 0.8rem; |
| | | font-size: 1.4rem; |
| | | color: #999; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .news-detail-popup { |
| | | .news-detail-inner { |
| | | padding: 0 2rem 2.4rem; |
| | | overflow-y: auto; |
| | | max-height: 100%; |
| | | background: #fff; |
| | | } |
| | | .news-detail-drag-bar { |
| | | width: 3.6rem; |
| | | height: 4px; |
| | | margin: 1rem auto 1.2rem; |
| | | background: #e0e0e0; |
| | | border-radius: 2px; |
| | | } |
| | | .news-detail-header { |
| | | margin-bottom: 0.6rem; |
| | | } |
| | | .news-detail-source { |
| | | font-size: 1.2rem; |
| | | color: #999; |
| | | } |
| | | .news-detail-title { |
| | | font-size: 2rem; |
| | | font-weight: 600; |
| | | line-height: 1.35; |
| | | margin: 0 0 1.4rem; |
| | | color: #1a1a1a; |
| | | } |
| | | .news-detail-img-wrap { |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | margin-bottom: 1.4rem; |
| | | background: #f5f5f5; |
| | | .news-detail-img { |
| | | width: 100%; |
| | | display: block; |
| | | object-fit: cover; |
| | | max-height: 22rem; |
| | | } |
| | | } |
| | | .news-detail-content { |
| | | font-size: 1.45rem; |
| | | line-height: 1.7; |
| | | color: #333; |
| | | white-space: pre-wrap; |
| | | word-break: break-word; |
| | | margin-bottom: 2rem; |
| | | } |
| | | .news-detail-close { |
| | | margin-top: 0.4rem; |
| | | height: 4.4rem; |
| | | font-size: 1.6rem; |
| | | } |
| | | } |
| | | </style> |