react结合vant的Dialog实现签到弹框操作

1.需求

有时候在开发的时候,需要实现一个签到获取积分的功能,使用react怎么实现呢?

需求如下:

        1.当点击“签到”按钮时,弹出签到框

        2.展示签到信息:

                签到天数,

                对应天数签到能够获取的积分,

                对应天数是否签到效果展示,

                签到按钮,

                签到说明,

        3.点击“签到”按钮,实现签到功能

                (1).如果当天没有签到,按钮文案“请签到”,点击后,执行签到功能,签到成功后,提示签到获取,然后提示慢慢隐藏

                (2).如果已经签到,按钮文案“已签到”,不能触发点击事件

 图示如下:

2.实现 

要实现上面的功能,需要使用vant的Dialog弹出框组件,代码如下:

主页代码:

        点击“签到按钮”,设置Dialog签到弹出框visible属性:显示弹出框


import GetSign from "../components/GetSign";const Index = () => {//签到弹出框显示设置const [signDiaLogVisible, setSignDiaLogVisible] = useState(false);return (//点击签到按钮,设置弹出框显示<div onClick={() => setVisible(true)}>签到按钮</div>//签到弹框组件引用<GetSign signDiaLogVisible={signDiaLogVisible} setSignDiaLogVisible={setSignDiaLogVisible} />);
}export default Index;

 签到弹框组件js:

import React, { useEffect } from "react";
import { useHistory } from "react-router-dom";
import { Dialog } from "react-vant";
import { PersistContext } from "../../data/PersistProvider";
import { RootStateContext } from "../../data/RootStateProvider";
import { SendCMD } from "../../utils/HTTPRequest";
import style from "./style.less";//todo: 签到数据(可根据自己项目需求自行构建结构):
//checked:是否已经签到,award:积分, 
//数组的key就是天数,key从0开始,所以需要加1才是真正的天数const data = {  //前端构建的签到结构,这里一般是从服务端获取数据,具体字段名称根据需求情况自行确定check_days: [ //天数{ // key: 0, 第一天checked: true, //是否已经签到award: 2000, //积分数},{  // key: 1, 第二天,下面依次类推checked: true,award: 3000,},{checked: true,award: 3000,},{checked: false,award: 4000,},{checked: false,award: 5000,},{checked: false,award: 5000,},{checked: false,award: 8000,},],today_checkable: true,  //今天是否可以签到
};const GetSign = (props) => {let history = useHistory();//persist:保存到浏览器的临时缓存数据const { getPersist} = React.useContext(PersistContext);//用户信息const userInfo = getPersist("user_info");//是否展示签到所得const [visible, setVisible] = React.useState(-1);//弹框数据初始化const [signData, setSignData] = React.useState(data);//获取签到数据const sign_data = () => {  //从服务端api获取签到数据SendCMD("getCheckIn", { token: userInfo.token }).then((res) => {if (res.check_in_data) {setSignData(res.check_in_data);  //数据应该和上面data中的保持一致}});};//签到请求const sign_cmd = () => {SendCMD("doCheckIn", { token: userInfo.token }).then((res) => {if (res[0].check_success && res[0].check_in_data) { //判断是否签到成功,并更新签到信息setSignData(res[0].check_in_data);        }//判断最后一次签到的indexlet activeIndex = -1;res[0].check_in_data.check_days.map((item, index) => { //循环,设置最后一次签到的indexif (item.checked) {activeIndex = index;}});//设置显示的log indexsetVisible(activeIndex);});};//初始化签到数据useEffect(() => {if (userInfo) {sign_data();}}, [userInfo]);//点击签到按钮事件const onSignClick = () => {//判断是否登录if (!userInfo) {//跳转到注册页面history.push("./login");return;}//todo 判断是否可以点击if (!signData["today_checkable"]) {//已经签到,弹框提示alert("今天已签到");return;}//请求接口签到,并根据返回结果响应改变展示效果sign_cmd();};return (<Dialogcloseable={true}closeOnClickOverlay={true}width={"85%"}// closeIcon={<Close />}visible={props.visible != 0}showCancelButton={false}className={style.signDialog}showConfirmButton={false}onClose={() => {props.setVisible(false);}}><div class={style.firstSignDialog}><div style={{ width: "100%", height: "4rem" }}><img style={{ width: "43%", marginTop: "1.2rem" }} src="../images/sign_title.png" /></div><div class={style.firstSignSteps}><div class={style.btntop}>{signData.check_days? signData.check_days.map((item, index) => {return (<div key={index} class={style.checkactivebox} id={"index" + index}><div class={style.c_l}><div class={style.c_l_text}><span>+{item.award / 100}</span></div><div class={item.checked ? style.yuanbox_yes : style.yuanbox}>{item.checked ? (<sapn className={style.yuanbox_num}><img src={"../images/sign_yes.png"} style={{ width: "1rem" }} /></sapn>) : (<sapn className={style.yuanbox_num}>{index + 1}</sapn>)}</div><div class={style.tian}>Day {index + 1}</div></div><div>{index === 3 || index === 6 ? (<img alt="" />) : signData.check_days[index + 1].checked ? (<img className={style.img_2} src="../images/sign_line2.png" alt="" />) : (<img className={style.img_2} src="../images/sign_line.png" alt="" />)}</div><div class={`${style.p_log} ${pLogVisible == index ? style.p_log_active : ""}`}>{" "}Coins +{item.award / 100}</div></div>);}): null}</div></div><div class={style.firstSignBtn} onClick={onSignClick}><div class={style.firstSignDialogBtnText}>{!userInfo ? (<span>注册</span>) : !signData.today_checkable ? (<span>已签到</span>) : (<span>签到</span>)}</div></div><div class={style.signBottom}><div class={style.signBottom_title}>签到说明</div><div class={style.signBottom_content}><span>.说明1</span><br /><span>.说明2</span><br /><span>.说明3</span></div></div></div></Dialog>);
};export default GetSign;

签到弹出框css:


.signDialog {--rv-dialog-background-color: rgba(0, 0, 0, 0);
}.firstSignDialog {text-align: center;background-size: 100% 100%;background-repeat: no-repeat;background-image: url("../assets/images/sign.png");
}.btntop {margin: 0 0.53333rem;display: flex;flex-wrap: wrap;font-weight: 700;
}.c_l_text {color: #CAE7DC;font-weight: bold;
}.img_1 {width: 0.66667rem;
}.tian {color: #CAE7DC;text-align: center;font-weight: bold;
}.checkactivebox {width: 25%;position: relative;
}.img_1 {width: 0.66667rem;
}.yuanbox_yes {width: 2rem;height: 2rem;z-index: 2;border-radius: 99rem;background-color:  #00FFCC;
}.yuanbox {width: 2rem;height: 2rem;z-index: 2;border-radius: 99rem;background-color:#CAE7DC;
}.yuanbox_num {color: #035d3f;font-weight: 700;font-size: 1.2rem;line-height: 2rem;text-align: center;
}.sign_toast {margin-top: -7rem;background-color: #f00 !important;color: #006a2d !important;
}.c_l {display: flex;flex-direction: column;align-items: center;justify-content: space-between;font-size: 1rem;
}.img_2 {position: absolute;top: 1.9rem;z-index: 1;width: 100%;
}.p_log {position: absolute;top: -0.53333rem;left: 0.47333rem;line-height: 1.43333rem;text-align: center;background-color: #035d3f;font-size: 0.5rem;color: #ffffff;border-radius: 0.5rem;padding-left: 0.15rem;padding-right: 0.15rem;z-index: 100;opacity: 0;
}@keyframes fadenum{0%{opacity: 1;}100%{opacity: 0;}
}.p_log_active {animation:fadenum 5s 1;
}.firstCoinsSteps {margin-top: 3%;
}.firstSignBtn {display: inline-block;margin-bottom: 1.5rem;background: url("../assets/home/sign_btn.png") no-repeat 100%;background-size: 100%;width: 80%;border-radius: 2rem;height: 3rem;
}.firstSignDialogBtnText {margin-top: 1rem;transform: scale(1, 1.5);
}.firstSignDialogBtnText span {text-align: center;font-weight: 700;font-size: 1rem;background-color: #000000;color: #035d3f;text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.925);-webkit-background-clip: text;-moz-background-clip: text;background-clip: text;
}.signBottom {margin-top: 2%;color: #969696;font-weight: 700;
}.signBottom_title {font-size: 1.2rem;
}.signBottom_content {margin-top: 0.3rem;
}.signBottom_content span {text-align: left;margin-left: 0.5rem;width: 96%;font-size: 0.8rem;font-weight: 700;display: inline-block;
}

上面要引入的setPersist组件:       

import { createContext, useState, useEffect } from "react";
import { SendCMD } from "../utils/HTTPRequest";
import { DeepEqual, GetOS, GetBrowser } from "../utils/JSTool";// 创建一个 Context
export const PersistContext = createContext(defaultPersist);let untrackedData = defaultPersist;// 创建一个 DataProvider 组件
export const PersistProvider = ({ children }) => {const [data, setData] = useState(untrackedData);const [expires, setExpires] = useState({});useEffect(() => {loadPersistDataOnce();}, []);const loadPersistDataOnce = () => {if (untrackedData.dataLoaded) {return;}let persistStr = localStorage.getItem("persist");if (persistStr) {try {let persistData = JSON.parse(persistStr);for (let key in persistData) {if (typeof persistData[key] == "undefined" || persistData[key] == null) {delete persistData[key];}}untrackedData = Object.assign({}, untrackedData, persistData);} catch (e) {console.error(e);}}let expiresStr = localStorage.getItem("expires");if (expiresStr) {try {let expires = JSON.parse(expiresStr);setExpires(expires);} catch (e) {console.error(e);}}untrackedData.dataLoaded = true;setData(Object.assign({}, untrackedData));};const setPersist = (key, value, expireSeconds) => {loadPersistDataOnce();if (DeepEqual(untrackedData[key], value)) return;untrackedData[key] = value;if (expireSeconds && expireSeconds > 0) {let expireData = { ...expires };expireData[key] = Date.now() + expireSeconds * 1000;setExpires(expireData);localStorage.setItem("expires", JSON.stringify(expireData));}setData(() => Object.assign({}, untrackedData));localStorage.setItem("persist", JSON.stringify(untrackedData));};const getPersist = (key) => {loadPersistDataOnce();let value = data[key];if (typeof value == "undefined") return null;let keyExpire = expires[key];if (keyExpire && keyExpire < Date.now()) {let dataTmp = { ...data };delete dataTmp[key];delete untrackedData[key];let expiresTmp = { ...expires };delete expiresTmp[key];localStorage.setItem("persist", JSON.stringify(dataTmp));localStorage.setItem("expires", JSON.stringify(expiresTmp));return null;}return value;};return (<PersistContext.Provider value={{ getPersist, setPersist, reloadUserInfo }}>{children}</PersistContext.Provider>);
};

好了,签到获取积分操作ok

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/196690.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI代码助手:写代码“如虎添翼”

当你还在头疼如何写好代码&#xff0c;如何更好的快速完成项目时&#xff0c; 这些工具能自动为你编写代码或提供替代的解决方案&#xff1a; 1.Cursor Cursor&#xff0c;一个看上去平平无奇的IDE&#xff0c;但它可以直接调用GPT-4来帮你生成代码。作者Aman Sanger说他们是…

两年外包生涯做完,技术退步了5年不止。。。。

先说一下自己的情况。大专生&#xff0c;17年通过校招进入湖南某软件公司&#xff0c;干了接近2年的点点点&#xff0c;今年年上旬&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经在一个企业干了五年的功能测试…

DistributionBalancedLoss

Distribution-Balanced Loss P I ( x k ) P^I(x^k) PI(xk) 1 C ∑ y i k 1 1 n i {1\over C}\sum\limits_{y_i^k1}{1\over{n_i}} C1​yik​1∑​ni​1​&#xff0c; P i C ( x k ) P^C_i(x^k) PiC​(xk) 1 C 1 n i {1\over C}{1\over{n_i}} C1​ni​1​ r i k _i^k ik​ P i …

使用正则表达式时-可能会导致性能下降的情况

目录 前言 正则表达式引擎 NFA自动机的回溯 解决方案 前言 正则表达式是一个用正则符号写出的公式&#xff0c;程序对这个公式进行语法分析&#xff0c;建立一个语法分析树&#xff0c;再根据这个分析树结合正则表达式的引擎生成执行程序(这个执行程序我们把它称作状态机&a…

初步认识结构体

hello&#xff0c;hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习结构体&#xff0c;并跟大家一边做题一边进行学习和理解。感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教&#xff01; 如果本篇文章对你有帮助&#xff0c;还请…

贝叶斯网络 (人工智能期末复习)

文章目录 贝叶斯网络&#xff08;概率图模型&#xff09;定义主要考点例题- 要求画出贝叶斯网络图- 计算各节点的条件概率表- 计算概率- 分析独立性 贝叶斯网络&#xff08;概率图模型&#xff09; 定义 一种简单的用于表示变量之间条件独立性的有向无环图&#xff08;DAG&am…

BGP基本配置

一、知识补充 1、BGP BGP是Border Gateway Protocol&#xff08;边界网关协议&#xff09;的缩写。它是用于在互联网中交换路由信息的一种协议。BGP被广泛应用于大规模的自治系统&#xff08;AS&#xff09;之间&#xff0c;用于实现跨网络的路由选择和交换。 BGP的主要功能…

基于Cocos2D-X框架闯关游戏的设计

摘 要 随着智能设备平台的普及、用户数量的增多&#xff0c;智能平台的应用&#xff0c;尤其是游戏异常火爆&#xff0c;从植物大战僵尸到愤怒的小鸟&#xff0c;移动平台游戏的开发进入了新的阶段。但是另一方面&#xff0c;平台的多样性也给开发者带来诸多不便&#xff0c;怎…

单片机第三季-第四课:STM32下载、MDK和调试器

目录 1&#xff0c;扩展板使用的STM32芯片类型 2&#xff0c;使用普中科技软件下载程序 3&#xff0c;keil介绍 4&#xff0c;JLINK调试器介绍 5&#xff0c;使用普中的调试器进行debug 6&#xff0c;使用Simulator仿真 1&#xff0c;扩展板使用的STM32芯片类型 扩展版…

什么是网络可视化?网络可视化工具有用吗

网络可视化定义是自我描述的&#xff0c;因为它在单个屏幕上重新创建网络布局&#xff0c;以图形和图表的形式显示有关网络设备、网络指标和数据流的信息&#xff0c;为 IT 运营团队提供一目了然的理解和决策。 网络是复杂的实体&#xff0c;倾向于持续进化&#xff0c;随着业…

【C++】异常处理 ⑧ ( 标准异常类 | 标准异常类继承结构 | 常用的标准异常类 | 自定义异常类继承 std::exception 基类 )

文章目录 一、抛出 / 捕获 多个类型异常对象1、标准异常类2、标准异常类继承结构3、常用的标准异常类 二、自定义异常类继承 std::exception 基类1、自定义异常类继承 std::exception 基类2、完整代码示例 - 自定义异常类继承 std::exception 基类 一、抛出 / 捕获 多个类型异常…

java常用知识点记忆

类的继承与多态 类的继承不支持多重继承非private 方法才可以被覆盖覆盖的方法要求&#xff0c;子类中的方法的名字&#xff0c;参数列表&#xff0c;返回类型与父类相同方法的重载是在一个类中定义方法名字相同&#xff0c;但是参数列表不同的方法要是在子类中定义了与父类名字…

【Windows】使用SeaFile搭建本地私有云盘并结合内网穿透实现远程访问

1. 前言 现在我们身边的只能设备越来越多&#xff0c;各种智能手机、平板、智能手表和数码相机充斥身边&#xff0c;需要存储的数据也越来越大&#xff0c;一张手机拍摄的照片都可能有十多M&#xff0c;电影和视频更是按G计算。而智能设备的存储空间也用的捉襟见肘。能存储大量…

JDBC常见的几种连接池使用(C3P0、Druid、HikariCP 、DBCP)(附上代码详细讲解)

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍JDBC常见的几种连接池使用&#xff08;C3P0、Druid、HikariCP 、DBCP&#xff09;以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主收将持续更新学…

开启全新消费革命——消费增值,让每一笔消费变成财富!

你是否厌倦了仅仅购买物品或享受服务后便一无所有的消费方式&#xff1f;现在&#xff0c;消费增值的概念将彻底改变你的消费观念&#xff01;通过参与消费增值&#xff0c;你的每一笔消费都将变得更有价值&#xff01; 消费增值是一种全新的消费理念&#xff0c;它让你在购物的…

tex中的边框

文章目录 利用tcolorbox宏包给公式加框 利用tcolorbox宏包 tcolorbox可以创建一个盒子的环境&#xff0c;例如&#xff1a; \documentclass{article} \usepackage{tcolorbox} \begin{document}\begin{tcolorbox}[left1cm, right1cm, top0.5cm, bottom0.5cm,colbackblue!10!wh…

CSRF之pikachu靶场DW

1&#xff0c;登录皮卡丘靶场&#xff0c;get请求&#xff1b; 2&#xff0c;抓包并修改标记后的个人信息 最后放通一下&#xff0c;发现账号信息被修改 2&#xff0c;post请求 1提交post数据并使用bp抓包 2.利用工具改包&#xff0c;并生成url 3&#xff0c;点击提交后&#…

SpringBoot自定义异常处理机制

说明&#xff1a;在完整的项目结构中&#xff0c;我们通常会创建一个自定义的异常处理机制&#xff0c;在系统可能出现异常的地方手动抛出这些异常&#xff0c;可以快速定位到异常代码片段&#xff0c;提供项目的可维护性。 本文介绍在SpringBoot项目中&#xff0c;搭建一套自…

ssm党务政务服务热线平台源码和论文答辩PPT

摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计…

任意密码重置+CRRF

一、XSS漏洞 在商城的搜索处&#xff0c;输入标准语句的传参直接就可以弹窗 二、逻辑漏洞-用户枚举 在用户注册界面&#xff0c;点击发送验证码&#xff0c;然后用BURP发包 更改手机号传参&#xff0c;这里手机号传参没有进行加密&#xff0c;直接用手机号的位置进行爆破 正确的…