v3里h5 根据后台配置的图片自适应显示弹框里的图片,里面配置多张,点击x关闭下一张打开,限制弹出次数

本次需求新更~
总能有些奇奇怪怪的需求,这次需求这样定义的:
打开app后台管理系统如果配置了图片,就自适应显示在首页;
配置多张,点击关闭,下一张打开,以此类推
首先想到的问题:
没有定义弹框的宽高,而是根据图片的宽高,去自适应每个图片的大小,那么我们一张配置1000, 一张配置500, 一张配置250,那显示的每张图片关闭后的效果大小图片都是不一样的~

主要更改说明:
弹框控制逻辑:
添加了 currentPopupIndex 来控制当前显示的弹框
通过 v-if 控制弹框的显示和隐藏
添加了 handleClose 方法来处理弹框的关闭和切换
样式适配:
使用 position: fixed 创建全屏遮罩
弹框内容区域使用 max-width 和 max-height 控制最大尺寸
图片使用 max-width: 100% 和 max-height: 90vh 确保在容器内自适应显示
添加了关闭按钮样式
图片自适应:
使用 object-fit: contain 确保图片保持原比例并完整显示
通过 max-width 和 max-height 控制图片不会超出屏幕范围
这样实现后:
弹框会根据图片尺寸自动调整大小
图片会保持原比例显示
点击关闭按钮会显示下一个弹框
所有弹框显示完后会完全关闭
弹框不会超出屏幕范围
适配各种屏幕尺寸
你可以根据需要调整样式中的具体数值,比如间距、最大宽高比例等。

中途遇到一个问题,设置了宽100%,显示的话却是90%;
使用 Teleport 将弹框组件传送到 body 元素下,避免被其他容器样式影响
使用 inset: 0 替代分别设置位置
使用 vw 和 vh 单位确保真正占满视口
添加 margin: 0 和 padding: 0 确保没有额外的间距

<template>
  <Teleport to="body">
    <div
      v-if="
        currentPopupIndex !== -1 &&
        diaData[$global.AD_POSITION_HOME_POPUP]?.[currentPopupIndex]
      "
      class="popup-container"
    >
      <div class="popup-content">
        <img
          :src="diaData[$global.AD_POSITION_HOME_POPUP][currentPopupIndex].pic"
          @click="$adRouter(diaData[$global.AD_POSITION_HOME_POPUP][currentPopupIndex])"
        />
        <div class="close-btn" @click="handleClose">×</div>
      </div>
    </div>
  </Teleport>
</template>

<script setup>
import { ref, getCurrentInstance } from 'vue';
import { getAdList } from "@/api/base";

const { proxy } = getCurrentInstance();
const diaData = ref({});
const currentPopupIndex = ref(0); // 控制当前显示的弹框索引

const handleClose = () => {
  if (currentPopupIndex.value < diaData.value[proxy.$global.AD_POSITION_HOME_POPUP].length - 1) {
    // 如果还有下一个弹框,显示下一个
    currentPopupIndex.value++;
  } else {
    // 所有弹框都显示完了,设置为-1表示全部关闭
    currentPopupIndex.value = -1;
  }
};

getAdList({
  regionType: [proxy.$global.AD_POSITION_HOME_POPUP],
}).then((res) => {
  console.log("首页弹框的数据", res);
  diaData.value = res.data || {};
});
</script>

<style lang="scss" scoped>
.popup-container {
  position: fixed;
  inset: 0; // 使用 inset 替代分别设置 top, right,       bottom, left
  width: 100vw; // 使用 vw 单位
  height: 100vh; // 使用 vh 单位
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 999;
  margin: 0; // 确保没有外边距
  padding: 0; // 确保没有内边距
}

.popup-content {
  position: relative;
  max-width: 90vw;
  max-height: 90vh;
  
  img {
    max-width: 100%;
    max-height: 90vh;
    object-fit: contain;
  }
}

.close-btn {
  position: absolute;
  top: -40px;
  right: -40px;
  width: 30px;
  height: 30px;
  background: rgba(255, 255, 255, 0.8);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  font-size: 20px;
  color: #333;
  
  &:hover {
    background: #fff;
  }
}
</style>

完成, diaData.value[proxy.$global.AD_POSITION_HOME_POPUP]这里面就是个数组对象,大家可以去模拟

之后我这边的参考路径: src\views\home\components\HomeDialog.vue (fzh5)

11.27需求又迭代更新~
这次需求变更: 前景就是,弹框配置太多张图片,他们显示的太多了,导致太烦, 后台管理系统增加了一个配置的数值,限制次数显示弹框弹出的数量的

<script setup>
import { ref, getCurrentInstance, onMounted } from "vue";
import { getAdList, getConfing } from "@/api/base";

const { proxy } = getCurrentInstance();
const diaData = ref({});
const currentPopupIndex = ref(-1); // 默认设为-1,表示不显示
const maxShowCount = ref(0); // 存储最大显示次数

// 获取今天已经显示的次数
const getTodayShowCount = () => {
  const today = new Date().toDateString();
  const storageKey = 'popupShowCount_' + today;
  return parseInt(localStorage.getItem(storageKey) || '0');
};

// 增加显示次数
const incrementShowCount = () => {
  const today = new Date().toDateString();
  const storageKey = 'popupShowCount_' + today;
  const currentCount = getTodayShowCount();
  localStorage.setItem(storageKey, (currentCount + 1).toString());
};

// 检查是否可以显示弹框
const checkCanShow = () => {
  const currentCount = getTodayShowCount();
  return currentCount < maxShowCount.value;
};

const handleClose = () => {
  if (
    currentPopupIndex.value <
    diaData.value[proxy.$global.AD_POSITION_HOME_POPUP].length - 1
  ) {
    currentPopupIndex.value++;
  } else {
    currentPopupIndex.value = -1;
  }
  // 每次关闭时增加计数
  incrementShowCount();
};

onMounted(async () => {
  // 先获取配置的最大显示次数
  const configRes = await getConfing({ key: proxy.$global.ImageDialogCount });
  maxShowCount.value = parseInt(configRes.data[0].configValue || '0');

  // 检查是否可以显示
  if (checkCanShow()) {
    // 获取广告数据
    const adRes = await getAdList({
      regionType: [proxy.$global.AD_POSITION_HOME_POPUP],
    });
    diaData.value = adRes.data || {};
    
    // 如果有广告数据,则显示第一个
    if (diaData.value[proxy.$global.AD_POSITION_HOME_POPUP]?.length > 0) {
      currentPopupIndex.value = 0;
    }
  }
});
</script>
主要改动说明:
添加了 maxShowCount 来存储配置的最大显示次数
添加了三个辅助函数:
getTodayShowCount: 获取今天已经显示的次数
incrementShowCount: 增加显示次数
checkCanShow: 检查是否可以显示弹框
使用 localStorage 来存储显示次数,key 中包含日期,这样每天重置计数
修改了 onMounted 的逻辑:
先获取配置的最大显示次数
检查是否可以显示
如果可以显示,再获取广告数据并显示
这样实现后:
每天都会重新计数
当达到配置的最大次数后,不会再显示弹框
显示次数会持久化保存在本地存储中
每次关闭弹框时增加计数

至于这样设置键的存储值

 const today = new Date().toDateString();
  const storageKey = "popupShowCount_" + today;
  const currentCount = getTodayShowCount();
  localStorage.setItem(storageKey, (currentCount + 1).toString());
  

是因为如果配置最大显示10次,用户今天看了5次,第二天来时,会重新从0开始计数
每天都可以看到10次,如果你想要弹框永久限制显示次数
localStorage.setItem(“随便键”, (currentCount + 1).toString());就ok了~
完成

测试测出一个问题,后台管理系统设置弹出次数,可能多弹一次或者两次的问题:

主要改动:
在显示新弹框前先检查次数
在 handleClose 中先增加计数,再决定是否显示下一个

const handleClose = () => {
  // 先增加计数
  incrementShowCount();
  
  // 检查是否还可以继续显示
  if (!checkCanShow()) {
    currentPopupIndex.value = -1;
    return;
  }

  // 如果还可以显示,则显示下一个
  if (currentPopupIndex.value < diaData.value[proxy.$global.AD_POSITION_HOME_POPUP].length - 1) {
    currentPopupIndex.value++;
  } else {
    currentPopupIndex.value = -1;
  }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值