hookehuyr

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

添加图片加载状态管理,包括加载中、加载成功和失败状态
实现骨架屏效果提升用户体验
添加图片加载失败时的重试功能
更新分享标题文案
...@@ -60,4 +60,124 @@ ...@@ -60,4 +60,124 @@
60 font-size: 32rpx; 60 font-size: 32rpx;
61 color: #666; 61 color: #666;
62 font-weight: 500; 62 font-weight: 500;
63 -} 63 + }
64 +
65 + // 骨架屏样式
66 + .skeleton-container {
67 + position: absolute;
68 + top: 0;
69 + left: 0;
70 + width: 100%;
71 + height: 100vh;
72 + z-index: 1;
73 + }
74 +
75 + .skeleton-image {
76 + width: 100%;
77 + height: 100%;
78 + background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
79 + background-size: 200% 100%;
80 + animation: skeleton-loading 1.5s infinite;
81 + position: relative;
82 + overflow: hidden;
83 + display: flex;
84 + flex-direction: column;
85 + justify-content: center;
86 + align-items: center;
87 + }
88 +
89 + .skeleton-shimmer {
90 + position: absolute;
91 + top: 0;
92 + left: -100%;
93 + width: 100%;
94 + height: 100%;
95 + background: linear-gradient(
96 + 90deg,
97 + transparent,
98 + rgba(255, 255, 255, 0.4),
99 + transparent
100 + );
101 + animation: shimmer 1.5s infinite;
102 + }
103 +
104 + .skeleton-text {
105 + position: relative;
106 + z-index: 2;
107 + text-align: center;
108 + color: #666;
109 + }
110 +
111 + .loading-title {
112 + font-size: 36rpx;
113 + font-weight: 600;
114 + margin-bottom: 16rpx;
115 + opacity: 0.8;
116 + }
117 +
118 + .loading-subtitle {
119 + font-size: 28rpx;
120 + opacity: 0.6;
121 + animation: pulse 2s infinite;
122 + }
123 +
124 + @keyframes skeleton-loading {
125 + 0% {
126 + background-position: 200% 0;
127 + }
128 + 100% {
129 + background-position: -200% 0;
130 + }
131 + }
132 +
133 + @keyframes shimmer {
134 + 0% {
135 + left: -100%;
136 + }
137 + 100% {
138 + left: 100%;
139 + }
140 + }
141 +
142 + @keyframes pulse {
143 + 0%, 100% {
144 + opacity: 0.6;
145 + }
146 + 50% {
147 + opacity: 0.3;
148 + }
149 + }
150 +
151 + // 错误提示样式
152 + .error-container {
153 + position: absolute;
154 + top: 0;
155 + left: 0;
156 + width: 100%;
157 + height: 100vh;
158 + display: flex;
159 + flex-direction: column;
160 + justify-content: center;
161 + align-items: center;
162 + background-color: #f5f5f5;
163 + z-index: 1;
164 + }
165 +
166 + .error-text {
167 + font-size: 32rpx;
168 + color: #999;
169 + margin-bottom: 40rpx;
170 + }
171 +
172 + .retry-button {
173 + padding: 20rpx 40rpx;
174 + background-color: #007aff;
175 + color: white;
176 + border-radius: 8rpx;
177 + font-size: 28rpx;
178 + cursor: pointer;
179 +
180 + &:active {
181 + background-color: #0056cc;
182 + }
183 + }
......
1 <!-- 1 <!--
2 * @Date: 2022-09-19 14:11:06 2 * @Date: 2022-09-19 14:11:06
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-09-19 20:19:12 4 + * @LastEditTime: 2025-09-25 21:22:49
5 * @FilePath: /lls_program/src/pages/AdPage/index.vue 5 * @FilePath: /lls_program/src/pages/AdPage/index.vue
6 * @Description: 广告页面 6 * @Description: 广告页面
7 --> 7 -->
8 <template> 8 <template>
9 <view class="ad-page"> 9 <view class="ad-page">
10 + <!-- 骨架屏 -->
11 + <view v-if="imageLoading" class="skeleton-container">
12 + <view class="skeleton-image">
13 + <view class="skeleton-shimmer"></view>
14 + <view class="skeleton-text">
15 + <view class="loading-title">正在加载精彩内容</view>
16 + <view class="loading-subtitle">请稍候...</view>
17 + </view>
18 + </view>
19 + </view>
20 +
10 <!-- 背景图片 --> 21 <!-- 背景图片 -->
11 <image 22 <image
23 + v-show="!imageLoading && !imageLoadError"
12 :src="adImageUrl" 24 :src="adImageUrl"
13 class="ad-background" 25 class="ad-background"
14 mode="scaleToFill" 26 mode="scaleToFill"
15 @tap="handleImageClick" 27 @tap="handleImageClick"
28 + @load="handleImageLoad"
29 + @error="handleImageError"
16 /> 30 />
17 31
32 + <!-- 图片加载失败提示 -->
33 + <view v-if="imageLoadError" class="error-container">
34 + <view class="error-text">图片加载失败</view>
35 + <view class="retry-button" @tap="retryLoadImage">重试</view>
36 + </view>
37 +
18 <!-- 右上角分享按钮 --> 38 <!-- 右上角分享按钮 -->
19 <view class="share-button-container" @tap.stop> 39 <view class="share-button-container" @tap.stop>
20 <button 40 <button
...@@ -44,6 +64,8 @@ import "./index.less"; ...@@ -44,6 +64,8 @@ import "./index.less";
44 const adImageUrl = ref(''); 64 const adImageUrl = ref('');
45 const loading = ref(true); 65 const loading = ref(true);
46 const hasFamily = ref(false); 66 const hasFamily = ref(false);
67 +const imageLoading = ref(true); // 图片加载状态
68 +const imageLoadError = ref(false); // 图片加载错误状态
47 69
48 /** 70 /**
49 * 获取广告配置 71 * 获取广告配置
...@@ -101,6 +123,32 @@ const handleImageClick = () => { ...@@ -101,6 +123,32 @@ const handleImageClick = () => {
101 }; 123 };
102 124
103 /** 125 /**
126 + * 图片加载完成处理
127 + */
128 +const handleImageLoad = () => {
129 + imageLoading.value = false;
130 + imageLoadError.value = false;
131 +};
132 +
133 +/**
134 + * 图片加载失败处理
135 + */
136 +const handleImageError = () => {
137 + imageLoading.value = false;
138 + imageLoadError.value = true;
139 +};
140 +
141 +/**
142 + * 重试加载图片
143 + */
144 +const retryLoadImage = () => {
145 + imageLoading.value = true;
146 + imageLoadError.value = false;
147 + // 重新获取广告配置
148 + fetchAdConfig();
149 +};
150 +
151 +/**
104 * 页面初始化 152 * 页面初始化
105 */ 153 */
106 onMounted(async () => { 154 onMounted(async () => {
...@@ -126,7 +174,7 @@ onMounted(async () => { ...@@ -126,7 +174,7 @@ onMounted(async () => {
126 */ 174 */
127 const onShareAppMessage = (res) => { 175 const onShareAppMessage = (res) => {
128 const shareData = { 176 const shareData = {
129 - title: '和家一起走路、一起打卡、一起兑换', 177 + title: '和家一起走路、一起打卡、一起兑换',
130 path: `/pages/AdPage/index`, 178 path: `/pages/AdPage/index`,
131 imageUrl: '' 179 imageUrl: ''
132 }; 180 };
......