<template>
<div class="login_wrap">
<div class="form_wrap">
<!-- 账号输入-->
<el-form ref="formRef" :model="user" class="demo-dynamic" >
<!--prop要跟属性名称对应-->
<el-form-item prop="id" :rules="[ { required: true, message: '账号不能为空', trigger: 'blur',}, ]">
<el-input style="height: 50px;font-size: 30px" v-model="user.id" ><template #prepend>账号</template></el-input>
</el-form-item>
<!--密码输入-->
<el-form-item prop="password" class="password-input" :rules="[ { required: true, message: '密码不能为空', trigger: 'blur',}, ]">
<el-input type="password" style="height: 50px;font-size: 30px" v-model="user.password" ><template #prepend>密码</template></el-input>
</el-form-item>
<!-- 验证码-->
<el-form-item prop="identifyingcode.inputverificationcodenumber" :rules="[ { required: true, message: '验证码不能为空', trigger: 'blur',}, ]">
<el-input style="height: 50px;font-size: 30px" v-model="user.identifyingcode.inputverificationcodenumber" ><template #prepend>验证码</template></el-input>
</el-form-item>
<el-form-item>
<div style="font-size: 30px"> 用户角色:</div>
<el-select v-model="user.role">
<el-option
v-for="item in option.role"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
<canvas class='code' ref="codeimg" @click="codetrigger"></canvas>
</el-form>
<el-button type="primary" style="width: 100px;height: 40px" @click='lgintrigger' class="login-btn">登录</el-button>
</div>
</div>
<div class="information">作者:甘世涛
<br/>版权所有 违者必究
<br/>前端框架:vue <br/> 后端框架springboot
</div>
</template>
<script>
import {useRouter} from "vue-router";
import {useStore} from "vuex";
import {get,post} from "@/util/service";
import { reactive, onMounted, ref, toRefs } from 'vue'
import { ElMessage} from 'element-plus'
export default {
setup()
{ const router=useRouter()
const store=useStore()
const codeimg = ref(null)//获取div对象 ref属性为codeimg的对象 这个对象是验证码
let userrole=""
const data = reactive ({
option:{
role:['管理员','教师','学生']
},
user:{//用户
id:"",//用户账号
password:"",//用户密码
role:"",//用户角色
identifyingcode: {//验证码
pool: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890', // 随机生成A-F 1-9的验证码
// pool: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890', // 字符串
width: 360,
height: 200,
verificationcodenumber: "",/*随机生成的验证码*/
inputverificationcodenumber:""/*键盘输入的验证码*/
}
},
shishi:"",
})
onMounted(() => {//初始化函数
data.user.identifyingcode.verificationcodenumber = draw() // 初始化绘制图片验证码
})
const codetrigger = () => {
data.user.identifyingcode.verificationcodenumber = draw() // 点击图片重新绘制
}
// 随机数
const randomNum = (min, max) => {
return parseInt(Math.random() * (max - min) + min)
}
const randomColor = (min, max) => { // 随机颜色
const r = randomNum(min, max)
const g = randomNum(min, max)
const b = randomNum(min, max)
return `rgb(${r},${g},${b})`
}
const draw = () => {// 绘制图片
const ctx = codeimg.value.getContext('2d')// 3.填充背景颜色,背景颜色要浅一点
ctx.fillStyle = randomColor(180, 230) // 填充颜色颜色不要太深
ctx.fillRect(0, 0, data.user.identifyingcode.width, data.user.identifyingcode.height)// 填充的位置
let verificationcodenumber = ''//存储四个验证码
for (let i = 0; i < 4; i++) { // 4.随机产生字符串,并且随机旋转
const text = data.user.identifyingcode.pool[randomNum(0, data.user.identifyingcode.pool.length)] // 随机的四个字
verificationcodenumber += text
const fontSize = randomNum(100, 200) // 随机的字体大小
const deg = randomNum(-30, 30) // 字体随机的旋转角度
ctx.font = fontSize + 'px SimSun'//宋体
ctx.textBaseline = 'top'
ctx.fillStyle = randomColor(80, 150)
/* 用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。
restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。
*/
ctx.save()
ctx.translate(60 * i + 15, 15)//平移
ctx.rotate((deg * Math.PI) / 180)//旋转
ctx.fillText(text, -15 + 5, -15)//填充文本
ctx.restore()
}
// 5.随机产生5条干扰线,干扰线的颜色要浅一点
for (let i = 0; i < 5; i++) {
ctx.beginPath()
ctx.moveTo(randomNum(0, data.user.identifyingcode.width), randomNum(0, data.user.identifyingcode.height))
ctx.lineTo(randomNum(0, data.user.identifyingcode.width), randomNum(0, data.user.identifyingcode.height))
ctx.strokeStyle = randomColor(180, 230)
ctx.closePath()
ctx.stroke()
}
// 6.随机产生40个干扰的小点
for (let i = 0; i < 40; i++) {
ctx.beginPath()
ctx.arc(randomNum(0, data.user.identifyingcode.width), randomNum(0, data.user.identifyingcode.height), 1, 0, 2 * Math.PI)
ctx.closePath()
ctx.fillStyle = randomColor(150, 200)
ctx.fill()
}
return verificationcodenumber
}
onMounted( async () => {
})
const lgintrigger=async () => {
if (data.user.role === "" && data.user.accountnumber === "" || data.user.password === "" || data.user.identifyingcode.inputverificationcodenumber === "") {
ElMessage.error("输入信息不能为空")
return
}
if (data.user.identifyingcode.inputverificationcodenumber !== data.user.identifyingcode.verificationcodenumber) {
ElMessage.error("验证码不正确")
return
}
let flag;
localStorage.setItem('userrole', data.user.role)//当前用户角色
localStorage.setItem('id', data.user.id)//当前用户角色
var formdata = new FormData()
formdata.append("id", data.user.id)
formdata.append("password", data.user.password)
if (data.user.role === "管理员") {
await post("/admin/login", formdata).then(res => {
if (res) {
localStorage.setItem('userrole', data.user.role)//当前用户角色
router.push('/home')
} else {
alert("不存在该账号和密码")
}
})
} else if (data.user.role === "教师") {
await post("/teacher/login", formdata).then(res => {
if (res) {
localStorage.setItem('id', data.user.id)//当前用户编号
localStorage.setItem('userrole', data.user.role)//当前用户角色
router.push('/home')
} else {
alert("不存在该账号和密码")
}
})
} else {
await post("/student/login", formdata).then(res => {
if (res) {
localStorage.setItem('id', data.user.id)//当前用户编号
localStorage.setItem('userrole', data.user.role)//当前用户角色
router.push('/home')
} else {
alert("不存在该账号和密码")
}
})
}
}
return{
...toRefs(data),
lgintrigger,
codeimg,
codetrigger
}
//
}
}
</script>
<style scoped>
.login_wrap{
width: 100%;
height: 80vh;
background: rgb(0,186,255,100);
background-image: url("../assets/shouye.png");
/*
position: relative;
*/
}
.information{
width: 100%;
height: 80vh;
background: rgb(0,100,255,100);
font-size: 30px;
text-align: center;
}
/*这个是包括登录还有验证码一系列的框*/
.form_wrap{
width: 500px;
height: 380px;
position: fixed;
top:50%;
left: 50%;
transform: translate(-50%,-50%);
background: #fff;
padding:10px 10px;/*子组件内部变距*/
border-radius: 5px;
border-radius: 7%;
}
.form_wrap button{
}
.form_wrap el-input{
height: 900px;
}
/*这个是登录按钮*/
.login-btn
{ position: fixed;
display: block;
margin: 0px auto;
top:80%;
left:40%;
}
/*这个是角色选择 角色的名称 有三种 admin student teacher*/
#rolename
{
position: fixed;
top:4%;
left: 10%;
}
/*}*/
/*鼠标移动到验证码显示一个手*/
.code {
cursor: pointer;
width: 160px;
height: 50px;
}
</style>
vue3启动
dev代表启动的环境