|
|
<!doctype html>
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
<head>
|
|
|
<meta charset="UTF-8" />
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
|
<meta name="description" content="登录与注册页面" details="提供用户登录和注册功能的页面,支持用户名/手机号登录及第三方登录">
|
|
|
<title>登录与注册</title>
|
|
|
<style>
|
|
|
body {
|
|
|
font-family: var(--font-family);
|
|
|
height: 100vh;
|
|
|
overflow: hidden;
|
|
|
background-color: var(--bg-color-secondary);
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
/* 背景装饰 */
|
|
|
.bg-decoration {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
z-index: 0;
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.circle {
|
|
|
position: absolute;
|
|
|
border-radius: 50%;
|
|
|
background: radial-gradient(circle, color-mix(in srgb, var(--color-primary), transparent 70%), transparent);
|
|
|
filter: blur(40px);
|
|
|
animation: float 10s infinite ease-in-out;
|
|
|
}
|
|
|
|
|
|
.circle:nth-child(1) {
|
|
|
width: 500px;
|
|
|
height: 500px;
|
|
|
top: -100px;
|
|
|
left: -100px;
|
|
|
animation-delay: 0s;
|
|
|
}
|
|
|
|
|
|
.circle:nth-child(2) {
|
|
|
width: 400px;
|
|
|
height: 400px;
|
|
|
bottom: -50px;
|
|
|
right: -50px;
|
|
|
background: radial-gradient(circle, color-mix(in srgb, var(--color-secondary), transparent 70%), transparent);
|
|
|
animation-delay: -5s;
|
|
|
}
|
|
|
|
|
|
@keyframes float {
|
|
|
|
|
|
0%,
|
|
|
100% {
|
|
|
transform: translate(0, 0);
|
|
|
}
|
|
|
|
|
|
50% {
|
|
|
transform: translate(30px, 20px);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 主容器 */
|
|
|
.container {
|
|
|
background-color: var(--color-primary-text);
|
|
|
border-radius: var(--radius-xl);
|
|
|
box-shadow: var(--shadow-xl);
|
|
|
position: relative;
|
|
|
overflow: hidden;
|
|
|
width: 850px;
|
|
|
max-width: 95%;
|
|
|
min-height: 600px;
|
|
|
z-index: 1;
|
|
|
}
|
|
|
|
|
|
.form-container {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
height: 100%;
|
|
|
transition: all 0.6s ease-in-out;
|
|
|
background: var(--color-primary-text);
|
|
|
}
|
|
|
|
|
|
.sign-in-container {
|
|
|
left: 0;
|
|
|
width: 50%;
|
|
|
z-index: 2;
|
|
|
}
|
|
|
|
|
|
.sign-up-container {
|
|
|
left: 0;
|
|
|
width: 50%;
|
|
|
opacity: 0;
|
|
|
z-index: 1;
|
|
|
}
|
|
|
|
|
|
.container.right-panel-active .sign-in-container {
|
|
|
transform: translateX(100%);
|
|
|
}
|
|
|
|
|
|
.container.right-panel-active .sign-up-container {
|
|
|
transform: translateX(100%);
|
|
|
opacity: 1;
|
|
|
z-index: 5;
|
|
|
animation: show 0.6s;
|
|
|
}
|
|
|
|
|
|
@keyframes show {
|
|
|
|
|
|
0%,
|
|
|
49.99% {
|
|
|
opacity: 0;
|
|
|
z-index: 1;
|
|
|
}
|
|
|
|
|
|
50%,
|
|
|
100% {
|
|
|
opacity: 1;
|
|
|
z-index: 5;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.form-container-inner {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
height: 100%;
|
|
|
padding: 0 40px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
/* 标题与文本 */
|
|
|
h1 {
|
|
|
font-weight: bold;
|
|
|
margin: 0 0 10px;
|
|
|
color: var(--text-color);
|
|
|
font-size: 28px;
|
|
|
}
|
|
|
|
|
|
.subtitle {
|
|
|
font-size: 14px;
|
|
|
color: var(--text-color-secondary);
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
.social-container {
|
|
|
margin: 15px 0 20px;
|
|
|
display: flex;
|
|
|
gap: 15px;
|
|
|
}
|
|
|
|
|
|
.social-btn {
|
|
|
width: 40px;
|
|
|
height: 40px;
|
|
|
border-radius: 50%;
|
|
|
border: 1px solid var(--border-color);
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
color: var(--text-color-secondary);
|
|
|
transition: all 0.3s;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.social-btn:hover {
|
|
|
border-color: var(--color-primary);
|
|
|
color: var(--color-primary);
|
|
|
background-color: color-mix(in srgb, var(--color-primary), transparent 95%);
|
|
|
}
|
|
|
|
|
|
/* 切换 Tab */
|
|
|
.login-tab {
|
|
|
display: flex;
|
|
|
margin-bottom: 25px;
|
|
|
position: relative;
|
|
|
background: var(--bg-color-secondary);
|
|
|
border-radius: var(--radius-full);
|
|
|
padding: 4px;
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
.tab-item {
|
|
|
flex: 1;
|
|
|
text-align: center;
|
|
|
padding: 8px 0;
|
|
|
font-size: 14px;
|
|
|
cursor: pointer;
|
|
|
border-radius: var(--radius-full);
|
|
|
color: var(--text-color-secondary);
|
|
|
transition: all 0.3s ease;
|
|
|
position: relative;
|
|
|
z-index: 1;
|
|
|
}
|
|
|
|
|
|
.tab-item.active {
|
|
|
color: var(--color-primary);
|
|
|
background: var(--color-primary-text);
|
|
|
box-shadow: var(--shadow-sm);
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
|
|
|
/* 输入框区域 */
|
|
|
.input-group {
|
|
|
width: 100%;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 15px;
|
|
|
margin-bottom: 10px;
|
|
|
}
|
|
|
|
|
|
.phone-row {
|
|
|
display: flex;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
.verify-row {
|
|
|
display: flex;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
/* 链接与错误信息 */
|
|
|
.forgot-password {
|
|
|
color: var(--text-color-tertiary);
|
|
|
font-size: 13px;
|
|
|
text-decoration: none;
|
|
|
margin: 15px 0;
|
|
|
align-self: flex-end;
|
|
|
transition: color 0.3s;
|
|
|
}
|
|
|
|
|
|
.forgot-password:hover {
|
|
|
color: var(--color-primary);
|
|
|
}
|
|
|
|
|
|
.error-message {
|
|
|
color: var(--color-danger);
|
|
|
font-size: 13px;
|
|
|
min-height: 20px;
|
|
|
margin-bottom: 10px;
|
|
|
text-align: left;
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
/* 侧边遮罩 */
|
|
|
.overlay-container {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 50%;
|
|
|
width: 50%;
|
|
|
height: 100%;
|
|
|
overflow: hidden;
|
|
|
transition: transform 0.6s ease-in-out;
|
|
|
z-index: 100;
|
|
|
border-top-right-radius: var(--radius-xl);
|
|
|
border-bottom-right-radius: var(--radius-xl);
|
|
|
}
|
|
|
|
|
|
.container.right-panel-active .overlay-container {
|
|
|
transform: translateX(-100%);
|
|
|
border-radius: var(--radius-xl) 0 0 var(--radius-xl);
|
|
|
}
|
|
|
|
|
|
.overlay {
|
|
|
background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
|
|
|
background-repeat: no-repeat;
|
|
|
background-size: cover;
|
|
|
background-position: 0 0;
|
|
|
color: var(--color-primary-text);
|
|
|
position: relative;
|
|
|
left: -100%;
|
|
|
height: 100%;
|
|
|
width: 200%;
|
|
|
transform: translateX(0);
|
|
|
transition: transform 0.6s ease-in-out;
|
|
|
}
|
|
|
|
|
|
.container.right-panel-active .overlay {
|
|
|
transform: translateX(50%);
|
|
|
}
|
|
|
|
|
|
.overlay-panel {
|
|
|
position: absolute;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
flex-direction: column;
|
|
|
padding: 0 40px;
|
|
|
text-align: center;
|
|
|
top: 0;
|
|
|
height: 100%;
|
|
|
width: 50%;
|
|
|
transform: translateX(0);
|
|
|
transition: transform 0.6s ease-in-out;
|
|
|
}
|
|
|
|
|
|
.overlay-panel h1 {
|
|
|
color: var(--color-primary-text);
|
|
|
}
|
|
|
|
|
|
.overlay-panel p {
|
|
|
font-size: 14px;
|
|
|
font-weight: 300;
|
|
|
line-height: 24px;
|
|
|
margin: 20px 0 30px;
|
|
|
color: color-mix(in srgb, var(--color-primary-text), transparent 10%);
|
|
|
}
|
|
|
|
|
|
.overlay-left {
|
|
|
transform: translateX(-20%);
|
|
|
}
|
|
|
|
|
|
.container.right-panel-active .overlay-left {
|
|
|
transform: translateX(0);
|
|
|
}
|
|
|
|
|
|
.overlay-right {
|
|
|
right: 0;
|
|
|
transform: translateX(0);
|
|
|
}
|
|
|
|
|
|
.container.right-panel-active .overlay-right {
|
|
|
transform: translateX(20%);
|
|
|
}
|
|
|
|
|
|
/* 按钮覆盖样式 - REMOVED to avoid conflict with internal styles */
|
|
|
|
|
|
/* v-btn 通用样式微调 - REMOVED to avoid conflict with internal styles */
|
|
|
</style>
|
|
|
</head>
|
|
|
|
|
|
<body layout='public'>
|
|
|
<!-- 背景动画 -->
|
|
|
<div class="bg-decoration">
|
|
|
<div class="circle"></div>
|
|
|
<div class="circle"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="container" :class="{ 'right-panel-active': isSignUp }" id="container">
|
|
|
|
|
|
<!-- 注册表单 -->
|
|
|
<div class="form-container sign-up-container">
|
|
|
<div class="form-container-inner">
|
|
|
<h1>创建账户</h1>
|
|
|
<div class="subtitle">填写以下信息开始您的旅程</div>
|
|
|
|
|
|
<div class="social-container">
|
|
|
<div class="social-btn" @click="handleSocialLogin('github')"><i class="fa-brands fa-github"></i></div>
|
|
|
<div class="social-btn" @click="handleSocialLogin('weixin')"><i class="fa-brands fa-weixin"></i></div>
|
|
|
<div class="social-btn" @click="handleSocialLogin('google')"><i class="fa-brands fa-google"></i></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="subtitle" style="margin: 0 0 15px; font-size: 12px;">或使用手机/邮箱注册</div>
|
|
|
|
|
|
<div class="input-group">
|
|
|
<v-input v:value="signUpForm.username" placeholder="用户名"></v-input>
|
|
|
|
|
|
<!-- 手机号输入框带区域选择 -->
|
|
|
<div v-if='$G.cfg.sms' class="phone-row">
|
|
|
<v-input type="select" v:value="signUpForm.region" :opts="{options: regions}"></v-input>
|
|
|
<v-input v:value="signUpForm.phone" placeholder="手机号"></v-input>
|
|
|
</div>
|
|
|
|
|
|
<div v-if='$G.cfg.sms' class="verify-row">
|
|
|
<v-input v:value="signUpForm.verifyCode" placeholder="验证码"></v-input>
|
|
|
<v-btn variant="outline" :disabled="smsCountdown > 0 || smsLoading" :click="() => sendVerifyCode('signup')"
|
|
|
style="min-width: 100px;">
|
|
|
{{ smsCountdown > 0 ? `${smsCountdown}s` : '获取验证码' }}
|
|
|
</v-btn>
|
|
|
</div>
|
|
|
|
|
|
<v-input type="password" v:value="signUpForm.password" placeholder="密码"></v-input>
|
|
|
</div>
|
|
|
|
|
|
<div class="error-message">{{ signUpError }}</div>
|
|
|
|
|
|
<v-btn round block size="lg" :loading="signUpLoading" :click="handleSignUp">立即注册</v-btn>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 登录表单 -->
|
|
|
<div class="form-container sign-in-container">
|
|
|
<div class="form-container-inner">
|
|
|
<h1>欢迎回来</h1>
|
|
|
<div class="subtitle">登录您的账户以继续</div>
|
|
|
|
|
|
<div class="social-container">
|
|
|
<div class="social-btn" @click="handleSocialLogin('github')"><i class="fa-brands fa-github"></i></div>
|
|
|
<div class="social-btn" @click="handleSocialLogin('weixin')"><i class="fa-brands fa-weixin"></i></div>
|
|
|
<div class="social-btn" @click="handleSocialLogin('google')"><i class="fa-brands fa-google"></i></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="subtitle" style="margin: 0 0 15px; font-size: 12px;">或使用您的账户</div>
|
|
|
|
|
|
<!-- 登录方式选择 -->
|
|
|
<div class="login-tab" v-if="$G.cfg.sms">
|
|
|
<div class="tab-item" :class="{ active: loginType === 'username' }" @click="switchLoginType('username')">
|
|
|
账号密码
|
|
|
</div>
|
|
|
<div class="tab-item" :class="{ active: loginType === 'phone' }" @click="switchLoginType('phone')">
|
|
|
手机验证码
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 用户名登录 -->
|
|
|
<div v-if="loginType === 'username'" class="input-group">
|
|
|
<v-input v:value="signInForm.username" placeholder="用户名"></v-input>
|
|
|
<v-input type="password" v:value="signInForm.password" placeholder="密码"></v-input>
|
|
|
</div>
|
|
|
|
|
|
<!-- 手机号登录 -->
|
|
|
<div v-if="loginType === 'phone'" class="input-group">
|
|
|
<div class="phone-row">
|
|
|
<v-input type="select" v:value="signInForm.region" :opts="{options: regions}"></v-input>
|
|
|
<v-input v:value="signInForm.phone" placeholder="手机号"></v-input>
|
|
|
</div>
|
|
|
|
|
|
<div class="verify-row">
|
|
|
<v-input v:value="signInForm.verifyCode" placeholder="验证码"></v-input>
|
|
|
<v-btn variant="outline" :disabled="smsCountdown > 0 || smsLoading" :click="() => sendVerifyCode('signin')"
|
|
|
style="min-width: 100px;">
|
|
|
{{ smsCountdown > 0 ? `${smsCountdown}s` : '获取验证码' }}
|
|
|
</v-btn>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<a href="#" class="forgot-password">忘记密码?</a>
|
|
|
<div class="error-message">{{ signInError }}</div>
|
|
|
|
|
|
<v-btn round block size="lg" :loading="signInLoading" :click="handleSignIn">登 录</v-btn>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 覆盖层 -->
|
|
|
<div class="overlay-container">
|
|
|
<div class="overlay">
|
|
|
<div class="overlay-panel overlay-left">
|
|
|
<h1>已有账户?</h1>
|
|
|
<p>请使用您的个人信息登录,保持连接。</p>
|
|
|
<v-btn variant="outline" round class="btn-ghost" :click="switchToSignIn" size="lg"
|
|
|
style="width: 120px;">去登录</v-btn>
|
|
|
</div>
|
|
|
<div class="overlay-panel overlay-right">
|
|
|
<h1>新朋友?</h1>
|
|
|
<p>输入您的个人信息,开始您的旅程。</p>
|
|
|
<v-btn variant="outline" round class="btn-ghost" :click="switchToSignUp" size="lg"
|
|
|
style="width: 120px;">去注册</v-btn>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<script setup>
|
|
|
// 响应式数据
|
|
|
logout = $router.query.logout;
|
|
|
redirect = $router.query.redirect || '/';
|
|
|
isSignUp = false;
|
|
|
loginType = 'username'; // 'username' 或 'phone'
|
|
|
signUpForm = {username: '', phone: '', verifyCode: '', password: '', region: '+86'};
|
|
|
signInForm = {username: '', password: '', phone: '', verifyCode: '', region: '+86'};
|
|
|
signUpError = '';
|
|
|
signInError = '';
|
|
|
smsCountdown = 0; // 验证码倒计时
|
|
|
smsLoading = false; // 验证码发送加载状态
|
|
|
signUpLoading = false; // 注册按钮加载状态
|
|
|
signInLoading = false; // 登录按钮加载状态
|
|
|
|
|
|
// 常用国家/地区代码 - 转换为 v-select 格式
|
|
|
regions = [
|
|
|
{value: '+86', label: '+86 中国'},
|
|
|
{value: '+1', label: '+1 美国'},
|
|
|
{value: '+44', label: '+44 英国'},
|
|
|
{value: '+81', label: '+81 日本'},
|
|
|
{value: '+82', label: '+82 韩国'},
|
|
|
{value: '+65', label: '+65 新加坡'},
|
|
|
{value: '+852', label: '+852 香港'},
|
|
|
{value: '+853', label: '+853 澳门'},
|
|
|
{value: '+886', label: '+886 台湾'},
|
|
|
{value: '+91', label: '+91 印度'},
|
|
|
{value: '+33', label: '+33 法国'},
|
|
|
{value: '+49', label: '+49 德国'},
|
|
|
{value: '+7', label: '+7 俄国'},
|
|
|
{value: '+61', label: '+61 澳大利亚'},
|
|
|
{value: '+55', label: '+55 巴西'},
|
|
|
{value: '+39', label: '+39 意大利'},
|
|
|
{value: '+34', label: '+34 西班牙'},
|
|
|
{value: '+31', label: '+31 荷兰'},
|
|
|
{value: '+46', label: '+46 瑞典'},
|
|
|
{value: '+47', label: '+47 挪威'}
|
|
|
];
|
|
|
|
|
|
// 验证手机号格式(根据不同地区调整)
|
|
|
validatePhone = (phone, region) => {
|
|
|
if (region === '+86') {
|
|
|
const regex = /^1[3-9]\d{9}$/;
|
|
|
return regex.test(phone);
|
|
|
} else if (region === '+1') {
|
|
|
const regex = /^\d{10}$/;
|
|
|
return regex.test(phone);
|
|
|
} else {
|
|
|
const regex = /^\d{7,15}$/;
|
|
|
return regex.test(phone);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 验证密码是否符合要求
|
|
|
validatePassword = (password) => {
|
|
|
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[_]).{9,}$/;
|
|
|
return regex.test(password);
|
|
|
};
|
|
|
|
|
|
// 切换登录方式
|
|
|
switchLoginType = (type) => {
|
|
|
if (signInLoading) return;
|
|
|
loginType = type;
|
|
|
signInError = '';
|
|
|
signInForm.username = '';
|
|
|
signInForm.password = '';
|
|
|
signInForm.phone = '';
|
|
|
signInForm.verifyCode = '';
|
|
|
};
|
|
|
|
|
|
// 切换到注册页面
|
|
|
switchToSignUp = () => {
|
|
|
if (signInLoading || signUpLoading) return;
|
|
|
isSignUp = true;
|
|
|
signUpError = '';
|
|
|
signInError = '';
|
|
|
};
|
|
|
|
|
|
// 切换到登录页面
|
|
|
switchToSignIn = () => {
|
|
|
if (signInLoading || signUpLoading) return;
|
|
|
isSignUp = false;
|
|
|
signUpError = '';
|
|
|
signInError = '';
|
|
|
};
|
|
|
|
|
|
// 发送验证码
|
|
|
sendVerifyCode = async (type) => {
|
|
|
if (smsLoading) return;
|
|
|
const phone = type === 'signup' ? signUpForm.phone : signInForm.phone;
|
|
|
const region = type === 'signup' ? signUpForm.region : signInForm.region;
|
|
|
|
|
|
if (!phone) {
|
|
|
const errorMsg = '请输入手机号';
|
|
|
type === 'signup' ? signUpError = errorMsg : signInError = errorMsg;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!validatePhone(phone, region)) {
|
|
|
const errorMsg = '请输入正确的手机号格式';
|
|
|
type === 'signup' ? signUpError = errorMsg : signInError = errorMsg;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
smsLoading = true;
|
|
|
try {
|
|
|
type === 'signup' ? signUpError = '' : signInError = '';
|
|
|
await $axios.post('/api/sms', {phone, region, purpose: type});
|
|
|
$message.success('验证码已发送');
|
|
|
smsCountdown = 60;
|
|
|
const timer = setInterval(() => {
|
|
|
smsCountdown--;
|
|
|
if (smsCountdown <= 0) clearInterval(timer);
|
|
|
}, 1000);
|
|
|
} catch (error) {
|
|
|
const errorMsg = error.message || '发送验证码失败,请重试';
|
|
|
type === 'signup' ? signUpError = errorMsg : signInError = errorMsg;
|
|
|
$message.warning(errorMsg);
|
|
|
} finally {
|
|
|
smsLoading = false;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 处理第三方登录
|
|
|
handleSocialLogin = (provider) => {
|
|
|
$message.warning(`未开放 ${provider} 登录`);
|
|
|
};
|
|
|
|
|
|
// 处理注册表单提交
|
|
|
handleSignUp = async () => {
|
|
|
if (signUpLoading) return;
|
|
|
signUpError = '';
|
|
|
|
|
|
if (signUpForm.username.length < 5) {
|
|
|
signUpError = '用户名必须大于5位。';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if ($G.cfg.sms) {
|
|
|
if (!validatePhone(signUpForm.phone, signUpForm.region)) {
|
|
|
signUpError = '请输入正确的手机号格式。';
|
|
|
return;
|
|
|
}
|
|
|
if (!signUpForm.verifyCode) {
|
|
|
signUpError = '请输入验证码。';
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!validatePassword(signUpForm.password)) {
|
|
|
signUpError = '密码必须大于8位,且包含大小写字母、下划线和数字。';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
signUpLoading = true;
|
|
|
try {
|
|
|
await $axios.post('/api/user', {
|
|
|
username: signUpForm.username,
|
|
|
phone: signUpForm.phone,
|
|
|
region: signUpForm.region,
|
|
|
verify_code: signUpForm.verifyCode,
|
|
|
code: btoa(signUpForm.password),
|
|
|
}, {noretry: true});
|
|
|
|
|
|
$message.success('注册成功!');
|
|
|
signUpForm = {username: '', phone: '', verifyCode: '', password: '', region: '+86'};
|
|
|
switchToSignIn();
|
|
|
} catch (error) {
|
|
|
signUpError = error.message || '注册失败,请重试。';
|
|
|
$message.warning(signUpError);
|
|
|
} finally {
|
|
|
signUpLoading = false;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 处理登录表单提交
|
|
|
handleSignIn = async () => {
|
|
|
if (signInLoading) return;
|
|
|
signInError = '';
|
|
|
|
|
|
try {
|
|
|
let loginData = {};
|
|
|
if (loginType === 'username') {
|
|
|
if (!signInForm.username) {signInError = '请输入用户名'; return;}
|
|
|
if (!signInForm.password) {signInError = '请输入密码'; return;}
|
|
|
loginData = {username: signInForm.username, code: btoa(signInForm.password), type: 'username'};
|
|
|
} else {
|
|
|
if (!signInForm.phone) {signInError = '请输入手机号'; return;}
|
|
|
if (!signInForm.verifyCode) {signInError = '请输入验证码'; return;}
|
|
|
loginData = {phone: signInForm.phone, region: signInForm.region, verify_code: signInForm.verifyCode, type: 'phone'};
|
|
|
}
|
|
|
|
|
|
signInLoading = true;
|
|
|
await $axios.post('/api/token', loginData, {noretry: true});
|
|
|
$message.success('登录成功!');
|
|
|
$router.push(redirect);
|
|
|
} catch (error) {
|
|
|
signInError = error.message || '登录失败,请重试';
|
|
|
$message.warning(signInError);
|
|
|
} finally {
|
|
|
signInLoading = false;
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
</body>
|
|
|
|
|
|
</html>
|