说明
项目基于若依管理系统进行开发,部分接口来源于若依管理系统后端项目,如本文的登录接口、获取验证码接口。
请求包创建
小程序的数据需要向后端发请求进行获取,为了简化后续的开发,需要创建一个包专门存放所有发请求的js方法。
创建文件夹
创建api的存放包
再创建工具js的存放包
请求工具request.js
注意使用该文件,请修改baseUrl
对应的值,配置好你的后端的请求Ip和端口。
export default { common: { baseUrl: 'http://localhost:8085', // 如果需要真机调试,打开cmd使用ipconfig命令,这样手机才可以在同一局域网访问到后端 // baseUrl: 'http://10.23.12.180:6001', data: {}, header: {}, method: "GET", dataTyoe: 'json' }, /** * 请求拦截器 */ request(options = {}) { let token = uni.getStorageSync('token') if (token) { this.common.header = { 'token': token, // 若依管理系统后端识别的是这个 'Authorization': token } } options.url = this.common.baseUrl + options.url; options.data = options.data || this.common.data; options.header = options.header || this.common.header; options.method = options.method || this.common.method; options.dataTyoe = options.dataTyoe || this.common.dataTyoe; return new Promise((res, rej) => { uni.request({ ...options, success: (result) => { // console.log("请求响应:" + JSON.stringify(result)); let data = result.data; if (data.code != 200) { // 报错提示 // uni.showToast({ // title: data.msg, // icon: 'none', // duration: 2000 // }) if (data.code == 401) { console.log("跳转到登录页") // 清除掉token,因为token在后端已经过期 uni.clearStorage(); uni.reLaunch({ url: "/pages/login/login" }) } else { // catch可以接收data return rej(data); } } // then可以接收data res(data); } }) }) }, }
关于下面所示的代码,需要根据你的后端来修改,例如你的响应码不一定叫code,你的信息也不一定叫做msg,请求成功的状态码不一定是200,登录的token失效的状态码不一定是401,需要改成自己的
success: (result) => { // console.log("请求响应:" + JSON.stringify(result)); let data = result.data; if (data.code != 200) { // 报错提示 // uni.showToast({ // title: data.msg, // icon: 'none', // duration: 2000 // }) if (data.code == 401) { console.log("跳转到登录页") // 清除掉token,因为token在后端已经过期 uni.clearStorage(); uni.reLaunch({ url: "/pages/login/login" }) } else { // catch可以接收data return rej(data); } } // then可以接收data res(data); }
登录功能实现
请求方法
创建login.js
文件
import httpRequest from '@/utils/request' // 登录方法 export function login(username, password, code, uuid) { const data = { username, password, code, uuid } return httpRequest.request({ url: '/login', headers: { isToken: false }, method: 'post', data: data }) } // 获取验证码 export function getCodeImg() { return httpRequest.request({ url: '/captchaImage', headers: { isToken: false }, method: 'get', timeout: 20000 }) }
页面
创建login.vue
文件
<template> <view class="login"> <u-toast ref="uToast"></u-toast> <view class="form"> <view class="title"> <text>易售二手平台</text> </view> <u--form labelPosition="left" :model="model" :rules="rules" ref="loginForm"> <u-form-item prop="loginForm.username" leftIcon="account-fill" borderBottom ref="item1"> <view class="item"> <u--input v-model="model.loginForm.username" border="none"></u--input> </view> </u-form-item> <u-form-item prop="loginForm.password" leftIcon="lock-fill" borderBottom ref="item1"> <view class="item"> <u--input v-model="model.loginForm.password" password border="none"></u--input> </view> </u-form-item> <u-form-item prop="loginForm.code" leftIcon="integral-fill" borderBottom ref="item1"> <view class="item"> <u-input v-model="model.loginForm.code" clearable border placeholder="验证码"></u-input> <img :src="codeUrl" @click="getCode" class="login-code-img" /> </view> </u-form-item> </u--form> <view style="margin-top: 20rpx;"> </view> <u-button type="primary" class="login-button" @click="login()">登录</u-button> </view> </view> </template> <script> import { getCodeImg, login } from "@/api/login"; export default { data() { return { model: { loginForm: { username: 'admin', password: 'admin123', uuid: '', code: '', }, }, // 登录表单字段校验过程 rules: { 'loginForm.username': { type: 'string', required: true, message: '请填写用户名', trigger: ['blur', 'change'] }, 'loginForm.password': { type: 'string', required: true, message: '请填写密码', trigger: ['blur', 'change'] }, 'loginForm.code': { type: 'number', required: true, message: '请输入数字类型的验证码', trigger: ['blur', 'change'] }, }, codeUrl: "", } }, onReady() { //onReady 为uni-app支持的生命周期之一 this.$refs.loginForm.setRules(this.rules) }, created() { let token = uni.getStorageSync('token') if (token) { this.toIndex(); } this.getCode(); }, methods: { /** * 获取验证码 */ getCode() { // console.log("获取验证码") getCodeImg().then(res => { // console.log("获取验证码:" + JSON.stringify(res)) let captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled; if (captchaEnabled) { this.codeUrl = "data:image/gif;base64," + res.img; this.model.loginForm.uuid = res.uuid; } }); }, login() { this.$refs.loginForm.validate().then(res => { // console.log("登录:"); login(this.model.loginForm.username, this.model.loginForm.password, this.model.loginForm.code, this.model .loginForm.uuid).then( res => { // console.log("登录:" + JSON.stringify(res)) // 存储token uni.setStorage({ key: "token", data: res.token, success: (res) => { this.toIndex(); } }) }).catch(res => { this.$refs.uToast.show({ type: 'error', message: res.msg }) }) }).catch(errors => { this.$refs.uToast.show({ type: 'error', message: "表单数据校验失败,请检查后再登录" }) }) }, toIndex() { // 跳转到首页 uni.reLaunch({ url: "/pages/index/index" }) } } } </script> <style lang="scss"> .login { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; // background: #2b92ff; background-color: #0093E9; background-image: linear-gradient(135deg, #0093E9 0%, #80D0C7 100%); .title { width: 100%; font-weight: bold; font-size: 45rpx; display: flex; align-items: center; justify-content: center; margin-bottom: 30rpx; } .form { width: 600rpx; background: #ffffff; padding: 30rpx; border-radius: 20rpx; .item { display: flex; height: 80rpx; } .login-code-img { float: right; height: 80rpx; width: 160rpx; padding-left: 12rpx; } .login-button { margin-top: 50rpx; width: 80%; } } } </style>
涉及知识点
错误提示
当用户登录时密码或者验证码出错时,需要提示用户登录出错的原因
this.$refs.uToast.show({ type: 'error', message: res.msg })
前端校验
现在出错是后端校验的,其实前端也可以做很多校验,在前端不让不合法的输入提交,这样可以减轻后端服务器的压力。如已经验证码为算术题,答案肯定是数字,那就限制用户不能输入字符串。
首先需要定义规则,如下面的代码
rules: { 'loginForm.username': { type: 'string', required: true, message: '请填写用户名', trigger: ['blur', 'change'] }, 'loginForm.password': { type: 'string', required: true, message: '请填写密码', trigger: ['blur', 'change'] }, 'loginForm.code': { type: 'number', required: true, message: '请输入数字类型的验证码', trigger: ['blur', 'change'] }, },
在页面初始化的时候,给表单设置规则,如下面的代码
onReady() { //onReady 为uni-app支持的生命周期之一 this.$refs.loginForm.setRules(this.rules) },
最后使用:rules="rules"
给表单绑定规则,如下面的代码
<u--form labelPosition="left" :model="model" :rules="rules" ref="loginForm">
在点击登录按钮之后,一定要通过校验之后,才真正向后端发请求
this.$refs.loginForm.validate().then(res => { // 校验通过之后,向后端发登录请求 }).catch(errors => { this.$refs.uToast.show({ type: 'error', message: "表单数据校验失败,请检查后再登录" }) })
当校验不通过时,不会发请求
设置token
到客户端缓存中
当用户登录成功之后,后端给前端返回一个凭证,即token,可以理解为一把钥匙,用户后面访问其他接口的时候,就带上这把钥匙,后端判断用户有钥匙之后,就让用户访问接口。当然,钥匙是有过期时间的,当过期之后,用户就需要重新登录。下面是设置缓存的代码:
uni.setStorage({ key: "token", data: res.token, success: (res) => { // 跳转到首页 } })
在前面的request.js
文件中,有这么一段代码,作用就是在发请求之前,从缓存中取出token
对应的值,然后放到请求头中,这样后端就可以去请求头中获取token
的值
let token = uni.getStorageSync('token') if (token) { this.common.header = { 'token': token } }
路由跳转
当登录成功之后,需要跳转到小程序首页
// 跳转到首页 uni.reLaunch({ url: "/pages/index/index" })
如果已经登录过,访问登录页直接跳转到首页
created() { let token = uni.getStorageSync('token') if (token) { this.toIndex(); } this.getCode(); },