| | |
| | | <template> |
| | | <!-- <section class="inner-tab-container"> --> |
| | | <!-- <p class="title">{{ t('news') }}</p> --> |
| | | <!-- <div class="news-container"> --> |
| | | <!-- <van-steps direction="vertical" :active="0" active-color="#fff"> --> |
| | | <!-- <van-step v-for="(item, index) in list" :key="item.uuid || index"> |
| | | <p class="time">{{ item.createTime }}</p> |
| | | <p class="context">{{ item.description }}</p> |
| | | </van-step> --> |
| | | <!-- <van-step> |
| | | <p class="time">2023-06-15 11:30</p> |
| | | <p class="context">南非汇市:兰特兑美元走高,美国通胀报告发布后美元跌至约两周地点</p> |
| | | </van-step> |
| | | <van-step> |
| | | <p class="time">2023-06-14 14:20</p> |
| | | <p class="context">降息预期遭重挫败!CPI环比增速抬头 美联储抗通胀之路注定崎岖</p> |
| | | </van-step> --> |
| | | <!-- </van-steps> --> |
| | | <!-- </div> --> |
| | | <!-- </section> --> |
| | | |
| | | <!-- 顶部用户信息栏 --> |
| | | <div class="flex items-center justify-between px-17 pt-10"> |
| | | <div class="text-20 font-bold">{{ username }}</div> |
| | |
| | | <!-- 热门货币卡片部分 --> |
| | | <div class="mt-10"> |
| | | <div class="block text-22 font-medium px-17">{{ t('热门') }}</div> |
| | | <div class="flex overflow-x-auto mt-10 px-17"> |
| | | <!-- DOGE/USDT 卡片 --> |
| | | <div class="w-140 h-160 mr-10 flex-none rounded-15 text-black" v-for="(item, index) in hotItems" :key="item" |
| | | :class="index % 2 === 1 ? 'bg-#9f9cff' : 'bg-#d8f0dd'"> |
| | | <div v-if="isLoading" class="flex overflow-x-auto mt-10 px-17"> |
| | | <Skeleton v-for="i in 3" :key="i" class="w-140 h-160 mr-10 flex-none rounded-15" title :row="4" animated |
| | | :loading="isLoading"></Skeleton> |
| | | </div> |
| | | <div v-else class="flex overflow-x-auto mt-10 px-17"> |
| | | <!-- DOGE/USDT 卡片 --> |
| | | <div class="w-140 h-160 mr-10 flex-none rounded-15 text-black" v-for="(item, index) in hotItems" |
| | | :key="item.uuid || index" :class="index % 2 === 1 ? 'bg-#9f9cff' : 'bg-#d8f0dd'"> |
| | | <div class="py-17 px-13"> |
| | | <div class="font-bold block text-18">{{ item.name }}</div> |
| | | <div class="font-bold block text-20">{{ item.ask }}</div> |
| | | <div class="w-full h-50"> |
| | | <div id="DOGEUSDT" class="w-full h-full" |
| | | style="user-select: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"> |
| | | <!-- 图表容器保持不变 --> |
| | | <div id="DOGEUSDT" class="w-full h-full relative overflow-hidden" |
| | | style="user-select: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);margin: 0 10px;"> |
| | | <!-- 添加进度条动画 --> |
| | | <div class="absolute top-10 left-0 h-1 bg-blue-500 progress-bar-animation" :style="{ width: '80%' }"> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="flex justify-between"> |
| | | <div class="py-2 px-8 rounded-full text-13 font-medium bg-white">{{item.change_ratio}}</div> |
| | | <span class="text-18">→</span> |
| | | <div class="py-2 px-8 rounded-full text-13 font-medium bg-white">{{ item.change_ratio }}</div> |
| | | <span class="text-18" :class="index % 2 === 1 ? 'c2c_color' : ''">→</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="flex justify-between text-12 mt-20"> |
| | | <div class="flex-1 flex flex-col items-center" @click="goToPage('/mining')"> |
| | | <div class="w-40 h-40 rounded-full flex items-center justify-center"> |
| | | <img class="w-33 h-33" src="@/assets/a.jpg" draggable="false"> |
| | | <img class="w-33 h-33" src="@/assets/a.jpg" draggable="false" width="33" height="33"> |
| | | </div> |
| | | <div class="text-center">{{t('理財')}}</div> |
| | | <div class="text-center">{{ t('理财') }}</div> |
| | | </div> |
| | | <div class="flex-1 flex flex-col items-center" @click="goToPage('/cryptos/trade/btcusdt')"> |
| | | <div class="flex-1 flex flex-col items-center" @click="goToPage('/cryptos/trade/USDSGD')"> |
| | | <div class="w-40 h-40 rounded-full flex items-center justify-center"> |
| | | <img class="w-33 h-33" src="@/assets/c.jpg" draggable="false"> |
| | | <img class="w-33 h-33" src="@/assets/c.jpg" draggable="false" width="33" height="33"> |
| | | </div> |
| | | <div class="text-center">{{t('币币交易')}}</div> |
| | | <div class="text-center">{{ t('外汇交易') }}</div> |
| | | </div> |
| | | <div class="flex-1 flex flex-col items-center" @click="goToPage('/cryptos/perpetualContract/USDSGD?selectIndex=2')"> |
| | | <div class="w-40 h-40 rounded-full flex items-center justify-center"> |
| | | <img class="w-33 h-33" src="@/assets/c.jpg" draggable="false"> |
| | | </div> |
| | | <div class="text-center">{{t('外汇交割')}}</div> |
| | | <div class="text-center">{{ t('货币兑换') }}</div> |
| | | </div> |
| | | <div class="flex-1 flex flex-col items-center" @click="copyInviteLink"> |
| | | <!-- <div class="flex-1 flex flex-col items-center" @click="copyInviteLink"> |
| | | <div class="w-40 h-40 rounded-full flex items-center justify-center"> |
| | | <img class="w-33 h-33" src="@/assets/d.jpg" draggable="false"> |
| | | </div> |
| | | <div class="text-center">{{t('邀请好友')}}</div> |
| | | </div> |
| | | <div class="text-center">{{ t('邀请好友') }}</div> |
| | | </div> --> |
| | | </div> |
| | | |
| | | <!-- 新手指南部分 --> |
| | | <div class="mt-20 mx-17 h-50 rounded-5 bg-#d8f0dd font-500 flex items-center justify-between text-16 px-15" @click="goToExplanation"> |
| | | <span>{{t('新手')}}</span> |
| | | <div class="i-material-symbols:arrow-right-alt-rounded text-20"></div> |
| | | <div class="mt-20 mx-17 h-50 rounded-5 bg-#d8f0dd font-500 flex items-center justify-between text-16 px-15" |
| | | @click="goToExplanation"> |
| | | <span>{{ t('新手') }}</span> |
| | | <div class="text-20">→</div> |
| | | </div> |
| | | |
| | | |
| | |
| | | |
| | | <div class="mt-20"> |
| | | <div class="flex items-end justify-between px-17"> |
| | | <span class="block text-22 font-medium">{{t('news')}}</span> |
| | | <span class="block text-22 font-medium">{{ t('news') }}</span> |
| | | </div> |
| | | <div class="px-17 mt-10"> |
| | | <div v-if="isLoading" class="px-17 mt-10 space-y-10"> |
| | | <div v-for="i in 3" :key="i" class="rounded-5 overflow-hidden"> |
| | | <div class="py-12 px-15 flex items-center space-x-4"> |
| | | <Skeleton class="flex-1" title :row="1" :loading="isLoading"></Skeleton> |
| | | <Skeleton class="w-20 h-16 rounded-10" animated :loading="isLoading"></Skeleton> |
| | | </div> |
| | | <div class="mt-5 px-15"> |
| | | <Skeleton class="w-1/4" :row="1" animated :loading="isLoading"></Skeleton> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-else class="px-17 mt-10"> |
| | | <!-- 新闻条目1 --> |
| | | <div class="rounded-5 overflow-hidden mb-10" v-for="(t , i) in list" :key="t.dataId" > |
| | | <div class="bg-#f5f7f9 py-12 px-15 " @click="openOriginUrl(t.originUrl)"> |
| | | <div class="rounded-5 overflow-hidden mb-10" v-for="(t) in list" :key="t.dataId"> |
| | | <div class="bg-#f5f7f9 py-12 px-15 "> |
| | | <div class="flex" style="border-bottom: 1px solid rgb(209, 209, 209);"> |
| | | <div class="text-12 h-70 flex-1 line3">{{ t.description }}</div> |
| | | <!-- <img class="w-90 h-55 flex-none rounded-10 ml-10" |
| | | :src="t.img" |
| | | draggable="false"> --> |
| | | <div class="text-12 h-70 flex-1 line3">{{ t.title }}</div> |
| | | <img class="w-90 h-55 flex-none rounded-10 ml-10" :src="t.imgUrl" loading="lazy" width="90" height="55" |
| | | draggable="false"> |
| | | </div> |
| | | <div class="mt-5 text-10 text-#8c8c8c flex justify-between"> |
| | | <span>{{t.createTime}}</span> |
| | | <span>{{ t.createTime }}</span> |
| | | <!-- <div>全球股市</div> --> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue'; |
| | | import { ref, onMounted, onUnmounted, computed } from 'vue'; |
| | | import { Skeleton } from 'vant'; |
| | | import { _getInformationList } from '@/service/etf.api' |
| | | import {_getHomeList} from '@/service/cryptos.api' |
| | | import { _getHomeList } from '@/service/cryptos.api' |
| | | import { showToast } from 'vant' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { useRouter } from 'vue-router' |
| | | import { _getCoinList } from '@/service/quotes.api' |
| | | import { setStorage } from '@/utils/index' |
| | | const router = useRouter() |
| | | |
| | | const { t } = useI18n() |
| | | const list = ref([]) |
| | | const hotItems = ref([]) // 热门 |
| | | const infoLoading = ref(true); |
| | | const homeLoading = ref(true); |
| | | const isLoading = computed(() => infoLoading.value || homeLoading.value); |
| | | const username = ref('') |
| | | const usercode = ref('') |
| | | |
| | |
| | | |
| | | // 从localStorage获取用户信息 |
| | | const user = JSON.parse(localStorage.getItem('user')) |
| | | console.log('user', user) |
| | | |
| | | username.value = user.userInfo?.username || '' |
| | | usercode.value = user.userInfo?.usercode || '' |
| | | |
| | | // 如果本地没有 coins,拉取接口 |
| | | const cachedQuotes = localStorage.getItem('qoutes'); |
| | | let quotesData; |
| | | if (cachedQuotes) { |
| | | quotesData = JSON.parse(cachedQuotes).coins; |
| | | } else { |
| | | quotesData = await _getCoinList(); |
| | | setStorage('qoutes', { coins: quotesData }); // 仅在获取新数据时更新缓存 |
| | | } |
| | | }) |
| | | |
| | | const goToExplanation = () => { |
| | |
| | | goToPage('/customerService') |
| | | } |
| | | const goToPage = (path) => { |
| | | router.push(path) |
| | | if (path == '/mining') { |
| | | showToast({ |
| | | message: 'Stay tuned', |
| | | position: 'bottom', |
| | | }) |
| | | } else { |
| | | router.push(path) |
| | | } |
| | | } |
| | | |
| | | const getInformationList = () => { |
| | | const cachedNews = localStorage.getItem('cachedNews'); |
| | | if (cachedNews) { |
| | | list.value = JSON.parse(cachedNews); |
| | | infoLoading.value = false; |
| | | return; |
| | | } |
| | | _getInformationList().then(data => { |
| | | list.value = data |
| | | updateNewsData(data); |
| | | infoLoading.value = false; |
| | | }) |
| | | } |
| | | |
| | | const updateNewsData = (newData) => { |
| | | const cachedNews = localStorage.getItem('cachedNews'); |
| | | if (cachedNews) { |
| | | try { |
| | | const oldData = JSON.parse(cachedNews); |
| | | // 比较新旧数据是否不同 |
| | | if (JSON.stringify(oldData) !== JSON.stringify(newData)) { |
| | | list.value = newData; |
| | | localStorage.setItem('cachedNews', JSON.stringify(newData)); |
| | | } |
| | | } catch (e) { |
| | | // 处理JSON解析错误 |
| | | localStorage.removeItem('cachedNews'); |
| | | list.value = newData; |
| | | localStorage.setItem('cachedNews', JSON.stringify(newData)); |
| | | } |
| | | } else { |
| | | list.value = newData; |
| | | localStorage.setItem('cachedNews', JSON.stringify(newData)); |
| | | } |
| | | } |
| | | |
| | | |
| | | const getHomeList = () => { |
| | | _getHomeList().then(data => { |
| | | hotItems.value = data.slice(0, 3) // 取前3条数据 |
| | | const intervalId = ref(null) |
| | | if (intervalId.value) { |
| | | clearInterval(intervalId.value) |
| | | } |
| | | |
| | | const fetchData = () => { |
| | | _getHomeList().then(data => { |
| | | hotItems.value = data.slice(0, 3) // 取前3条数据 |
| | | homeLoading.value = false |
| | | }) |
| | | } |
| | | |
| | | // 立即执行一次 |
| | | fetchData() |
| | | |
| | | intervalId.value = setInterval(fetchData, 2000) |
| | | |
| | | onUnmounted(() => { |
| | | if (intervalId.value) { |
| | | clearInterval(intervalId.value) |
| | | } |
| | | }) |
| | | |
| | | router.beforeEach((to, from, next) => { |
| | | if (from.path === '/news/index') { |
| | | clearInterval(intervalId.value) |
| | | } |
| | | next() |
| | | }) |
| | | } |
| | | |
| | | // 添加跳转方法 |
| | | const openOriginUrl = (url) => { |
| | | window.open(url, '_blank') |
| | | } |
| | | onMounted(() => { |
| | | // 初始加载新闻数据 |
| | | getInformationList(); |
| | | |
| | | const copyInviteLink = () => { |
| | | const inviteLink = 'https://www.thinkmarketga.com/#/pages/register?c=' + usercode.value // 替换为你的实际邀请链接 |
| | | navigator.clipboard.writeText(inviteLink) |
| | | .then(() => { |
| | | // 可以添加提示,比如使用Toast组件 |
| | | showToast({ |
| | | message: '邀请链接已复制', |
| | | position: 'bottom', |
| | | }) |
| | | }) |
| | | } |
| | | // 设置静默更新定时器,每5分钟检查一次 |
| | | const newsUpdateInterval = setInterval(() => { |
| | | _getInformationList().then(newData => { |
| | | updateNewsData(newData); |
| | | }).catch(error => { |
| | | console.error('Silent update failed:', error); |
| | | }); |
| | | }, 5 * 60 * 1000); // 5分钟间隔 |
| | | |
| | | onUnmounted(() => { |
| | | clearInterval(newsUpdateInterval); |
| | | }); |
| | | }); |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | @import '@/assets/css/deepseek_css_20250625_30ff932.css'; |
| | | |
| | | .line3{ |
| | | .line3 { |
| | | display: -webkit-box; |
| | | -webkit-line-clamp: 3; |
| | | -webkit-box-orient: vertical; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | .progress-bar-animation { |
| | | animation: progress 1.5s ease-in-out forwards; |
| | | transform-origin: left; |
| | | } |
| | | |
| | | @keyframes progress { |
| | | // 0% { |
| | | // transform: scaleX(0); |
| | | // } |
| | | // 100% { |
| | | // transform: scaleX(1); |
| | | // } |
| | | } |
| | | |
| | | .c2c_color { |
| | | color: #fff; |
| | | } |
| | | </style> |