一,驗證碼功能
1,創建一個組件。顯示驗證碼圖片
<template> <div class="s-canvas"> <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas> </div> </template> <script> export default{ name: 'SIdentify', props: { identifyCode: { // 默認注冊碼 type: String, default: '1234' }, fontSizeMin: { // 字體最小值 type: Number, default: 25 }, fontSizeMax: { // 字體最大值 type: Number, default: 35 }, backgroundColorMin: { // 驗證碼圖片背景色最小值 type: Number, default: 200 }, backgroundColorMax: { // 驗證碼圖片背景色最大值 type: Number, default: 220 }, dotColorMin: { // 背景干擾點最小值 type: Number, default: 60 }, dotColorMax: { // 背景干擾點最大值 type: Number, default: 120 }, contentWidth: { // 容器寬度 type: Number, default: 90 }, contentHeight: { // 容器高度 type: Number, default: 38 } }, methods: { // 生成一個隨機數 randomNum (min, max) { return Math.floor(Math.random() * (max - min) + min) }, // 生成一個隨機的顏色 randomColor (min, max) { let r = this.randomNum(min, max) let g = this.randomNum(min, max) let b = this.randomNum(min, max) return 'rgb(' + r + ',' + g + ',' + b + ')' }, drawPic () { let canvas = document.getElementById('s-canvas') let ctx = canvas.getContext('2d') ctx.textBaseline = 'bottom' // 繪制背景 ctx.fillStyle = '#e6ecfd' ctx.fillRect(0, 0, this.contentWidth, this.contentHeight) // 繪制文字 for (let i = 0; i < this.identifyCode.length; i++) { this.drawText(ctx, this.identifyCode[i], i) } this.drawLine(ctx) this.drawDot(ctx) }, drawText (ctx, txt, i) { ctx.fillStyle = this.randomColor(50, 160) // 隨機生成字體顏色 ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei' // 隨機生成字體大小 let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1)) let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5) var deg = this.randomNum(-30, 30) // 修改坐標原點和旋轉角度 ctx.translate(x, y) ctx.rotate(deg * Math.PI / 180) ctx.fillText(txt, 0, 0) // 恢復坐標原點和旋轉角度 ctx.rotate(-deg * Math.PI / 180) ctx.translate(-x, -y) }, drawLine (ctx) { // 繪制干擾線 for (let i = 0; i < 4; i++) { ctx.strokeStyle = this.randomColor(100, 200) ctx.beginPath() ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) ctx.stroke() } }, drawDot (ctx) { // 繪制干擾點 for (let i = 0; i < 30; i++) { ctx.fillStyle = this.randomColor(0, 255) ctx.beginPath() ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI) ctx.fill() } } }, watch: { identifyCode () { this.drawPic() } }, mounted () { this.drawPic() } } </script>
2,在登錄頁面中 驗證碼輸輸入框
<el-form-item prop="verificationCode"> <el-input type="text" v-model="loginForm.verificationCode" placeholder="- - - -"> <template slot="prepend">驗證碼</template> <template slot="append"> <div class="login-code" @click="refreshCode"> <Identify :identifyCode="identifyCode"></Identify> </div> </template> </el-input> </el-form-item> //引入驗證碼組件 import Identify from './identify'
3,登錄按鈕
<el-button-group> <el-button style="width:100%" @click="handleLogin" type="primary">登錄</el-button> </el-button-group>
4,在data中
data() {
const validateUsername = (rule, value, callback) => {
if (!value) {
callback(new Error("請輸入用戶名"));
} else {
callback();
}
};
const validatePassword = (rule, value, callback) => {
if (!value) {
callback(new Error("請輸入密碼"));
} else {
callback();
}
};
const validateCode = (rule, value, callback) => {
if (value.toLowerCase() !== this.identifyCode.toLowerCase()) {
this.refreshCode();
callback(new Error("請填寫正確驗證碼"));
} else {
callback();
}
};
return {
loginForm: {
username: "",
password: "",
verificationCode: ""
},
loginRules: {
username: [
{ required: true, trigger: "blur", validator: validateUsername }
],
password: [
{ required: true, trigger: "blur", validator: validatePassword }
],
verificationCode: [
{ required: true, trigger: "blur", validator: validateCode }
]
},
passwordType: "password",
capsTooltip: false,
loading: false,
identifyCodes: "1234567890abcdefjhijklinopqrsduvwxyz",
identifyCode: ""
};
},
5,在mounted中
mounted () {
// 初始化驗證碼
this.identifyCode = ''
this.makeCode(this.identifyCodes, 4)
},
6,在method中
//驗證碼事件 refreshCode() { this.identifyCode = ""; this.makeCode(this.identifyCodes, 4); }, makeCode(o, l) { for (let i = 0; i < l; i++) { this.identifyCode += this.identifyCodes[ this.randomNum(0, this.identifyCodes.length) ]; } }, randomNum(min, max) { return Math.floor(Math.random() * (max - min) + min); }, //登錄事件 hhandleLogin(formName) { let paramt = { username: this.loginForm.username, password: this.$md5(this.loginForm.password) }; this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true; this.$store.dispatch("Login/getLogin", paramt).then(res => { let userList = res.data.data; sessionStorage.setItem("token", res.data.data.token); //vuex中的數據刷新頁面會消失 this.$router.push("/layout"); this.loading = false; }) .catch(() => { this.loading = false; }); } else { console.log("error submit!!"); return false; } }); },
二,MD5加密
1、npm安裝
npm install --save js-md5
2,第一種使用方法
在需要使用的項目文件中引入:
import md5 from 'js-md5';
使用:
md5('mima')//612341288a285f5b188163482320e88f
3,第二種使用方法
在main.js文件中將md5轉換成vue原型:
import md5 from 'js-md5';
Vue.prototype.$md5 = md5;
在需要用到的文件中使用:
this.$md5('mima')//612341288a285f5b188163482320e88f
最后附登錄頁完整代碼
<template> <div class="login-container"> <nav></nav> <main> <div class="main-l"></div> <div class="main-r"> <img src="../../assets/image/l-t.png" alt /> <div class="form-login"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left" > <el-form-item prop="username"> <span class="svg-container"> <i class="el-icon-user"></i> </span> <el-input ref="username" v-model="loginForm.username" placeholder="請輸入用戶名" name="username" type="text" tabindex="1" autocomplete="on" /> </el-form-item> <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual> <el-form-item prop="password"> <span class="svg-container"> <i class="el-icon-lock"></i> </span> <el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType" placeholder="請輸入密碼" name="password" tabindex="2" autocomplete="on" @keyup.native="checkCapslock" @blur="capsTooltip = false" @keyup.enter.native="handleLogin" /> <span class="show-pwd" @click="showPwd"> <i :class="passwordType === 'password' ? 'iconfont zhzyguanbi-yanjing' : 'el-icon-view'" ></i> </span> </el-form-item> </el-tooltip> <el-form-item prop="verificationCode"> <span class="svg-container"> <i class="el-icon-key"></i> </span> <el-input ref="verificationCode" v-model="loginForm.verificationCode" placeholder="請輸入驗證碼" name="verificationCode" type="text" tabindex="1" autocomplete="on" > <template slot="append"> <div class="login-code" @click="refreshCode"> <Identify :identifyCode="identifyCode"></Identify> </div> </template> </el-input> </el-form-item> <el-button :loading="loading" type="primary" style="width:100%;height:60px;font-size:20px" @click.native.prevent="handleLogin" >立即登錄</el-button> </el-form> </div> </div> </main> </div> </template> <script> import Identify from "../../components/VerificationCode/VerificationCode"; import { login } from "../../api/login"; import { mapActions } from "vuex"; export default { name: "Login", components: { Identify }, data() { const validateUsername = (rule, value, callback) => { if (!value) { callback(new Error("請輸入用戶名")); } else { callback(); } }; const validatePassword = (rule, value, callback) => { if (!value) { callback(new Error("請輸入密碼")); } else { callback(); } }; const validateCode = (rule, value, callback) => { if (value.toLowerCase() !== this.identifyCode.toLowerCase()) { this.refreshCode(); callback(new Error("請填寫正確驗證碼")); } else { callback(); } }; return { loginForm: { username: "", password: "", verificationCode: "" }, loginRules: { username: [ { required: true, trigger: "blur", validator: validateUsername } ], password: [ { required: true, trigger: "blur", validator: validatePassword } ], verificationCode: [ { required: true, trigger: "blur", validator: validateCode } ] }, passwordType: "password", capsTooltip: false, loading: false, identifyCodes: "1234567890abcdefjhijklinopqrsduvwxyz", identifyCode: "" }; }, created() {}, mounted() { if (this.loginForm.username === "") { this.$refs.username.focus(); } else if (this.loginForm.password === "") { this.$refs.password.focus(); } // 初始化驗證碼 this.identifyCode = ""; this.makeCode(this.identifyCodes, 4); }, methods: { checkCapslock({ shiftKey, key } = {}) { if (key && key.length === 1) { if ( (shiftKey && (key >= "a" && key <= "z")) || (!shiftKey && (key >= "A" && key <= "Z")) ) { this.capsTooltip = true; } else { this.capsTooltip = false; } } if (key === "CapsLock" && this.capsTooltip === true) { this.capsTooltip = false; } }, showPwd() { if (this.passwordType === "password") { this.passwordType = ""; } else { this.passwordType = "password"; } this.$nextTick(() => { this.$refs.password.focus(); }); }, handleLogin(formName) { let paramt = { username: this.loginForm.username, password: this.$md5(this.loginForm.password) }; this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true; this.$store.dispatch("Login/getLogin", paramt).then(res => { let userList = res.data.data; sessionStorage.setItem("token", res.data.data.token); //vuex中的數據刷新頁面會消失 this.$router.push("/layout"); this.loading = false; }) .catch(() => { this.loading = false; }); } else { console.log("error submit!!"); return false; } }); }, //驗證碼事件 refreshCode() { this.identifyCode = ""; this.makeCode(this.identifyCodes, 4); }, makeCode(o, l) { for (let i = 0; i < l; i++) { this.identifyCode += this.identifyCodes[ this.randomNum(0, this.identifyCodes.length) ]; } }, randomNum(min, max) { return Math.floor(Math.random() * (max - min) + min); } } }; </script> <style lang="scss"> /* 修復input 背景不協調 和光標變色 */ /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */ $bg: #283443; $light_gray: #fff; $cursor: #fff; @supports (-webkit-mask: none) and (not (cater-color: $cursor)) { .login-container .el-input input { color: $cursor; } } /* reset element-ui css */ .login-container { .el-input { display: inline-block; height: 47px; width: 85%; input { background: transparent; border: 0px; -webkit-appearance: none; border-radius: 0px; padding: 12px 5px 12px 15px; color: $light_gray; height: 47px; caret-color: $cursor; &:-webkit-autofill { box-shadow: 0 0 0px 1000px $bg inset !important; -webkit-text-fill-color: $cursor !important; } } } .el-form-item { border: 1px solid rgba(255, 255, 255, 0.1); background: rgba(0, 0, 0, 0.1); border-radius: 5px; color: #454545; } nav { width: 555px; height: 80px; background: pink; margin: 0 auto; margin-top: 150px; margin-bottom: 30px; background: url("../../assets/image/login-text.png") center no-repeat; } main { width: 910px; height: 505px; background: url("../../assets/image/l-code.png") center no-repeat; margin: 0 auto; display: flex; .main-l { width: 390px; height: 505px; } .main-r { width: 520px; height: 505px; padding: 50px 60px 0 55px; box-sizing: border-box; .form-login { margin-top: 30px; } .login-code { width: 90px; background: rgda(0, 0, 0, 0.6); } } } } </style> <style lang="scss" scoped> $bg: #2d3a4b; $dark_gray: #889aa4; $light_gray: #eee; .login-container { width: 100%; min-height: calc(100vh); background: url("../../assets/image/l-bge.png") center no-repeat; overflow: hidden; .login-form { position: relative; width: 520px; max-width: 100%; margin: 0 auto; overflow: hidden; } .tips { font-size: 14px; color: #fff; margin-bottom: 10px; span { &:first-of-type { margin-right: 16px; } } } .svg-container { padding: 6px 5px 6px 15px; color: $dark_gray; vertical-align: middle; width: 30px; display: inline-block; } .title-container { position: relative; .title { font-size: 26px; color: $light_gray; margin: 0px auto 40px auto; text-align: center; font-weight: bold; } } .show-pwd { position: absolute; right: 10px; top: 7px; font-size: 16px; color: $dark_gray; cursor: pointer; user-select: none; } .thirdparty-button { position: absolute; right: 0; bottom: 6px; } @media only screen and (max-width: 470px) { .thirdparty-button { display: none; } } } </style> <style lang="scss"> .form-login .el-input-group__append { background: rgba(0, 0, 0, 0.3); padding: 0; left: 260px; bottom: 44px; } </style>
轉自:https://blog.csdn.net/LONGLONGAGO_RU/article/details/103908405
在需要使用的項目文件中引入: import md5 from 'js-md5'; 使用: md5('mima')//612341288a285f5b188163482320e88f