主要的逻辑是先是通过数字和字母组合生成四位数,并通过包裹不同的颜色和旋转角度实现假装的图片功能,图片其实就是四位数字或字母通过旋转角度呈现,判断的时候只要判断生成的四位数和输入的是否相同即可。
dom部分:
<template>
<div>
<div class="list-code" v-if="true"
:style='{"width":"76%","margin":"20px auto","alignItems":"center","display":"flex","justifyContent":"center"}'>
<input
:style='{"border":"0px solid rgba(64, 158, 255, 1)","padding":"0 10px","boxShadow":"0px 0px 2px 0px rgba(0,0,0,0.3020)","outline":"none","color":"#333","width":"70%","fontSize":"14px","height":"60px"}'
placeholder="请输入验证码" name="code" type="text" v-model="rulesForm.code">
<div class="getCodeBt"
:style='{"cursor":"pointer","boxShadow":"0px 0px 2px 0px rgba(0,0,0,0.3020)","borderColor":"rgba(64, 158, 255, 1)","alignItems":"center","borderWidth":"0","background":"#f5f5f5","display":"flex","width":"100px","borderStyle":"solid","justifyContent":"center","height":"60px"}'
@click="getRandCode(4)">
<span
:style="{color:item.color,transform:item.rotate,fontSize:item.size,padding: '0 3px',display:'inline-block'}"
v-for="(item, index) in codes" :key="index">{{ item.num }}</span>
</div>
</div>
<div :style='{"width":"80%","margin":"20px auto","alignItems":"center","flexWrap":"wrap","justifyContent":"center","display":"flex"}'>
<el-button :style='{"border":"0","cursor":"pointer","padding":"0 24px","margin":"0 50px","outline":"none","color":"#fff","borderRadius":"4px","background":"rgba(253, 190, 96, 1)","width":"150px","fontSize":"16px","height":"44px"}' type="primary" @click="login()" class="loginInBt">登录</el-button>
</div>
</div>
</template>
说明:input部分是输入的框,getCodeBt部分就是图片部分,包括点击事件。主要实现的假图片就是这一行。
<span
:style="{color:item.color,transform:item.rotate,fontSize:item.size,padding: '0 3px',display:'inline-block'}"
v-for="(item, index) in codes" :key="index">{{ item.num }}</span>就是这样实现的验证码排列。
js部分
export default {
data() {
return {
rulesForm: {
username: "",
password: "",
role: "",
code: '',
},
roles: [],
codes: [{
num: 1,
color: '#000',
rotate: '10deg',
size: '16px'
},{
num: 2,
color: '#000',
rotate: '10deg',
size: '16px'
},{
num: 3,
color: '#000',
rotate: '10deg',
size: '16px'
},{
num: 4,
color: '#000',
rotate: '10deg',
size: '16px'
}],
};
},
mounted() {
},
created() {
this.getRandCode()
},
destroyed() {
},
methods: {
// 登陆
login() {
let code = ''
for (let i in this.codes) {
code += this.codes[i].num
}
if ('true' && !this.rulesForm.code) {
this.$message.error("请输入验证码");
return;
}
if ('true' && this.rulesForm.code.toLowerCase() != code.toLowerCase()) {
this.$message.error("验证码输入有误");
this.getRandCode()
return;
}
if (!this.rulesForm.username) {
this.$message.error("请输入用户名");
return;
}
if (!this.rulesForm.password) {
this.$message.error("请输入密码");
return;
}
if(this.roles.length>1) {
if (!this.rulesForm.role) {
this.$message.error("请选择角色");
return;
}
let menus = this.menus;
for (let i = 0; i < menus.length; i++) {
if (menus[i].roleName == this.rulesForm.role) {
this.tableName = menus[i].tableName;
}
}
} else {
this.tableName = this.roles[0].tableName;
this.rulesForm.role = this.roles[0].roleName;
}
this.$http({
url: `${this.tableName}/login?username=${this.rulesForm.username}&password=${this.rulesForm.password}`,
method: "post"
}).then(({ data }) => {
if (data && data.code === 0) {
this.$storage.set("Token", data.token);
this.$storage.set("role", this.rulesForm.role);
this.$storage.set("sessionTable", this.tableName);
this.$storage.set("adminName", this.rulesForm.username);
this.$router.replace({ path: "/index/" });
} else {
this.$message.error(data.msg);
}
});
},
getRandCode(len = 4){
this.randomString(len)
},
randomString(len = 4) {
let chars = [
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
"w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
"3", "4", "5", "6", "7", "8", "9"
]
let colors = ["0", "1", "2","3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"]
let sizes = ['14', '15', '16', '17', '18']
for (let i = 0; i < len; i++) {
// 随机验证码
let key = Math.floor(Math.random()*chars.length)
this.codes[i].num = chars[key]
// 随机验证码颜色
let code = '#'
for (let j = 0; j < 6; j++) {
let key = Math.floor(Math.random()*colors.length)
code += colors[key]
}
this.codes[i].color = code
// 随机验证码方向
let rotate = Math.floor(Math.random()*60)
let plus = Math.floor(Math.random()*2)
if(plus == 1) rotate = '-'+rotate
this.codes[i].rotate = 'rotate('+rotate+'deg)'
// 随机验证码字体大小
let size = Math.floor(Math.random()*sizes.length)
this.codes[i].size = sizes[size]+'px'
}
},
}
};
</script>
说明:里面还有一些其他的登录逻辑混在里面,要辨别。要先在data里定义codes,包含旋转角度,尺寸等信息。再是getRandCode这个方法用于生成验证码,randomString是主要实现的方法,通常可以放在utils里面,主要靠随机数生成随机的排序。并且在登录方法login里面,通过this.rulesForm.code.toLowerCase() != code.toLowerCase())这个去判断是否相同。
最后是style部分
.list-code /deep/ .el-input .el-input__inner {
border: 0;
padding: 0 10px;
box-shadow: 0px 4px 10px 0px rgba(0,0,0,0.3020);
outline: none;
color: #000;
width: 100%;
font-size: 14px;
height: 44px;
}
.list-type /deep/ .el-radio__input .el-radio__inner {
background: rgba(53, 53, 53, 0);
border-color: #666666;
}
最后的实现效果如图(代码部分绝大部分只有实现验证码的):