<template>
<div class="login">
<div class="login-card">
<div class="title">服务平台管理中心</div>
<el-form :model="loginForm" ref="loginForm" :rules="rules">
<div v-if="showPhone">
<el-form-item prop="userName">
<el-input
v-model="loginForm.userName"
prefix-icon="el-icon-user"
placeholder="请输入账号"
></el-input>
</el-form-item>
<el-form-item prop="passWord">
<el-input
v-model="loginForm.passWord"
prefix-icon="el-icon-user"
placeholder="请输入密码"
show-password
></el-input>
</el-form-item>
<el-form-item class="identifyingCode" prop="identifyingCode">
<el-input
v-model="loginForm.identifyingCode"
prefix-icon="el-icon-user"
placeholder="请输入验证码"
></el-input>
<canvas ref="canvas" @click="request_getCode"></canvas>
</el-form-item>
</div>
<div v-if="!showPhone">
<el-form-item prop="phone">
<el-input
v-model="loginForm.phone"
prefix-icon="el-icon-user"
placeholder="请输入手机号"
></el-input>
</el-form-item>
<el-form-item prop="code">
<el-input
v-model="loginForm.code"
prefix-icon="el-icon-user"
placeholder="请输入验证码"
>
<el-button
slot="append"
:disabled="countingDown"
@click="getIdentifyingCode"
v-text="buttonText"
></el-button>
</el-input>
</el-form-item>
</div>
<el-form-item class="identifyingCode">
<div class="phone" @click="togglePhone" v-text="loginTitle"></div>
<div class="password">忘记密码</div>
</el-form-item>
<el-form-item>
<el-button type="primary" style="width: 100%" @click="handleLogin"
>登录</el-button
>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
export default {
data() {
return {
showPhone: true,
loginForm: {
userName: "",
passWord: "",
identifyingCode: "",
phone: "",
code: "",
},
rules: {
userName: [{ required: true, message: "请输入账号", trigger: "blur" }],
passWord: [{ required: true, message: "请输入密码", trigger: "blur" }],
identifyingCode: [
{ required: true, message: "请输入验证码", trigger: "blur" },
],
phone: [{ required: true, message: "请输入手机号", trigger: "blur" }],
code: [{ required: true, message: "请输入验证码", trigger: "blur" }],
},
countingDown: false,
seconds: 10,
timer: null,
};
},
created() {},
computed: {
buttonText() {
return this.countingDown ? `${this.seconds} 秒后重新获取` : "获取验证码";
},
loginTitle() {
return this.showPhone == true ? "手机号码登录" : "账号密码登录";
},
},
watch: {
showPhone(val) {
if (val == true) {
this.$nextTick(() => {
this.request_getCode();
});
}
},
},
components: {},
mounted() {
this.request_getCode();
},
methods: {
request_getCode() {
// getCode().then((res) => {
// if (res.data.code == 0) {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext("2d");
// 获取画布的宽度和高度
const width = canvas.width;
const height = canvas.height;
// 清空画布
ctx.clearRect(0, 0, width, height);
// 设置字体样式和颜色
const fontSizes = [
"bold 60px sans-serif",
"bold 62px sans-serif",
"bold 64px sans-serif",
];
ctx.font = fontSizes[Math.floor(Math.random() * fontSizes.length)];
// 获取每个字符的宽度
const textWidth = ctx.measureText("W").width;
// 获取文本的初始位置
const startX = (width - textWidth * 4) / 2;
// 生成四位数字,并将其转成字符串
let randomNumbers = [];
for (let i = 0; i < 4; i++) {
let randomNumber = Math.floor(Math.random() * 10); // 生成 0 到 9 的随机整数
randomNumbers.push(randomNumber);
}
const code = randomNumbers;
// 绘制验证码
for (let i = 0; i < code.length; i++) {
// 设置随机颜色
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
ctx.fillStyle = `rgb(${r},${g},${b})`;
// 绘制字符
ctx.fillText(code[i], startX + textWidth * i, height / 1.5);
}
// 绘制干扰线
for (let i = 0; i < 12; i++) {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
ctx.strokeStyle = `rgb(${r},${g},${b})`;
ctx.beginPath();
ctx.moveTo(Math.random() * width, Math.random() * height);
ctx.lineTo(Math.random() * width, Math.random() * height);
ctx.stroke();
}
// 绘制干扰点
for (let i = 0; i < 100; i++) {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
ctx.fillStyle = `rgb(${r},${g},${b})`;
ctx.beginPath();
ctx.arc(
Math.random() * width,
Math.random() * height,
1,
0,
2 * Math.PI
);
ctx.fill();
}
// }
// else {
// this.$message.error(res.data.message);
// }
// });
},
getIdentifyingCode() {
if (this.countingDown) return;
this.countingDown = true;
this.timer = setInterval(() => {
this.seconds--;
if (this.seconds <= 0) {
clearInterval(this.timer);
this.countingDown = false;
this.seconds = 10; // 重置倒计时时间
}
}, 1000);
},
handleLogin() {
this.$refs["loginForm"].validate((valid) => {
if (valid) {
alert("submit!");
} else {
return false;
}
});
},
togglePhone() {
this.showPhone = !this.showPhone;
this.$refs.loginForm.resetFields();
},
},
destroyed() {
// 在组件销毁时清除计时器,避免内存泄漏
if (this.timer) {
clearInterval(this.timer);
}
}
};
</script>
<style lang="scss" scoped>
.login {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.login-card {
width: 22rem;
.title {
font-size: 1.375rem;
font-weight: 600;
height: 2.5rem;
}
}
.identifyingCode {
::v-deep .el-form-item__content {
display: flex;
}
::v-deep .el-input {
flex: 1;
}
::v-deep .el-input__inner {
border-radius: 0.25rem 0 0 0.25rem;
}
}
.phone {
flex: 1;
text-align: left;
color: #4096ee;
cursor: pointer;
}
.password {
flex: 1;
text-align: right;
color: #4096ee;
cursor: pointer;
}
canvas {
cursor: pointer;
border: 1px solid #ccc;
border-radius: 0 0.25rem 0.25rem 0;
width: 9rem;
height: 2.5rem;
box-sizing: border-box;
border-left: 0;
}
</style>
08-05
3013
02-01
1082
08-05