<el-form-item prop="phoneCode" label="验证码">
<el-input
ref="phoneCode"
v-model="loginForm.phoneCode"
placeholder="请输入验证码"
name="phoneCode"
type="text"
tabindex="1" //tab键切换
auto-complete="on"
style="width: 65%"
/>
<div class="code" @click="refreshCode" style="float: right">
<s-identify :identifyCode="identifyCode"></s-identify>
</div>
</el-form-item>
<el-button :loading="loading" type="success" style="width: 81%; margin-bottom: 10px; letter-spacing: 5px; float: right;border-radius: 0;" @click.native.prevent="handleLogin">登录</el-button>
import SIdentify from '../../components/page/identify'
components:{
SIdentify
},
data() { const validateUsername = (rule, value, callback) => { if (value.trim().length > 0) { callback() } else { callback(new Error('请输入用户名')) } }; const validatePassword = (rule, value, callback) => { if (value.length < 6) { callback(new Error('密码不能少于6位')) } else { callback() } }; const validatephoneCode = (rule, value, callback) => { if (value !== this.identifyCode) { callback(new Error('请输入正确的验证码')); //当错误时刷新验证码 this.identifyCode = ''; this.makeCode(this.identifyCodes, 4); } else { callback() } }; return { identifyCodes: "1234567890", identifyCode: "", loginForm: { username: '', password: '', phoneCode: '', }, loginRules: { username: [{ trigger: 'blur', validator: validateUsername }], password: [{ trigger: 'blur', validator: validatePassword }], phoneCode: [{trigger: true, validator: validatephoneCode }],//点击登录时校验,而不是在光标离开后校验 }, loading: false, passwordType: 'password', redirect: undefined, pasChecked:false } }, watch: { $route: { handler: function(route) { this.redirect = route.query && route.query.redirect }, immediate: true } }, mounted() { this.identifyCode = ""; this.makeCode(this.identifyCodes, 4); tokenUtils.getCookie() }, methods: { randomNum(min, max) { return Math.floor(Math.random() * (max - min) + min); }, 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) ]; } }, showPwd() { if (this.passwordType === 'password') { this.passwordType = '' } else { this.passwordType = 'password' } this.$nextTick(() => { this.$refs.password.focus() }) }, changeChecked() { this.pasChecked = !this.pasChecked; this.handleLogin(); }, handleLogin() { //保存的账号 let name=this.loginForm.username; //保存的密码 let pass=this.loginForm.password; //判断复选框是否被勾选 勾选则调用配置cookie方法 if(this.pasChecked == true){ //传入账号名,密码,和保存天数3个参数 tokenUtils.setCookie(name,pass,7); }else{ tokenUtils.clearCookie() } this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true; this.$store.dispatch('login_store', this.loginForm).then(response => { var res=response.data; console.log(res); if (res.status === 200){ console.log('用户名密码和验证码',this.loginForm); console.log('验证码图片中数字',this.identifyCode); this.loading = false; this.$router.push({ path: '/' }) }else { Message({ message: res.message, type: 'error', duration: 800 }) } this.loading = false }).catch(() => { this.loading = false }) } }); },
/components/page/identify文件
<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: 85 }, contentHeight: { //容器高度 type: Number, default: 32 } }, 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 = this.randomColor(this.backgroundColorMin, this.backgroundColorMax) 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>
点击图片切换数字,并在输入错误后点击登录会刷新验证码