hookehuyr

feat(AdPage): 添加图片加载状态管理和骨架屏效果

添加图片加载状态管理,包括加载中、加载成功和失败状态
实现骨架屏效果提升用户体验
添加图片加载失败时的重试功能
更新分享标题文案
......@@ -60,4 +60,124 @@
font-size: 32rpx;
color: #666;
font-weight: 500;
}
}
// 骨架屏样式
.skeleton-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 1;
}
.skeleton-image {
width: 100%;
height: 100%;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: skeleton-loading 1.5s infinite;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.skeleton-shimmer {
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.4),
transparent
);
animation: shimmer 1.5s infinite;
}
.skeleton-text {
position: relative;
z-index: 2;
text-align: center;
color: #666;
}
.loading-title {
font-size: 36rpx;
font-weight: 600;
margin-bottom: 16rpx;
opacity: 0.8;
}
.loading-subtitle {
font-size: 28rpx;
opacity: 0.6;
animation: pulse 2s infinite;
}
@keyframes skeleton-loading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
@keyframes shimmer {
0% {
left: -100%;
}
100% {
left: 100%;
}
}
@keyframes pulse {
0%, 100% {
opacity: 0.6;
}
50% {
opacity: 0.3;
}
}
// 错误提示样式
.error-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
z-index: 1;
}
.error-text {
font-size: 32rpx;
color: #999;
margin-bottom: 40rpx;
}
.retry-button {
padding: 20rpx 40rpx;
background-color: #007aff;
color: white;
border-radius: 8rpx;
font-size: 28rpx;
cursor: pointer;
&:active {
background-color: #0056cc;
}
}
......
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-19 20:19:12
* @LastEditTime: 2025-09-25 21:22:49
* @FilePath: /lls_program/src/pages/AdPage/index.vue
* @Description: 广告页面
-->
<template>
<view class="ad-page">
<!-- 骨架屏 -->
<view v-if="imageLoading" class="skeleton-container">
<view class="skeleton-image">
<view class="skeleton-shimmer"></view>
<view class="skeleton-text">
<view class="loading-title">正在加载精彩内容</view>
<view class="loading-subtitle">请稍候...</view>
</view>
</view>
</view>
<!-- 背景图片 -->
<image
v-show="!imageLoading && !imageLoadError"
:src="adImageUrl"
class="ad-background"
mode="scaleToFill"
@tap="handleImageClick"
@load="handleImageLoad"
@error="handleImageError"
/>
<!-- 图片加载失败提示 -->
<view v-if="imageLoadError" class="error-container">
<view class="error-text">图片加载失败</view>
<view class="retry-button" @tap="retryLoadImage">重试</view>
</view>
<!-- 右上角分享按钮 -->
<view class="share-button-container" @tap.stop>
<button
......@@ -44,6 +64,8 @@ import "./index.less";
const adImageUrl = ref('');
const loading = ref(true);
const hasFamily = ref(false);
const imageLoading = ref(true); // 图片加载状态
const imageLoadError = ref(false); // 图片加载错误状态
/**
* 获取广告配置
......@@ -101,6 +123,32 @@ const handleImageClick = () => {
};
/**
* 图片加载完成处理
*/
const handleImageLoad = () => {
imageLoading.value = false;
imageLoadError.value = false;
};
/**
* 图片加载失败处理
*/
const handleImageError = () => {
imageLoading.value = false;
imageLoadError.value = true;
};
/**
* 重试加载图片
*/
const retryLoadImage = () => {
imageLoading.value = true;
imageLoadError.value = false;
// 重新获取广告配置
fetchAdConfig();
};
/**
* 页面初始化
*/
onMounted(async () => {
......@@ -126,7 +174,7 @@ onMounted(async () => {
*/
const onShareAppMessage = (res) => {
const shareData = {
title: '和家一起走路、一起打卡、一起兑换',
title: '和家一起走路、一起打卡、一起兑换',
path: `/pages/AdPage/index`,
imageUrl: ''
};
......