Files
tk-mini-program-PC/src/views/emailRegistration.vue
pengxiaolong 89014e306e 优化代码
2025-08-21 21:36:08 +08:00

388 lines
9.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="email-registration">
<div class="stepBar">
<el-steps
style="background-color: #f5f5f500"
:active="active"
finish-status="success"
simple
>
<el-step title="账号信息" />
<el-step title="邮箱验证" />
</el-steps>
</div>
<!-- 账号信息 -->
<div class="form" v-if="active === 0">
<div class="title">注册</div>
<div class="Email">
<el-input type="text" size="large" class="input-item" v-model="Email" placeholder="请输入邮箱" />
</div>
<div class="Email">
<el-input type="text" size="large" class="input-item" v-model="userName" placeholder="请输入用户名" @blur="userNameBlur"/>
</div>
<div class="Password">
<el-input type="Password" size="large" class="input-item" v-model="Password" show-password placeholder="请输入密码" />
<text class="password-tip">您的密码必须包含大小字母和数字长度在6-16位之间</text>
</div>
<div class="ConfirmPassword">
<el-input type="Password" size="large" class="input-item" v-model="ConfirmPassword" show-password placeholder="请再次输入密码" />
</div>
<div class="btn">
<div class="Return" @click="Return">返回</div>
<div class="nextStep" @click="nextStep" >下一步</div>
</div>
</div>
<!-- 完成注册 -->
<div class="form" v-if="active === 1">
<div class="title">邮箱验证</div>
<div class="Hint">
已向您的{{Email}}邮箱发送了一封验证邮件请点击邮件中的链接完成注册
</div>
<div
class="ResendEmail"
@click="ResendEmail"
:style="isCounting ? 'background-image: linear-gradient(0deg, #cccccc, #dddddd); cursor: not-allowed;' : ''"
>
{{ isCounting ? `${countdown}秒后重发` : '重发邮件' }}
</div>
</div>
</div>
</template>
<script setup>
import { register,checkStatus,resendEmail,checkUsername} from "@/api/account"; // 导入登录接口
import { tokenStore, UserStore } from '@/stores/notice'
import { setStorage , getStorage } from '@/utils/storage.js';
import {
ref, // 响应式基础
watch, // 侦听器
onMounted, // 组件挂载完成后执行
onUpdated, // 组件更新后执行
onUnmounted, // 组件销毁前执行
} from "vue";
import { ElMessage } from "element-plus";
import { useRouter } from 'vue-router'
const router = useRouter()
const active = ref(0);// 当前步骤
const Email = ref("");// 邮箱
const userName = ref("");// 用户名
const Password = ref("");// 密码
const ConfirmPassword = ref("");// 确认密码
const token = tokenStore()
const user = UserStore()
const userNamebtn = ref(false)
const countdown = ref(0); // 倒计时秒数
const isCounting = ref(false); // 是否正在倒计时
let timer = null; // 定时器
function startCountdown() {
countdown.value = 60;
isCounting.value = true;
timer = setInterval(() => {
countdown.value--;
if (countdown.value <= 0) {
clearInterval(timer);
isCounting.value = false;
}
}, 1000);
}
// 用户名失去焦点
function userNameBlur() {
if (userName.value.length < 6 || userName.value.length > 16 || userName.value == '' || userName.value == null) {
ElMessage.error('用户名长度不能小于2不能大于16,不能为空');
return;
}
checkUsername({ userName: userName.value }).then(res => {
if (res==false) {
ElMessage.error('用户名已存在');
userNamebtn.value = false
return;
} else {
ElMessage.success('用户名可用');
userNamebtn.value = true
}
}).catch((err) => {});
}
//下一步
function nextStep() {
//用户名验证
if (userNamebtn.value == false) {
ElMessage.error('用户名已存在');
return;
}
// 邮箱验证
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailRegex.test(Email.value)) {
ElMessage.error('请输入有效的邮箱地址');
return;
}
// 密码验证
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{6,16}$/;
if (!passwordRegex.test(Password.value)) {
ElMessage.error('密码必须包含大小写字母和数字长度6-16位');
return;
}
//用户名验证
if (userName.value.length < 6 || userName.value.length > 16 || userName.value == '' || userName.value == null) {
ElMessage.error('用户名长度不能小于2不能大于16,不能为空');
return;
}
// 确认密码验证
if (Password.value !== ConfirmPassword.value) {
ElMessage.error('两次输入的密码不一致');
return;
}
register({ userName: userName.value,password: Password.value, email: Email.value, nickName: '用户' + Math.floor(Math.random() * 1000000),headerIcon:'181754562968_.pic_hd.jpg'}).then(res => {
active.value = active.value + 1;
check(res.id);
token.setToken(res.token);
setStorage('token', res.token)
startCountdown();
}).catch(err => {});
}
//检查验证
let poll;
function check(id) {
poll = setInterval(() => {
checkStatus({id: id}).then(res => {
if (res.status === 0) {
user.setUser(res)
setStorage('user', res)
pollstop()
router.push('/nav')
}
}).catch((err) => {});
}, 2000);
}
function pollstop() {
clearInterval(poll)
}
/// 重发邮件
function ResendEmail() {
resendEmail({mailAddress: Email.value,type:1}).then(res => {
ElMessage.success('邮件已重新发送');
startCountdown();
}).catch(err => {});
}
//返回登录页
function Return() {
router.push('/')
}
// watch(refname, async (newQuestion, oldQuestion) => {
// // 变化后执行
// });
onMounted(() => {
// 组件挂载完成后执行
});
onUpdated(() => {
// 组件更新后执行
});
onUnmounted(() => {
// 组件销毁前执行
});
</script>
<style scoped>
.email-registration {
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
background-image: url(../assets/bg.png);
background-size: 100% 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.stepBar {
width: 900px;
}
.form {
margin-top: 30px;
width: 900px;
height: 600px;
background-image: linear-gradient(180deg, #dbf0f1, #ffffff);
border-radius: 10px;
border: 1px solid #4fcacd;
display: flex;
flex-direction: column;
align-items: center;
}
.title{
font-size: 30px;
color: #4fcacd;
margin-top: 70px;
text-align: center;
font-weight: bold;
}
.Hint{
width: 900px;
height: 400px;
color:#4fcacd;
font-size: 20px;
text-align: center;
line-height: 500px;
margin-top: -50px;
}
.ResendEmail{
width: 200px;
height: 40px;
background-image: linear-gradient(0deg, #4fcacd, #5fdbde);
border-radius: 10px;
color: #ffffff;
font-size: 16px;
text-align: center;
line-height: 40px;
cursor: pointer;
transition: all 0.3s ease;
margin-top: 50px;
}
.ResendEmail:hover{
box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3);
transform: scale(1.08);
opacity: 0.8;
}
.Email{
margin-top: 30px;
width: 90%;
display: flex;
justify-content: center;
align-items: center;
}
.Password{
margin-top: 30px;
width: 90%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.ConfirmPassword{
margin-top: 30px;
width: 90%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.password-tip{
font-size: 12px;
color: #8c939d;
margin-top: 10px;
}
.btn{
width: 70%;
margin-top: 70px;
display: flex;
justify-content: space-between;
align-items: center;
}
.Return{
width: 200px;
height: 40px;
background-image: linear-gradient(0deg, #4fcacd, #5fdbde);
border-radius: 10px;
color: #ffffff;
font-size: 16px;
text-align: center;
line-height: 40px;
cursor: pointer;
transition: all 0.3s ease;
}
.Return:hover{
box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3);
transform: scale(1.08);
opacity: 0.8;
}
.nextStep{
width: 200px;
height: 40px;
background-image: linear-gradient(0deg, #4fcacd, #5fdbde);
border-radius: 10px;
color: #ffffff;
font-size: 16px;
text-align: center;
line-height: 40px;
cursor: pointer;
transition: all 0.3s ease;
}
.nextStep:hover{
box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3);
transform: scale(1.08);
opacity: 0.8;
}
.avatar {
width: 90%;
margin-top: 30px;
height: 178px;
}
.input {
width: 90%;
margin-top: 100px;
height: 50px;
}
.input-item {
border: none;
width: 80%;
height: 100%;
background-color: #ffffff00;
border-bottom: 1px solid #4fcacd;
}
:deep(.el-input__wrapper) {
box-shadow: none !important;
background-color: transparent !important;
}
:deep(.el-input__wrapper.is-focus) {
box-shadow: none !important;
}
.avatar-uploader {
width: 178px;
height: 178px;
border: 3px solid #4fcacd;
border-radius: 10px;
}
.avatar-uploader .avatar {
width: 178px;
height: 178px;
display: block;
}
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar-tip {
width: 178px;
text-align: center;
font-size: 12px;
color: #8c939d;
}
</style>