m2pool_web_frontend/mining-pool/src/views/register/register.vue

832 lines
22 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="loginPage">
<section class="mobileMain" v-if="$isMobile">
<header class="headerBox2">
<img
@click="handelJump(`/`)"
src="../../assets/mobile/login/LOGO.svg"
alt="logo"
/>
<span class="title">{{ $t(`home.MRegister`) }}</span>
<span></span>
</header>
<div class="imgTop">
<img
src="../../assets/mobile/login/registertop.svg"
alt="register"
loading="lazy"
/>
</div>
<section class="formInput">
<el-form
:model="registerForm"
status-icon
:rules="registerRules"
ref="registerForm"
class="demo-ruleForm"
>
<el-form-item prop="email">
<el-input
type="email"
prefix-icon="el-icon-message"
v-model="registerForm.email"
autocomplete="off"
:placeholder="$t(`user.Account`)"
></el-input>
</el-form-item>
<el-form-item prop="emailCode">
<div class="verificationCode">
<el-input
type="text"
prefix-icon="el-icon-chat-line-square"
v-model="registerForm.emailCode"
autocomplete="off"
:placeholder="$t(`user.verificationCode`)"
></el-input>
<el-button
class="codeBtn"
:disabled="btnDisabled"
@click="handelCode"
><span v-if="countDownTime < 60 && countDownTime > 0">{{
countDownTime
}}</span
>{{ $t(bthText) }}</el-button
>
</div>
</el-form-item>
<el-form-item prop="password">
<el-input
:title="$t(`user.passwordPrompt`)"
type="password"
v-model="registerForm.password"
prefix-icon="el-icon-unlock"
autocomplete="off"
:placeholder="$t(`user.password`)"
show-password
></el-input>
<p class="remind" :title="$t(`user.passwordPrompt`)">
{{ $t(`user.passwordPrompt`) }}
</p>
</el-form-item>
<el-form-item prop="confirmPassword">
<el-input
type="password"
v-model="registerForm.confirmPassword"
prefix-icon="el-icon-unlock"
autocomplete="off"
:placeholder="$t(`user.confirmPassword`)"
show-password
></el-input>
</el-form-item>
<div class="register">
<span
>{{ $t(`user.havingAnAccount`) }}
<span class="goLogin" @click="goLogin">{{
$t(`user.login`)
}}</span>
</span>
</div>
<el-form-item>
<el-button
style="
width: 100%;
background: #661fff;
color: aliceblue;
margin-top: 6%;
"
:loading="registerLoading"
@click="handleRegister"
>{{ $t(`user.register`) }}</el-button
>
<div style="text-align: left">
<el-radio @input="handelRadio" v-model="radio" label="zh"
>简体中文</el-radio
>
<el-radio @input="handelRadio" v-model="radio" label="en"
>English</el-radio
>
</div>
</el-form-item>
</el-form>
</section>
</section>
<section class="loginModular" v-else>
<div class="leftBox">
<img
class="logo"
src="../../assets/img/WILOGO.png"
alt="logo"
@click="handleClick"
/>
<img src="../../assets/img/reincon.png" alt="Register Mining Pool" />
</div>
<div class="loginBox">
<div class="closeBox" @click="handleClick">
<i class="iconfont icon-guanbi1 close"></i>
</div>
<el-form
:model="registerForm"
status-icon
:rules="registerRules"
ref="registerForm"
class="demo-ruleForm"
>
<el-form-item>
<p class="loginTitle">{{ $t(`user.newUser`) }}</p>
</el-form-item>
<el-form-item prop="email">
<el-input
type="email"
prefix-icon="el-icon-message"
v-model="registerForm.email"
autocomplete="off"
:placeholder="$t(`user.Account`)"
></el-input>
</el-form-item>
<el-form-item prop="emailCode">
<div class="verificationCode">
<el-input
type="text"
prefix-icon="el-icon-chat-line-square"
v-model="registerForm.emailCode"
autocomplete="off"
:placeholder="$t(`user.verificationCode`)"
></el-input>
<el-button
class="codeBtn"
:disabled="btnDisabled"
@click="handelCode"
><span v-if="countDownTime < 60 && countDownTime > 0">{{
countDownTime
}}</span
>{{ $t(bthText) }}</el-button
>
</div>
</el-form-item>
<el-form-item prop="password">
<el-input
:title="$t(`user.passwordPrompt`)"
type="password"
v-model="registerForm.password"
prefix-icon="el-icon-unlock"
autocomplete="off"
:placeholder="$t(`user.password`)"
show-password
></el-input>
<p class="remind" :title="$t(`user.passwordPrompt`)">
{{ $t(`user.passwordPrompt`) }}
</p>
</el-form-item>
<el-form-item prop="confirmPassword">
<el-input
type="password"
v-model="registerForm.confirmPassword"
prefix-icon="el-icon-unlock"
autocomplete="off"
:placeholder="$t(`user.confirmPassword`)"
show-password
></el-input>
</el-form-item>
<div class="register">
<span
>{{ $t(`user.havingAnAccount`) }}
<span class="goLogin" @click="goLogin">{{
$t(`user.login`)
}}</span>
</span>
</div>
<el-form-item>
<el-button
style="
width: 100%;
background: #661fff;
color: aliceblue;
margin-top: 6%;
"
:loading="registerLoading"
@click="handleRegister"
>{{ $t(`user.register`) }}</el-button
>
<div style="text-align: left">
<el-radio @input="handelRadio" v-model="radio" label="zh"
>简体中文</el-radio
>
<el-radio @input="handelRadio" v-model="radio" label="en"
>English</el-radio
>
</div>
</el-form-item>
</el-form>
</div>
</section>
</div>
</template>
<script>
import { getRegister, getRegisterCode } from "../../api/login";
import { encryption } from "../../utils/fun";
export default {
data() {
// const equalToPassword = (rule, value, callback) => {
// if (this.registerForm.password !== value) {
// callback(new Error("两次输入的密码不一致"));
// } else {
// callback();
// }
// };
return {
registerForm: {
// userName: "",
password: "",
email: "",
emailCode: "",
confirmPassword: "",
},
registerRules: {
userName: [
{ required: true, trigger: "blur", message: "请输入您的账号" },
{
min: 3,
max: 16,
message: "用户账号长度必须介于 3 和 16 之间",
trigger: "blur",
},
],
email: [
{
required: true,
trigger: "blur",
message: this.$t(`user.emailVerification`),
type: "email",
},
],
password: [
{
required: true,
trigger: "blur",
message: this.$t(`user.inputPassword`),
},
{
min: 8,
max: 32,
message: this.$t(`user.passwordVerification`),
trigger: "blur",
},
],
confirmPassword: [
{
required: true,
trigger: "blur",
message: this.$t(`user.secondaryPassword`),
},
// { required: true, validator: equalToPassword, trigger: "blur" },
],
emailCode: [
{
required: true,
trigger: "blur",
message: this.$t(`user.inputCode`),
},
],
},
radio: `zh`,
loading: false,
codeParams: {
// userName: "",
email: "",
},
btnDisabled: false,
bthText: "user.obtainVerificationCode",
time: "",
registerLoading: false,
countDownTime: 60,
timer: null,
lang: "zh",
};
},
computed: {
countDown() {
const minutes = Math.floor(this.countDownTime / 60);
const seconds = this.countDownTime % 60;
const m = minutes < 10 ? "0" + minutes : minutes;
const s = seconds < 10 ? "0" + seconds : seconds;
return `${s}`;
// return`${s}`
},
},
created() {
if (window.sessionStorage.getItem("register_time")) {
this.countDownTime = Number(
window.sessionStorage.getItem("register_time")
);
this.startCountDown();
this.btnDisabled = true;
this.bthText = `user.again`;
}
},
watch: {
'$route'(to) {
// 路由变化时自动同步语言和radio
const match = to.path.match(/^\/(zh|en)(\/|$)/);
if (match) {
this.radio = match[1];
this.lang = match[1];
this.$i18n.locale = match[1];
localStorage.setItem("lang", match[1]);
}
},
"$i18n.locale": function () {
this.translate();
},
},
mounted() {
// this.lang = this.$i18n.locale;
// this.radio = localStorage.getItem("lang")
// ? localStorage.getItem("lang")
// : "en";
// 获取当前路由路径
const path = this.$route.path;
// 匹配 /zh/ 或 /en/ 作为语言前缀
const match = path.match(/^\/(zh|en)(\/|$)/);
if (match) {
this.radio = match[1];
this.lang = match[1];
this.$i18n.locale = match[1];
localStorage.setItem("lang", match[1]);
} else {
// fallback 到 localStorage 或 "en"
this.radio = localStorage.getItem("lang") || "en";
this.lang = this.radio;
this.$i18n.locale = this.radio;
}
for (const key in this.registerForm) {
this.registerForm[key] = "";
}
},
methods: {
handelJump(url) {
const cleanPath = url.startsWith("/") ? url.slice(1) : url;
this.$router.push(`/${this.lang}/${cleanPath}`);
},
translate() {
this.registerRules = {
userName: [
{
required: true,
trigger: "blur",
message: this.$t(`user.inputAccount`),
},
{
min: 3,
max: 16,
message: "用户账号长度必须介于 3 和 16 之间",
trigger: "blur",
},
],
email: [
{
required: true,
trigger: "blur",
message: this.$t(`user.emailVerification`),
type: "email",
},
],
password: [
{
required: true,
trigger: "blur",
message: this.$t(`user.inputPassword`),
},
{
min: 8,
max: 32,
message: this.$t(`user.passwordVerification`),
trigger: "blur",
},
],
confirmPassword: [
{
required: true,
trigger: "blur",
message: this.$t(`user.secondaryPassword`),
},
// { required: true, validator: equalToPassword, trigger: "blur" },
],
emailCode: [
{
required: true,
trigger: "blur",
message: this.$t(`user.inputCode`),
},
],
};
},
async fetchRegisterCode(params) {
const data = await getRegisterCode(params);
if (data && data.code === 200) {
this.$message({
message: this.$t(`user.verificationCodeSuccessful`),
type: "success",
showClose: true,
});
}
},
handelCode() {
// this.codeParams.userName = this.registerForm.userName;
this.codeParams.email = this.registerForm.email;
// if (!this.codeParams.userName) {
// this.$message({
// message: "请输入账号",
// type: "error",
// });
// return
// }
//邮箱格式验证 /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/;
let isMailbox = emailRegex.test(this.codeParams.email);
if (!this.codeParams.email || !isMailbox) {
this.$message({
message: this.$t(`user.emailVerification`),
type: "error",
showClose: true,
});
return;
}
this.fetchRegisterCode(this.codeParams);
if (window.sessionStorage.getItem("register_time") == null) {
this.startCountDown();
} else {
this.countDownTime = Number(
window.sessionStorage.getItem("register_time")
);
this.startCountDown();
}
// this.time = 60;
// let timer = setInterval(()=>{
// if ( this.time) {
// this.time--
// this.btnDisabled = true;
// // this.bthText= this.time+`s后重新获取`
// this.bthText= `user.again`
// }else {
// this.btnDisabled = false;
// this.bthText="user.obtainVerificationCode"
// this.time = "";
// clearTimeout(timer)
// }
// },1000)
},
startCountDown() {
this.timer = setInterval(() => {
if (this.countDownTime <= 1) {
//当监测到countDownTime为0时,清除计数器并且移除sessionStorage,然后执行提交试卷逻辑
clearInterval(this.timer);
sessionStorage.removeItem("register_time");
this.countDownTime = 60;
this.btnDisabled = false;
this.bthText = `user.obtainVerificationCode`;
} else if (this.countDownTime > 0) {
//每秒让countDownTime -1秒,并设置到sessionStorage中
this.countDownTime--;
this.btnDisabled = true;
this.bthText = `user.again`;
window.sessionStorage.setItem("register_time", this.countDownTime);
}
}, 1000);
},
goLogin() {
this.$router.push(`/${this.lang}/login`);
},
handelRadio(val) {
// 保存旧的语言值
const oldLang = this.lang;
// 更新语言设置
this.lang = val;
this.$i18n.locale = val;
localStorage.setItem("lang", val);
// 更新当前路由的语言部分
const currentPath = this.$route.path;
const newPath = currentPath.replace(`/${oldLang}`, `/${val}`);
// 保持查询参数
this.$router
.push({
path: newPath,
query: this.$route.query,
})
.catch((err) => {
if (err.name !== "NavigationDuplicated") {
console.error("Navigation failed:", err);
}
});
},
//点击注册
handleRegister() {
this.$refs.registerForm.validate((valid) => {
if (valid) {
this.loading = true;
//用户名规则1.长度限制3<=用户名<=16; 字符限制:仅允许使用字母、数字、下划线 用户名必须以字母开头
// const regex = /^[a-zA-Z][a-zA-Z0-9_]{2,15}$/; // 正则表达式
// const isValid = regex.test(this.registerForm.userName);
// if (!isValid) {
//
// this.$message({
// message: `请检查账户是否输入正确`,
// type: "error",
// });
// return;
// }
//邮箱格式验证
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/;
let isMailbox = emailRegex.test(this.registerForm.email);
if (!this.registerForm.email || !isMailbox) {
this.$message({
message: this.$t(`user.emailVerification`),
type: "error",
showClose: true,
});
return;
}
// 密码验证 8<=密码<=32 包含大小写字母、数字和特殊字符(!@#¥%……&*
// const regexPassword =
// /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/; // 正则表达式
const regexPassword =
/^(?!.*[\u4e00-\u9fa5])(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/;
const PasswordIsValid = regexPassword.test(
this.registerForm.password
);
if (!PasswordIsValid) {
this.$message({
message: this.$t(`user.passwordFormat`),
type: "error",
});
return;
}
this.registerLoading = true;
//加密
const form = { ...this.registerForm };
form.password = encryption(this.registerForm.password);
form.confirmPassword = encryption(this.registerForm.confirmPassword);
getRegister(form)
.then((res) => {
const userName = this.registerForm.userName;
if (res.code == 200) {
this.$alert(
`<font color='red'>${this.$t(`user.congratulations`)}</font>`,
`${this.$t(`user.system`)}`,
{
dangerouslyUseHTMLString: true,
}
)
.then(() => {
this.$router.push(`/${this.lang}/login`);
})
.catch(() => {});
}
})
.catch(() => {
this.loading = false;
if (this.captchaOnOff) {
// this.getCode();
}
});
this.registerLoading = false;
}
});
},
handleClick() {
this.$router.push(`/${this.lang}`);
},
},
};
</script>
<style scoped lang="scss">
.loginPage {
width: 100%;
height: 100%;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
background-image: url(../../assets/img/logBg.png);
background-size: cover;
background-repeat: no-repeat;
.loginModular {
width: 53%;
height: 68%;
display: flex;
border-radius: 10px;
overflow: hidden;
box-shadow: 0px 0px 20px 18px #d6d2ea;
// box-shadow: 0px 0px 20PX 30PX #000;
}
.remind {
font-size: 0.8em;
padding: 0;
margin: 0;
min-height: 15px;
line-height: 15px;
color: #ff4081;
// text-overflow: ellipsis;
// overflow: hidden;
// white-space: nowrap;
// cursor: pointer;
}
.leftBox {
width: 47%;
height: 100%;
background-image: linear-gradient(150deg, #18b7e6 -20%, #651fff 60%);
position: relative;
img {
width: 100%;
position: absolute;
right: -15%;
bottom: 0;
z-index: 99;
}
.logo {
position: absolute;
left: 30px;
top: 18px;
width: 22%;
}
}
}
.el-form {
width: 90%;
padding: 0px 20px 50px 20px;
}
.el-form-item {
width: 100%;
}
.loginBox {
width: 53%;
// box-shadow: 0PX 0PX 5PX 1PX #ccc;
display: flex;
justify-content: center;
align-items: center;
border-radius: 10px;
position: relative;
flex-direction: column;
overflow: hidden;
padding: 0px 25px;
background: #fff;
.demo-ruleForm {
height: 100%;
padding-top: 3%;
}
img {
width: 18%;
position: absolute;
top: 20px;
right: 30px;
cursor: pointer;
}
.closeBox {
position: absolute;
top: 18px;
right: 30px;
cursor: pointer;
.close {
font-size: 1.3em;
}
}
.closeBox:hover {
color: #661fff;
}
}
.loginTitle {
font-size: 20px;
font-weight: 600;
margin-bottom: 30px;
text-align: center;
}
.loginColor {
width: 100%;
height: 15px;
background: #661fff;
}
.langBox {
display: flex;
justify-content: space-between;
align-content: center;
}
.register {
display: flex;
justify-content: start;
/* background: #CCC; */
margin: 0;
font-size: 12px;
height: 10px;
.goLogin:hover {
color: #661fff;
cursor: pointer;
}
}
.forget {
margin-left: 10px;
}
.forgotPassword {
display: inline-block;
width: 20%;
}
.verificationCode {
display: flex;
.codeBtn {
font-size: 13px;
margin-left: 2px;
}
}
// 手机端适配
@media screen and (min-width: 220px) and (max-width: 1279px) {
.mobileMain {
width: 100vw;
min-height: 100vh;
background: #fff;
background-image: url("../../assets/mobile/login/bgtop.svg");
background-repeat: no-repeat;
background-size: 115%;
background-position: 49% 47%;
box-sizing: border-box;
}
.headerBox2 {
width: 100%;
height: 60px;
// background: palegoldenrod;
// border-bottom: 1px solid #ccc;
display: flex;
align-items: center;
justify-content: space-between;
line-height: 60px;
padding: 0px 20px;
padding-top: 10px;
box-shadow: 0px 0px 2px 1px #ccc;
img {
width: 30px;
}
.title {
height: 100%;
font-weight: 600;
}
}
.imgTop {
width: 100%;
display: flex;
justify-content: center;
margin-top: 2%;
img {
height: 159px;
}
}
.formInput {
width: 100%;
display: flex;
justify-content: center;
}
.register {
.goLogin {
color: #651fff;
padding: 0px 8px;
}
}
}
</style>