feat(周星榜): 使用网络图片,并对接图片的缓存,预加载等功能

This commit is contained in:
hzj 2025-12-03 10:10:23 +08:00
parent f6f4aca4de
commit 078871804e
2 changed files with 94 additions and 43 deletions

View File

@ -1,5 +1,6 @@
<!-- src/views/Ranking/WeeklyStar/WeeklyStar.vue -->
<template>
<div class="fullPage">
<div class="fullPage" :style="{ '--bg-url': `url(${imageUrl('bg')})` }">
<!-- 状态栏占位区域仅在APP中显示 -->
<div v-if="isInAppEnvironment" style="height: 30px"></div>
@ -15,7 +16,7 @@
<!-- history按钮 -->
<img
v-smart-img
:src="images.history"
:src="imageUrl('history')"
alt=""
style="width: 20%; margin-top: 20px"
@click="historyShow = true"
@ -30,31 +31,37 @@
: 'calc(65vw - 10vw - 10vw - 20px)',
}"
>
<img v-smart-img :src="images.gifts" alt="" style="width: 20%" @click="giftsShow = true" />
<img
v-smart-img
:src="imageUrl('gifts')"
alt=""
style="width: 20%"
@click="giftsShow = true"
/>
</div>
<!-- 倒计时 -->
<div style="display: flex; justify-content: center; margin-top: -10%">
<div style="width: 15%">
<itemCenter :imgUrl="images.dayBg">
<itemCenter :imgUrl="imageUrl('dayBg')">
<div class="timeText">{{ Days }}D</div>
</itemCenter>
</div>
<div class="timeText timeGap" style="width: 6px"></div>
<div style="width: 15%">
<itemCenter :imgUrl="images.hourAndMinBg">
<itemCenter :imgUrl="imageUrl('hourAndMinBg')">
<div class="timeText">{{ Hours }}</div>
</itemCenter>
</div>
<div class="timeText timeGap">:</div>
<div style="width: 15%">
<itemCenter :imgUrl="images.hourAndMinBg">
<itemCenter :imgUrl="imageUrl('hourAndMinBg')">
<div class="timeText">{{ Minutes }}</div>
</itemCenter>
</div>
<div class="timeText timeGap">:</div>
<div style="width: 15%">
<itemCenter :imgUrl="images.secBg">
<itemCenter :imgUrl="imageUrl('secBg')">
<div class="timeText">{{ Second }}</div>
</itemCenter>
</div>
@ -63,17 +70,17 @@
<!-- 切换按钮 -->
<div style="margin: 22% 0 8% 0; display: flex; justify-content: space-around">
<div style="width: 30%" @click="handleBt('Ranking')">
<itemCenter :imgUrl="rankingShow ? images.btActive : images.btNoActive">
<itemCenter :imgUrl="rankingShow ? imageUrl('btActive') : imageUrl('btNoActive')">
<div class="btTitle">Ranking</div>
</itemCenter>
</div>
<div style="width: 30%" @click="handleBt('Rewards')">
<itemCenter :imgUrl="rewardShow ? images.btActive : images.btNoActive">
<itemCenter :imgUrl="rewardShow ? imageUrl('btActive') : imageUrl('btNoActive')">
<div class="btTitle">Rewards</div>
</itemCenter>
</div>
<div style="width: 30%" @click="handleBt('Exchange')">
<itemCenter :imgUrl="exchargeShow ? images.btActive : images.btNoActive">
<itemCenter :imgUrl="exchargeShow ? imageUrl('btActive') : imageUrl('btNoActive')">
<div class="btTitle">Exchange</div>
</itemCenter>
</div>
@ -88,10 +95,16 @@
>
<!-- 背景板 -->
<div>
<img v-smart-img :src="images.RankingMain" alt="" width="100%" style="display: block" />
<img
v-smart-img
:src="images.RankingItem"
:src="imageUrl('RankingMain')"
alt=""
width="100%"
style="display: block"
/>
<img
v-smart-img
:src="imageUrl('RankingItem')"
alt=""
width="100%"
style="display: block; margin-top: -2px"
@ -100,7 +113,7 @@
/>
<img
v-smart-img
:src="images.RankingBottomBorder"
:src="imageUrl('RankingBottomBorder')"
alt=""
width="100%"
style="display: block; margin-top: -12%"
@ -114,7 +127,7 @@
<!-- 第一 -->
<div style="display: flex; justify-content: center">
<TopUser
:BorderImgUrl="images.topOne"
:BorderImgUrl="imageUrl('topOne')"
:avatarUrl="RankingHasTop3[0].userAvatar"
:name="RankingHasTop3[0].userNickname"
:distributionValue="RankingHasTop3[0].quantity"
@ -126,7 +139,7 @@
<div style="display: flex; justify-content: space-between; margin-top: -20%">
<TopUser
:isTopOne="false"
:BorderImgUrl="images.topTwo"
:BorderImgUrl="imageUrl('topTwo')"
:avatarUrl="RankingHasTop3[1].userAvatar"
:name="RankingHasTop3[1].userNickname"
:distributionValue="RankingHasTop3[1].quantity"
@ -135,7 +148,7 @@
/>
<TopUser
:isTopOne="false"
:BorderImgUrl="images.topThree"
:BorderImgUrl="imageUrl('topThree')"
:avatarUrl="RankingHasTop3[2].userAvatar"
:name="RankingHasTop3[2].userNickname"
:distributionValue="RankingHasTop3[2].quantity"
@ -150,7 +163,7 @@
v-for="listItem in showRanking"
style="margin-top: 3%; position: relative"
@click="viewUserInfo(listItem.userId)"
:imgUrl="images.itemUser"
:imgUrl="imageUrl('itemUser')"
:contentStyle="`justify-content: flex-start;padding: 0 3%;gap: 4px;`"
>
<!-- 基本信息 -->
@ -232,7 +245,7 @@
<!-- top模块 -->
<div v-for="(topItem, topIndex) in rewardsList" style="position: relative; width: 90%">
<!-- top背景图 -->
<img v-smart-img :src="images.topBg" alt="" style="width: 100%; display: block" />
<img v-smart-img :src="imageUrl('topBg')" alt="" style="width: 100%; display: block" />
<!-- 标题 -->
<div
style="
@ -265,7 +278,7 @@
v-for="gift in topItem.propsGroup.activityRewardProps"
style="display: flex; flex-direction: column; align-items: center"
>
<itemCenter :imgUrl="images.giftItemBg" style="width: 90%; margin-bottom: 3px">
<itemCenter :imgUrl="imageUrl('giftItemBg')" style="width: 90%; margin-bottom: 3px">
<!-- gift图 -->
<img
v-smart-img
@ -276,7 +289,7 @@
/>
</itemCenter>
<itemCenter :imgUrl="images.btBg" style="width: 75%">
<itemCenter :imgUrl="imageUrl('btBg')" style="width: 75%">
<div style="font-weight: 700">
{{ showDetail(gift.type, gift.quantity) }}
</div>
@ -290,7 +303,7 @@
<div v-show="exchargeShow" style="display: flex; justify-content: center">
<div style="position: relative; width: 90%">
<!-- 背景图 -->
<img v-smart-img :src="images.longBg" alt="" style="width: 100%; display: block" />
<img v-smart-img :src="imageUrl('longBg')" alt="" style="width: 100%; display: block" />
<!-- 标题 -->
<div
style="
@ -326,7 +339,7 @@
<div style="display: flex; align-items: center">
<img
v-smart-img
:src="images.debris"
:src="imageUrl('debris')"
alt=""
style="width: 15%; display: block; margin-right: 5px"
/>
@ -340,7 +353,7 @@
:key="goodsIndex"
style="display: flex; flex-direction: column; align-items: center"
>
<itemCenter :imgUrl="images.giftItemBg">
<itemCenter :imgUrl="imageUrl('giftItemBg')">
<!-- gift图 -->
<img
v-smart-img
@ -353,7 +366,11 @@
Permanent/{{ JSON.parse(goods.rule.jsonData).need_fragments }} Star
</div>
<itemCenter style="width: 75%" @click="selectGood(goods)" :imgUrl="images.btBg">
<itemCenter
style="width: 75%"
@click="selectGood(goods)"
:imgUrl="imageUrl('btBg')"
>
<div style="font-weight: 700" class="needDebris">Redeem</div>
</itemCenter>
</div>
@ -381,7 +398,7 @@
>
<img
v-smart-img
:src="images.myRankingBg"
:src="imageUrl('myRankingBg')"
alt=""
style="width: calc(100% - 1px); display: block"
/>
@ -469,13 +486,13 @@
<maskLayer :maskLayerShow="maskLayerShow" @click="closedPopup">
<!-- help弹窗 -->
<div v-show="helpInfoShow" style="margin: 20% 0" @click.stop>
<img v-smart-img :src="images.helpInfo" alt="" style="width: 100%" />
<img v-smart-img :src="imageUrl('helpInfo')" alt="" style="width: 100%" />
</div>
<!-- history弹窗 -->
<div v-show="historyShow" style="position: relative; margin: 20% 0" @click.stop>
<!-- 背景图 -->
<img v-smart-img :src="images.mediumBg" alt="" style="width: 100%; display: block" />
<img v-smart-img :src="imageUrl('mediumBg')" alt="" style="width: 100%; display: block" />
<!-- 标题 -->
<div
style="
@ -514,7 +531,7 @@
<!-- 头像框 -->
<img
v-smart-img
:src="images.topOneHistory"
:src="imageUrl('topOneHistory')"
alt=""
style="width: 100%; display: block; position: relative; z-index: 1"
/>
@ -542,7 +559,7 @@
<!-- 名字 -->
<div style="position: relative; width: 25%">
<!-- 背景图 -->
<img v-smart-img :src="images.nameBg" alt="" style="width: 100%; display: block" />
<img v-smart-img :src="imageUrl('nameBg')" alt="" style="width: 100%; display: block" />
<div
style="
position: absolute;
@ -616,13 +633,13 @@
v-show="giftsShow"
style="margin: 20% 0"
@click.stop
:imgUrl="images.giftsBg"
:imgUrl="imageUrl('giftsBg')"
:contentStyle="`padding: 30% 5% 12%;display: flex;justify-content: space-between;`"
>
<!-- 礼物单元 -->
<div style="width: 30%" v-for="gift in gifts" :key="gift.id">
<!-- 礼物背景 -->
<itemCenter :imgUrl="images.giftItemBg">
<itemCenter :imgUrl="imageUrl('giftItemBg')">
<!-- 礼物 -->
<img
v-smart-img
@ -650,7 +667,7 @@
<!-- 交易商品弹窗 -->
<div v-if="exchargeGoodsShow" style="position: relative; margin: 20% 0" @click.stop>
<!-- 背景图 -->
<img v-smart-img :src="images.mediumBg" alt="" style="width: 100%; display: block" />
<img v-smart-img :src="imageUrl('mediumBg')" alt="" style="width: 100%; display: block" />
<!-- 标题 -->
<div
style="
@ -693,7 +710,7 @@
<div>Permanent/{{ JSON.parse(selectedGood.rule.jsonData).need_fragments }} Star</div>
<img
v-smart-img
:src="images.ConfirmBt"
:src="imageUrl('ConfirmBt')"
alt=""
style="width: 30%; display: block"
@click="exchangeSelectedGood(selectedGood.rule.id)"
@ -710,6 +727,8 @@ import { isInApp, viewUserInfo } from '@/utils/appBridge.js'
import { connectToApp } from '@/utils/appConnector.js'
import { useThrottle } from '@/utils/useDebounce'
import { showWarning } from '@/utils/toast.js'
import { getPngUrl } from '@/config/imagePaths.js'
import { preloadImages } from '@/utils/imagePreloader.js'
import { getMemberProfile } from '@/api/wallet'
import {
@ -727,15 +746,8 @@ import itemCenter from '@/components/itemCenter.vue'
import maskLayer from '@/components/MaskLayer.vue'
import TopUser from './components/topUser.vue'
//vite
const imageModules = import.meta.glob('@/assets/images/WeeklyStar/*.{png,jpg,svg}', { eager: true })
//
const images = Object.fromEntries(
Object.entries(imageModules).map(([Path2D, module]) => {
const fileName = Path2D.split('/').pop().split('.')[0]
return [fileName, module.default]
})
)
// OSSURL
const imageUrl = (filename) => getPngUrl('Ranking/WeeklyStar/', filename)
// 使APP
const connectToAppHandler = async () => {
@ -743,6 +755,7 @@ const connectToAppHandler = async () => {
//
getUserInfo()
updatePageData() //
preloadCriticalImages() //
})
}
@ -1050,6 +1063,41 @@ const updatePageData = () => {
getThisWeekExchangeGoods() //
}
//
const preloadCriticalImages = () => {
const criticalImages = [
imageUrl('bg'),
imageUrl('history'),
imageUrl('gifts'),
imageUrl('dayBg'),
imageUrl('hourAndMinBg'),
imageUrl('secBg'),
imageUrl('btActive'),
imageUrl('btNoActive'),
imageUrl('RankingMain'),
imageUrl('RankingItem'),
imageUrl('RankingBottomBorder'),
imageUrl('topOne'),
imageUrl('topTwo'),
imageUrl('topThree'),
imageUrl('itemUser'),
imageUrl('topBg'),
imageUrl('giftItemBg'),
imageUrl('btBg'),
imageUrl('longBg'),
imageUrl('debris'),
imageUrl('myRankingBg'),
imageUrl('helpInfo'),
imageUrl('mediumBg'),
imageUrl('topOneHistory'),
imageUrl('nameBg'),
imageUrl('giftsBg'),
imageUrl('ConfirmBt'),
]
preloadImages(criticalImages, { useSmartCache: true })
}
const debouceGetThisWeekRanking = useThrottle(() => {
getThisWeekRanking()
}, 1000)
@ -1094,7 +1142,7 @@ onUnmounted(() => {
width: 100vw;
min-height: 100vh;
background-color: #311300;
background-image: url('@/assets/images/WeeklyStar/bg.png');
background-image: var(--bg-url);
background-size: 100% auto;
background-repeat: no-repeat;
position: relative;

View File

@ -1,3 +1,4 @@
<!-- src/views/Ranking/WeeklyStar/components/topUser.vue -->
<template>
<div style="width: 100%">
<div style="position: relative">
@ -74,6 +75,8 @@
</template>
<script setup>
import { getPngUrl } from '@/config/imagePaths.js'
const props = defineProps({
isTopOne: {
type: Boolean,