智慧商城项目2-登录模块

news2024/11/26 15:32:07

 登录页静态布局

1.先重置默认样式

找到styles/common.less文件,没有就新建

// 重置默认样式
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
  
  // 文字溢出省略号
  .text-ellipsis-2 {
    overflow: hidden;
    -webkit-line-clamp: 2;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-box-orient: vertical;
  }
.van-nav-bar {
    .van-nav-bar__arrow{
        color: #333;
    }
}

2.在main.js 中导入应用

import '@/styles/common.less'

 3.导入素材

可以另起一个文件夹在终端输入,这个命令,找到里面的src/assets,把里面的文件全部复制过来即可

git clone https://gitee.com/yangLLHGS/vue2-shopping.git

4.在utils/vant-ui.js下导入使用

import { NavBar } from 'vant'
Vue.use(NavBar)

5.复制下面的基本静态布局到views/login/index.vue

<template>
  <div class="login">
    <van-nav-bar title="会员登录" left-arrow @click-left="$router.go(-1)" />
    <div class="container">
      <div class="title">
        <h3>手机号登录</h3>
        <p>未注册的手机号登录后将自动注册</p>
      </div>

      <div class="form">
        <div class="form-item">
          <input class="inp" maxlength="11" placeholder="请输入手机号码" type="text">
        </div>
        <div class="form-item">
          <input class="inp" maxlength="5" placeholder="请输入图形验证码" type="text">
          <img src="@/assets/code.png" alt="">
        </div>
        <div class="form-item">
          <input class="inp" placeholder="请输入短信验证码" type="text">
          <button>获取验证码</button>
        </div>
      </div>

      <div class="login-btn">登录</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'LoginPage'
}
</script>

<style lang="less" scoped>
.container {
  padding: 49px 29px;

  .title {
    margin-bottom: 20px;
    h3 {
      font-size: 26px;
      font-weight: normal;
    }
    p {
      line-height: 40px;
      font-size: 14px;
      color: #b8b8b8;
    }
  }

  .form-item {
    border-bottom: 1px solid #f3f1f2;
    padding: 8px;
    margin-bottom: 14px;
    display: flex;
    align-items: center;
    .inp {
      display: block;
      border: none;
      outline: none;
      height: 32px;
      font-size: 14px;
      flex: 1;
    }
    img {
      width: 94px;
      height: 31px;
    }
    button {
      height: 31px;
      border: none;
      font-size: 13px;
      color: #cea26a;
      background-color: transparent;
      padding-right: 9px;
    }
  }

  .login-btn {
    width: 100%;
    height: 42px;
    margin-top: 39px;
    background: linear-gradient(90deg,#ecb53c,#ff9211);
    color: #fff;
    border-radius: 39px;
    box-shadow: 0 10px 20px 0 rgba(0,0,0,.1);
    letter-spacing: 2px;
    display: flex;
    justify-content: center;
    align-items: center;
  }
}
</style>

requests模块

api的接口文档(你可以点击查看)wiki - 智慧商城-实战项目 (apifox.com)icon-default.png?t=O83Ahttps://apifox.com/apidoc/shared-12ab6b18-adc2-444c-ad11-0e60f5693f66/doc-2221080

axios封装

  先去下载axios,npm install axios,报错的话可以切换成这个npm install axios --save --legacy-peer-deps

然后新建 utils/request.js 封装 axios 模块

/* 封装axios用于发送请求 */
import axios from 'axios'
// 约定一个统一键名
const INFO_KEY = 'hm_shopping_info'
// 创建一个新的axios实例
const request = axios.create({
  baseURL: 'http://cba.itlike.com/public/index.php?s=/api/',
  timeout: 5000,
  headers: {
    platform: 'H5',
    'Access-Token': localStorage.getItem(INFO_KEY) || '' // 设置请求头,携带token
  }
})

// 添加请求拦截器
request.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})

// 添加响应拦截器
request.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  return response.data
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error)
})

export default request

图形验证码功能 

 此处的功能具体编写请见下方的api接口,因为我们是需要将这个接口封装到appi里面的

api接口模块

 所以要将所有请求封装在api模块里,统一管理

好处

新建 api/login.js 提供获取图形验证码 Api 函数

import request from '@/utils/request'

// 获取图形验证码
export const getPicCode = () => {
  return request.get('/captcha/image')
}

 在login/index.vue页面中的script标签调用测试

import { getPicCode } from '@/api/login'


data () {
    return {
      picCode: '', // 用户输入的图形验证码
      picUrl: '', // 存储请求渲染的图片地址
      picKey: '', // 图形验证码的唯一标识
    }
  },
async created () {
    this.getPicCode()
  },
// 获取图片验证码
async getPicCode () {
    const { data: { base64, key } } = await getPicCode()
    this.picUrl = base64
    this.picKey = key // 将来验证需要携带
    // this.$toast('图片验证码已更新')
 },

之后在模板中,也就是<template>标签 改成如下,添加了点击事件,src改成动态的:src,v-if是为了防止图片加载的时候不会闪,因为一开始的图片默认是空的

如果这里能成功拿到图片验证码,并且点击之后会切换那么这个图片验证码功能完成了

Toast轻提示

所以,我们先在utils/vant-ui.js导入

import { Toast } from 'vant'

Vue.use(Toast)

 然后直接在我们刚才写的getPrcCode()这个方法去调用,这样

有这种效果表明Toast轻提示使用成功

短信验证功能

1.首先我们需要封装请求验证码的接口 api/login.js

// 获取短信验证码
export const getMsgCode = (captchaCode, captchaKey, mobile) => {
  return request.post('/captcha/sendSmsCaptcha', {
    form: {
      captchaCode,
      captchaKey,
      mobile
    }
  })
}

注意,此时模板要进行v-model绑定

2.然后我们需要 准备data数据

data () {
  return {
    totalSecond: 60, // 总秒数
    second: 60, // 倒计时的秒数
    timer: null // 定时器 id
  }
},

3.给按钮注册点击事件

<button @click="getCode">
  {{ second === totalSecond ? '获取验证码' : second + `秒后重新发送`}}
</button>

 4. methods中封装校验方法 

// 校验输入框内容
validFn () {
  if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
    this.$toast('请输入正确的手机号')
    return false
  }
  if (!/^\w{4}$/.test(this.picCode)) {
    this.$toast('请输入正确的图形验证码')
    return false
  }
  return true
},

5.之后开启倒计时去获取验证码

不过验证之前是需要校验的

// 获取短信验证码
    async getCode () {
      // 如果输入的手机号和图像验证码正确才往下走
      if (!this.validFn()) {
        return// 不合法就不往下走
      }
      // 当前定时器没开且秒数相等
      if (!this.timer && this.second === this.totalSecond) {
        // 发送请求
        // const res = await getMsgCode(this.picCode, this.picKey, this.mobile)
        await getMsgCode(this.picCode, this.picKey, this.mobile)
        this.$toast('发送成功,请注意查收')
        // 对于非200的状态码,要跑出一个Promise的错误
        // console.log(res)
        this.timer = setInterval(() => {
          this.second--
          if (this.second <= 0) {
            clearInterval(this.timer)
            this.timer = null // 清除定时器
            this.second = this.totalSecond // 重新赋值
          }
        }, 1000)
        this.$toast('短信验证码已发送')
      }
    },

 6.离开页面是也要记得清除定时器

destroyed () {
    // 离开页面时清除定时器
    clearInterval(this.timer)
  }

登录功能

登录功能先提供api函数

// 登录
export const CodeLogin = (mobile, smsCode) => {
  return request.post('/passport/login', {
    form: {
      isParty: false,
      mobile,
      partyData: {},
      smsCode
    }
  })
}

然后在页面去调用

async login () {
      // 校验手机号和短信验证码是否合法
      if (!this.validFn()) {
        return
      }
      if (!/^\d{6}$/.test(this.msgCode)) {
        this.$toast('请输入正确的短信验证码')
        return
      }
      // 发送请求
      const res = await CodeLogin(this.mobile, this.msgCode)
      // console.log(res)
      this.$toast('登录成功')
      // 登录成功后跳转到个人中心

      // 得先判断是否有回跳地址
      const url = this.$route.query.backUrl || '/'
      this.$router.replace(url)
    }

响应拦截器统一处理错误提示

但是忘记请求失败咋办,他会有状态码返回过来的,那么

在响应拦截器里面填写

// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 2xx 范围内的状态码都会触发该函数。
  // 对相应数据做点什么
  const res = response.data
  // console.log(res)
  if (res.status !== 200) {
    Toast(res.message) // 这个要用全局导入,因为当前的this不是组件
    return Promise.reject(res.message)
  } else {
    Toast.clear() // 清除loading
  }
  // 对响应数据做点什么
  return res
}, function (error) {
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error)
})

登录权证信息

 为啥要有这个,你登录之后软件肯定要存储你的登录信息,之后每次获取页面都需要去从vuex读取,判断token是否合法

Storage存储模块---vuex持久化处理

 vuex的数据刷新之后会消失的,那么用户的信息是需要保存到本地里面的,所以新建utils/storage.js,需要持久化保存数据的则在这个文件去写方法

// 约定一个统一键名
const INFO_KEY = 'hm_shopping_info'
// 获取个人信息
export const getInfo = () => {
  const defaultObj = { token: '', userId: '' }
  const res = localStorage.getItem(INFO_KEY)
  return res ? JSON.parse(res) : defaultObj // 有值赋值,没有值默认值
}

// 设置个人信息
export const setInfo = (info) => {
  localStorage.setItem(INFO_KEY, JSON.stringify(info))
}

// 移除个人信息
export const removeInfo = () => {
  localStorage.removeItem(INFO_KEY)
}

然后在下方文件=创建如下文件

之后在user.js中,导入刚才编写的持久化存储

import { getInfo, setInfo } from '@/utils/storage'
export default {
  namespaced: true,
  state () {
    return {
      userInfo: getInfo()
    }
  },
  mutations: {
    // mutations中任何一个放法的第一个参数就是state
    setUserInfo (state, obj) {
      // 修改state中的数据
      state.userInfo = obj
      // 修改本地存储的值
      setInfo(obj)
    }
  },
  actions: {
    logout (context) {
      // 个人信息重置
      context.commit('setUserInfo', {})
      // 购物车信息重置(跨模块调用) ---> 开启全局模式
      context.commit('cart/setCartList', [], { root: true })
    }
  },
  getters: {}
}

 然后挂载在index.js上

最后在登录页面去调用这个vuex的user模块的方法

添加loading效果

那么我们在utils/request.js中去请求拦截器添加loading效果

因为这是网络原因造成的,肯定要走axios,所以在这一步添加

 

之后在响应拦截器清除loading效果

 

至此我们的登录功能这个大模块就正式完成了。

接下来我会更新其他页面的功能,大家敬请期待~~~~

 

 

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

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

相关文章

CentOS7安装RabbitMQ-3.13.7、修改端口号

本文安装版本&#xff1a; Erlang&#xff1a;26.0 官网下载地址 Erlang RabbitMQ&#xff1a;3.13.7 官网下载地址 RabbitMQ RabbitMQ和Erlang对应关系查看&#xff1a;https://www.rabbitmq.com/which-erlang.html 注&#xff1a;安装erlang之前先安装下依赖文件&#xff0…

无人机之放电速率篇

无人机的放电速率是指电池在一定时间内放出其储存电能的能力&#xff0c;这一参数对无人机的飞行时间、性能以及安全性都有重要影响。 一、放电速率的表示方法 放电速率通常用C数来表示。C数越大&#xff0c;表示放电速率越快。例如&#xff0c;一个2C的电池可以在1/2小时内放…

《知道做到》

整体看内容的信息密度较低。绿灯思维、积极心态、反复练习值得借鉴。 引言 行动是老子&#xff0c;知识是儿子&#xff0c;创造是孙子&#xff01;行是知之始&#xff0c;知是行之成。 前言 工作中最让你失望的事情是什么&#xff1f; 一个人行为的改变总是先从内心想法的转…

MySQL 【日期】函数大全(六)

目录 1、TIME_FORMAT() 按照指定的格式格式化时间。 2、TIME_TO_SEC() 将指定的时间值转为秒数。 3、TIMEDIFF() 返回两个时间之间的差值。 4、TIMESTAMP() 累加所有参数并将结果作为日期时间值返回。 5、TIMESTAMPADD() 将指定的时间间隔加到一个日期时间值上并返回结果。…

数据库->库的操作

目录 一、查看数据库 1.显示所有的数据库 二、创建数据库 1.创建数据库 2.查看警告信息 3.创建一个名为database的数据库 三、字符集编码和校验(排序)规则 1.查看数据库⽀持的字符集编码 2.查看数据库⽀持的排序规则 3.一条完整创建库的语句 4. 不同的字串集与排序规…

keepalived(高可用)+nginx(负载均衡)+web

环境 注意&#xff1a; (1) 做高可用负载均衡至少需要四台服务器&#xff1a;两台独立的高可用负载均衡器&#xff0c;两台web服务器做集群 (2) vip&#xff08;虚拟ip&#xff09;不能和物理ip冲突 (3) vip&#xff08;虚拟ip&#xff09;最好设置成和内网ip同一网段&#xf…

传感器驱动系列之PAW3212DB鼠标光电传感器

目录 一、PAW3212DB鼠标光电传感器简介 1.1 主要特点 1.2 引脚定义 1.3 传感器组装 1.4 应用场景 1.5 传感器使用注意 1.5.1 供电选择 1.5.2 SPI读写设置 1.5.3 MOTION引脚 1.6 寄存器说明 1.6.1 Product_ID1寄存器 1.6.2 MOTION_Status寄存器 1.6.3 Delta_X寄存器…

【论文笔记】X-Former: Unifying Contrastive and Reconstruction Learning for MLLMs

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: X-Former: Unifying Contr…

为您的 WordPress 网站打造完美广告布局 A5广告单元格插件

一个为 WordPress 网站量身定制的强大工具,它将彻底改变您展示广告的方式 灵活多变的布局设计 A5 广告单元格插件的核心优势在于其无与伦比的灵活性。无论您是想要创建整齐的网格布局,还是希望打造独特的不规则设计,这款插件都能满足您的需求。 自定义网格数量&#xff1a;从 2…

C# 条形码、二维码标签打印程序

1、条码标答打印主界面 2、打印设置 3、生成QR代码 private void GetBarcode_T(string lr) { QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();//创建一个对象 qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE; //设置编码测量…

Mamba学习笔记(2)—序列数据处理基础

文章目录 (1) RNN&#xff08;Recurrent Neural Networks&#xff09;基本原理代码定义 (2) SLTM (Long Short-Term Memory)基本原理代码定义 (3) GRU (Gated Recurrent Unit)基本原理代码定义 (4) Transformer&#xff08;☆☆☆Attention Is All You Need☆☆☆&#xff09;0…

量子门电路开销——T门、clifford门、toffoli门、fredkin门

在量子计算中&#xff0c;T门的成本比Clifford门高出很多倍的原因与量子计算中纠错的实现、物理门操作的复杂性以及容错量子计算架构中的成本评估有关。以下是几个关键原因&#xff0c;解释了为什么 T 门的成本在量子计算中远远高于 Clifford 门&#xff1a; 1. T 门和 Cliffo…

递归、搜索与回溯(二)——递归练习与快速幂

文章目录 递归、搜索与回溯——递归两两交换链表中的节点Pow(x, n) 递归、搜索与回溯——递归 该文仍然是解决递归问题&#xff0c;值得注意的是快速幂算法。接下来会系统学习二叉树深搜题目&#xff0c;慢慢走向搜索与回溯。 两两交换链表中的节点 原题链接&#xff1a;24. 两…

AI识谱——将乐曲转化为五线谱

导言&#xff1a; 会乐曲的小伙伴在听到一首好听的乐曲的时候&#xff0c;肯定想过将这首歌曲转换为谱子给弹出来。除了上网找乐谱、请大神帮忙扒谱或者自己扒谱外&#xff0c;小伙伴也可以尝试一下本文介绍的AI识谱流程&#xff0c;让我们开始吧&#xff01; 注意了&#xf…

2024 Python3.10 系统入门+进阶(十七):面向对象基础

目录 一、面向对象概述1.1 面向对象简介1.2 对象和类1.3 定义属性和行为1.3.1 用数据描述对象的状态1.3.2 行为就是动作 1.4 隐藏细节并创建公共接口1.5 组合1.6 继承1.6.1 继承提供抽象1.6.2 多重继承 二、封装2.1 Python类定义2.2 创建类的成员2.2.1 创建实例方法并访问2.2.2…

PythonExcel批量pingIP地址

问题&#xff1a; 作为一个电气工程师&#xff08;PLC&#xff09;&#xff0c;当设备掉线的时候&#xff0c;需要用ping工具来检查网线物理层是否可靠连接&#xff0c;当项目体量过大时&#xff0c;就不能一个手动输入命令了。 解决方案一&#xff1a; 使用CMD命令 for /L %…

机器学习在聚合物及其复合材料中的应用与实践

在当前的工业和科研领域&#xff0c;聚合物及其复合材料因其卓越的物理和化学性能而受到广泛关注。这些材料在航空航天、汽车制造、能源开发和生物医学等多个行业中发挥着至关重要的作用。随着材料科学的发展&#xff0c;传统的实验和理论分析方法已逐渐无法满足新材料研发的需…

【力扣打卡系列】滑动窗口与双指针(无重复字符的最长子串)

坚持按题型打卡&刷&梳理力扣算法题系列&#xff0c;语言为go&#xff0c;Day7 无重复字符的最长子串 题目描述解题思路 不含重复字符——》考虑使用哈希表来存储记录为了提高效率也可以用数组&#xff0c;hash : [128]bool{} &#xff08;因为存的是字符的ASCLL码&…

【Unity踩坑】无法关闭Unity(Application.Shutdown.CleanupEngine)

安装了Unity 6正式版&#xff0c;在关闭Unity 项目时&#xff0c;会出现下面的提示&#xff0c;一直无法关闭。 一直显示 Application.Shutdown.CleanupEngine。 查了一下。这是一个历史性问题了&#xff0c;看来依然没有解决。 参考&#xff1a;Application.Shutdown.Cleanu…

web API基础

作用和分类 作用: 就是使用 JS 去操作 html 和浏览器 分类&#xff1a; DOM (文档对象模型)、 BOM &#xff08;浏览器对象模型&#xff09; 什么是DOM DOM (Document Object Model) 译为文档对象模型&#xff0c;是 HTML 和 XML 文档的编程接口。 HTML DOM 定义了访问和操作 …