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

This commit is contained in:
hzj 2025-12-02 17:26:48 +08:00
parent 22bd6a106d
commit ce99c7978e

View File

@ -1,7 +1,7 @@
<!-- src/views/Activities/heroesDay/index.vue --> <!-- src/views/Activities/Yemen/IndependenceDay/index.vue -->
<template> <template>
<div class="fullPage"> <div class="fullPage">
<div class="bg"> <div class="bg" :style="{ '--bg-url': `url(${imageUrl('bg')})` }">
<!-- 状态栏占位区域仅在APP中显示 --> <!-- 状态栏占位区域仅在APP中显示 -->
<div v-if="isInAppEnvironment" style="height: 30px"></div> <div v-if="isInAppEnvironment" style="height: 30px"></div>
@ -20,25 +20,25 @@
<!-- 倒计时 --> <!-- 倒计时 -->
<div style="display: flex; justify-content: center; margin-top: 0vw"> <div style="display: flex; justify-content: center; margin-top: 0vw">
<div style="width: 20%"> <div style="width: 20%">
<itemCenter :imgUrl="images.timeBg"> <itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Days }}D</div> <div class="timeText" style="">{{ Days }}D</div>
</itemCenter> </itemCenter>
</div> </div>
<div class="timeText timeGap"></div> <div class="timeText timeGap"></div>
<div style="width: 20%"> <div style="width: 20%">
<itemCenter :imgUrl="images.timeBg"> <itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Hours }}</div> <div class="timeText" style="">{{ Hours }}</div>
</itemCenter> </itemCenter>
</div> </div>
<div class="timeText timeGap">:</div> <div class="timeText timeGap">:</div>
<div style="width: 20%"> <div style="width: 20%">
<itemCenter :imgUrl="images.timeBg"> <itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Minutes }}</div> <div class="timeText" style="">{{ Minutes }}</div>
</itemCenter> </itemCenter>
</div> </div>
<div class="timeText timeGap">:</div> <div class="timeText timeGap">:</div>
<div style="width: 20%"> <div style="width: 20%">
<itemCenter :imgUrl="images.timeBg"> <itemCenter :imgUrl="imageUrl('timeBg')">
<div class="timeText" style="">{{ Second }}</div> <div class="timeText" style="">{{ Second }}</div>
</itemCenter> </itemCenter>
</div> </div>
@ -46,21 +46,22 @@
<!-- 每周礼物 --> <!-- 每周礼物 -->
<div style="display: flex; justify-content: center; margin-top: 10px"> <div style="display: flex; justify-content: center; margin-top: 10px">
<itemCenter :imgUrl="images.giftsBg" :contentStyle="'paddingTop: 5%;'"> <itemCenter :imgUrl="imageUrl('giftsBg')" :contentStyle="'paddingTop: 5%;'">
<div style="width: 85%; display: flex; justify-content: space-around; margin-top: 10%"> <div style="width: 85%; display: flex; justify-content: space-around; margin-top: 10%">
<div <div
v-for="(gift, index) in gifts" v-for="(gift, index) in gifts"
:key="index" :key="index"
style="width: 30%; display: flex; flex-direction: column" style="width: 30%; display: flex; flex-direction: column"
> >
<itemCenter :imgUrl="images.giftItemBg" <itemCenter :imgUrl="imageUrl('giftItemBg')">
><img <img
v-smart-img v-smart-img
:src="gift.giftPhoto" :src="gift.giftPhoto"
alt="" alt=""
width="70%" width="70%"
style="display: block; object-fit: cover" style="display: block; object-fit: cover"
/></itemCenter> />
</itemCenter>
<div style="display: flex; justify-content: center; align-items: center; gap: 5px"> <div style="display: flex; justify-content: center; align-items: center; gap: 5px">
<img <img
v-smart-img v-smart-img
@ -78,21 +79,46 @@
</div> </div>
<!-- 切换按钮 --> <!-- 切换按钮 -->
<div style="display: flex; justify-content: space-around"> <div style="display: flex; justify-content: space-around; margin-top: 2vw">
<img <!-- 排行榜按钮 -->
v-smart-img <div style="width: 40%; position: relative">
:src="rankingShow ? images.rankingBtActive : images.rankingBt" <img
alt="" v-smart-img
style="display: block; width: 40%" :src="imageUrl('rankingBt')"
@click="rankingShow = true" alt=""
/> style="display: block; width: 100%"
<img :style="{ opacity: rankingShow ? 0 : 1 }"
v-smart-img @click="rankingShow = true"
:src="!rankingShow ? images.rewardBtActive : images.rewardsBt" />
alt="" <img
style="display: block; width: 40%" v-smart-img
@click="rankingShow = false" :src="imageUrl('rankingBtActive')"
/> alt=""
style="display: block; width: 100%; position: absolute; top: 0; left: 0"
:style="{ opacity: rankingShow ? 1 : 0 }"
@click="rankingShow = true"
/>
</div>
<!-- 奖励按钮 -->
<div style="width: 40%; position: relative">
<img
v-smart-img
:src="imageUrl('rewardsBt')"
alt=""
style="display: block; width: 100%"
:style="{ opacity: rankingShow ? 1 : 0 }"
@click="rankingShow = false"
/>
<img
v-smart-img
:src="imageUrl('rewardBtActive')"
alt=""
style="display: block; width: 100%; position: absolute; top: 0; left: 0"
:style="{ opacity: rankingShow ? 0 : 1 }"
@click="rankingShow = false"
/>
</div>
</div> </div>
<!-- 展示内容 --> <!-- 展示内容 -->
@ -100,19 +126,22 @@
<!-- Ranking --> <!-- Ranking -->
<div v-show="rankingShow" style="position: relative; width: 100%"> <div v-show="rankingShow" style="position: relative; width: 100%">
<!-- 背景图 --> <!-- 背景图 -->
<div class="ranking-bg"></div> <div
class="ranking-bg"
:style="{ '--ranking-bg-url': `url(${imageUrl('RankingBg')})` }"
></div>
<div style="position: relative; z-index: 1"> <div style="position: relative; z-index: 1">
<!-- 前三名 --> <!-- 前三名 -->
<itemCenter <itemCenter
:imgUrl="images.RankingMain" :imgUrl="imageUrl('RankingMain')"
:contentStyle="`padding: 20% 5% 0;flex-direction: column;`" :contentStyle="`padding: 20% 5% 0;flex-direction: column;`"
> >
<div> <div>
<!-- 第一 --> <!-- 第一 -->
<div style="display: flex; justify-content: center"> <div style="display: flex; justify-content: center">
<TopUser <TopUser
:BorderImgUrl="images.topOne" :BorderImgUrl="imageUrl('topOne')"
:avatarUrl="RankingHasTop3[0].avatar" :avatarUrl="RankingHasTop3[0].avatar"
:name="RankingHasTop3[0].nickname" :name="RankingHasTop3[0].nickname"
:distributionValue="RankingHasTop3[0].quantity" :distributionValue="RankingHasTop3[0].quantity"
@ -125,7 +154,7 @@
<TopUser <TopUser
:isTopOne="false" :isTopOne="false"
ranking="2" ranking="2"
:BorderImgUrl="images.topTwo" :BorderImgUrl="imageUrl('topTwo')"
:avatarUrl="RankingHasTop3[1].avatar" :avatarUrl="RankingHasTop3[1].avatar"
:name="RankingHasTop3[1].nickname" :name="RankingHasTop3[1].nickname"
:distributionValue="RankingHasTop3[1].quantity" :distributionValue="RankingHasTop3[1].quantity"
@ -135,7 +164,7 @@
<TopUser <TopUser
:isTopOne="false" :isTopOne="false"
ranking="3" ranking="3"
:BorderImgUrl="images.topThree" :BorderImgUrl="imageUrl('topThree')"
:avatarUrl="RankingHasTop3[2].avatar" :avatarUrl="RankingHasTop3[2].avatar"
:name="RankingHasTop3[2].nickname" :name="RankingHasTop3[2].nickname"
:distributionValue="RankingHasTop3[2].quantity" :distributionValue="RankingHasTop3[2].quantity"
@ -149,9 +178,12 @@
<!-- 第四名开始 --> <!-- 第四名开始 -->
<div v-if="showRanking.length > 0" style="margin-bottom: 6vw"> <div v-if="showRanking.length > 0" style="margin-bottom: 6vw">
<itemCenter <itemCenter
v-for="listItem in showRanking" v-for="(listItem, index) in showRanking"
:imgUrl="images.RankingItem" :key="listItem.userId"
:imgUrl="imageUrl('RankingItem')"
:contentStyle="`padding: 0 10%`" :contentStyle="`padding: 0 10%`"
:lazy="true"
:immediate="index < 2"
@click="viewUserInfo(listItem.userId)" @click="viewUserInfo(listItem.userId)"
> >
<!-- 基本信息 --> <!-- 基本信息 -->
@ -234,7 +266,7 @@
<!-- 底框 --> <!-- 底框 -->
<img <img
v-smart-img v-smart-img
:src="images.RankingBottomBorder" :src="imageUrl('RankingBottomBorder')"
alt="" alt=""
width="100%" width="100%"
style="display: block; margin-top: -22vw; position: relative; z-index: 9" style="display: block; margin-top: -22vw; position: relative; z-index: 9"
@ -261,7 +293,7 @@
:key="rewardIndex" :key="rewardIndex"
style="width: 100%" style="width: 100%"
> >
<itemCenter :imgUrl="images.giftItemBg"> <itemCenter :imgUrl="imageUrl('giftItemBg')">
<img <img
v-smart-img v-smart-img
:src="reward.cover || ''" :src="reward.cover || ''"
@ -271,7 +303,7 @@
@error="(e) => handleImageError(e, reward.type)" @error="(e) => handleImageError(e, reward.type)"
/> />
</itemCenter> </itemCenter>
<div class="valueBg" style="position: relative"> <div class="valueBg" :style="{ '--value-bg-url': `url(${imageUrl('valueBg')})` }">
<div <div
style=" style="
text-align: center; text-align: center;
@ -307,7 +339,7 @@
<!-- 我的排名 --> <!-- 我的排名 -->
<itemCenter <itemCenter
style="position: fixed; bottom: 0; z-index: 2" style="position: fixed; bottom: 0; z-index: 2"
:imgUrl="images.myRankingBg" :imgUrl="imageUrl('myRankingBg')"
:contentStyle="`padding: 2% 7% 0`" :contentStyle="`padding: 2% 7% 0`"
> >
<!-- 基本信息 --> <!-- 基本信息 -->
@ -386,7 +418,7 @@
<maskLayer :maskLayerShow="maskLayerShow" @click="maskLayerShow = false"> <maskLayer :maskLayerShow="maskLayerShow" @click="maskLayerShow = false">
<!-- help弹窗 --> <!-- help弹窗 -->
<div style="margin: 20% 0" @click.stop> <div style="margin: 20% 0" @click.stop>
<img v-smart-img :src="images.helpInfo" alt="" style="display: block; width: 100%" /> <img v-smart-img :src="imageUrl('helpInfo')" alt="" style="display: block; width: 100%" />
</div> </div>
</maskLayer> </maskLayer>
</div> </div>
@ -396,28 +428,18 @@
<script setup> <script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue' import { computed, onMounted, onUnmounted, ref } from 'vue'
import { isInApp, viewUserInfo } from '@/utils/appBridge.js' import { isInApp, viewUserInfo } from '@/utils/appBridge.js'
import { connectToApp } from '@/utils/appConnector.js'
import { getPngUrl } from '@/config/imagePaths.js'
import { preloadImages } from '@/utils/imagePreloader.js'
import { getThisWeekRewardsAndGifts, getRankingListAndMyRanking } from '@/api/activity.js' import { getThisWeekRewardsAndGifts, getRankingListAndMyRanking } from '@/api/activity.js'
import { connectToApp } from '@/utils/appConnector.js'
import itemCenter from '@/components/itemCenter.vue' import itemCenter from '@/components/itemCenter.vue'
import TopUser from './components/topUser.vue' import TopUser from './components/topUser.vue'
import maskLayer from '@/components/MaskLayer.vue' import maskLayer from '@/components/MaskLayer.vue'
// vite // OSSURL
const imageModules = import.meta.glob( const imageUrl = (filename) => getPngUrl('Activities/Yemen/IndependenceDay/', filename)
'@/assets/images/Activities/Yemen/IndependenceDay/*.{png,jpg,svg}',
{
eager: true,
}
)
//
const images = Object.fromEntries(
Object.entries(imageModules).map(([path, module]) => {
const fileName = path.split('/').pop().split('.')[0]
return [fileName, module.default]
})
)
const isInAppEnvironment = ref(false) // APP const isInAppEnvironment = ref(false) // APP
const maskLayerShow = ref(false) // const maskLayerShow = ref(false) //
@ -437,7 +459,7 @@ const myRanking = ref({}) // 我的排名
const rewardsList = ref([]) // const rewardsList = ref([]) //
const gifts = ref([]) // const gifts = ref([]) //
const topImg = ref([images.top1RewardBg, images.top2RewardBg, images.top3RewardBg]) // top const topImg = ref([imageUrl('top1RewardBg'), imageUrl('top2RewardBg'), imageUrl('top3RewardBg')]) // top
// 3 // 3
const RankingHasTop3 = computed(() => { const RankingHasTop3 = computed(() => {
@ -456,7 +478,6 @@ const RankingHasTop3 = computed(() => {
// //
const showRanking = computed(() => { const showRanking = computed(() => {
return Ranking.value.filter((_, index) => index >= 3) return Ranking.value.filter((_, index) => index >= 3)
// return []
}) })
// //
@ -553,11 +574,41 @@ const initData = () => {
getRewardsAndGifts() // getRewardsAndGifts() //
} }
//
const preloadCriticalImages = () => {
const criticalImages = [
imageUrl('bg'),
imageUrl('timeBg'),
imageUrl('rankingBt'),
imageUrl('rankingBtActive'),
imageUrl('rewardBtActive'),
imageUrl('rewardsBt'),
imageUrl('RankingMain'),
imageUrl('RankingBg'),
imageUrl('topOne'),
imageUrl('topTwo'),
imageUrl('topThree'),
imageUrl('RankingItem'),
imageUrl('RankingBottomBorder'),
imageUrl('myRankingBg'),
imageUrl('helpInfo'),
imageUrl('top1RewardBg'),
imageUrl('top2RewardBg'),
imageUrl('top3RewardBg'),
imageUrl('giftItemBg'),
imageUrl('giftsBg'),
imageUrl('valueBg'),
]
preloadImages(criticalImages, { useSmartCache: true })
}
// 使APP // 使APP
const connectToAppHandler = async () => { const connectToAppHandler = async () => {
await connectToApp(() => { await connectToApp(() => {
// //
initData() // initData() //
preloadCriticalImages() //
}) })
} }
@ -589,7 +640,7 @@ onUnmounted(() => {
.bg { .bg {
width: 100vw; width: 100vw;
min-height: 100vh; min-height: 100vh;
background-image: url(../../../../assets/images/Activities/Yemen/IndependenceDay/bg.png); background-image: var(--bg-url);
background-size: 100% auto; background-size: 100% auto;
background-repeat: no-repeat; background-repeat: no-repeat;
position: relative; position: relative;
@ -597,10 +648,11 @@ onUnmounted(() => {
} }
.valueBg { .valueBg {
background-image: url(../../../../assets/images/Activities/Yemen/IndependenceDay/valueBg.png); background-image: var(--value-bg-url);
background-size: auto 100%; background-size: auto 100%;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center center; background-position: center center;
position: relative;
} }
.timeText { .timeText {
@ -621,7 +673,7 @@ onUnmounted(() => {
.ranking-bg { .ranking-bg {
background-color: linear-gradient(180deg, #7c0101 0%, #400000 100%), #d9d9d9; background-color: linear-gradient(180deg, #7c0101 0%, #400000 100%), #d9d9d9;
background-image: url(../../../../assets/images/Activities/Yemen/IndependenceDay/RankingBg.png); background-image: var(--ranking-bg-url);
background-size: 100% auto; background-size: 100% auto;
background-repeat: no-repeat; background-repeat: no-repeat;