1 向src\router\index.js添加定义
{
path: '/LoginSms',
name: '手机号登录',
component: () => import('../views/LoginSmsView.vue')
},
{
path: '/Users/Register',
name: '用户注册',
component: () => import('../views/Users/RegisterView.vue'),
},
2 向src\common\http.api.js添加定义
/****************************API集中管理--用户模块************************************/
//通过1个指定电子邮箱获取1个指定的用户实例,该API主要用于验证电子邮箱的唯一性。
export const getCustomerByEmail = async params => {
return await axiosInterceptor.get('/Customer/IsEmail', {
params: params
});
};
//通过1个指定手机号获取1个指定的用户实例,该API主要用于验证手机号的唯一性。
export const getCustomerByPhone = async params => {
return await axiosInterceptor.get('/Customer/IsPhone', {
params: params
});
};
//通过1个指定手机号获取1个指定的有效短信验证码。
export const getCodeByPhone = async params => {
return await axiosInterceptor.get('/Customer/IsCode', {
params: params
});
};
//把1个指定用户实例持久化到用户表中。
export const postCustomerRegister = async params => {
return await axiosInterceptor.post('/Customer/Register', params);
};
//向1个指定手机发送1个指定的短信验证码,并把该短信验证码实例例持久化到短信验证表中。
export const postSmsValidateCreate = async params => {
return await axiosInterceptor.post('/Customer/SmsValidateCreate', params);
};
//1个指定手机号的登录操作。
export const postCustomerLoginSms = async params => {
return await axiosInterceptor.post('/Customer/LoginSms', params);
};
3 src\views\Users\RegisterView.vue
<template>
<el-form :model="registerForm" :rules="registerRule" ref="refRule" label-width="100px" class="demo-ruleForm"
label-position="left" status-icon>
<h3 class="title">用户注册</h3>
<el-form-item label="账号:" prop="name">
<el-input type="text" v-model="registerForm.name" maxlength="16" minlength="2" show-word-limit />
</el-form-item>
<el-form-item label="电子邮箱:" prop="email">
<el-input v-model="registerForm.email" />
</el-form-item>
<el-form-item label="手机号:" prop="phone">
<el-input type="text" v-model="registerForm.phone">
<template #prepend>+86</template>
</el-input>
</el-form-item>
<el-form-item label="密码:" prop="password">
<el-input type="password" v-model="registerForm.password" show-password />
</el-form-item>
<el-form-item label="确认密码:" prop="confirmPassword">
<el-input type="password" v-model="registerForm.confirmPassword" show-password />
</el-form-item>
</el-form>
<el-button type="primary" @click="onSubmit">提 交</el-button>
</template>
<script>
import {
getCustomerByEmail,
getCustomerByPhone,
postCustomerRegister
} from '../../common/http.api.js';
export default {
data() {
//验证1个指定的电子邮箱已经是否被注册。
const validateEmailUnique = async (rule, value, callback) => {
if (value) {
let data = await this.isEmailUnique(value);
//console.log(data);
if (data.status == 200 && data.response) {
callback(new Error("该电子邮箱已经被注册!"));
} else {
callback();
}
}
};
//验证1个指定的手机号已经是否被注册。
const validatePhoneUnique = async (rule, value, callback) => {
if (value) {
let data = await this.isPhoneUnique(value);
// console.log(data);
if (data.status == 200 && data.response) {
callback(new Error("该手机号已经被注册!"));
} else {
callback();
}
}
};
//验证密码与确认密码的输入是否一致。
const validateConfirmPassword = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入确认密码!"));
} else if (value !== this.registerForm.password) {
callback(new Error("两次输入密码不一致!"));
} else {
callback();
}
};
return {
//用户注册表单初始化。
registerForm: {
name: '',
email: '',
phone: '',
password: '',
confirmPassword: '',
},
//用户注册表单输入验证初始化。
registerRule: {
name: [{
required: true,
message: '请输入账号名!',
trigger: 'blur',
},
{
min: 2,
max: 16,
message: '账号名的长度应在2到16个字符之间!',
trigger: 'blur'
},
],
email: [{
required: true,
message: '请输入电子邮箱!',
trigger: 'blur',
},
{
pattern: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/,
message: "电子邮箱格式错误!"
},
{
validator: validateEmailUnique,
trigger: "blur",
},
],
phone: [{
required: true,
message: "请输入手机号!",
trigger: 'blur',
},
{
pattern: 11 && /^((13|14|15|16|17|18|19)[0-9]{1}\d{8})$/,
message: "手机号格式错误!"
},
{
validator: validatePhoneUnique,
trigger: "blur",
},
],
password: [{
required: true,
message: "请输入密码!",
trigger: "blur"
},
{
min: 6,
max: 20,
message: "长度在6到20个字符!",
trigger: "blur",
},
{
required: true,
pattern: /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\W_!@#$%^&*`~()-+=]+$)(?![0-9\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\W_!@#$%^&*`~()-+=]{6,20}$/,
message: "包含大小写字母、数字和特殊字符的三种!",
trigger: "blur",
},
],
confirmPassword: [{
validator: validateConfirmPassword,
trigger: "blur"
}, ],
},
};
},
methods: {
//通过1个指定电子邮箱获取1个指定的用户实例,验证电子邮箱的唯一性。
async isEmailUnique(email) {
let emailParam = {
email: email,
};
let res = await getCustomerByEmail(emailParam);
return res.data;
},
//过1个指定手机号获取1个指定的用户实例,验证手机号的唯一性。
async isPhoneUnique(phone) {
let phoneParam = {
phone: phone,
};
let res = await getCustomerByPhone(phoneParam);
return res.data;
},
//添加提交事件
async onSubmit() {
this.$refs.refRule.validate(async (valid) => {
if (valid) {
let customer = {
Name: this.registerForm.name,
Email: this.registerForm.email,
Phone: this.registerForm.phone,
Password: this.registerForm.password,
};
let res = await postCustomerRegister(JSON.stringify(customer));
if (res.status == 200) {
this.$router.push('/LoginSms')
} else {
this.$message.error(res.msg);
}
} else {
this.$message.error('输入不能通过验证 !');
return false;
}
});
},
},
async mounted() {
},
}
</script>
<style>
</style>
4 src\views\LoginSmsView.vue
<template>
<div class="wrapper">
<div class="bg bg-blur" style="display: none;"></div>
<div style="height: 20%;"></div>
<el-form :model="loginSmsForm" :rules="loginSmsRule" ref="refRule" label-position="left" label-width="0px"
class="login-container">
<h3 class="title">手机号登录</h3>
<el-form-item prop="phone">
<!-- refPhoneRequired:用于在短信验证码发送前必须先输入1个指定的手机号。 -->
<el-input type="text" v-model="loginSmsForm.phone" ref="refPhoneRequired" auto-complete="off" placeholder="手机号" >
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginSmsForm.password" auto-complete="off" show-password placeholder="密码"></el-input>
</el-form-item>
<el-form-item prop="code">
<el-input v-model="loginSmsForm.code" auto-complete="off" placeholder="短信验证码" class="inputCode">
</el-input>
<el-button v-show="sendCode" type="primary" style="width:130px" @click="postSmsValidate">
<el-icon style="vertical-align: middle; margin-right: 5px;">
<Iphone />
</el-icon>
发送短信验证码
</el-button>
<el-button v-show="!sendCode" color="#909399" :dark="isDark" disabled style="width:130px">
<el-icon style="vertical-align: middle; margin-right: 5px;">
<Clock />
</el-icon>
重新发送<strong>{{time}}</strong>秒
</el-button>
</el-form-item>
<el-form-item style="width:100%;">
<el-button type="primary" style="width:100%;" @click="onSubmit">
登录
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import {
postSmsValidateCreate,
getCustomerByPhone,
getCodeByPhone,
postCustomerLoginSms
} from '../common/http.api.js';
export default {
data() {
//验证1个指定的手机号已经是否被注册。
const validatePhoneUnique = async (rule, value, callback) => {
if (value) {
let data = await this.isPhoneUnique(value);
// console.log(data);
if (data.status == 200 && data.response) {
callback();
} else {
callback(new Error("该手机号未被注册,请使用该手机号进行注册!"));
}
}
};
//验证1个指定手机号获取1个指定的有效短信验证码是否有效。
const validateCode = async (rule, value, callback) => {
if (value) {
let data = await this.isCode(this.loginSmsForm.phone, value);
// console.log(data);
if (data.status == 200 && data.response) {
callback();
} else {
callback(new Error("没有有效短信验证码,请重新发送短信验证码到手机!"));
}
}
};
return {
//通过v-show控制显示‘获取按钮'还是‘倒计时'。
sendCode: true,
//短信验证码发送最小间隔倒计时时间:60秒。
time: 60,
isDark: true,
loginSmsForm: {
phone: '',
password: '',
code: '',
},
//用户注册表单输入验证初始化。
loginSmsRule: {
phone: [{
required: true,
message: "请输入手机号!",
trigger: 'blur',
},
{
pattern: 11 && /^((13|14|15|16|17|18|19)[0-9]{1}\d{8})$/,
message: "手机号格式错误!"
},
{
validator: validatePhoneUnique,
trigger: "blur",
},
],
password: [{
required: true,
message: "请输入密码!",
trigger: "blur"
}],
code: [{
required: true,
message: "请输入短信验证码!",
trigger: 'blur',
},
{
min: 6,
max: 6,
message: "短信验证码必是6位数字!",
trigger: "blur",
},
{
validator: validateCode,
trigger: "blur",
},
],
},
};
},
methods: {
//过1个指定手机号获取1个指定的用户实例,验证手机号的唯一性。
async isPhoneUnique(phone) {
let phoneParam = {
phone: phone,
};
let res = await getCustomerByPhone(phoneParam);
return res.data;
},
//通过1个指定手机号获取1个指定的有效短信验证码,为登录操作提供数据支撑。
async isCode(phone, code) {
let codeParam = {
phone: phone,
code: code,
};
console.log(codeParam)
let res = await getCodeByPhone(codeParam);
return res.data;
},
async postSmsValidate() {
if (this.loginSmsForm.phone == '') {
this.$refs.refPhoneRequired.focus();
this.$message.error('必须先输入手机号!');
} else {
let phone = this.loginSmsForm.phone;
let res = await postSmsValidateCreate(JSON.stringify(phone));
if (res.status == 200) {
this.sendCode = false;
//设置秒倒计时器。
var timetimer = setInterval(() => {
this.time--;
if (this.time <= 0) {
this.sendCode = true;
this.time = 60;
//用于限定秒倒计时器实例,能且只能被触发执行1次。
clearInterval(timetimer);
}
}, 1000);
} else {
this.$message.error(res.msg);
}
}
},
async onSubmit() {
this.$refs.refRule.validate(async (valid) => {
if (valid) {
let loginParams = {
phone: this.loginSmsForm.phone,
password: this.loginSmsForm.password,
code: this.loginSmsForm.code
};
let res = await postCustomerLoginSms(JSON.stringify(loginParams));
//console.log(res);
let userToken = 'Bearer ' + res.data.response.token;
this.$store.commit("saveToken", userToken);
//把1个指定用户的1个指定令牌字符串的过期时间进行全局化存储。
var curTime = new Date();
var expiresIn = new Date(curTime.setSeconds(curTime.getSeconds() + res.data
.response.expiresIn));
this.$store.commit("saveExpiresIn", expiresIn);
if (res.status == 200) {
let token = localStorage.getItem('Token');
if (token === null || token === '') {
await this.$router.replace(this.$route.query.redirect ? this.$route.query
.redirect : "/");
}
await this.$router.replace(this.$route.query.redirect ? this.$route.query
.redirect : "/Login");
} else {
this.$message.error(res.msg);
}
}
});
},
},
mounted() {
},
}
</script>
<style lang="scss">
.wrapper {
background: #50a3a2;
background: -webkit-linear-gradient(top left, #50a3a2 0%, #53e3a6 100%);
background: linear-gradient(to bottom right, #127c7b 0, #50a3a2);
opacity: 0.8;
position: absolute;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.bg {
margin: 0px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-repeat: no-repeat;
background-size: cover;
width: 100%;
height: 100%;
}
.login-container {
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
background-clip: padding-box;
margin: auto;
width: 350px;
padding: 35px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
box-shadow: 0 0 25px #cac6c6;
z-index: 9999;
position: relative;
}
.login-container .title {
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
.inputCode {
width: 150px;
margin-right: 10px;
}
</style>
对以上功能更为具体实现和注释见:230304_012shopvue(短信验证服务和登录的前端定义实现)。