vue3.0微信活动推广分享项目-实现验证码登录功能

news2024/11/30 0:52:51

⭐️⭐️⭐️  作者:船长在船上
🚩🚩🚩  主页:来访地址船长在船上的博客
🔨🔨🔨  简介:CSDN前端领域优质创作者,资深前端开发工程师,专注前端开发,在CSDN总结工作中遇到的问题或者问题解决方法以及对新技术的分享,欢迎咨询交流,共同学习。

🔔🔔🔔   感谢:如果觉得博主的文章不错或者对你的工作有帮助或者解决了你的问题,可以关注、支持一下博主。如有疑问可以留言、评论,看到后会及时回复。

 vue3.0活动推广项目:测一测船舶价值

技术选型:Vue3Vant3移动端ui框架

推广活动功能需求:

  • 用户使用验证码登录,登录成功之后跳转船值计算页;
  • 填写船名、吨位等信息利用计算公式测一测船舶价值,获取船舶价值计算结果;
  • 实现船值价值排行榜
  • 实现船值计算结果可生成图片长按保存到手机相册、生成二维码直接访问活动功能;

功能介绍:

1.vant3配置手机端适配,采用Rem 布局适配,官网有文档可查看

需要使用 rem 单位进行适配,推荐使用以下两个工具:

  • postcss-pxtorem 是一款 PostCSS 插件,用于将 px 单位转化为 rem 单位
  • lib-flexible 用于设置 rem 基准值

2.微信浏览器访问页面,实现使用验证码登录

  • 登录成功之后,会使用cookie存储信息,采用插件js-cookie保存实现,这里会判断用户是否是第二次或者当前信息是否过期,如果过期获取再次访问则重新登录,会跳过船值计算页,直接跳转到船值结果页。

3.船值计算页

  • 通过输入自己名下船名、吨位、生产年月、船舶类型信息通过公式计算得出船值价值

4.船值结果页

  • 船值价值排行榜
  • 船值计算结果可生成图片长按保存到手机相册、生成二维码直接访问活动功能

实现效果预览

 

 

 代码实现:验证码登录功能

 注意事项:

v-throttle自定义指令,自定义延迟事件,起到按钮多次、连续点击防抖作用,当前登录、获取验证码按钮已添加自定义指令

1.页面结构 

<template>
  <div class="loginContent">
      <img src="../assets/logo.png" class="logo"/>
      <img src="../assets/ceyice.png" class="ceyice"/>
      <van-form class="vanform">
        <van-cell-group class="formItem" :border="false" >
          <van-field type="number" autocomplete="off" v-model.trim="logonForm.loginPhone" clearable placeholder="请输入手机号" class="addbg">
            <template #left-icon>
              <img :src="loginPhoneIcon" class="loginPhoneIcon">
            </template>
          </van-field>
        </van-cell-group>
        <van-cell-group class="formItem mt25" :border="false">
          <van-field type="number" autocomplete="off" v-model.trim="logonForm.loginCode" maxlength="6" clearable placeholder="请输入验证码" class="addbg">
            <template #left-icon>
              <img :src="loginCodeIcon" class="loginCodeIcon">
            </template>
          </van-field>
          <!-- <div @click="sendCode" class="codeBtn" v-throttle>{{ buttonText }}</div> -->
          <van-button type="info" @click="sendCode" color="#024EE0" :disabled="isDisabled" class="codeBtn" v-throttle>{{ buttonText }}</van-button>
        </van-cell-group>
        <div style="margin: 30px 0 0px">
          <van-button type="primary" color="#3EA3FF" class="sub-btn" block @click="submitApply">登录</van-button>
        </div>
      </van-form>
  </div>
</template>

2.页面样式

less预编译语言

<style lang="less" scoped>
.loginContent{
  width: 100%;
  height: 100%;
  background: url("../assets/bg3.jpg") no-repeat;
  background-size:100%;
  box-sizing: border-box;
  .logo{
    display: block;
    width: 213px;
    height: 73px;
    margin:0 auto;
    padding-top:30px;
  }
  .ceyice{
    display: block;
    width: 642px;
    height: 256px;
    margin:0 auto;
    margin-top:50px;
  }
}
.vanform{
  width: 80%;
  margin:30px auto 0;
  padding:20px;
  border: 2px solid #6283ff;
  border-radius: 4px;
  background: #13115C;
}
.addbg{
  height: 96px;
  background: #2B3591;
  border-radius: 10px;
  border: 1px #6283ff solid;
}
.van-cell:after{
  border:0;
}
.formItem {
  position: relative;
  background: none;
}
.codeBtn {
  position: absolute;
  top: 4px;
  right: 100px;
  border-radius:10px;
  z-index: 100;
  font-size: 28px;
  font-weight: 600;
  color: #3EA3FF !important;
  background: none !important;
  border:0;
}
.sub-btn{
  height:96px;
  border-radius: 10px;
  font-size: 34px;
}
</style>
<style>
  .van-field__control{
    color:#fff;
  }
</style>

3.vue3.0模块引入

<script setup>
    import Cookies from 'js-cookie'
    import { Toast } from 'vant'//弹窗
    import { ref, reactive ,onMounted,onUnmounted} from "vue"
    import {useStore} from 'vuex'
    const store = useStore()
    import { useRouter } from "vue-router"
    import {
        login,//登录接口
        smsCode,//获取验证码接口
        checkUser//检查用户是否注册计算过船舶价值
    } from "../api/userMG"
    const $router = useRouter();
    const loginCodeIcon = ref(require("../assets/loginCode.png"))
    const loginPhoneIcon = ref(require("../assets/loginPhone.png"))
    // 定义表单的数据
    const logonForm = reactive({
        loginPhone: "",
        loginCode: ""
    })

    ..........
    .........
    .........
</script>

4.获取验证码功能

手机号正则验证;验证码接口调用smsCode;

const buttonText = ref("获取验证码");
const isDisabled = ref(false);
const times = ref(60)
const timer = ref(null)
const flag = ref(true)
// 获取验证码
const sendCode = () =>{
  // 验证手机号
  let reg = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
  if(logonForm.loginPhone==""){
    Toast("手机号不能为空");
    return;
  }else if (!reg.test(logonForm.loginPhone)) {
    Toast("手机号格式不正确");
    return;
  }else{
    let params = {
      phone: logonForm.loginPhone
    };
    smsCode(params).then(res => {
      // console.log(res, "发送验证码请求接口");
      if (res.code == 200) {
        // 成功的弹框
        Toast.success({
          message: "验证码发送成功,请注意查收,5分钟之内有效",
          forbidClick:true,
          onClose: () => {
            buttonText.value = "已发送至手机";
            isDisabled.value = true;
            let time = times.value;
            // 定时器获取剩余时间
            if (flag.value) {
              flag.value = false;
              timer.value = setInterval(() => {
                time--;
                buttonText.value = "剩余" + time + " 秒";
                if (time === 0) {
                  clearInterval(timer.value);
                  timer.value = null;
                  buttonText.value = "重新获取";
                  isDisabled.value = false;
                  times.value = 60;
                  flag.value = true;
                }
              }, 1000);
            }
          }
        });
      } else {
        Toast("获取验证码超过次数,一小时10次,一天20次");
      }
    });
  }

}

5.登录功能

js-cookie存储信息:

//保存帐号到cookie,有效期1天

Cookies.set('phone', logonForm.loginPhone, { expires: 1 });

const submitApply = () =>{
  // 验证手机号
  let reg = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
  if(logonForm.loginPhone==""){
    Toast("手机号不能为空");
    return;
  }else if (!reg.test(logonForm.loginPhone)) {
    Toast("手机号格式不正确");
    return;
  }else if(logonForm.loginCode==""){
    Toast("验证码不能为空");
    return;
  }else{

    // 登录
    store.commit('showLoading');//显示loading
    let params = {
      code:logonForm.loginCode,
      phone:logonForm.loginPhone
    }
    console.log(params,"登录")
    login(params).then(res=>{
      if(res.code == 200){
        clearInterval(timer.value);
        timer.value = null;

        //保存帐号到cookie,有效期1天
        Cookies.set('phone', logonForm.loginPhone, { expires: 1 });

        store.commit('hideLoading');//隐藏loading
        Toast({
          message:"登录成功",
          forbidClick:true,
          onClose:()=>{
            checkUser({phone:logonForm.loginPhone}).then(res=>{
              if(res.code == 200){
                if(res.data){
                  // 已注册手机号
                  $router.push({path:"/ship",query:{phone:logonForm.loginPhone}})
                }else{
                  // 未注册
                  $router.push({path: '/home',query:{phone:logonForm.loginPhone}});
                }
              }
            })

          }
        });
        
      }else{
        store.commit('hideLoading');//隐藏loading
        Toast(res.msg);
      }
    }).catch(()=>{
      store.commit('hideLoading');//隐藏loading
      Toast("请求错误");
    })
    
  }
  
}

6.页面加载完成onMounted

Cookies.get("phone")  获取cookie

这里需要判断cookie是否存在phone字段设置的时间不过期,并且当前用户是否参与活动,如果参与过则直接跳转船值结果页

onMounted(() => {
  console.log(Cookies.get("phone"))
  // 如果设置的时间过期,重新登录
  // console.log($router.currentRoute.value.path)
  // 用户活动参与校验
  if(Cookies.get("phone")){
    checkUser({phone:Cookies.get("phone")}).then(res=>{
      if(res.code == 200){
        console.log(res)
        if(res.data){
          $router.push({path:"/ship",query:{phone:Cookies.get("phone")}})
        }
      }
    })
  }

})

7.页面卸载

初始化值

onUnmounted(()=>{
    flag.value = true;
    buttonText.value = "发送验证码";
    isDisabled.value = false;
    times.value = 60;
    clearInterval(timer.value);
    timer.value = null;
})

 👉👉👉  欢迎来访船长在船上的博客,文章持续更新;项目功能持续迭代,项目开发测试完成会把完整代码上传码云,请及时收藏关注,方便查看。 发文不易,点赞 收藏 评论 关注一下!   

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

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

相关文章

二、稀疏数组和队列

稀疏数组 1、基本介绍 当一个数组中大部分元素为0&#xff0c;或者为同一个值的数组时&#xff0c;可以用稀疏数组来保存该数组。 2、处理方式 记录数组一共有几行几列&#xff0c;有多少个不同的值把具有不同值的元素的行列及值记录在一个小规模数组中&#xff0c;从而缩小…

【OpenCV】红绿灯检测C++Demo实现

很久以来一直想实现红绿灯检测&#xff0c;今天它来了。 文章目录原理代码实现打包程序为exe原理 OpenCV好强&#xff0c;能够提取红绿灯的轮廓&#xff0c;并根据颜色空间判断红绿&#xff0c;不依赖深度学习算法也能做到可用的效果/demo。 红绿灯检测的基本步骤如下&#x…

20221103使用ffmpeg提取mp4视频的字幕

20221103使用ffmpeg提取mp4视频的字幕 2022/11/3 12:19 百度搜索&#xff1a; MP4 内置字幕 提取 https://www.6yxk.com/ruanjianjiaocheng/224526.html 提取mp4格式视频字幕的方法&#xff08;工具) ffmpeg -i D:\temp\001.mp4 -map 0:s:0 sub1.srt 百度搜索&#xff1a; ffmp…

web前端面试题附答案044 - vue获取param参数,有什么缺点吗?

看这个vue的图标像不像小时候看的《魔神坛斗士》身上的某个元素。真希望成年人的世界就像小时候一样简单快乐。 今天这道面试题主要围绕vue中获取param参数展开&#xff0c;看完本文你可以吸取到以下知识点 ◇ 首先是最基本的2中获取方式 ◇ 如果不用vue应该怎么获取&#xff…

Linux查看性能相关命令

#Linux查看性能相关命令 ##CPU性能 ###/cat/proc/cpuinfo 这个文件能够获取到物理cpu的数量,每个物理cpu的核心数,是否开启超线程等信息 物理cpu: 表示主板上实际存在的cpu数量 cpu核数: 单个cpu上可以处理数据的芯片组数量,如双核,四核等 逻辑cpu数量: 一般来说&#xff0c;…

数据链路层 随机接入-CSMA/CA协议

媒体接入控制-动态接入控制-随机接入 CSMA/CA协议 载波监听多址接入/碰撞避免CSMA/CA 既然CSMA/CA协议已经成功的应用于使用广播信道的有限局域网&#xff0c;那么同样使用广播信道的无线局域网能不能也使用CSMA/CD协议呢&#xff1f; 在无线局域网中&#xff0c;仍然可以使…

httpClient同步、异步性能对比

0、测试目的 同步阻塞模式下&#xff0c;如果服务端接口响应较慢&#xff0c;那会直接影响客户端接口请求的吞吐量&#xff0c;虽然可以通过在应用代码中通过异步线程的方式优化&#xff0c;但是会增加客户端的线程开销。所以考虑用异步模式来解决这个问题 因此测试时&#x…

【网络篇】如何给虚拟机添加网卡,设置固定ip

引言 基于Centos7&#xff0c;准备两台虚拟机作为rac服务器。 以Oracle rac集群的配置说明。 网络分配 根据子网地址&#xff0c;我们给虚拟机分配如下ip: 名称公网私网网关rac1192.168.189.10192.168.83.10192.168.189.2rac2192.168.189.11192.168.83.11192.168.189.2 说明…

从零到一手写迷你版Vue

Vue响应式设计思路 Vue响应式主要包含&#xff1a; 数据响应式监听数据变化&#xff0c;并在视图中更新Vue2使用Object.defineProperty实现数据劫持Vu3使用Proxy实现数据劫持模板引擎提供描述视图的模板语法插值表达式{{}}指令 v-bind, v-on, v-model, v-for,v-if渲染将模板转…

高性能服务器之Reactor设计

今天来针对上一节课讲的多路转接知识再进一步进行设计&#xff0c;Reactor是基于epoll的ET模式设计的&#xff0c;在现在的高校和企业中是广泛应用的&#xff0c;今天我们来实现一个简洁版&#xff0c;完整版博主可没那个实力~ 目录 基本原理 代码实现 epoll_server.cc A…

当面试官让我回答React和Vue框架的区别......

我们为什么需要错误边界 在React组件中可能会由于某些JavaScript错误&#xff0c;导致一些无法追踪的错误&#xff0c;导致应用崩溃。部分 UI 的 JavaScript 错误不应该导致整个应用崩溃。为此&#xff0c;React引入了错误边界(Error Boundary)的概念&#xff1a;可以捕获发生…

MySQL搭建主从复制流程及相关问题

目录一、关于主从复制1.1 关于主从复制1.2 应用场景1.3 优缺点1.4 原理二、配置主从复制2.1 同步各个服务器的时间2.2 修改主库&#xff08;M1&#xff09;配置2.3 主库&#xff08;M1&#xff09;为从库&#xff08;S1\S2&#xff09;增加账号2.3 查看主库&#xff08;M1&…

欢迎女神科学家颜宁回国,并祝她如愿以偿

目录1、女神科学家颜宁是谁2、颜宁在深圳人才论坛最新演讲&#xff0c;以及招聘邮箱3、颜宁微博回应4、结论与展望最近女神科学家颜宁回国了&#xff0c;整个科学界和中国都沸腾了&#xff0c;也上了热搜&#xff0c;成了热门话题&#xff0c;越来越多的海归精英选择回国 1、…

Python 和Java 哪个更适合做自动化测试?

很多小伙伴在功能测试行业工作了2、3年后&#xff0c;发现自己已经把功能测试做的非常好了&#xff0c;已经到职业发展和薪资发展的瓶颈期了&#xff0c;就想着学点东西&#xff0c;提升一下技能。 而对于功能测试升级来说&#xff0c;一般有这么3个主流的发展方向&#xff1a;…

事件/边沿检测--上升沿检测、下降沿检测

检测上升沿&#xff1a;&#xff08;从低到高的跳变 __| ) input sig_a; reg sig_a_d1; wire sig_a_risedge; alaways (posedge clk or negedge rstb) begin if(!rstb) sig_a_d1 < 1b0; else sig_a_d1 < sig_a; end assign sig_a_risedge sig_a & !sig_a_d1; …

【02】概率图模型在真实世界中的应用案例

概率图模型在真实世界中的应用案例 概率图模型有许多不同的实际应用。 为了激起大家对概率图模型的兴趣&#xff0c;也为了让大家能够对概率图模型有感性的认知&#xff0c;本章我会分享概率图模型的诸多实际应用案例。 文章目录图像中的概率模型图像生成图像修复图像降噪语言…

【Python百日进阶-WEB开发】Day171 - Django案例:03配置工程日志

文章目录八、配置工程日志8.1 目的和原因8.2 配置工程日志的步骤8.2.1 配置工程日志8.2.2 准备日志文件目录8.2.3 日志器记录器的使用8.2.4 Git管理工程日志九、配置前端静态文件9.1 准备静态文件9.2 指定静态文件的加载路径十、相关文档八、配置工程日志 8.1 目的和原因 目的…

什么是跨域?以及解决方案

现在的web项目&#xff0c;很多都是前后端分离&#xff0c;特别容易出现跨域问题 那么什么是跨域问题呢?本篇文章带你彻底从本质上弄明白什么是跨域问题以及如何解决 一、跨域有什么现象 首先我们看一下现象&#xff0c;如何出现的跨域问题。例&#xff1a; 前段&#xff1a…

【Linux】基础IO —— 上

&#x1f387;Linux&#xff1a;基础IO详解 博客主页&#xff1a;一起去看日落吗分享博主的在Linux中学习到的知识和遇到的问题博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 看似不起波澜的日复一日&#xff0c;一定会在某一天让…

Web渗透测试攻防之浅述信息收集

前言 众所周知渗透测试的本质是信息收集&#xff0c;在渗透测试中信息收集的质量直接关系到渗透测试成果的与否。在对系统进行渗透测试前的信息收集是通过各种方式获取所需要的信息&#xff0c;收集的信息越多对目标进行渗透的优势越有利。通过利用获取到的信息对系统进行渗透…