| | |
| | | <template> |
| | | <div class="home"> |
| | | <!-- 顶部搜索栏 --> |
| | | <div class="home-page"> |
| | | <!-- Header --> |
| | | <div class="header"> |
| | | <div class="avatar"> |
| | | <Icon icon="carbon:user-avatar" width="24" height="24" /> |
| | | </div> |
| | | <div class="search-box"> |
| | | <Icon icon="ri:search-line" width="20" height="20" color="#999" /> |
| | | <input type="text" :placeholder="$t('搜索.占位符')"> |
| | | <div class="header-left"> |
| | | <img src="@/assets/image/login_logo.png" alt="Wealthinfra" class="logo" /> |
| | | <span class="logo-text">Wealthinfra</span> |
| | | </div> |
| | | <div class="header-right"> |
| | | <Icon icon="material-symbols:headphones" width="24" height="24" /> |
| | | <Icon icon="mdi:bell-outline" width="24" height="24" /> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 新人礼包banner --> |
| | | <div class="gift-banner"> |
| | | <div class="gift-left"> |
| | | <div class="gift-icon"> |
| | | <Icon icon="mdi:gift-outline" width="32" height="32" /> |
| | | <div class="lang-selector" @click="$router.push('/language')"> |
| | | <span class="lang-text">{{ currentLangName }}</span> |
| | | </div> |
| | | <div class="gift-info"> |
| | | <div class="gift-amount">1,000USD {{ $t('新人欢迎.礼包') }}</div> |
| | | <div class="gift-desc">{{ $t('新人欢迎.新用户') }}</div> |
| | | <div class="icon-btn"> |
| | | <img src="@/assets/image/notice.png" alt="notice" /> |
| | | </div> |
| | | <div class="icon-btn" @click="$router.push('/my/index')"> |
| | | <img src="@/assets/image/noticeMore.png" alt="menu" /> |
| | | </div> |
| | | </div> |
| | | <button class="register-btn">{{ $t('新人欢迎.注册') }}</button> |
| | | </div> |
| | | |
| | | <!-- 功能导航 --> |
| | | <div class="nav-section"> |
| | | <div class="nav-item" v-for="(item, index) in navList" :key="index"> |
| | | <Icon :icon="item.icon" width="28" height="28" /> |
| | | <span class="nav-name">{{ item.name }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 广告轮播 --> |
| | | <div class="banner-section"> |
| | | <div class="banner-item"> |
| | | <div class="banner-left"> |
| | | <div class="banner-tag"> |
| | | <Icon icon="ph:fire-bold" color="#ff6b00" width="16" height="16" /> |
| | | {{ $t('活动.热门') }} |
| | | </div> |
| | | <div class="banner-title">JD Trader {{ $t('活动.首次交易') }}</div> |
| | | <button class="join-btn"> |
| | | {{ $t('活动.参与') }} |
| | | <Icon icon="material-symbols:chevron-right" width="16" height="16" /> |
| | | <!-- Hero Banner --> |
| | | <van-swipe class="hero-section" :autoplay="3000" indicator-color="#92D1FF"> |
| | | <!-- 第一张:一应俱全的金融交易体验 --> |
| | | <van-swipe-item> |
| | | <div class="hero-card"> |
| | | <h1 class="hero-title">{{ $t('home.heroTitle1') }}</h1> |
| | | <p class="hero-desc">{{ $t('home.heroFeatures1') }}</p> |
| | | <button class="trade-btn" @click="router.push('/trade/options')"> |
| | | {{ $t('立即交易') }} |
| | | <img src="@/assets/image/but_to.png" alt="play" class="play-icon" /> |
| | | </button> |
| | | <div class="hero-illustration"> |
| | | <div class="device-illustration"> |
| | | <img src="@/assets/image/home/banner_1.png" alt=""> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="banner-right"> |
| | | <img src="@/assets/trader.png" alt="trader"> |
| | | </van-swipe-item> |
| | | |
| | | <!-- 第二张:您可以信赖的经济人 --> |
| | | <van-swipe-item> |
| | | <div class="hero-card"> |
| | | <h1 class="hero-title">{{ $t('home.heroTitle') }}</h1> |
| | | <p class="hero-desc">{{ $t('home.heroDesc') }}</p> |
| | | <button class="trade-btn" @click="router.push('/trade/options')"> |
| | | {{ $t('立即交易') }} |
| | | <img src="@/assets/image/but_to.png" alt="play" class="play-icon" /> |
| | | </button> |
| | | <div class="hero-illustration"> |
| | | <div class="robot-illustration"> |
| | | <img src="@/assets/image/home/banner_2.png" alt=""> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </van-swipe-item> |
| | | |
| | | <!-- 第三张:顶尖交易技术 --> |
| | | <van-swipe-item> |
| | | <div class="hero-card"> |
| | | <h1 class="hero-title">{{ $t('home.heroTitle2') }}</h1> |
| | | <p class="hero-desc">{{ $t('home.heroDesc2') }}</p> |
| | | <button class="trade-btn" @click="router.push('/trade/options')"> |
| | | {{ $t('立即交易') }} |
| | | <img src="@/assets/image/but_to.png" alt="play" class="play-icon" /> |
| | | </button> |
| | | <div class="hero-illustration"> |
| | | <div class="crypto-illustration"> |
| | | <img src="@/assets/image/home/banner_3.png" alt=""> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </van-swipe-item> |
| | | </van-swipe> |
| | | |
| | | <div class="no-more-notice"> |
| | | <img src="@/assets/image/notice.png" alt="bell" /> |
| | | <span>No More</span> |
| | | <img src="@/assets/image/icon-right.png" alt="play" class="arrow" /> |
| | | </div> |
| | | |
| | | <!-- Quick Access --> |
| | | <div class="quick-access"> |
| | | <div class="quick-item" @click="$router.push('/cryptos/recharge/rechargeList?isForeign=true')"> |
| | | <div class="quick-icon"> |
| | | <img src="@/assets/image/cz.png" alt="recharge" /> |
| | | </div> |
| | | <span>{{ $t('recharge') }}</span> |
| | | </div> |
| | | <div class="quick-item" @click="$router.push('/cryptos/withdraw/withdrawPage?type=exchange')"> |
| | | <div class="quick-icon"> |
| | | <img src="@/assets/image/tx.png" alt="withdraw" /> |
| | | </div> |
| | | <span>{{ $t('withdraw') }}</span> |
| | | </div> |
| | | <div class="quick-item" @click="$router.push('/cryptos/loan')"> |
| | | <div class="quick-icon"> |
| | | <img src="@/assets/image/dk.png" alt="loan" /> |
| | | </div> |
| | | <span>{{ $t('home.loan') }}</span> |
| | | </div> |
| | | <div class="quick-item" @click="$router.push('/customerService')"> |
| | | <div class="quick-icon"> |
| | | <img src="@/assets/image/lxkf.png" alt="service" /> |
| | | </div> |
| | | <span>{{ $t('ContactService') }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 市场行情 --> |
| | | <div class="market-section"> |
| | | <div class="market-tabs"> |
| | | <div v-for="tab in marketTabs" :key="tab.id" :class="['tab-item', { active: currentTab === tab.id }]" |
| | | @click="currentTab = tab.id"> |
| | | {{ tab.name }} |
| | | </div> |
| | | </div> |
| | | <div class="market-list"> |
| | | <div class="market-item" v-for="item in marketData" :key="item.code"> |
| | | <div class="stock-info"> |
| | | <div class="stock-name">{{ item.name }}</div> |
| | | <div class="stock-code">{{ item.code }}</div> |
| | | </div> |
| | | <div class="stock-price"> |
| | | <div class="current-price">{{ item.price }}</div> |
| | | <div :class="['price-change', item.change >= 0 ? 'up' : 'down']"> |
| | | {{ item.change >= 0 ? '+' : '' }}{{ item.change }}% |
| | | <!-- Market Overview --> |
| | | <div class="market-overview"> |
| | | <div class="currency-cards"> |
| | | <div class="currency-card" v-for="pair in currencyPairs" :key="pair.symbol" |
| | | @click="goToOptions(pair.symbol, pair.type)"> |
| | | <div class="currency-info"> |
| | | <div class="currency-pair-row"> |
| | | <template v-if="activeTab === 'forex' && getPairIconUrl(pair)"> |
| | | <div class="currency-card-icon-wrap"> |
| | | <img :src="getPairIconUrl(pair)" alt="" |
| | | class="currency-card-icon currency-card-icon--large" /> |
| | | <img v-if="getPairIconUrlSm(pair)" :src="getPairIconUrlSm(pair)" alt="" |
| | | class="currency-card-icon currency-card-icon--sm" /> |
| | | </div> |
| | | </template> |
| | | <img v-else-if="getPairIconUrl(pair)" :src="getPairIconUrl(pair)" alt="" |
| | | class="currency-card-icon" /> |
| | | <div class="currency-pair">{{ pair.symboltxt.toUpperCase() }}</div> |
| | | </div> |
| | | <div class="currency-price">{{ pair.price }}</div> |
| | | <div class="currency-change" :class="pair.change >= 0 ? 'up' : 'down'"> |
| | | {{ pair.change >= 0 ? '+' : '' }}{{ pair.change }}% |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 跟单板块 --> |
| | | <div class="section-block"> |
| | | <div class="section-header"> |
| | | <h3>{{ $t('板块.跟单') }}</h3> |
| | | <button class="more-btn"> |
| | | {{ $t('通用.更多') }} |
| | | <Icon icon="material-symbols:chevron-right" width="16" height="16" /> |
| | | </button> |
| | | <!-- Trading Instruments --> |
| | | <div class="trading-section"> |
| | | <div class="trading-tabs"> |
| | | <div class="tab-item" :class="{ active: activeTab === 'forex' }" @click="activeTab = 'forex'"> |
| | | {{ $t('外汇') }} |
| | | </div> |
| | | <div class="tab-item" :class="{ active: activeTab === 'crypto' }" @click="activeTab = 'crypto'"> |
| | | {{ $t('加密货币') }} |
| | | </div> |
| | | <div class="tab-item" :class="{ active: activeTab === 'stock' }" @click="activeTab = 'stock'"> |
| | | {{ $t('股票') }} |
| | | </div> |
| | | <div class="tab-item" :class="{ active: activeTab === 'etf' }" @click="activeTab = 'etf'"> |
| | | ETF |
| | | </div> |
| | | </div> |
| | | <div class="trader-list"> |
| | | <div class="trader-card" v-for="trader in traders" :key="trader.id"> |
| | | <div class="trader-info"> |
| | | <img :src="trader.avatar" class="trader-avatar"> |
| | | <div class="trader-detail"> |
| | | <div class="trader-name">{{ trader.name }}</div> |
| | | <div class="trader-stats"> |
| | | <span>{{ $t('交易员.收益率') }} <b class="up">{{ trader.profit }}%</b></span> |
| | | <span>{{ $t('交易员.跟随者') }} {{ trader.followers }}</span> |
| | | </div> |
| | | <div class="trading-pairs"> |
| | | <div class="pair-item" v-for="pair in tradingPairs" :key="pair.symbol" |
| | | @click="goToOptions(pair.symbol, pair.type)"> |
| | | <div class="pair-header"> |
| | | <div class="pair-symbol"> |
| | | <template v-if="activeTab === 'forex' && getPairIconUrl(pair)"> |
| | | <div class="pair-symbol-icon-wrap"> |
| | | <img :src="getPairIconUrl(pair)" alt="" |
| | | class="pair-symbol-icon pair-symbol-icon--large" /> |
| | | <img v-if="getPairIconUrlSm(pair)" :src="getPairIconUrlSm(pair)" alt="" |
| | | class="pair-symbol-icon pair-symbol-icon--sm" /> |
| | | </div> |
| | | </template> |
| | | <img v-else-if="getPairIconUrl(pair)" :src="getPairIconUrl(pair)" alt="" |
| | | class="pair-symbol-icon" /> |
| | | {{ pair.symboltxt.toUpperCase() }} |
| | | </div> |
| | | <div class="pair-change" :class="pair.change >= 0 ? 'up' : 'down'"> |
| | | {{ pair.change >= 0 ? '+' : '' }}{{ pair.change.toFixed(4) }}% |
| | | </div> |
| | | </div> |
| | | <button class="follow-btn">{{ $t('交易员.跟随') }}</button> |
| | | <div class="pair-bottom"> |
| | | <button class="sell"> |
| | | <span class="action-price">{{ pair.sellPrice }}</span> |
| | | <span class="action-label action-btn ">{{ $t('卖出') }}</span> |
| | | </button> |
| | | <div class="pair-chart"> |
| | | <MiniKlineChart :key="pair.symbol" :data="pair.klineData || []" :up="pair.change >= 0" /> |
| | | </div> |
| | | <button class=" buy"> |
| | | <span class="action-price">{{ pair.buyPrice }}</span> |
| | | <span class="action-label action-btn">{{ $t('买入') }}</span> |
| | | </button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 理财板块 --> |
| | | <div class="section-block"> |
| | | <div class="section-header"> |
| | | <h3>{{ $t('板块.理财') }}</h3> |
| | | <button class="more-btn"> |
| | | {{ $t('通用.更多') }} |
| | | <Icon icon="material-symbols:chevron-right" width="16" height="16" /> |
| | | </button> |
| | | <!-- About Us --> |
| | | <div class="about-section"> |
| | | <div class="section-header" @click="router.push('/aboutUs')"> |
| | | <h2>{{ $t('关于我们') }}</h2> |
| | | <span class="more-link">{{ $t('More') }} ></span> |
| | | </div> |
| | | <div class="finance-list"> |
| | | <div class="finance-card" v-for="item in financeProducts" :key="item.id"> |
| | | <div class="finance-info"> |
| | | <div class="finance-name">{{ item.name }}</div> |
| | | <div class="finance-rate"> |
| | | <span class="rate-num">{{ item.rate }}%</span> |
| | | <span class="rate-label">{{ $t('理财.年化收益') }}</span> |
| | | </div> |
| | | <div class="finance-desc">{{ item.desc }}</div> |
| | | </div> |
| | | <button class="invest-btn">{{ $t('理财.投资') }}</button> |
| | | <div class="video-thumbnail" role="button"> |
| | | <div class="video-placeholder"> |
| | | <video class="home-video" :src="homeVideoUrl" controls preload="metadata" @click.stop></video> |
| | | </div> |
| | | </div> |
| | | <p class="about-desc">{{ $t('home.aboutDesc') }}</p> |
| | | <ul class="feature-list"> |
| | | <li v-for="feature in features" :key="feature">{{ feature }}</li> |
| | | </ul> |
| | | </div> |
| | | |
| | | <!-- 资讯板块 --> |
| | | <div class="section-block"> |
| | | <div class="section-header"> |
| | | <h3>{{ $t('板块.资讯') }}</h3> |
| | | <button class="more-btn"> |
| | | {{ $t('通用.更多') }} |
| | | <Icon icon="material-symbols:chevron-right" width="16" height="16" /> |
| | | </button> |
| | | <!-- News Section --> |
| | | <div class="news-section"> |
| | | <div class="section-header" @click="router.push('/news')"> |
| | | <h2>{{ $t('home.news') }}</h2> |
| | | <span class="more-link">{{ $t('More') }} ></span> |
| | | </div> |
| | | <div class="news-list"> |
| | | <div class="news-item" v-for="news in newsList" :key="news.id"> |
| | | <div class="news-carousel"> |
| | | <div class="news-item" v-for="(item, index) in newsList" :key="item.id || index" |
| | | @click="router.push('/news')"> |
| | | <img v-if="item.urlToImage" :src="item.urlToImage" alt="" class="news-image" /> |
| | | <div class="news-content"> |
| | | <div class="news-title">{{ news.title }}</div> |
| | | <div class="news-meta"> |
| | | <span class="news-source">{{ news.source }}</span> |
| | | <span class="news-time">{{ news.time }}</span> |
| | | </div> |
| | | <h3 class="news-title">{{ (item.title || stripHtml(item.description || '')).slice(0, 40) }}{{ |
| | | (item.title || stripHtml(item.description || '')).length > 40 ? '...' : '' }}</h3> |
| | | <p class="news-excerpt">{{ stripHtml(item.description || '').slice(0, 80) }}{{ |
| | | stripHtml(item.description || '').length > 80 ? '...' : '' }}</p> |
| | | </div> |
| | | <img v-if="news.image" :src="news.image" class="news-image"> |
| | | </div> |
| | | <div class="news-item news-item--placeholder" v-if="!newsList.length"> |
| | | <div class="news-content"> |
| | | <h3 class="news-title">{{ $t('home.news') }}</h3> |
| | | <p class="news-excerpt">--</p> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 底部导航 --> |
| | | <div class="bottom-nav"> |
| | | <div v-for="item in bottomNavs" :key="item.id" :class="['nav-btn', { active: currentNav === item.id }]" |
| | | @click="currentNav = item.id"> |
| | | <Icon :icon="item.icon" width="24" height="24" /> |
| | | <span>{{ item.name }}</span> |
| | | <!-- Download Section --> |
| | | <div class="download-section"> |
| | | <h2>{{ $t('home.tradeGlobalMarkets') }}</h2> |
| | | <p class="download-desc">{{ $t('home.downloadDesc') }}</p> |
| | | <button class="download-btn"> |
| | | {{ $t('home.downloadNow') }} |
| | | </button> |
| | | <div class="phone-mockups"> |
| | | <!-- Phone mockups placeholder --> |
| | | <img src="@/assets/image/home/download.b711f9a.png" alt="phone-mockups" /> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- Partners --> |
| | | <div class="partners-section"> |
| | | <img src="@/assets/image/home/hezuo@3x.fcc1aa7.png" alt="partners" /> |
| | | </div> |
| | | |
| | | <!-- Footer Info --> |
| | | <div class="footer-info"> |
| | | <div class="footer-left"> |
| | | <div class="info-section"> |
| | | <h3>{{ $t('home.company') }}</h3> |
| | | <ul> |
| | | <li>{{ $t('关于我们') }}</li> |
| | | <li>{{ $t('home.teamIntro') }}</li> |
| | | <li>{{ $t('帮助中心') }}</li> |
| | | <li>{{ $t('home.emailSupport') }}</li> |
| | | <li>support@wealthinfra.com</li> |
| | | </ul> |
| | | </div> |
| | | <div class="info-section"> |
| | | <h3>{{ $t('home.statement') }}</h3> |
| | | <ul> |
| | | <li>{{ $t('home.riskDisclosure') }}</li> |
| | | <li>{{ $t('home.privacyStatement') }}</li> |
| | | <li>{{ $t('home.amlPolicy') }}</li> |
| | | <li>{{ $t('home.regulatoryLicense') }}</li> |
| | | </ul> |
| | | </div> |
| | | </div> |
| | | <div class="footer-right"> |
| | | <div class="info-section"> |
| | | <h3>{{ $t('home.policy') }}</h3> |
| | | <ul> |
| | | <li>{{ $t('home.userAgreement') }}</li> |
| | | </ul> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed } from 'vue' |
| | | import { ref, computed, onMounted, watch } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { useRouter } from 'vue-router' |
| | | import { IMG_PATH } from '@/config' |
| | | import homeVideoUrl from '@/assets/video/home_video.mp4' |
| | | import { _getRealtimeByType } from '@/service/quotes.api' |
| | | import MiniKlineChart from '@/components/MiniKlineChart/index.vue' |
| | | |
| | | const i18n = useI18n() |
| | | // 外汇货币代码 -> 国旗图国家/地区代码(用于 flagcdn.com) |
| | | const CURRENCY_TO_FLAG = { |
| | | eur: 'eu', usd: 'us', gbp: 'gb', jpy: 'jp', chf: 'ch', aud: 'au', cad: 'ca', nzd: 'nz', |
| | | cny: 'cn', cnh: 'cn', hkd: 'hk', sgd: 'sg', nok: 'no', sek: 'se', dkk: 'dk', mxn: 'mx', |
| | | zar: 'za', try: 'tr', pln: 'pl', inr: 'in', krw: 'kr', thb: 'th', myr: 'my', idr: 'id', |
| | | php: 'ph', brl: 'br', rub: 'ru', czk: 'cz', huf: 'hu', ron: 'ro', bgn: 'bg', hrk: 'hr' |
| | | } |
| | | const FLAG_CDN = 'https://flagcdn.com/w40' |
| | | import { _getUsHeadNews } from '@/service/user.api' |
| | | // import newsPlaceholder from '@/assets/image/news-placeholder.png' |
| | | |
| | | // 使用计算属性来处理动态变化的翻译内容 |
| | | const navList = computed(() => [ |
| | | { name: i18n.t('导航.期权'), icon: 'icon-park-outline:chart-stock' }, |
| | | { name: i18n.t('导航.美股'), icon: 'icon-park-outline:dollar' }, |
| | | { name: i18n.t('导航.A股'), icon: 'icon-park-outline:chinese' }, |
| | | { name: i18n.t('导航.港股'), icon: 'icon-park-outline:hk' }, |
| | | { name: i18n.t('导航.加密货币'), icon: 'cryptocurrency:btc' }, |
| | | { name: i18n.t('导航.资讯'), icon: 'icon-park-outline:news' }, |
| | | { name: i18n.t('导航.理财'), icon: 'icon-park-outline:finance' }, |
| | | { name: i18n.t('导航.下载'), icon: 'icon-park-outline:download' } |
| | | ]) |
| | | const { t, locale } = useI18n() |
| | | const router = useRouter() |
| | | |
| | | const marketTabs = computed(() => [ |
| | | { id: 'hot', name: i18n.t('市场.热门') }, |
| | | { id: 'us', name: i18n.t('市场.美股') }, |
| | | { id: 'a', name: i18n.t('市场.A股') }, |
| | | { id: 'hk', name: i18n.t('市场.港股') }, |
| | | { id: 'crypto', name: i18n.t('市场.加密货币') }, |
| | | { id: 'forex', name: i18n.t('市场.现货') } |
| | | ]) |
| | | function stripHtml(html) { |
| | | if (!html || typeof html !== 'string') return '' |
| | | const div = document.createElement('div') |
| | | div.innerHTML = html |
| | | return (div.textContent || div.innerText || '').trim() |
| | | } |
| | | |
| | | const bottomNavs = computed(() => [ |
| | | { id: 'home', name: i18n.t('底部导航.首页'), icon: 'material-symbols:home-outline' }, |
| | | { id: 'market', name: i18n.t('底部导航.市场'), icon: 'material-symbols:analytics-outline' }, |
| | | { id: 'trade', name: i18n.t('底部导航.交易'), icon: 'material-symbols:candlestick-chart-outline' }, |
| | | { id: 'discover', name: i18n.t('底部导航.发现'), icon: 'material-symbols:explore-outline' }, |
| | | { id: 'mine', name: i18n.t('底部导航.我的'), icon: 'material-symbols:person-outline' } |
| | | ]) |
| | | // 跳转到交易页 Options,并带上 symbol 与 activeTab |
| | | function goToOptions(symbol, type) { |
| | | if (!symbol) return |
| | | router.push({ |
| | | path: '/trade/options', |
| | | query: { symbol, activeTab: type || 'cryptos' } |
| | | }) |
| | | } |
| | | |
| | | const traders = computed(() => [ |
| | | { |
| | | id: 1, |
| | | name: i18n.t('交易员.达人A'), |
| | | avatar: "/avatars/trader1.png", |
| | | profit: 289.5, |
| | | followers: "12.5万" |
| | | }, |
| | | { |
| | | id: 2, |
| | | name: i18n.t('交易员.达人B'), |
| | | avatar: "/avatars/trader2.png", |
| | | profit: 156.8, |
| | | followers: "8.2万" |
| | | const YOUTUBE_LINK = 'https://www.youtube.com/watch?v=eAL5XVQtrxo&source_ve_path=OTY3MTQ&embeds_referring_euri=https%3A%2F%2Fwealthinfra.com%2F' |
| | | function openYouTubeLink() { |
| | | window.open(YOUTUBE_LINK, '_blank', 'noopener,noreferrer') |
| | | } |
| | | |
| | | // 语言映射表 |
| | | const langMap = { |
| | | 'de': 'Deutsch', |
| | | 'en': 'English', |
| | | 'es': 'Español', |
| | | 'fr': 'Français', |
| | | 'Italy': 'Italiano', |
| | | 'Japanese': '日本語', |
| | | 'Korean': '한국어', |
| | | 'pt': 'Português', |
| | | 'vi': 'Tiếng Việt', |
| | | 'CN': '繁体中文', |
| | | 'zh-CN': '简体', |
| | | 'gr': 'Ελληνικά', |
| | | 'th': 'ไทย' |
| | | } |
| | | |
| | | // 获取当前语言名称 |
| | | const currentLangName = computed(() => { |
| | | return langMap[locale.value] || '简体' |
| | | }) |
| | | |
| | | const activeTab = ref('forex') |
| | | |
| | | const tradingPairs = ref([]) |
| | | // 新闻列表,用于横向滚动轮播(与 news/index.vue 同源:_getUsHeadNews) |
| | | const newsList = ref([]) |
| | | |
| | | // Market Overview 使用 Trading Instruments 的前3条数据(保留完整 pair 用于展示图标) |
| | | const currencyPairs = computed(() => tradingPairs.value.slice(0, 3)) |
| | | |
| | | // 从外汇对取基础货币代码,如 EUR/USD -> eur,EURUSD -> eur(无斜杠取前3位) |
| | | function getForexBaseCurrency(symbol) { |
| | | if (!symbol || typeof symbol !== 'string') return '' |
| | | const s = symbol.trim() |
| | | if (s.includes('/')) return s.split('/')[0].trim().toLowerCase() |
| | | return s.slice(0, 3).toLowerCase() |
| | | } |
| | | |
| | | // 从外汇对取计价货币代码,如 EUR/USD -> usd(右下角小图用) |
| | | function getForexQuoteCurrency(symbol) { |
| | | if (!symbol || typeof symbol !== 'string') return '' |
| | | const s = symbol.trim() |
| | | if (s.includes('/')) return s.split('/')[1]?.trim().toLowerCase() || '' |
| | | return s.length > 3 ? s.slice(3, 6).toLowerCase() : '' |
| | | } |
| | | |
| | | // 列表项图标地址:外汇用国旗,加密货币用 symbol 图;股票、ETF 不展示图标 |
| | | function getPairIconUrl(pair) { |
| | | if (!pair) return '' |
| | | if (activeTab.value === 'stock' || activeTab.value === 'etf') return '' |
| | | if (activeTab.value === 'forex') { |
| | | const code = CURRENCY_TO_FLAG[getForexBaseCurrency(pair.symbol)] |
| | | return code ? `${FLAG_CDN}/${code}.png` : '' |
| | | } |
| | | return pair.iconImg ? `${IMG_PATH}/symbol/${pair.iconImg}.png` : '' |
| | | } |
| | | |
| | | // 小图用名字后面3位(计价货币)的国旗,仅外汇有效 |
| | | function getPairIconUrlSm(pair) { |
| | | if (!pair || activeTab.value !== 'forex') return '' |
| | | const quote = getForexQuoteCurrency(pair.symbol) |
| | | if (!quote) return '' |
| | | const code = CURRENCY_TO_FLAG[quote] |
| | | return code ? `${FLAG_CDN}/${code}.png` : '' |
| | | } |
| | | |
| | | // 获取交易数据 |
| | | const fetchTradingData = async () => { |
| | | let type = '' |
| | | let category = null |
| | | |
| | | switch (activeTab.value) { |
| | | case 'crypto': |
| | | type = 'cryptos' |
| | | break |
| | | case 'etf': |
| | | type = 'indices' |
| | | break |
| | | case 'stock': |
| | | type = 'US-stocks' |
| | | break |
| | | case 'forex': |
| | | type = 'forex' |
| | | category = 'forex' |
| | | break |
| | | default: |
| | | type = 'forex' |
| | | category = 'forex' |
| | | } |
| | | |
| | | try { |
| | | const params = { |
| | | type: type, |
| | | pageNo: 1 |
| | | } |
| | | if (category) { |
| | | params.category = category |
| | | } |
| | | |
| | | const data = await _getRealtimeByType(params) |
| | | |
| | | if (data && Array.isArray(data)) { |
| | | // 外汇 tab 只展示指定 symbol:EURUSD GBPUSD AUDUSD XAUUSD NZDUSD |
| | | const forexAllowedSymbols = ['EURUSD', 'GBPUSD', 'AUDUSD', 'XAUUSD', 'NZDUSD'] |
| | | let list = data |
| | | if (activeTab.value === 'forex') { |
| | | list = data.filter(item => { |
| | | const raw = (item.symbol || item.enName || '').toString().trim() |
| | | const normalized = raw.replace(/\//g, '').toUpperCase() |
| | | return forexAllowedSymbols.includes(normalized) |
| | | }) |
| | | } |
| | | // 只取前5条数据,并转换为需要的格式 |
| | | tradingPairs.value = list.slice(0, 5).map(item => { |
| | | const basePrice = parseFloat(item.close || item.lastPrice || 0) |
| | | const changeRatio = item.changeRatio || 0 |
| | | |
| | | // 生成小型 K 线图数据 [open, close, low, high] 若干根 |
| | | const klineData = generateMiniKlineData(basePrice, changeRatio) |
| | | |
| | | // 计算买入价和卖出价(买入价略高,卖出价略低) |
| | | const spread = basePrice * 0.0001 // 很小的价差 |
| | | const sellPrice = (basePrice - spread).toFixed(4) |
| | | const buyPrice = (basePrice + spread).toFixed(4) |
| | | const symboltxt = item.enName |
| | | const symbolStr = item.symbol || '--' |
| | | const iconImg = item.symbol_data || (symbolStr.includes('/') ? symbolStr.split('/')[0].toLowerCase() : symbolStr.replace(/USDT$/i, '').toLowerCase()) || symbolStr.toLowerCase() |
| | | return { |
| | | symboltxt: symboltxt, |
| | | symbol: symbolStr, |
| | | type: type, |
| | | iconImg: iconImg, |
| | | price: basePrice.toFixed(4), |
| | | change: changeRatio, |
| | | sellPrice: sellPrice, |
| | | buyPrice: buyPrice, |
| | | klineData: klineData |
| | | } |
| | | }) |
| | | } else { |
| | | tradingPairs.value = [] |
| | | } |
| | | } catch (error) { |
| | | console.error('获取交易数据失败:', error) |
| | | tradingPairs.value = [] |
| | | } |
| | | } |
| | | |
| | | // 监听 tab 切换 |
| | | watch(activeTab, () => { |
| | | fetchTradingData() |
| | | }) |
| | | |
| | | // 根据当前价与涨跌幅生成小型 K 线数据,每根 [open, close, low, high] |
| | | function generateMiniKlineData(basePrice, changeRatio) { |
| | | const candleCount = 12 |
| | | const startPrice = basePrice / (1 + (changeRatio || 0) / 100) |
| | | const range = basePrice - startPrice |
| | | const candles = [] |
| | | let prevClose = startPrice |
| | | for (let i = 0; i < candleCount; i++) { |
| | | const t = (i + 1) / candleCount |
| | | const trend = startPrice + range * t |
| | | const noise = (Math.random() - 0.5) * (Math.abs(range) * 0.15 + basePrice * 0.002) |
| | | const close = i === candleCount - 1 ? basePrice : Math.max(basePrice * 0.001, trend + noise) |
| | | const open = prevClose |
| | | const low = Math.min(open, close) - Math.random() * basePrice * 0.001 |
| | | const high = Math.max(open, close) + Math.random() * basePrice * 0.001 |
| | | candles.push([open, close, low, high]) |
| | | prevClose = close |
| | | } |
| | | return candles |
| | | } |
| | | |
| | | // 组件挂载时获取数据 |
| | | onMounted(() => { |
| | | fetchTradingData() |
| | | _getUsHeadNews().then((data) => { |
| | | const list = Array.isArray(data) ? data : (data && data.articles) ? data.articles : [] |
| | | newsList.value = list.slice(0, 10) |
| | | }).catch(() => { }) |
| | | }) |
| | | |
| | | const features = ref([ |
| | | t('home.feature1'), |
| | | t('home.feature2'), |
| | | t('home.feature3'), |
| | | t('home.feature4') |
| | | ]) |
| | | |
| | | const financeProducts = computed(() => [ |
| | | { |
| | | id: 1, |
| | | name: i18n.t('理财.稳健计划'), |
| | | rate: 12.8, |
| | | desc: i18n.t('理财.稳健描述') |
| | | }, |
| | | { |
| | | id: 2, |
| | | name: i18n.t('理财.高收益计划'), |
| | | rate: 25.6, |
| | | desc: i18n.t('理财.高收益描述') |
| | | } |
| | | ]) |
| | | |
| | | const marketData = ref([ |
| | | { |
| | | name: '腾讯控股', |
| | | code: 'HK 00700.HK', |
| | | price: '403.800', |
| | | change: 0.00 |
| | | }, |
| | | { |
| | | name: '英伟达', |
| | | code: 'US NVDA.US', |
| | | price: '146.990', |
| | | change: -0.88 |
| | | } |
| | | ]) |
| | | |
| | | const currentTab = ref('hot') |
| | | const currentNav = ref('home') |
| | | |
| | | const newsList = ref([ |
| | | { |
| | | id: 1, |
| | | title: "比特币突破48000美元,创下年内新高", |
| | | source: "币市快讯", |
| | | time: "10分钟前", |
| | | image: "/news/btc.png" |
| | | }, |
| | | { |
| | | id: 2, |
| | | title: "美联储暗示年内可能降息,加密货币市场全线上涨", |
| | | source: "财经日报", |
| | | time: "35分钟前", |
| | | image: "/news/fed.png" |
| | | } |
| | | const partners = ref([ |
| | | 'BINANCE', 'coinbase', 'Stralishit', 'Bitazza', |
| | | 'Vanguard', 'ETX Capital', 'Coinb', 'Bitbank Global', |
| | | 'FOREX.com', 'Bitget', 'JFX', 'ICDX' |
| | | ]) |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .home { |
| | | .home-page { |
| | | min-height: 100vh; |
| | | background: $main_background; |
| | | padding-bottom: 56px; |
| | | background: #fff; |
| | | padding-bottom: 12rem; |
| | | } |
| | | |
| | | /* Header */ |
| | | .header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 16px 20px; |
| | | background: $main_background; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 100; |
| | | border-bottom: 1px solid rgba(118, 128, 143, 0.1); |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04); |
| | | } |
| | | padding: 1.5rem; |
| | | background: #fff; |
| | | box-shadow: 0 1px 3px 1.5px #00000020; |
| | | |
| | | .avatar { |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 20px; |
| | | background: rgba(146, 209, 255, 0.08); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | |
| | | &:hover { |
| | | background: rgba(146, 209, 255, 0.12); |
| | | transform: scale(1.05); |
| | | .header-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1rem; |
| | | |
| | | .logo { |
| | | width: 4rem; |
| | | height: 4rem; |
| | | } |
| | | |
| | | .logo-text { |
| | | font-size: 2.25rem; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .search-box { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | background: $input_background; |
| | | border-radius: 12px; |
| | | margin: 0 12px; |
| | | padding: 10px 16px; |
| | | height: 40px; |
| | | border: 1px solid rgba(118, 128, 143, 0.1); |
| | | transition: all 0.2s ease; |
| | | |
| | | &:focus-within { |
| | | border-color: rgba(146, 209, 255, 0.3); |
| | | box-shadow: 0 0 0 3px rgba(146, 209, 255, 0.1); |
| | | } |
| | | } |
| | | .header-right { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1.5rem; |
| | | |
| | | .search-box input { |
| | | border: none; |
| | | background: transparent; |
| | | margin-left: 8px; |
| | | width: 100%; |
| | | font-size: 14px; |
| | | color: $text_color; |
| | | |
| | | &::placeholder { |
| | | color: $text_color1; |
| | | } |
| | | } |
| | | .lang-selector { |
| | | padding: 0.5rem 1rem; |
| | | background: #f5f5f5; |
| | | border-radius: 0.5rem; |
| | | font-size: 1.5rem; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | |
| | | .header-right { |
| | | display: flex; |
| | | gap: 12px; |
| | | color: $text_color1; |
| | | |
| | | svg { |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | |
| | | &:hover { |
| | | color: $color_main; |
| | | transform: scale(1.1); |
| | | &:hover { |
| | | background: #e8e8e8; |
| | | } |
| | | |
| | | .lang-text { |
| | | color: $text_color; |
| | | } |
| | | } |
| | | |
| | | .icon-btn { |
| | | width: 4rem; |
| | | height: 4rem; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | border-radius: 50%; |
| | | background: #f5f5f5; |
| | | cursor: pointer; |
| | | |
| | | img { |
| | | width: 2rem; |
| | | height: 2rem; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .gift-banner { |
| | | margin: 16px 20px; |
| | | background: linear-gradient(135deg, rgba(146, 209, 255, 0.1) 0%, rgba(123, 184, 255, 0.05) 100%); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | box-shadow: 0 2px 12px rgba(146, 209, 255, 0.08); |
| | | border: 1px solid rgba(146, 209, 255, 0.15); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 20px rgba(146, 209, 255, 0.12); |
| | | transform: translateY(-2px); |
| | | } |
| | | } |
| | | |
| | | .gift-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .gift-icon { |
| | | width: 48px; |
| | | height: 48px; |
| | | border-radius: 12px; |
| | | background: linear-gradient(135deg, #92D1FF 0%, #7BB8FF 100%); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #fff; |
| | | box-shadow: 0 4px 12px rgba(146, 209, 255, 0.3); |
| | | } |
| | | |
| | | .gift-amount { |
| | | font-size: 18px; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | letter-spacing: -0.3px; |
| | | } |
| | | |
| | | .gift-desc { |
| | | font-size: 13px; |
| | | color: $text_color1; |
| | | margin-top: 6px; |
| | | } |
| | | |
| | | .register-btn { |
| | | background: linear-gradient(135deg, #92D1FF 0%, #7BB8FF 100%); |
| | | color: #fff; |
| | | border: none; |
| | | padding: 10px 24px; |
| | | border-radius: 12px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | box-shadow: 0 4px 12px rgba(146, 209, 255, 0.3); |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | background: linear-gradient(135deg, #7BB8FF 0%, #6BA8FF 100%); |
| | | box-shadow: 0 6px 16px rgba(146, 209, 255, 0.4); |
| | | transform: translateY(-1px); |
| | | } |
| | | |
| | | &:active { |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | .nav-section { |
| | | background: $main_background; |
| | | padding: 24px 20px; |
| | | display: grid; |
| | | grid-template-columns: repeat(4, 1fr); |
| | | gap: 20px 0; |
| | | } |
| | | |
| | | .nav-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 8px; |
| | | cursor: pointer; |
| | | padding: 12px; |
| | | border-radius: 12px; |
| | | transition: all 0.2s ease; |
| | | |
| | | &:hover { |
| | | background: rgba(146, 209, 255, 0.05); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | svg { |
| | | transition: all 0.2s ease; |
| | | } |
| | | |
| | | &:hover svg { |
| | | color: $color_main; |
| | | transform: scale(1.1); |
| | | } |
| | | } |
| | | |
| | | .nav-name { |
| | | font-size: 13px; |
| | | color: $text_color; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .banner-section { |
| | | margin: 0 20px 16px; |
| | | } |
| | | |
| | | .banner-item { |
| | | background: $main_background; |
| | | border-radius: 16px; |
| | | padding: 24px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | box-shadow: 0 2px 12px rgba(146, 209, 255, 0.08); |
| | | border: 1px solid rgba(118, 128, 143, 0.1); |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 20px rgba(146, 209, 255, 0.12); |
| | | transform: translateY(-2px); |
| | | } |
| | | } |
| | | |
| | | .banner-tag { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | background: linear-gradient(135deg, rgba(255, 107, 0, 0.15) 0%, rgba(255, 107, 0, 0.08) 100%); |
| | | color: #ff6b00; |
| | | padding: 6px 12px; |
| | | border-radius: 8px; |
| | | font-size: 12px; |
| | | font-weight: 600; |
| | | border: 1px solid rgba(255, 107, 0, 0.2); |
| | | } |
| | | |
| | | .banner-title { |
| | | margin: 16px 0; |
| | | font-size: 18px; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | letter-spacing: -0.3px; |
| | | } |
| | | |
| | | .join-btn { |
| | | border: none; |
| | | background: transparent; |
| | | color: $color_main; |
| | | padding: 6px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | |
| | | &:hover { |
| | | color: #7BB8FF; |
| | | gap: 8px; |
| | | } |
| | | } |
| | | |
| | | .banner-right img { |
| | | width: 120px; |
| | | height: 120px; |
| | | object-fit: contain; |
| | | } |
| | | |
| | | .market-section { |
| | | background: $main_background; |
| | | margin-top: 0; |
| | | border-radius: 16px; |
| | | margin: 0 20px 16px; |
| | | box-shadow: 0 2px 12px rgba(146, 209, 255, 0.08); |
| | | border: 1px solid rgba(118, 128, 143, 0.1); |
| | | /* Hero Section */ |
| | | .hero-section { |
| | | border-radius: 2rem; |
| | | overflow: hidden; |
| | | } |
| | | margin: 0 auto; |
| | | box-shadow: 0 0.25rem 1.5rem rgba(0, 0, 0, 0.08); |
| | | width: calc(100% - 4rem); |
| | | margin-top: 3rem; |
| | | |
| | | .market-tabs { |
| | | display: flex; |
| | | padding: 0 20px; |
| | | border-bottom: 1px solid rgba(118, 128, 143, 0.1); |
| | | overflow-x: auto; |
| | | -webkit-overflow-scrolling: touch; |
| | | background: $main_background; |
| | | } |
| | | |
| | | .market-tabs::-webkit-scrollbar { |
| | | display: none; |
| | | } |
| | | |
| | | .tab-item { |
| | | padding: 16px 20px; |
| | | font-size: 14px; |
| | | color: $text_color1; |
| | | position: relative; |
| | | white-space: nowrap; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .tab-item.active { |
| | | color: $color_main; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | .tab-item.active::after { |
| | | content: ''; |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | width: 24px; |
| | | height: 3px; |
| | | background: $color_main; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | .market-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 20px; |
| | | border-bottom: 1px solid rgba(118, 128, 143, 0.1); |
| | | transition: all 0.2s ease; |
| | | cursor: pointer; |
| | | |
| | | &:hover { |
| | | background: rgba(146, 209, 255, 0.03); |
| | | :deep(.van-swipe) { |
| | | border-radius: 2rem; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | |
| | | :deep(.van-swipe-item) { |
| | | margin: 0 auto; |
| | | } |
| | | |
| | | :deep(.van-swipe__indicator) { |
| | | background-color: rgba(255, 255, 255, 0.5); |
| | | width: 1rem; |
| | | height: 1rem; |
| | | margin: 0 0.5rem; |
| | | } |
| | | |
| | | :deep(.van-swipe__indicator--active) { |
| | | background-color: #92D1FF; |
| | | } |
| | | |
| | | .hero-card { |
| | | background: #fff; |
| | | border-radius: 2rem; |
| | | padding: 3rem; |
| | | min-height: 40rem; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .hero-title { |
| | | font-size: 3.5rem; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | margin-bottom: 3rem; |
| | | margin-top: 1rem; |
| | | } |
| | | |
| | | .hero-desc { |
| | | font-size: 2.5rem; |
| | | color: $text_color; |
| | | margin-bottom: 3rem; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .trade-btn { |
| | | background: #0a6bfa; |
| | | color: #fff; |
| | | border: none; |
| | | padding: 1rem 3rem; |
| | | border-radius: 5rem; |
| | | font-size: 3rem; |
| | | font-weight: 300; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 1rem; |
| | | cursor: pointer; |
| | | margin-bottom: 3rem; |
| | | |
| | | .play-icon { |
| | | width: 4.5rem; |
| | | object-fit: contain; |
| | | } |
| | | } |
| | | |
| | | .hero-illustration { |
| | | position: relative; |
| | | margin-bottom: 2rem; |
| | | |
| | | .robot-illustration, |
| | | .device-illustration, |
| | | .crypto-illustration { |
| | | width: 100%; |
| | | border-radius: 1rem; |
| | | |
| | | img { |
| | | width: 70%; |
| | | margin: 0 auto; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .stock-name { |
| | | font-size: 16px; |
| | | .no-more-notice { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1rem; |
| | | margin: 2rem 1.5rem; |
| | | font-size: 2.5rem; |
| | | color: $text_color; |
| | | font-weight: 600; |
| | | letter-spacing: -0.2px; |
| | | padding: 2rem; |
| | | background-color: #f6f6f6; |
| | | border-radius: 2rem; |
| | | |
| | | img { |
| | | width: 2rem; |
| | | height: 2rem; |
| | | } |
| | | |
| | | .arrow { |
| | | margin-left: auto; |
| | | width: 2rem; |
| | | height: auto; |
| | | } |
| | | } |
| | | |
| | | .stock-code { |
| | | font-size: 12px; |
| | | color: $text_color1; |
| | | margin-top: 6px; |
| | | } |
| | | |
| | | .current-price { |
| | | font-size: 16px; |
| | | text-align: right; |
| | | color: $text_color; |
| | | font-weight: 600; |
| | | letter-spacing: -0.2px; |
| | | } |
| | | |
| | | .price-change { |
| | | font-size: 13px; |
| | | text-align: right; |
| | | margin-top: 6px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .up { |
| | | color: $green; |
| | | } |
| | | |
| | | .down { |
| | | color: $red; |
| | | } |
| | | |
| | | .bottom-nav { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | /* Quick Access */ |
| | | .quick-access { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | padding: 3rem 0; |
| | | background: #fff; |
| | | display: flex; |
| | | padding: 6px 0; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | box-shadow: 0rem 1rem 4rem 0rem rgba(0, 0, 0, .12); |
| | | margin: 3rem 1.5rem 4rem; |
| | | border-radius: 2rem; |
| | | |
| | | .nav-btn { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 2px; |
| | | font-size: 12px; |
| | | color: #999; |
| | | } |
| | | .quick-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 0.5rem; |
| | | cursor: pointer; |
| | | width: 25%; |
| | | |
| | | .nav-btn.active { |
| | | color: #000; |
| | | } |
| | | .quick-icon { |
| | | width: 5rem; |
| | | height: 5rem; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .section-block { |
| | | background: $main_background; |
| | | margin: 0 20px 16px; |
| | | padding: 20px; |
| | | border-radius: 16px; |
| | | box-shadow: 0 2px 12px rgba(146, 209, 255, 0.08); |
| | | border: 1px solid rgba(118, 128, 143, 0.1); |
| | | } |
| | | img { |
| | | width: 100%; |
| | | object-fit: contain; |
| | | } |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .section-header h3 { |
| | | font-size: 18px; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | letter-spacing: -0.3px; |
| | | } |
| | | |
| | | .more-btn { |
| | | border: none; |
| | | background: transparent; |
| | | color: $text_color1; |
| | | font-size: 14px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | font-weight: 500; |
| | | |
| | | &:hover { |
| | | color: $color_main; |
| | | gap: 6px; |
| | | span { |
| | | font-size: 2rem; |
| | | color: $text_color; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* 跟单样式 */ |
| | | .trader-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | /* Market Overview */ |
| | | .market-overview { |
| | | padding: 3rem; |
| | | background: #fff; |
| | | |
| | | .trader-card { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 16px; |
| | | background: $main2_background; |
| | | border-radius: 12px; |
| | | border: 1px solid rgba(118, 128, 143, 0.1); |
| | | transition: all 0.3s ease; |
| | | cursor: pointer; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 12px rgba(146, 209, 255, 0.08); |
| | | transform: translateY(-2px); |
| | | border-color: rgba(146, 209, 255, 0.2); |
| | | |
| | | .currency-cards { |
| | | display: flex; |
| | | gap: 1.5rem; |
| | | |
| | | .currency-card { |
| | | flex: 1; |
| | | padding: 2rem; |
| | | background: #f9f9f9; |
| | | border-radius: 1rem; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 1rem; |
| | | text-align: center; |
| | | |
| | | .currency-pair-row { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 0.5rem; |
| | | margin-bottom: 0.5rem; |
| | | } |
| | | |
| | | .currency-card-icon-wrap { |
| | | position: relative; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .currency-card-icon { |
| | | width: 3rem; |
| | | height: 3rem; |
| | | border-radius: 50%; |
| | | object-fit: cover; |
| | | |
| | | &--large { |
| | | width: 3rem; |
| | | height: 3rem; |
| | | } |
| | | |
| | | &--sm { |
| | | position: absolute; |
| | | right: -0.2rem; |
| | | bottom: -0.2rem; |
| | | width: 1.4rem; |
| | | height: 1.4rem; |
| | | border-radius: 50%; |
| | | object-fit: cover; |
| | | border: 0.15rem solid #fff; |
| | | box-shadow: 0 0 0.1rem rgba(0, 0, 0, 0.2); |
| | | } |
| | | } |
| | | |
| | | .currency-pair { |
| | | font-size: 2rem; |
| | | color: $text_color; |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .currency-price { |
| | | font-size: 2.5rem; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | margin-bottom: 1rem; |
| | | } |
| | | |
| | | .currency-change { |
| | | font-size: 2rem; |
| | | font-weight: 600; |
| | | |
| | | &.up { |
| | | color: $green; |
| | | } |
| | | |
| | | &.down { |
| | | color: $red; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .trader-info { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | /* Trading Section */ |
| | | .trading-section { |
| | | padding: 3rem; |
| | | background: #fff; |
| | | |
| | | .trading-tabs { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1.6rem; |
| | | margin-bottom: 3rem; |
| | | overflow-x: auto; |
| | | |
| | | .tab-item { |
| | | padding: 1.3rem 1rem; |
| | | font-size: 2rem; |
| | | color: $text_color; |
| | | white-space: nowrap; |
| | | cursor: pointer; |
| | | border-radius: 999px; |
| | | transition: background-color 0.2s, color 0.2s; |
| | | |
| | | &.active { |
| | | padding: 1.3rem 3.5rem; |
| | | background: #3478F6; |
| | | color: #fff; |
| | | font-weight: 600; |
| | | box-shadow: 0 0.2rem 0.6rem rgba(52, 120, 246, 0.35); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .trading-pairs { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 2rem; |
| | | |
| | | .pair-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 2rem; |
| | | background: #fff; |
| | | border-radius: 1rem; |
| | | border: 0.1rem solid #f0f0f0; |
| | | |
| | | .pair-header { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .pair-symbol { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 0.6rem; |
| | | font-size: 2rem; |
| | | font-weight: 600; |
| | | color: $text_color; |
| | | |
| | | .pair-symbol-icon-wrap { |
| | | position: relative; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .pair-symbol-icon { |
| | | width: 2.4rem; |
| | | height: 2.4rem; |
| | | border-radius: 50%; |
| | | // object-fit: contain; |
| | | |
| | | &--large { |
| | | width: 3rem; |
| | | height: 3rem; |
| | | } |
| | | |
| | | &--sm { |
| | | position: absolute; |
| | | right: -0.2rem; |
| | | bottom: -0.2rem; |
| | | width: 1.6rem; |
| | | height: 1.6rem; |
| | | border-radius: 50%; |
| | | object-fit: cover; |
| | | border: 0.15rem solid #fff; |
| | | box-shadow: 0 0 0.1rem rgba(0, 0, 0, 0.2); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .pair-change { |
| | | font-size: 1.75rem; |
| | | font-weight: 600; |
| | | |
| | | &.up { |
| | | color: $green; |
| | | } |
| | | |
| | | &.down { |
| | | color: $red; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .pair-bottom { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1rem; |
| | | position: relative; |
| | | top: -2.2rem; |
| | | |
| | | .action-price { |
| | | font-size: 2rem; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .action-btn { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 0.3rem 5rem; |
| | | border: 0.1rem solid #333; |
| | | border-radius: 0.2rem; |
| | | font-size: 1.8rem; |
| | | background: #fff; |
| | | cursor: pointer; |
| | | min-width: 7rem; |
| | | gap: 0.5rem; |
| | | flex-shrink: 0; |
| | | |
| | | |
| | | .action-label { |
| | | font-size: 1.5rem; |
| | | } |
| | | |
| | | &.sell { |
| | | .action-price { |
| | | color: $text_color; |
| | | } |
| | | |
| | | .action-label { |
| | | color: $red; |
| | | } |
| | | } |
| | | |
| | | &.buy { |
| | | .action-price { |
| | | color: $text_color; |
| | | } |
| | | |
| | | .action-label { |
| | | color: $green; |
| | | } |
| | | } |
| | | |
| | | &:hover { |
| | | background: #f9f9f9; |
| | | } |
| | | } |
| | | |
| | | .pair-chart { |
| | | flex: 1; |
| | | height: 2.5rem; |
| | | margin: 0 0.5rem; |
| | | min-width: 6rem; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .trader-avatar { |
| | | width: 48px; |
| | | height: 48px; |
| | | border-radius: 24px; |
| | | object-fit: cover; |
| | | border: 2px solid rgba(146, 209, 255, 0.1); |
| | | /* About Section */ |
| | | .about-section { |
| | | padding: 3rem; |
| | | background: #fff; |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 2rem; |
| | | |
| | | h2 { |
| | | font-size: 2.25rem; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | } |
| | | |
| | | .more-link { |
| | | font-size: 1.75rem; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | |
| | | .video-thumbnail { |
| | | margin-bottom: 2rem; |
| | | cursor: pointer; |
| | | |
| | | .video-placeholder { |
| | | width: 100%; |
| | | background: #1a1a1a; |
| | | border-radius: 1rem; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-bottom: 1rem; |
| | | |
| | | .home-video { |
| | | width: 100%; |
| | | height: 100%; |
| | | object-fit: cover; |
| | | border-radius: 1rem; |
| | | } |
| | | |
| | | .play-button { |
| | | width: 6rem; |
| | | height: 6rem; |
| | | background: rgba(255, 255, 255, 0.9); |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #000; |
| | | font-size: 2rem; |
| | | } |
| | | } |
| | | |
| | | .video-info { |
| | | .video-title { |
| | | font-size: 1.75rem; |
| | | font-weight: 600; |
| | | color: $text_color; |
| | | margin-bottom: 0.5rem; |
| | | } |
| | | |
| | | .video-platform { |
| | | font-size: 1.5rem; |
| | | color: $text_color1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .about-desc { |
| | | font-size: 1.75rem; |
| | | color: $text_color1; |
| | | line-height: 1.5; |
| | | margin-bottom: 2rem; |
| | | } |
| | | |
| | | .feature-list { |
| | | list-style: none; |
| | | padding: 0; |
| | | |
| | | li { |
| | | font-size: 1.75rem; |
| | | color: $text_color1; |
| | | margin-bottom: 1rem; |
| | | padding-left: 3rem; |
| | | position: relative; |
| | | |
| | | &::before { |
| | | content: '✓'; |
| | | position: absolute; |
| | | left: 0; |
| | | color: $green; |
| | | font-weight: 700; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .trader-name { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: $text_color; |
| | | letter-spacing: -0.2px; |
| | | /* News Section */ |
| | | .news-section { |
| | | padding: 3rem; |
| | | background: #fff; |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 2rem; |
| | | |
| | | h2 { |
| | | font-size: 2.25rem; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | } |
| | | |
| | | .more-link { |
| | | font-size: 1.75rem; |
| | | color: $text-color; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | |
| | | .news-carousel { |
| | | display: flex; |
| | | gap: 1.5rem; |
| | | overflow-x: auto; |
| | | overflow-y: hidden; |
| | | padding-bottom: 0.5rem; |
| | | scroll-snap-type: x mandatory; |
| | | -webkit-overflow-scrolling: touch; |
| | | |
| | | &::-webkit-scrollbar { |
| | | height: 0.4rem; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-thumb { |
| | | background: #ccc; |
| | | border-radius: 0.2rem; |
| | | } |
| | | |
| | | .news-item { |
| | | flex-shrink: 0; |
| | | width: 45rem; |
| | | min-width: 28rem; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 1rem; |
| | | padding: 1.5rem; |
| | | background: #f9f9f9; |
| | | border-radius: 1rem; |
| | | scroll-snap-align: start; |
| | | cursor: pointer; |
| | | |
| | | &.news-item--placeholder { |
| | | min-width: 100%; |
| | | } |
| | | |
| | | .news-image { |
| | | width: 100%; |
| | | height: 14rem; |
| | | border-radius: 0.5rem; |
| | | object-fit: cover; |
| | | } |
| | | |
| | | .news-content { |
| | | flex: 1; |
| | | min-width: 0; |
| | | |
| | | .news-title { |
| | | font-size: 1.75rem; |
| | | font-weight: 600; |
| | | color: $text_color; |
| | | margin-bottom: 1rem; |
| | | } |
| | | |
| | | .news-excerpt { |
| | | font-size: 1.5rem; |
| | | color: $text_color1; |
| | | line-height: 1.4; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .trader-stats { |
| | | display: flex; |
| | | gap: 16px; |
| | | font-size: 13px; |
| | | color: $text_color1; |
| | | margin-top: 6px; |
| | | |
| | | b { |
| | | /* Download Section */ |
| | | .download-section { |
| | | padding: 3rem; |
| | | background: #fff; |
| | | text-align: left; |
| | | box-shadow: 0rem .8rem 3.2rem 0rem rgba(0, 0, 0, .12); |
| | | border-radius: 1.6rem; |
| | | margin: 3rem 3rem; |
| | | |
| | | h2 { |
| | | font-size: 3rem; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | margin-bottom: 2rem; |
| | | } |
| | | |
| | | .download-desc { |
| | | font-size: 2.2rem; |
| | | color: $text_color; |
| | | margin-bottom: 3rem; |
| | | } |
| | | |
| | | .download-btn { |
| | | background: #0a6bfa; |
| | | color: #fff; |
| | | border: none; |
| | | padding: 1.2rem 3rem; |
| | | border-radius: 1rem; |
| | | font-size: 2rem; |
| | | font-weight: 600; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1rem; |
| | | cursor: pointer; |
| | | |
| | | img { |
| | | width: 2.5rem; |
| | | height: 2.5rem; |
| | | } |
| | | } |
| | | |
| | | .phone-mockups { |
| | | margin-top: 4rem; |
| | | border-radius: 1rem; |
| | | |
| | | img { |
| | | width: 80%; |
| | | margin: 0 auto; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .follow-btn { |
| | | background: linear-gradient(135deg, #92D1FF 0%, #7BB8FF 100%); |
| | | border: none; |
| | | padding: 8px 20px; |
| | | border-radius: 10px; |
| | | color: #fff; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | box-shadow: 0 2px 8px rgba(146, 209, 255, 0.3); |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | background: linear-gradient(135deg, #7BB8FF 0%, #6BA8FF 100%); |
| | | box-shadow: 0 4px 12px rgba(146, 209, 255, 0.4); |
| | | transform: translateY(-1px); |
| | | } |
| | | |
| | | &:active { |
| | | transform: translateY(0); |
| | | /* Partners */ |
| | | .partners-section { |
| | | padding: 3rem; |
| | | background: #fff; |
| | | text-align: center; |
| | | |
| | | img { |
| | | width: 100%; |
| | | max-width: 100%; |
| | | height: auto; |
| | | display: block; |
| | | } |
| | | } |
| | | |
| | | /* 理财样式 */ |
| | | .finance-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | /* Footer Info */ |
| | | .footer-info { |
| | | padding: 3rem; |
| | | background: #fff; |
| | | display: grid; |
| | | grid-template-columns: 1fr 1fr; |
| | | gap: 4rem; |
| | | |
| | | .finance-card { |
| | | padding: 20px; |
| | | background: $main2_background; |
| | | border-radius: 12px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | border: 1px solid rgba(118, 128, 143, 0.1); |
| | | transition: all 0.3s ease; |
| | | cursor: pointer; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 12px rgba(146, 209, 255, 0.08); |
| | | transform: translateY(-2px); |
| | | border-color: rgba(146, 209, 255, 0.2); |
| | | .footer-left { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 4rem; |
| | | } |
| | | |
| | | .footer-right { |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | position: relative; |
| | | } |
| | | |
| | | .info-section { |
| | | h3 { |
| | | font-size: 2rem; |
| | | font-weight: 700; |
| | | color: $text_color; |
| | | margin-bottom: 2rem; |
| | | } |
| | | |
| | | ul { |
| | | list-style: none; |
| | | padding: 0; |
| | | |
| | | li { |
| | | font-size: 1.75rem; |
| | | color: $text_color1; |
| | | margin-bottom: 1rem; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .finance-name { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: $text_color; |
| | | letter-spacing: -0.2px; |
| | | } |
| | | |
| | | .finance-rate { |
| | | margin: 12px 0; |
| | | } |
| | | |
| | | .rate-num { |
| | | font-size: 24px; |
| | | font-weight: 700; |
| | | background: linear-gradient(135deg, #92D1FF 0%, #7BB8FF 100%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | letter-spacing: -0.5px; |
| | | } |
| | | |
| | | .rate-label { |
| | | font-size: 13px; |
| | | color: $text_color1; |
| | | margin-left: 6px; |
| | | } |
| | | |
| | | .finance-desc { |
| | | font-size: 13px; |
| | | color: $text_color1; |
| | | margin-top: 4px; |
| | | } |
| | | |
| | | .invest-btn { |
| | | background: linear-gradient(135deg, #92D1FF 0%, #7BB8FF 100%); |
| | | color: #fff; |
| | | border: none; |
| | | padding: 10px 24px; |
| | | border-radius: 12px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | box-shadow: 0 4px 12px rgba(146, 209, 255, 0.3); |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | background: linear-gradient(135deg, #7BB8FF 0%, #6BA8FF 100%); |
| | | box-shadow: 0 6px 16px rgba(146, 209, 255, 0.4); |
| | | transform: translateY(-1px); |
| | | } |
| | | |
| | | &:active { |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | /* 资讯样式 */ |
| | | .news-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .news-item { |
| | | display: flex; |
| | | gap: 16px; |
| | | padding: 16px; |
| | | border-radius: 12px; |
| | | background: $main2_background; |
| | | border: 1px solid rgba(118, 128, 143, 0.1); |
| | | transition: all 0.3s ease; |
| | | cursor: pointer; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 12px rgba(146, 209, 255, 0.08); |
| | | transform: translateY(-2px); |
| | | border-color: rgba(146, 209, 255, 0.2); |
| | | } |
| | | } |
| | | |
| | | .news-content { |
| | | flex: 1; |
| | | } |
| | | |
| | | .news-title { |
| | | font-size: 16px; |
| | | color: $text_color; |
| | | line-height: 1.5; |
| | | font-weight: 600; |
| | | display: -webkit-box; |
| | | -webkit-line-clamp: 2; |
| | | -webkit-box-orient: vertical; |
| | | overflow: hidden; |
| | | letter-spacing: -0.2px; |
| | | } |
| | | |
| | | .news-meta { |
| | | margin-top: 10px; |
| | | font-size: 12px; |
| | | color: $text_color1; |
| | | display: flex; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .news-image { |
| | | width: 100px; |
| | | height: 70px; |
| | | border-radius: 10px; |
| | | object-fit: cover; |
| | | border: 1px solid rgba(118, 128, 143, 0.1); |
| | | } |
| | | </style> |
| | | </style> |