hookehuyr

feat(AdPage): 添加网络错误弹窗及降级图片处理逻辑

当广告图片加载失败时显示网络错误弹窗,并提供操作指引
初始化时使用默认图片作为降级方案,优化错误处理流程
......@@ -43,6 +43,106 @@
}
}
/* 网络错误弹窗样式 */
.network-error-popup {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
.popup-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(4rpx);
-webkit-backdrop-filter: blur(4rpx);
}
.popup-content {
position: relative;
width: 600rpx;
background: white;
border-radius: 24rpx;
padding: 60rpx 40rpx 40rpx;
text-align: center;
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.15);
.popup-icon {
font-size: 80rpx;
margin-bottom: 20rpx;
}
.popup-title {
font-size: 36rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
}
.popup-message {
font-size: 28rpx;
color: #666;
line-height: 1.5;
margin-bottom: 30rpx;
}
.popup-steps {
text-align: left;
margin-bottom: 40rpx;
.step-item {
font-size: 26rpx;
color: #888;
line-height: 1.6;
margin-bottom: 10rpx;
padding-left: 20rpx;
}
}
.popup-buttons {
display: flex;
gap: 20rpx;
.popup-button {
flex: 1;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 500;
transition: all 0.3s ease;
&.cancel {
background: #f5f5f5;
color: #666;
&:active {
background: #e8e8e8;
}
}
&.confirm {
background: #ff6b35;
color: white;
&:active {
background: #e55a2b;
}
}
}
}
}
}
.loading-container {
position: absolute;
top: 0;
......
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-28 14:03:53
* @LastEditTime: 2025-09-28 14:08:23
* @FilePath: /lls_program/src/pages/AdPage/index.vue
* @Description: 广告页面
-->
......@@ -36,7 +36,7 @@
<!-- 背景图片 -->
<image
v-show="!imageLoading && !imageLoadError"
:src="adImageUrl || defaultAdImage"
:src="adImageUrl"
class="ad-background"
mode="scaleToFill"
@tap="handleImageClick"
......@@ -64,6 +64,30 @@
<view v-if="loading" class="loading-container">
<view class="loading-text">加载中...</view>
</view>
<!-- 网络错误提示弹窗 -->
<view v-if="showNetworkErrorPopup" class="network-error-popup">
<view class="popup-overlay" @tap="closeNetworkErrorPopup"></view>
<view class="popup-content">
<view class="popup-icon">⚠️</view>
<view class="popup-title">网络不稳定</view>
<view class="popup-message">
当前网络连接不稳定,建议您:
</view>
<view class="popup-steps">
<view class="step-item">1. 检查网络连接</view>
<view class="step-item">2. 删除小程序后重新进入</view>
</view>
<view class="popup-buttons">
<view class="popup-button cancel" @tap="closeNetworkErrorPopup">
我知道了
</view>
<view class="popup-button confirm" @tap="deleteAndReenter">
删除重进
</view>
</view>
</view>
</view>
</view>
</template>
......@@ -79,7 +103,7 @@ import "./index.less";
const defaultAdImage = 'https://cdn.ipadbiz.cn/space_34093/%E5%BC%95%E5%AF%BC%E9%A1%B51_Fu2ZY_Tm6TL1OzbyrqQkeVRAdVfU.jpg?imageMogr2/strip/quality/60';
// 定义响应式数据
const adImageUrl = ref('');
const adImageUrl = ref(defaultAdImage); // 初始化为默认图片
const loading = ref(true);
const hasFamily = ref(false);
const imageLoading = ref(true); // 图片加载状态
......@@ -89,6 +113,8 @@ const retryCount = ref(0); // 重试次数
const maxRetries = ref(3); // 最大重试次数
const isTimeout = ref(false); // 是否超时
const showManualRefresh = ref(false); // 是否显示手动刷新按钮
const showNetworkErrorPopup = ref(false); // 是否显示网络错误弹窗
const useFallbackImage = ref(false); // 是否使用降级图片
/**
* 获取广告配置
......@@ -96,15 +122,45 @@ const showManualRefresh = ref(false); // 是否显示手动刷新按钮
const fetchAdConfig = async () => {
try {
const { code, data } = await getBootPageAPI();
if (code && data) {
if (code && data && data.adImageUrl) {
adImageUrl.value = data.adImageUrl;
useFallbackImage.value = false;
return true;
} else {
throw new Error('广告配置数据无效');
}
} catch (error) {
console.error('获取广告配置失败:', error);
// 使用降级图片
adImageUrl.value = defaultAdImage;
useFallbackImage.value = true;
throw error;
}
};
/**
* 关闭网络错误弹窗
*/
const closeNetworkErrorPopup = () => {
showNetworkErrorPopup.value = false;
};
/**
* 删除小程序并重新进入的提示
*/
const deleteAndReenter = () => {
Taro.showModal({
title: '操作提示',
content: '请按以下步骤操作:\n1. 点击右上角"..."菜单\n2. 选择"删除"小程序\n3. 重新搜索进入小程序',
showCancel: false,
confirmText: '我知道了',
success: () => {
closeNetworkErrorPopup();
}
});
};
/**
* 检查用户是否加入家庭
*/
const checkUserFamily = async () => {
......@@ -238,11 +294,19 @@ const handleLoadingTimeout = () => {
retryLoadImage();
}, 1000);
} else {
// 超过最大重试次数,显示手动刷新选项
// 超过最大重试次数
imageLoading.value = false;
loading.value = false;
showManualRefresh.value = true;
console.error('图片加载失败,已达到最大重试次数');
// 如果使用的是降级图片,显示网络错误弹窗
if (useFallbackImage.value) {
showNetworkErrorPopup.value = true;
console.log('使用降级图片,显示网络错误提示');
} else {
// 否则显示手动刷新选项
showManualRefresh.value = true;
console.error('图片加载失败,已达到最大重试次数');
}
}
};
......@@ -276,43 +340,48 @@ const initializePage = async () => {
await fetchAdConfig();
adConfigSuccess = true;
} catch (adError) {
console.error('获取广告配置失败,但继续执行后续逻辑:', adError);
console.error('获取广告配置失败,使用降级图片:', adError);
adConfigSuccess = false; // 使用降级图片也算是一种"成功"
}
// 无论广告配置是否成功,都要检查家庭状态
try {
await checkUserFamily();
// 如果家庭状态检查成功,但广告配置失败了,再次尝试获取广告配置
// 如果广告配置失败了(使用降级图片),再次尝试获取广告配置
if (!adConfigSuccess) {
try {
await fetchAdConfig();
adConfigSuccess = true;
console.log('重试获取广告配置成功');
} catch (retryError) {
console.error('重试获取广告配置仍然失败:', retryError);
console.error('重试获取广告配置仍然失败,继续使用降级图片:', retryError);
}
}
// 如果广告配置成功,清除超时定时器并设置成功状态
if (adConfigSuccess) {
clearLoadingTimeout();
imageLoading.value = false;
imageLoadError.value = false;
} else {
// 广告配置失败,触发重试逻辑
imageLoadError.value = true;
handleLoadingTimeout();
// 清除超时定时器并设置成功状态
clearLoadingTimeout();
imageLoading.value = false;
imageLoadError.value = false;
// 如果最终还是使用降级图片,显示网络错误提示
if (useFallbackImage.value) {
setTimeout(() => {
showNetworkErrorPopup.value = true;
}, 1000); // 延迟1秒显示,让用户先看到页面
}
} catch (familyError) {
console.error('检查家庭状态失败:', familyError);
// 家庭状态检查失败,但仍然尝试显示广告
if (adConfigSuccess) {
clearLoadingTimeout();
imageLoading.value = false;
} else {
handleLoadingTimeout();
clearLoadingTimeout();
imageLoading.value = false;
// 如果使用降级图片,显示网络错误提示
if (useFallbackImage.value) {
setTimeout(() => {
showNetworkErrorPopup.value = true;
}, 1000);
}
}
} catch (error) {
......