index.vue 8.86 KB
<!--
 * @Date: 2022-09-19 14:11:06
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-09-28 14:03:53
 * @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">
            {{ retryCount > 0 ? `正在重试加载 (${retryCount}/${maxRetries})` : '正在加载精彩内容' }}
          </view>
          <view class="loading-subtitle">请稍候...</view>
        </view>
      </view>
    </view>

    <!-- 手动刷新提示 -->
    <view v-if="showManualRefresh" class="manual-refresh-container">
      <view class="refresh-content">
        <view class="refresh-icon">⚠️</view>
        <view class="refresh-title">网络连接异常</view>
        <view class="refresh-subtitle">请检查网络连接后重新进入小程序</view>
        <view class="refresh-steps">
          <view class="step-item">1. 点击右上角 ⋯ 菜单</view>
          <view class="step-item">2. 选择重新进入小程序</view>
        </view>
      </view>
    </view>

    <!-- 背景图片 -->
    <image
      v-show="!imageLoading && !imageLoadError"
      :src="adImageUrl || defaultAdImage"
      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
        class="share-button"
        open-type="share"
      >
        推荐给朋友
      </button>
    </view>

    <!-- 加载状态 -->
    <view v-if="loading" class="loading-container">
      <view class="loading-text">加载中...</view>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted } from "vue";
import Taro from "@tarojs/taro";
import { getBootPageAPI } from "@/api";
import { getMyFamiliesAPI } from "@/api/family";
import { silentAuth } from "@/utils/authRedirect";
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 loading = ref(true);
const hasFamily = ref(false);
const imageLoading = ref(true); // 图片加载状态
const imageLoadError = ref(false); // 图片加载错误状态
const loadingTimeout = ref(null); // 加载超时定时器
const retryCount = ref(0); // 重试次数
const maxRetries = ref(3); // 最大重试次数
const isTimeout = ref(false); // 是否超时
const showManualRefresh = ref(false); // 是否显示手动刷新按钮

/**
 * 获取广告配置
 */
const fetchAdConfig = async () => {
  try {
    const { code, data } = await getBootPageAPI();
    if (code && data) {
      adImageUrl.value = data.adImageUrl;
    }
  } catch (error) {
    console.error('获取广告配置失败:', error);
  }
};

/**
 * 检查用户是否加入家庭
 */
const checkUserFamily = async () => {
  try {
    const { code, data } = await getMyFamiliesAPI();
    hasFamily.value = code && data && data?.families?.length > 0;
  } catch (error) {
    console.error('检查用户家庭状态失败:', error);
    hasFamily.value = false;
  }
};

/**
 * 静默授权
 */
const performSilentAuth = async () => {
  try {
    await silentAuth();
  } catch (error) {
    console.error('静默授权失败:', error);
  }
};

/**
 * 点击图片处理
 */
const handleImageClick = () => {
  if (hasFamily.value) {
    // 已加入家庭,跳转到dashboard页面
    Taro.redirectTo({
      url: '/pages/Dashboard/index'
    });
  } else {
    // 未加入家庭,跳转到welcome页面
    Taro.redirectTo({
      url: '/pages/Welcome/index'
    });
  }
};

/**
 * 图片加载完成处理
 */
const handleImageLoad = () => {
  console.log('图片加载成功');
  clearLoadingTimeout();
  imageLoading.value = false;
  imageLoadError.value = false;
  isTimeout.value = false;
  showManualRefresh.value = false;
  loading.value = false;
  retryCount.value = 0;
};

/**
 * 图片加载失败处理
 */
const handleImageError = () => {
  console.log('图片加载失败');
  clearLoadingTimeout();
  imageLoading.value = false;
  imageLoadError.value = true;
  // 不要在这里直接调用handleLoadingTimeout,让重试逻辑统一处理
  setTimeout(() => {
    handleLoadingTimeout();
  }, 100);
};

/**
 * 重试加载图片
 */
const retryLoadImage = async () => {
  // 重置状态
  imageLoading.value = true;
  imageLoadError.value = false;
  isTimeout.value = false;
  showManualRefresh.value = false;
  loading.value = true;

  try {
    // 开始超时检测
    startLoadingTimeout();

    // 重新获取广告配置
    await fetchAdConfig();

    // 广告配置成功后,清除超时定时器
    clearLoadingTimeout();
    imageLoading.value = false;

  } catch (error) {
    console.error('重试获取广告配置失败:', error);
    // 重试失败时触发超时处理
    handleLoadingTimeout();
  } finally {
    loading.value = false;
  }
};

/**
 * 开始加载超时检测
 */
const startLoadingTimeout = () => {
  // 清除之前的定时器
  clearLoadingTimeout();

  // 设置10秒超时
  loadingTimeout.value = setTimeout(() => {
    if (imageLoading.value || loading.value) {
      console.warn('图片加载超时');
      isTimeout.value = true;
      handleLoadingTimeout();
    }
  }, 10000);
};

/**
 * 处理加载超时
 */
const handleLoadingTimeout = () => {
  // 清除超时定时器
  clearLoadingTimeout();

  if (retryCount.value < maxRetries.value) {
    // 自动重试
    retryCount.value++;
    console.log(`第${retryCount.value}次自动重试加载`);

    // 延迟1秒后重试,避免频繁请求
    setTimeout(() => {
      retryLoadImage();
    }, 1000);
  } else {
    // 超过最大重试次数,显示手动刷新选项
    imageLoading.value = false;
    loading.value = false;
    showManualRefresh.value = true;
    console.error('图片加载失败,已达到最大重试次数');
  }
};

/**
 * 清除加载超时定时器
 */
const clearLoadingTimeout = () => {
  if (loadingTimeout.value) {
    clearTimeout(loadingTimeout.value);
    loadingTimeout.value = null;
  }
};

/**
 * 页面初始化逻辑
 */
const initializePage = async () => {
  try {
    // 重置重试计数
    retryCount.value = 0;

    // 开始超时检测
    startLoadingTimeout();

    // 执行静默授权
    await performSilentAuth();

    // 先获取广告配置
    let adConfigSuccess = false;
    try {
      await fetchAdConfig();
      adConfigSuccess = true;
    } catch (adError) {
      console.error('获取广告配置失败,但继续执行后续逻辑:', adError);
    }

    // 无论广告配置是否成功,都要检查家庭状态
    try {
      await checkUserFamily();

      // 如果家庭状态检查成功,但广告配置失败了,再次尝试获取广告配置
      if (!adConfigSuccess) {
        try {
          await fetchAdConfig();
          adConfigSuccess = true;
          console.log('重试获取广告配置成功');
        } catch (retryError) {
          console.error('重试获取广告配置仍然失败:', retryError);
        }
      }

      // 如果广告配置成功,清除超时定时器并设置成功状态
      if (adConfigSuccess) {
        clearLoadingTimeout();
        imageLoading.value = false;
        imageLoadError.value = false;
      } else {
        // 广告配置失败,触发重试逻辑
        imageLoadError.value = true;
        handleLoadingTimeout();
      }

    } catch (familyError) {
      console.error('检查家庭状态失败:', familyError);
      // 家庭状态检查失败,但仍然尝试显示广告
      if (adConfigSuccess) {
        clearLoadingTimeout();
        imageLoading.value = false;
      } else {
        handleLoadingTimeout();
      }
    }
  } catch (error) {
    console.error('页面初始化失败:', error);
    // 初始化失败时处理超时
    handleLoadingTimeout();
  } finally {
    loading.value = false;
  }
};

/**
 * 页面初始化
 */
onMounted(() => {
  initializePage();
});

/**
 * 定义分享给朋友的内容
 * @returns {Object} 分享配置对象
 */
const onShareAppMessage = (res) => {
    const shareData = {
        title: '和家长一起走路、一起打卡、一起兑换',
        path: `/pages/AdPage/index`,
        imageUrl: ''
    };

    return shareData;
}

// 使用Taro的useShareAppMessage Hook来处理分享
Taro.useShareAppMessage((res) => {
    return onShareAppMessage(res);
});
</script>