App端用户每日弹出签到弹窗如何实现?(uniapp+Vue)

需求:

  • 后端提供接口返回用户签到信息。
  • 应用启动或重新展示时,若用户未签到,需要弹出签到弹窗;已签到则不弹。
  • 签到成功后自动关闭弹窗。

思路:

  1. App.vueonShow 生命周期做全局判断,确保在任意页面激活时都能检查签到状态。
  2. 在签到弹窗页 pages/checkIn/checkIn.vue 中负责: 拉取签到详情、渲染奖励列表、调用签到接口并在成功后自动关闭。

实现步骤:

  1. 封装接口调用方法
js 复制代码
 // 获取签到信息
  getSigninInfoApi(data) {
    return http.get("/api/sign_in/info", { params: data || {} });
  },
  // 执行签到
  signInApi(data) {
    return http.post("/api/sign_in/sign", { data: data || {} });
  },
  1. 全局入口检查签到状态 (App.vue)
js 复制代码
import { loginApi } from '@/api/login.js';

const checkSigninStatus = async () => {
  // Step 1. 检查 token 是否存在,没有登录用户不触发签到逻辑
  const token = uni.getStorageSync('token');
  if (!token) return;

  try {
    // Step 2. 请求签到状态接口
    const res = await loginApi.getSigninInfoApi({});
    if (res?.code !== 1) return; // 接口异常直接退出

    const hasSignedToday = !!res?.data?.is_signed_today;
    if (hasSignedToday) return; // 已签到则不弹窗

    // Step 3. 打开签到弹窗(防止重复跳转)
    const openPopup = () => {
      const pages = getCurrentPages();
      const currentPage = pages[pages.length - 1];
      if (!currentPage || currentPage.route === 'pages/checkIn/checkIn') return;

      // 轻微延迟防止路由冲突
      uni.navigateTo({
        url: '/pages/checkIn/checkIn'
      });
    };

    setTimeout(openPopup, 300);
  } catch (e) {
    console.error('检查签到状态失败:', e);
  }
};

// 在 App.vue 的 onShow 生命周期中触发
onShow(() => {
  checkSigninStatus();
});
  1. 签到弹窗逻辑 (pages/checkIn/checkIn.vue)
  • 页面加载时展示签到按钮。
  • 点击"签到"后调用 loginApi.signInApi()
  • 签到成功后弹出提示并自动关闭弹窗。
js 复制代码
// pages/checkIn/checkIn.vue
import { loginApi } from '@/api/login.js';

const loading = ref(false);       // 按钮加载状态
const isSignedToday = ref(false); // 是否已签到

// 页面加载时拉取签到状态
onShow(async () => {
  const res = await loginApi.getSigninInfoApi({});
  if (res?.code === 1) {
    isSignedToday.value = !!res.data.is_signed_today;
  }
});

// 点击"立即签到"按钮
const handleSignIn = async () => {
  if (loading.value) return;
  loading.value = true;

  try {
    const res = await loginApi.signInApi({});
    if (res?.code === 1) {
      uni.showToast({
        title: '签到成功',
        icon: 'success'
      });
      // 延迟关闭弹窗
      setTimeout(() => {
        uni.navigateBack(); // 返回上一个页面(即关闭弹窗)
      }, 800);
    } else {
      uni.showToast({
        title: res?.msg || '签到失败,请稍后再试',
        icon: 'none'
      });
    }
  } catch (err) {
    console.error('签到请求失败:', err);
    uni.showToast({
      title: '网络异常,请稍后再试',
      icon: 'none'
    });
  } finally {
    loading.value = false;
  }
};
相关推荐
前端不太难11 分钟前
从 Navigation State 反推架构腐化
前端·架构·react
前端程序猿之路1 小时前
Next.js 入门指南 - 从 Vue 角度的理解
前端·vue.js·语言模型·ai编程·入门·next.js·deepseek
大布布将军1 小时前
⚡️ 深入数据之海:SQL 基础与 ORM 的应用
前端·数据库·经验分享·sql·程序人生·面试·改行学it
川贝枇杷膏cbppg1 小时前
Redis 的 RDB 持久化
前端·redis·bootstrap
D_C_tyu1 小时前
Vue3 + Element Plus | el-table 表格获取排序后的数据
javascript·vue.js·elementui
JIngJaneIL1 小时前
基于java+ vue农产投入线上管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
天外天-亮2 小时前
v-if、v-show、display: none、visibility: hidden区别
前端·javascript·html
jump_jump2 小时前
手写一个 Askama 模板压缩工具
前端·性能优化·rust
hellotutu2 小时前
vue2 从 sessionStorage 手动取 token 后,手动加入到 header
vue.js·token·session·header
be or not to be2 小时前
HTML入门系列:从图片到表单,再到音视频的完整实践
前端·html·音视频