登录逻辑:
1 验证手机号码输入框,分别判断以下情况并作出弹窗警告
(1:是否为空
(2:是否为11位数字
(3:是否是13,15, 17, 18开头的正确手机号码
2 输入框下面添加一个获取验证码的按钮,默认为关闭不可点击,
点击后,开启一个定时器setInterval,然后发送一个ajax请求给后台,把手机号传给后台,让后台去发送短信
在验证上面3种情况之后,得到为正确手机号码后
再将验证码按钮设置为可点击
3 验证验证码的输入框,分别判断以下情况并作出弹窗警告
1:是否为空
2:是否为6位数字
4 验证座位号的输入框,分别判断以下情况并作出弹窗警告
1:是否为空
2:
勾选华夏航空娱乐系统安全须知
原文:https://blog.csdn.net/weixin_41818920/article/details/82290511
手机注册验证逻辑是这样的:
首先要找短信服务商如:梦网、云信使、互亿无线等等申请短信发送接口。
网站实现流程如下:
第一步:用户注册时输入手机号,网站首先要通过JS或者ajax+php验证这个号码是不是正确的手机号。
第二步:用户点击发送手机验证码,通过ajax把手机号传到php,这时php生成一个随机的验证码保存在session中,然后通过短信接口把这个验证码发送到这个手机号中。
第三步:用户输入手机收到的验证码注册。网站用session中的验证码和用户输入的验证码比较。
平时我们在项目中进行注册等的时候,会经常用到短信验证的功能,但是现在现在很多短信验证都是存在下面几个问题,例如短信验证时间为60s的时候,
- 当点击完按钮时,倒计时还没到60s过完时,刷新浏览器,验证码按钮又可以重新点击
- 当点击按钮倒计时开始,例如在50s的时候我关闭了浏览器,过了5s后,我在打开,此时时间倒计时的时间应该是45s左右,但是当重新打开浏览器的时候,按钮又可以重新点击了
为了解决上面的两个问题,就需要把时间都写到localstorage里面去,当打开页面的时候,就去localstorage里面去取,
https://blog.csdn.net/qq_39581763/article/details/81739428
设置反向代理
https://blog.csdn.net/weixin_43067157/article/details/82079792?utm_source=blogxgwz0
devServer: {
// 设置代理
proxy: {
'/v1': {
target: 'http://localhost:8080/', // 域名
ws: true, // 是否启用websockets
changOrigin: true, // 开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
pathRewrite: {
'^/v1': '/'
}
}
}
},
element ui 的表单验证
H5学习之路-手机短信验证码的实现
https://blog.csdn.net/qiyongkang520/article/details/55007040
vue 实现通过手机发送验证码注册
https://www.jianshu.com/p/3a96636e7242
vue做一个有验证码的登陆页面和注册页面,敲回车登陆
https://blog.csdn.net/hani_wen/article/details/81545319
关于vue.js element ui 表单验证 this.$refs[formName].validate()的问题
https://blog.csdn.net/qq_41894865/article/details/80476736
一、element ui 表单验证源码
<templete>
<el-main>
<el-form :model="ReginForm" ref="ReginForm" :rules="rule" class="regform" label-width="0">
<h3 class="login-text">手机注册</h3>
<el-form-item prop="tel">
<el-input type="text" v-model.number="ReginForm.tel" placeholder="手机号码">
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input type="password" v-model="ReginForm.password" placeholder="密码">
</el-input>
</el-form-item>
<div>
<input class="auth_input" type="text" v-model="verification" placeholder="输入验证码" />
<span v-show="sendAuthCode" class="auth_text auth_text_blue" @click="getAuthCode">获取验证码</span>
<span v-show="!sendAuthCode" class="auth_text"> <span class="auth_text_blue">{{auth_time}} </span>
秒之后重新发送验证码</span>
</div>
<el-form-item>
<el-button type="success" class="submitBtn" round @click.native.prevent="submit" :loading="logining">
注册
</el-button>
<hr>
<p>已经有账号,马上去<span class="to" @click="tologin">登录</span></p>
</el-form-item>
</el-form>
</el-main>
</template>
<script>
export default {
data() {
let confirmpasswordCheck = (rule, value, callback) => {
if (value === "") {
return callback(new Error("密码是必须的"));
} else {
return callback();
}
};
let telCheck = (rule, value, callback) => {
if (value === "") {
return callback(new Error("电话号码是必须的"));
} else if (!Number.isInteger(value)) {
return callback(new Error("电话号码必须是数字"));
} else if (value.toString().length !== 11) {
return callback(new Error("电话号码必须是11位数字"));
} else {
callback();
}
};
return {
ReginForm: {
password: "",
tel: ""
},
logining: false,
sendAuthCode: true,
/*布尔值,通过v-show控制显示‘获取按钮’还是‘倒计时’ */
auth_time: 0,
/*倒计时 计数器*/
verification: "", //绑定输入验证码框框
rule: {
password: [
{
required: true,
message: "密码是必须的!",
trigger: "blur"
}
],
tel: [
{
required: true,
validator: telCheck,
trigger: "blur"
}
]
}
};
},
methods: {
// 验证
getAuthCode: function() {
const verification = this.ReginForm.tel;
const url = " ";
console.log("url", url);
this.$http.get(url).then(
function(response) {
console.log("请求成功", response);
},
function(error) {
console.log("请求失败", error);
}
);
this.sendAuthCode = false;
//设置倒计时秒
this.auth_time = 30;
var auth_timetimer = setInterval(() => {
this.auth_time--;
if (this.auth_time <= 0) {
this.sendAuthCode = true;
clearInterval(auth_timetimer);
}
}, 1000);
},
// 封装注册发送请求方法
thisAjax() {
const passwordData = this.ReginForm.password;
const phoneData = this.ReginForm.tel;
const mCodeData = this.verification;
// 手机注册
//emulateJSON:true设置后post可跨域
const url = " 填接口";
this.$http
.post(
url,
{
填传入的参数
},
{
emulateJSON: true
}
)
.then(
function(response) {
//登录后跳转的页面
this.$router.push("/");
},
function(error) {
alert("请求失败", error);
}
);
},
// ...
submit() {
this.$refs.ReginForm.validate(valid => {
if (valid) {
this.logining = true;
this.thisAjax();
console.log("开始写入后台数据!");
} else {
console.log("submit err");
}
});
},
reset() {
this.$refs.ReginForm.resetFields();
},
tologin() {
//已经注册过跳转到登入界面
this.$router.push("/phoneLogin");
}
}
};
</script>
<style>
.regform {
margin: 20px auto;
width: 310px;
background: #fff;
box-shadow: 0 0 10px #b4bccc;
padding: 30px 30px 0 30px;
border-radius: 25px;
}
.submitBtn {
width: 65%;
}
.to {
color: #fa5555;
cursor: pointer;
}
.auth_input {
width: 140px;
height: 38px;
margin-bottom: 20px;
border: 1px solid #dcdfe6;
/* color:red; */
padding-left: 10px;
border-radius: 8%;
}
.regform[data-v-92def6b0] {
width: 370px;
min-height: 440px;
}
.login-text {
text-align: center;
margin-bottom: 20px;
}
</style>
30s倒计时
<button class="close_tel" v-show="show" @click="getCode">获取验证码</button>
<button class="close_tel2" v-show="!show" > 重新获取({{count}}s)</button>
getCode() {
const TIME_COUNT = 30
if (!this.timer) {
this.count = TIME_COUNT
this.show = false
this.timer = setInterval(() => {
if (this.count > 0 && this.count <= TIME_COUNT) {
this.count--
} else {
this.show = true
clearInterval(this.timer)
this.timer = null
}
}, 1000)
}
},
二、自己写
<template>
<div>
<div class="login">
<div class="logo">
<div>
<img src="../assets/images/logo.png" alt>
</div>
</div>
<p class="welcome">
<span>欢迎乘坐</span>
<span>G5XXXX</span>
<span>航班,</span>
<span>重庆-贵阳</span>
</p>
<p class="info">为了给您更好的服务,请填写以下信息:</p>
<form :model="ReginForm" ref="ReginForm">
<input type="tel" class="phone" placeholder="手机号" v-model="loginForm.tel">
<input class="phone" type="number" placeholder="验证码" v-model="loginForm.msg">
<button class="close_tel" v-show="show" @click="getCode">获取验证码</button>
<button class="close_tel2" v-show="!show" > 重新获取({{count}}s)</button>
<input type="text" class="phone" placeholder="座位号" v-model="loginForm.seat">
<div class="check-item">
<cube-checkbox v-model="loginForm.check" :option="option">华夏航空娱乐系统安全须知</cube-checkbox>
</div>
<cube-button class="subLogin" @click="submit">登录</cube-button>
</form>
</div>
<p class="online">在线</p>
<!-- <Count v-bind:num="num" ></Count>-->
<!-- <Menu></Menu> -->
</div>
</template>
<script>
// import { mapMutations } from 'vuex'
// import Count from '../components/shop/Count.vue'
// import Menu from '../components/common/Menu.vue'
export default {
name: 'login',
data() {
return {
show: true,
count: '',
timer: null,
check: '',
// num: 10,
loginForm: {
tel: '',
seat: '',
check: false,
msg: ''
},
option: {
label: 'Option Checkbox',
value: 'optionValue',
disabled: false
}
}
},
methods: {
getCode() {
const TIME_COUNT = 30
if (!this.timer) {
this.count = TIME_COUNT
this.show = false
this.timer = setInterval(() => {
if (this.count > 0 && this.count <= TIME_COUNT) {
this.count--
} else {
this.show = true
clearInterval(this.timer)
this.timer = null
}
}, 1000)
}
},
submit() {
var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\d{8})$/ // 验证是不是以13,15,18,17开头的数字
var num = /^\d{6}$/ // 验证是否6位数字
if (this.loginForm.tel === '') {
alert('手机号不能为空!')
} else if (this.loginForm.tel.length !== 11) {
alert('请输入11位的手机号码!')
} else if (!myreg.test(this.loginForm.tel)) {
alert('请输入有效的手机号码!')
} else if (this.loginForm.msg === '') {
alert('请填写验证码!')
} else if (!num.test(this.loginForm.msg)) {
alert('请填写正确的验证码!')
} else if (this.loginForm.seat === '') {
alert('座位号不能为空!')
} else if (this.loginForm.check === false) {
alert('请确认勾选华夏航空娱乐系统安全须知!')
} else {
this.$router.push('/main')
}
}
}
// components: { Count, Menu }
}
</script>
<style scoped>
* {
margin: 0;
padding: 0;
}
input {
flex: 1;
}
a {
cursor: pointer;
}
.phone {
width: 220px;
display: block;
margin: 0 auto;
font-size: 16px;
/* color: #666; */
outline: none;
padding-top: 30px;
border-left: none;
border-right: none;
border-top: none;
border-bottom: 0.1px solid rgb(196, 194, 194);
position: relative;
}
.close_tel {
font-size: 12px;
width: 100px;
height: 23px;
line-height: 25px;
border-radius: 5px;
background-color: rgb(86, 159, 255);
color: white;
position: absolute;
right: 20%;
top: 255px;
outline: none;
border: 0;
font-weight: 400;
cursor: pointer;
}
.close_tel2 {
font-size: 12px;
width: 100px;
height: 23px;
line-height: 25px;
border-radius: 5px;
background-color: rgb(211, 211, 211);
color: white;
position: absolute;
right: 20%;
top: 255px;
outline: none;
border: 0;
font-weight: 400;
cursor: pointer;
}
.login {
padding-top: 50px;
background-color: white;
font-size: 16px;
}
.logo {
width: 220px;
/* border: #666 1px solid; */
margin: 0 auto;
}
.logo img {
display: block;
width: 100%;
height: auto;
}
.login p {
font-size: 13px;
width: 260px;
text-align: center;
margin: 0 auto;
}
.welcome {
color: #338bff;
}
.check-item {
width: 220px;
margin: 10px auto;
font-size: 12px;
color: grey;
}
.info {
color: grey;
letter-spacing: 1.2px;
}
.phone {
width: 220px;
display: block;
margin: 0 auto;
font-size: 16px;
/* color: #999; */
outline: none;
padding-top: 30px;
border-left: none;
border-right: none;
border-top: none;
border-bottom: 0.1px solid rgb(196, 194, 194);
}
input {
padding-bottom: 10px;
font-weight: 700;
color: #666;
letter-spacing: 2px;
}
::-webkit-input-placeholder {
/* WebKit, Blink, Edge */
color: #999;
}
.subLogin {
display: block;
margin: 0 auto;
width: 240px;
height: 50px;
margin-top: 40px;
background-color: #338bff;
color: white;
border-radius: 10px;
font-size: 18px;
outline: none;
border: 0;
cursor: pointer;
letter-spacing: 10px;
}
.online {
width: 100%;
margin: 0 auto;
text-align: center;
letter-spacing: 15px;
color: rgb(180, 173, 173);
position: fixed;
bottom: 30px;
}
</style>