AdOverlay.vue 4.74 KB
<template>
  <nut-overlay
    v-model:visible="visible"
    :z-index="9999"
    :close-on-click-overlay="false"
    :lock-scroll="true"
  >
    <view class="overlay-body">
      <view class="overlay-content">
        <!-- 广告图片 -->
        <view class="ad-image-container" @click="handleAdClick">
          <image
            :src="adConfig.adImageUrl"
            mode="aspectFill"
            class="ad-image"
            alt="广告图片"
          />
        </view>

        <!-- 关闭按钮 -->
        <view class="close-button" @click="handleClose">
          <Close size="24" class="close-icon" />
        </view>
      </view>
    </view>
  </nut-overlay>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import Taro from '@tarojs/taro'
import { Close } from '@nutui/icons-vue-taro'
// 导入接口
import { getBootPageAPI } from '@/api'

// 广告配置数据
const adConfig = ref({
  // 广告图片URL
  adImageUrl: '',
  // 点击跳转的页面路径
  targetPage: '',
  // 存储键名(用于区分不同的广告)
  storageKey: ''
})

// Emits
const emit = defineEmits(['close', 'click'])

// 响应式数据
const visible = ref(false)

/**
 * 获取今天的日期字符串(YYYY-MM-DD格式)
 * @returns {string} 今天的日期
 */
const getTodayDateString = () => {
  const today = new Date()
  const year = today.getFullYear()
  const month = String(today.getMonth() + 1).padStart(2, '0')
  const day = String(today.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}

/**
 * 获取广告配置数据
 */
const fetchAdConfig = async () => {
  try {
    const response = await getBootPageAPI()
    if (response.code && response.data) {
      // 使用接口返回的数据更新配置
      adConfig.value = {
        adImageUrl: response.data.adImageUrl,
        targetPage: response.data.targetPage,
        storageKey: response.data.storageKey
      }

      // 延迟一点显示,避免页面加载时的闪烁
      setTimeout(() => {
        show()
      }, 500)
    }
  } catch (error) {
    console.error('获取广告配置失败:', error)
    // 使用默认配置,不影响功能
  }
}

/**
 * 检查今天是否已经显示过广告
 * @returns {boolean} 是否已显示
 */
const hasShownToday = () => {
  try {
    const lastShownDate = Taro.getStorageSync(adConfig.value.storageKey)
    const today = getTodayDateString()
    return lastShownDate === today
  } catch (error) {
    console.error('获取存储数据失败:', error)
    return false
  }
}

/**
 * 记录今天已显示广告
 */
const markAsShownToday = () => {
  try {
    const today = getTodayDateString()
    Taro.setStorageSync(adConfig.value.storageKey, today)
  } catch (error) {
    console.error('保存存储数据失败:', error)
  }
}

/**
 * 显示广告遮罩
 */
const show = () => {
  if (!hasShownToday()) {
    visible.value = true
  }
}

/**
 * 隐藏广告遮罩
 */
const hide = () => {
  visible.value = false
}

/**
 * 处理广告图片点击事件
 */
const handleAdClick = () => {
  // 记录已显示
  markAsShownToday()

  // 隐藏遮罩
  hide()

  // 跳转到目标页面
  // Taro.navigateTo({
  //   url: adConfig.value.targetPage
  // }).catch(error => {
  //   console.error('页面跳转失败:', error)
  //   Taro.showToast({
  //     title: '页面跳转失败',
  //     icon: 'none'
  //   })
  // })

  // 触发点击事件
  emit('click', adConfig.value.targetPage)
}

/**
 * 处理关闭按钮点击事件
 */
const handleClose = () => {
  // 记录已显示
  markAsShownToday()

  // 隐藏遮罩
  hide()

  // 触发关闭事件
  emit('close')
}

// 暴露方法给父组件
defineExpose({
  show,
  hide,
  hasShownToday
})

// 组件挂载时获取配置并检查是否需要显示
onMounted(async () => {
  // 先获取广告配置
  await fetchAdConfig()
})
</script>

<style lang="less">
.overlay-body {
  display: flex;
  height: 100%;
  align-items: center;
  justify-content: center;
}

.overlay-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 80vw;
  max-width: 600rpx;
}

.ad-image-container {
  width: 100%;
  border-radius: 16rpx;
  overflow: hidden;
  box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.3);
  cursor: pointer;
  margin-bottom: 40rpx;
}

.ad-image {
  width: 100%;
  height: 50vh;
  display: block;
  border-radius: 16rpx;
}

.close-button {
  width: 60rpx;
  height: 60rpx;
  // background-color: rgba(0, 0, 0, 0.6);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.close-icon {
  color: white;
}

/* 点击效果 */
.ad-image-container:active {
  transform: scale(0.98);
  transition: transform 0.1s ease;
}

.close-button:active {
  transform: scale(0.9);
  transition: transform 0.1s ease;
}
</style>