用户登录🔒~生成图片验证码(identify(生成图片验证码)插件)
1.效果图:
2.以用户登录实现 生成图片验证功能:使用 identify(生成图片验证码)插件
identify:这是一个vue的插件,使用canvas来生成图形验证码
2.1 下载identify插件,npm安装
npm i identify
2.2 具体参数如下:
2.2 在components目录新建一个SIdentify.vue,把以下代码复制进去!
<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: 20
},
fontSizeMax: {
type: Number,
default: 35
},
backgroundColorMin: {
type: Number,
default: 180
},
backgroundColorMax: {
type: Number,
default: 240
},
colorMin: {
type: Number,
default: 50
},
colorMax: {
type: Number,
default: 160
},
lineColorMin: {
type: Number,
default: 40
},
lineColorMax: {
type: Number,
default: 180
},
dotColorMin: {
type: Number,
default: 0
},
dotColorMax: {
type: Number,
default: 255
},
contentWidth: {
type: Number,
default: 112
},
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 = 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(this.colorMin, this.colorMax)
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(-45, 45)
// 修改坐标原点和旋转角度
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 < 3; i++) {
ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax)
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.3 在你需要验证码的页面引入组件并写好方法
也可以main.js 中注册全局注册
import SIdentify from './components/page/identify'
Vue.use(SIdentify)
也可以组件中直接引入注册使用
登录表单loginForm
<!-- 登录的表单区域 -->
<el-form :model="loginForm" :rules="loginRules" ref="loginForm">
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="请输入用户名" prefix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" placeholder="请输入密码" prefix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item label="" prop="code">
<el-input v-model="loginForm.code" style='width:54%;display:inline-block;vertical-align:top;'
prefix-icon="el-icon-check" placeholder="请输入验证码" @keyup.enter.native="submit('loginForm')">
</el-input>
<s-identify style='display:inline-block;margin-left: 40px; height:40px;vertical-align:top;cursor:pointer;'
:identifyCode="code" :contentHeight='40' @click.native="handleRefreshCode" />
</el-form-item>
<el-form-item prop="password">
<el-button type="primary" class="login-btn" @click="login">登录</el-button>
<el-link type="info" @click="$router.push('/reg')">去注册</el-link>
</el-form-item>
</el-form>
data return里的数据
2.4 自定义校验规则:自定义提示
rules自定义提示~
//验证码
code: [
{ required: true, message: '请输入验证码', trigger: 'blur' },
{
validator: (rule, value, callback) => {
if (value !== this.code) {
callback(new Error('验证码错误!重新输入~'));
}else {
callback();
}
},
trigger: 'blur'
}
]
2.5 随机生成验证码
handleRefreshCode() {
this.code = (Math.random() * 8999 + 1000).toFixed(0).toString();
},
methods
methods: {
handleRefreshCode() {
this.code = (Math.random() * 8999 + 1000).toFixed(0).toString();
},
// 输入框确定按钮事件
submit(name) {
// 后端交互时需注释
// 没有登陆接口时,直接放开登陆,默认以超级管理员登陆
// var userInfo = {
// nickname: "超级管理员",
// username: 'admin',
// roles: 1,
// token: "eyJhbGciOiJIUzI1NiJ9.eyJqd3Qt",
// "isAuth": false // true开启权限验证模式 ,false 不使用权限验证,默认无权限验证
// };
if (!this.loginForm.code) {
console.log(this.loginForm.code)
this.$message.error('请输入验证码!');
// this.loading = false;
// this.$progress.done();
} else if (this.loginForm.code !== this.code) {
this.$message.error('验证码错误!')
} else {
console.log(this.loginForm.code);
return this.loginForm.code
}
// this.$ls.set('userInfo',userInfo);
// this.success('登陆成功!');
// this.$router.push('/');
return;
// ============
// ---
},
login() {
this.$refs.loginForm.validate(async valid => {
if (!valid) return
const { data: res } = await this.$http.post('/api/login', this.loginForm)
if (res.code !== 0) return this.$message.error(res.message)
this.$message.success(res.message)
// console.log(res.token)
//利用localstorage存储到本地
// localStorage.setItem("token",res.token)
//利用localstorage获取本地已存储的token
// localStorage.getItem('token')
//利用localstorage删除本地已存储的token
// localStorage.removeItem('token')
// ***将 token 存储至 vuex
this.$store.commit('user/updateToken', res.token)
this.$router.push('/')
})
},
// ---
}
3. 完整代码
完整code
<template>
<!-- 登录页面的整体盒子 -->
<div class="login-container">
<!-- 登录的盒子 -->
<div class="login-box">
<!-- 标题的盒子 -->
<div class="title-box"></div>
<!-- 登录的表单区域 -->
<el-form :model="loginForm" :rules="loginRules" ref="loginForm">
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="请输入用户名" prefix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" placeholder="请输入密码" prefix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item label="" prop="code">
<el-input v-model="loginForm.code" style='width:54%;display:inline-block;vertical-align:top;'
prefix-icon="el-icon-check" placeholder="请输入验证码" @keyup.enter.native="submit('loginForm')">
</el-input>
<s-identify style='display:inline-block;margin-left: 40px; height:40px;vertical-align:top;cursor:pointer;'
:identifyCode="code" :contentHeight='40' @click.native="handleRefreshCode" />
</el-form-item>
<el-form-item prop="password">
<el-button type="primary" class="login-btn" @click="login">登录</el-button>
<el-link type="info" @click="$router.push('/reg')">去注册</el-link>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import SIdentify from '@/views/SIdentify/SIdentify.vue'
export default {
components: { SIdentify },
name: 'Login',
data() {
return {
loading: false,
code: '6666',
loginForm: {
username: '',
password: '',
code: '',
type: 1
},
loginRules: {
username: [
{ required: true, message: '请输入用户名称', trigger: 'blur', },
// {min:2,max:5,message: '用户名称长度是2-5字符之间',trigger: 'blur'}
// pattern: 指定正则来匹配
{ pattern: /^[a-zA-Z][a-zA-Z0-9]{0,9}$/, message: '用户名必须是1 ~ 10位的字母或数字, 不能以数字开头', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur', },
// {min:6,max:15,message: '密码长度是6-15字符之间',trigger: 'blur'}
// pattern: 指定正则来匹配
{ pattern: /^\S{6,15}$/, message: '密码必须是6 ~ 15位的非空字符', trigger: 'blur' }
],
//验证码
code: [
{ required: true, message: '请输入验证码', trigger: 'blur' },
{
validator: (rule, value, callback) => {
if (value !== this.code) {
callback(new Error('验证码错误!重新输入~'));
}else {
callback();
}
},
trigger: 'blur'
}
]
},
}
},
methods: {
handleRefreshCode() {
this.code = (Math.random() * 8999 + 1000).toFixed(0).toString();
},
// 输入框确定按钮事件
submit(name) {
// 后端交互时需注释
// 没有登陆接口时,直接放开登陆,默认以超级管理员登陆
// var userInfo = {
// nickname: "超级管理员",
// username: 'admin',
// roles: 1,
// token: "eyJhbGciOiJIUzI1NiJ9.eyJqd3Qt",
// "isAuth": false // true开启权限验证模式 ,false 不使用权限验证,默认无权限验证
// };
if (!this.loginForm.code) {
console.log(this.loginForm.code)
this.$message.error('请输入验证码!');
// this.loading = false;
// this.$progress.done();
} else if (this.loginForm.code !== this.code) {
this.$message.error('验证码错误!')
} else {
console.log(this.loginForm.code);
return this.loginForm.code
}
// this.$ls.set('userInfo',userInfo);
// this.success('登陆成功!');
// this.$router.push('/');
return;
// ============
// ---
},
login() {
this.$refs.loginForm.validate(async valid => {
if (!valid) return
const { data: res } = await this.$http.post('/api/login', this.loginForm)
if (res.code !== 0) return this.$message.error(res.message)
this.$message.success(res.message)
// console.log(res.token)
//利用localstorage存储到本地
// localStorage.setItem("token",res.token)
//利用localstorage获取本地已存储的token
// localStorage.getItem('token')
//利用localstorage删除本地已存储的token
// localStorage.removeItem('token')
// ***将 token 存储至 vuex
this.$store.commit('user/updateToken', res.token)
this.$router.push('/')
})
},
// ---
}
}
</script>
<style lang="less" scoped>
.login-container {
background: url('../../assets/images/login_bg.jpg') center;
background-size: cover;
height: 100%;
.login-box {
width: 400px;
height: 370px;
background-color: #fff;
border-radius: 3px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 0 30px;
box-sizing: border-box;
box-shadow: 8px 8px 14px rgba(23, 23, 23, 0.5);
.title-box {
height: 60px;
background: url('../../assets/images/login_title.png') center no-repeat;
}
.btn-login {
width: 100%;
}
.login-btn {
width: 100%;
}
}
}
</style>