登錄頁面:
<template>
<div id="login">
<div class="login-wrap">
<ul class="menu-tab">
<li v-for="item in menuTab" :key="item.id" :class="{'current': item.current}" @click="toggleMenu(item)">
{{ item.txt }}
</li>
</ul>
<svg-icon icon-name="menu" class-name="menu"></svg-icon>
<!--表單 start-->
<el-form :model="ruleForm" status-icon :rules="rules" ref="loginForm" class="login-form" size="medium">
<el-form-item prop="username" class="item-from">
<label for="username">郵箱</label>
<el-input id="username" type="text" v-model="ruleForm.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item prop="password" class="item-from">
<label for="password">密碼</label>
<el-input id="password" type="password" v-model="ruleForm.password" autocomplete="off" minlength="6" maxlength="20"></el-input>
</el-form-item>
<el-form-item prop="passwords" class="item-from" v-show="model === 'register'">
<label>重複密碼</label>
<el-input type="password" v-model="ruleForm.passwords" autocomplete="off" minlength="6" maxlength="20"></el-input>
</el-form-item>
<el-form-item prop="code" class="item-from">
<label>驗證碼</label>
<el-row :gutter="10">
<el-col :span="15">
<el-input v-model="ruleForm.code" minlength="6" maxlength="6"></el-input>
</el-col>
<el-col :span="9">
<el-button type="success" class="block" @click="getSms()" :disabled="codeButtonStatus.status">{{ codeButtonStatus.text }}</el-button>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-button type="danger" @click="submitForm('loginForm')" class="login-btn block" :disabled="loginButtonStatus">{{ model === 'login' ? "登錄" : "註冊" }}</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import sha1 from 'js-sha1';
import { Message } from 'element-ui';
import { GetSms, Register, Login } from "@/api/login";
import { reactive, ref, isRef, toRefs, onMounted, watch } from '@vue/composition-api';
import { stripscript, validatePass, validateEmail, validateVCode } from '@/utils/validate';
export default {
name: 'login',
// setup(props, context){
/**
*attrs: (...) == this.$attrs
emit: (...) == this.$emit
listeners: (...) == this.$listeners
parent: (...) == this.$parent
refs: (...) == this.$refs
root: (...) == this
*/
setup(props, { refs, root }){
// 驗證用戶名
let validateUsername = (rule, value, callback) => {
if (value === '') {
callback(new Error('請輸入用戶名'));
} else if(validateEmail(value)){
callback(new Error('用戶名格式有誤'));
} else {
callback(); //true
}
};
// 驗證密碼
let validatePassword = (rule, value, callback) => {
// 過濾後的數據
ruleForm.password = stripscript(value);
value = ruleForm.password;
if (value === '') {
callback(new Error("請輸入密碼"));
} else if (validatePass(value)) {
callback(new Error("密碼爲6至20位數字+字母"));
} else {
callback();
}
};
// 驗證重複密碼
let validatePasswords = (rule, value, callback) => {
// 如果模塊值爲login, 直接通過
if(model.value === 'login') { callback(); }
// 過濾後的數據
ruleForm.passwords = stripscript(value);
value = ruleForm.passwords;
if (value === '') {
callback(new Error('請再次輸入密碼'));
} else if (value != ruleForm.password) {
callback(new Error('重複密碼不正確'));
} else {
callback();
}
};
// 驗證驗證碼
let validateCode = (rule, value, callback) => {
if (value === '') {
return callback(new Error('請輸入驗證碼'));
}else if(validateVCode(value)){
return callback(new Error('驗證碼格式有誤'));
}else{
callback();
}
};
/*********************************************************************************************************************
* 聲明數據
*/
// 這裏面放置data數據、生命週期、自定義的函數
const menuTab = reactive([
{ txt: '登錄', current: true, type: 'login' },
{ txt: '註冊', current: false, type: 'register' }
]);
// 模塊值
const model = ref('login');
// 登錄按鈕禁用狀態
const loginButtonStatus = ref(true);
// 驗證碼按鈕狀態
const codeButtonStatus = reactive(
{
status: false,
text: '獲取驗證碼'
}
);
// 倒計時
const timer = ref(null);
// 表單綁定數據
const ruleForm = reactive({
username: '[email protected]',
password: 'wo123456789',
passwords: '',
code: ''
});
// 表單的驗證
const rules = reactive({
username: [
{ validator: validateUsername, trigger: 'blur' }
],
password: [
{ validator: validatePassword, trigger: 'blur' }
],
passwords: [
{ validator: validatePasswords, trigger: 'blur' }
],
code: [
{ validator: validateCode, trigger: 'blur' }
]
});
/**
* 1、不建議在一個方法裏面做多件不同的事件(儘可能只做自己本身的事,不要做其他人的事情)
* 2、儘量把相同的事情封裝一個方法裏面,通過調用函數進行執行
*/
/**
* 聲明函數
*/
// 切換模塊
const toggleMenu = (data => {
menuTab.forEach((elem, index) => {
elem.current = false;
});
// 高光
data.current = true;
// 修改模塊值
model.value = data.type;
resetFromData()
clearCountDown()
});
// 清除表單數據
const resetFromData = (() => {
// 重置表單
// this.$refs[formName].resetFields(); //2.0
refs.loginForm.resetFields(); // 3.0
})
// 更新按鈕狀態
const updataButtonStatus = ((params) => {
codeButtonStatus.status = params.status;
codeButtonStatus.text = params.text;
})
const getSms = (() => {
// 進行提示
if(ruleForm.username == '' ) {
root.$message.error('郵箱不能爲空!!');
return false;
}
if(validateEmail(ruleForm.username)) {
root.$message.error('郵箱格式有誤,請重新輸入!!');
return false;
}
// 獲取驗證碼
let requestData = {
username: ruleForm.username,
module: model.value
}
// 修改獲取驗證按鈕狀態
updataButtonStatus({
status: true,
text: '發送中'
})
// 延時多長時間
GetSms(requestData).then(response => {
let data = response.data;
root.$message({
message: data.message,
type: 'success',
dangerouslyUseHTMLString: true
});
// 啓用登錄或註冊按鈕
loginButtonStatus.value = false;
// 調定時器,倒計時
countDown(60);
}).catch(error => {
console.log(error);
})
})
/**
* 提交表單
*/
const submitForm = (formName => {
refs[formName].validate((valid) => {
// 表單驗證通過
if (valid) {
// 三元運算
model.value === 'login' ? login() : register()
} else {
console.log('error submit!!');
return false;
}
})
})
/**
* 登錄
*/
const login = (() => {
let repuestData = {
username: ruleForm.username,
password: sha1(ruleForm.password),
code: ruleForm.code
}
root.$store.dispatch('app/login', repuestData).then(response => {
// 頁面跳轉
root.$router.push({
name: 'Console'
})
}).catch(error => {});
})
/**
* 註冊
*/
const register = (() => {
let requestData = {
username: ruleForm.username,
password: sha1(ruleForm.password),
code: ruleForm.code,
module: 'register'
}
// 註冊接口
Register(requestData).then(response => {
let data = response.data
root.$message({
message: data.message,
type: 'success'
})
// 模擬註冊成功
toggleMenu(menuTab[0])
clearCountDown()
}).catch(error => {
// 失敗時執行的代碼
})
})
/**
* 倒計時
*/
const countDown = ((number) => {
// 60 和 0不見了,故意留BUG
// setTimeout:clearTimeout(變量) 只執行一次
// setInterval:clearInterval(變量)) 不斷的執行,需要條件纔會停止
// 判斷定時器是否存在,存在則清除
if(timer.value) { clearInterval(timer.value); }
let time = number
timer.value = setInterval(() => {
time--;
if(time === 0) {
clearInterval(timer.value)
updataButtonStatus({
status: false,
text: '再次獲取'
})
}else{
codeButtonStatus.text = `倒計時${time}秒` // es5 '倒計時' + time + '秒'
}
}, 1000)
})
/**
* 清除倒計時
*/
const clearCountDown = (() => {
// 還原驗證碼按鈕默認狀態
updataButtonStatus({
status: false,
text: '獲取驗證碼'
})
// 清除倒計時
clearInterval(timer.value)
})
/**
* 生命週期
*/
// 掛載完成後
onMounted(() => {
})
return {
menuTab,
model,
loginButtonStatus,
codeButtonStatus,
ruleForm,
rules,
timer,
toggleMenu,
submitForm,
getSms
}
}
}
</script>
<style lang="scss" scoped>
#login {
height: 100vh;
background-color: #344a5f;
}
.login-wrap {
width: 330px;
margin: auto;
}
.menu-tab {
text-align: center;
li {
display: inline-block;
width: 88px;
line-height: 36px;
font-size: 14px;
color: #fff;
border-radius: 2px;
cursor: pointer;
}
.current {
background-color: rgba(0, 0, 0, .1);
}
}
.login-form {
margin-top: 29px;
label {
display: block;
margin-bottom: 3px;
font-size: 14px;
color: #fff;
}
.item-from { margin-bottom: 13px; }
.block {
display: block;
width: 100%;
}
.login-btn { margin-top: 19px; }
}
</style>
<!--
密碼加密:
1、在前端預先加密一次
登錄的密碼:123456(普通字符串)
經過加密後:sha1('123456') == '541216ad5s4f5ds1f5asd4f65asd4' (加密後的字符串)
2、後臺加密
接收到字符串:'541216ad5s4f5ds1f5asd4f65asd4'
後臺再次加密:md5('541216ad5s4f5ds1f5asd4f65asd4') == '8f9qwersd3g165y4d1sf3s1f6aew4'(最終的加密後的密碼)
最終新的字符串寫入數據庫:8f9qwersd3g165y4d1sf3s1f6aew4
3、登錄
用戶名與加密後的密碼進行匹配,成功則登錄,失敗則提示
-->
Vue:登錄頁面用到的驗證函數:
import { MessageBox } from 'element-ui';
/**
* 過濾特殊字符
*/
export function stripscript(str) {
var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()&;—|{ }【】‘;:”“'。,、?]")
var rs = "";
for (var i = 0; i < str.length; i++) {
rs = rs + str.substr(i, 1).replace(pattern, '');
}
return rs;
}
/**
* 驗證郵箱
*/
export function validateEmail(value){
let reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
return !reg.test(value) ? true : false;
}
/**
* 驗證密碼 6至20位的字母+數字
*/
export function validatePass(value){
let reg = /^(?!\D+$)(?![^a-zA-Z]+$)\S{6,20}$/;
return !reg.test(value) ? true : false;
}
/**
* 驗證驗證碼,字母和數字的組合
*/
export function validateVCode(value){
let reg = /^[a-z0-9]{6}$/;
return !reg.test(value) ? true : false;
}
/**
* 沒有使用default時,可以同時聲明多個export。
* 文件 import 需要花括號。
*/