763 lines
21 KiB
HTML
763 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>邀请注册</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
min-height: 100vh;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20px;
|
||
}
|
||
|
||
.register-container {
|
||
background: #ffffff;
|
||
border-radius: 20px;
|
||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||
padding: 40px 50px;
|
||
width: 100%;
|
||
max-width: 600px;
|
||
max-height: 95vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.register-header {
|
||
text-align: center;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.register-header h1 {
|
||
color: #333;
|
||
font-size: 24px;
|
||
font-weight: 600;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.register-header p {
|
||
color: #666;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.invite-code-badge {
|
||
display: inline-block;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 8px 16px;
|
||
border-radius: 20px;
|
||
font-size: 13px;
|
||
margin-bottom: 20px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.invite-code-badge.hidden {
|
||
display: none;
|
||
}
|
||
|
||
.form-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.form-label {
|
||
display: inline-block;
|
||
color: #333;
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
margin-bottom: 0;
|
||
margin-right: 15px;
|
||
min-width: 100px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.form-input {
|
||
flex: 1;
|
||
padding: 12px 16px;
|
||
border: 2px solid #e0e0e0;
|
||
border-radius: 10px;
|
||
font-size: 15px;
|
||
background: #fafafa;
|
||
}
|
||
|
||
.form-input:focus {
|
||
outline: none;
|
||
border-color: #667eea;
|
||
background: #fff;
|
||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||
}
|
||
|
||
.form-input.error {
|
||
border-color: #ff4757;
|
||
background: #fff5f5;
|
||
}
|
||
|
||
.sms-code-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
flex: 1;
|
||
}
|
||
|
||
.form-group .sms-code-wrapper .form-input {
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.send-code-btn {
|
||
padding: 12px 20px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 10px;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
min-width: 120px;
|
||
}
|
||
|
||
.send-code-btn:disabled {
|
||
opacity: 0.6;
|
||
cursor: not-allowed;
|
||
transform: none;
|
||
}
|
||
|
||
.error-message {
|
||
color: #ff4757;
|
||
font-size: 13px;
|
||
margin-top: 6px;
|
||
margin-left: 0;
|
||
width: 100%;
|
||
flex-basis: 100%;
|
||
display: none;
|
||
padding-left: 115px;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.error-message.show {
|
||
display: block;
|
||
}
|
||
|
||
.submit-btn {
|
||
width: 100%;
|
||
padding: 14px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 10px;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
margin-top: 10px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.submit-btn:disabled {
|
||
opacity: 0.6;
|
||
cursor: not-allowed;
|
||
transform: none;
|
||
}
|
||
|
||
.submit-btn.loading {
|
||
color: transparent;
|
||
}
|
||
|
||
.submit-btn.loading::after {
|
||
content: '';
|
||
position: absolute;
|
||
width: 20px;
|
||
height: 20px;
|
||
top: 50%;
|
||
left: 50%;
|
||
margin-left: -10px;
|
||
margin-top: -10px;
|
||
border: 3px solid rgba(255, 255, 255, 0.3);
|
||
border-top-color: white;
|
||
border-radius: 50%;
|
||
animation: spin 0.8s linear infinite;
|
||
}
|
||
|
||
@keyframes spin {
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
|
||
.success-message {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
padding: 15px;
|
||
border-radius: 10px;
|
||
margin-bottom: 20px;
|
||
display: none;
|
||
text-align: center;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.success-message.show {
|
||
display: block;
|
||
}
|
||
|
||
.error-alert {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
padding: 15px;
|
||
border-radius: 10px;
|
||
margin-bottom: 20px;
|
||
display: none;
|
||
text-align: center;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.error-alert.show {
|
||
display: block;
|
||
}
|
||
|
||
.register-tips {
|
||
margin-top: 15px;
|
||
padding: 12px 15px;
|
||
background: #f8f9fa;
|
||
border-radius: 10px;
|
||
border-left: 4px solid #667eea;
|
||
}
|
||
|
||
.register-tips h3 {
|
||
color: #333;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.register-tips ul {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
|
||
.register-tips li {
|
||
color: #666;
|
||
font-size: 12px;
|
||
line-height: 1.6;
|
||
padding-left: 18px;
|
||
position: relative;
|
||
margin-bottom: 3px;
|
||
}
|
||
|
||
.register-tips li::before {
|
||
content: '✓';
|
||
position: absolute;
|
||
left: 0;
|
||
color: #667eea;
|
||
font-weight: bold;
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.register-container {
|
||
padding: 30px 20px;
|
||
}
|
||
|
||
.register-header h1 {
|
||
font-size: 24px;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="register-container">
|
||
<div class="register-header">
|
||
<h1>🎉 邀请注册</h1>
|
||
<p>填写信息完成注册,邀请人将获得奖励</p>
|
||
<div id="inviteCodeBadge" class="invite-code-badge hidden"></div>
|
||
</div>
|
||
|
||
<div id="successMessage" class="success-message"></div>
|
||
<div id="errorAlert" class="error-alert"></div>
|
||
|
||
<form id="registerForm">
|
||
<div class="form-group">
|
||
<label class="form-label" for="email">邮箱地址</label>
|
||
<input
|
||
type="email"
|
||
id="email"
|
||
class="form-input"
|
||
placeholder="请输入您的邮箱地址"
|
||
required
|
||
autocomplete="email"
|
||
/>
|
||
<div class="error-message" id="emailError"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="emailCode">验证码</label>
|
||
<div class="sms-code-wrapper">
|
||
<input
|
||
type="text"
|
||
id="emailCode"
|
||
class="form-input"
|
||
placeholder="请输入邮箱验证码"
|
||
required
|
||
maxlength="6"
|
||
style="flex: 1; margin-right: 10px;"
|
||
/>
|
||
<button
|
||
type="button"
|
||
id="sendCodeBtn"
|
||
class="send-code-btn"
|
||
>
|
||
发送验证码
|
||
</button>
|
||
</div>
|
||
<div class="error-message" id="emailCodeError"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="password">密码</label>
|
||
<input
|
||
type="password"
|
||
id="password"
|
||
class="form-input"
|
||
placeholder="请输入密码(至少6位)"
|
||
required
|
||
autocomplete="new-password"
|
||
minlength="6"
|
||
/>
|
||
<div class="error-message" id="passwordError"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="confirmPassword">确认密码</label>
|
||
<input
|
||
type="password"
|
||
id="confirmPassword"
|
||
class="form-input"
|
||
placeholder="请再次输入密码"
|
||
required
|
||
autocomplete="new-password"
|
||
minlength="6"
|
||
/>
|
||
<div class="error-message" id="confirmPasswordError"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="inviteCode">邀请码(选填)</label>
|
||
<input
|
||
type="text"
|
||
id="inviteCode"
|
||
class="form-input"
|
||
placeholder="请输入邀请码(可选)"
|
||
/>
|
||
<div class="error-message" id="inviteCodeError"></div>
|
||
</div>
|
||
|
||
<button type="submit" class="submit-btn" id="submitBtn">
|
||
立即注册
|
||
</button>
|
||
</form>
|
||
|
||
<div class="register-tips">
|
||
<h3>注册说明</h3>
|
||
<ul>
|
||
<li>邮箱将作为您的登录账号</li>
|
||
<li>密码长度至少6位,建议使用字母+数字组合</li>
|
||
<li>邮箱验证码有效期为5分钟</li>
|
||
<li>邀请码为选填,填写邀请码注册成功后,邀请人将获得3天试用期奖励</li>
|
||
<li>请妥善保管您的账号信息</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// 配置 API 地址(根据环境自动判断)
|
||
const API_BASE_URL = window.location.hostname === 'localhost'
|
||
? 'http://localhost:9097/admin_api'
|
||
: 'https://work.light120.com/admin_api';
|
||
|
||
// 获取 URL 参数中的邀请码
|
||
function getInviteCodeFromUrl() {
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
return urlParams.get('code') || '';
|
||
}
|
||
|
||
// 倒计时状态
|
||
let countdownTimer = null;
|
||
let countdownSeconds = 0;
|
||
|
||
// 显示/隐藏消息
|
||
function showMessage(elementId, message, isError = false) {
|
||
const element = document.getElementById(elementId);
|
||
element.textContent = message;
|
||
element.className = isError ? 'error-alert show' : 'success-message show';
|
||
|
||
// 3秒后自动隐藏
|
||
setTimeout(() => {
|
||
element.className = isError ? 'error-alert' : 'success-message';
|
||
}, 3000);
|
||
}
|
||
|
||
// 显示邀请码徽章
|
||
function displayInviteCodeBadge(code) {
|
||
if (code) {
|
||
const badge = document.getElementById('inviteCodeBadge');
|
||
badge.textContent = `邀请码: ${code}`;
|
||
badge.classList.remove('hidden');
|
||
}
|
||
}
|
||
|
||
// 自动填充邀请码
|
||
function autoFillInviteCode(code) {
|
||
if (code) {
|
||
const inviteCodeInput = document.getElementById('inviteCode');
|
||
inviteCodeInput.value = code;
|
||
}
|
||
}
|
||
|
||
// 发送邮箱验证码
|
||
async function sendEmailCode(email) {
|
||
try {
|
||
const response = await fetch(`${API_BASE_URL}/invite/send-email-code`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
email: email
|
||
})
|
||
});
|
||
|
||
const data = await response.json();
|
||
return data;
|
||
} catch (error) {
|
||
console.error('发送验证码失败:', error);
|
||
throw new Error('网络请求失败,请检查网络连接');
|
||
}
|
||
}
|
||
|
||
// 开始倒计时
|
||
function startCountdown(seconds = 60) {
|
||
const sendBtn = document.getElementById('sendCodeBtn');
|
||
countdownSeconds = seconds;
|
||
sendBtn.disabled = true;
|
||
|
||
const updateCountdown = () => {
|
||
if (countdownSeconds > 0) {
|
||
sendBtn.textContent = `${countdownSeconds}秒后重新发送`;
|
||
countdownSeconds--;
|
||
countdownTimer = setTimeout(updateCountdown, 1000);
|
||
} else {
|
||
sendBtn.disabled = false;
|
||
sendBtn.textContent = '发送验证码';
|
||
if (countdownTimer) {
|
||
clearTimeout(countdownTimer);
|
||
countdownTimer = null;
|
||
}
|
||
}
|
||
};
|
||
|
||
updateCountdown();
|
||
}
|
||
|
||
// 验证邮箱格式
|
||
function validateEmail(email) {
|
||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||
return emailRegex.test(email);
|
||
}
|
||
|
||
// 显示字段错误
|
||
function showFieldError(fieldId, message) {
|
||
const input = document.getElementById(fieldId);
|
||
const errorDiv = document.getElementById(fieldId + 'Error');
|
||
|
||
input.classList.add('error');
|
||
errorDiv.textContent = message;
|
||
errorDiv.classList.add('show');
|
||
}
|
||
|
||
// 清除字段错误
|
||
function clearFieldError(fieldId) {
|
||
const input = document.getElementById(fieldId);
|
||
const errorDiv = document.getElementById(fieldId + 'Error');
|
||
|
||
input.classList.remove('error');
|
||
errorDiv.classList.remove('show');
|
||
}
|
||
|
||
// 验证表单
|
||
function validateForm() {
|
||
const inviteCode = document.getElementById('inviteCode').value.trim();
|
||
const email = document.getElementById('email').value.trim();
|
||
const emailCode = document.getElementById('emailCode').value.trim();
|
||
const password = document.getElementById('password').value;
|
||
const confirmPassword = document.getElementById('confirmPassword').value;
|
||
|
||
let isValid = true;
|
||
|
||
// 邀请码为选填,无需验证
|
||
|
||
// 验证邮箱
|
||
if (!email) {
|
||
showFieldError('email', '请输入邮箱地址');
|
||
isValid = false;
|
||
} else if (!validateEmail(email)) {
|
||
showFieldError('email', '邮箱格式不正确');
|
||
isValid = false;
|
||
} else {
|
||
clearFieldError('email');
|
||
}
|
||
|
||
// 验证邮箱验证码
|
||
if (!emailCode) {
|
||
showFieldError('emailCode', '请输入邮箱验证码');
|
||
isValid = false;
|
||
} else if (!/^\d{6}$/.test(emailCode)) {
|
||
showFieldError('emailCode', '验证码为6位数字');
|
||
isValid = false;
|
||
} else {
|
||
clearFieldError('emailCode');
|
||
}
|
||
|
||
// 验证密码
|
||
if (!password) {
|
||
showFieldError('password', '请输入密码');
|
||
isValid = false;
|
||
} else if (password.length < 6) {
|
||
showFieldError('password', '密码长度不能少于6位');
|
||
isValid = false;
|
||
} else {
|
||
clearFieldError('password');
|
||
}
|
||
|
||
// 验证确认密码
|
||
if (!confirmPassword) {
|
||
showFieldError('confirmPassword', '请再次输入密码');
|
||
isValid = false;
|
||
} else if (password !== confirmPassword) {
|
||
showFieldError('confirmPassword', '两次输入的密码不一致');
|
||
isValid = false;
|
||
} else {
|
||
clearFieldError('confirmPassword');
|
||
}
|
||
|
||
return isValid;
|
||
}
|
||
|
||
// 注册请求
|
||
async function register(email, emailCode, password, inviteCode) {
|
||
try {
|
||
const requestBody = {
|
||
email: email,
|
||
email_code: emailCode,
|
||
password: password
|
||
};
|
||
|
||
// 如果邀请码不为空,则添加到请求中
|
||
if (inviteCode) {
|
||
requestBody.invite_code = inviteCode;
|
||
}
|
||
|
||
const response = await fetch(`${API_BASE_URL}/invite/register`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify(requestBody)
|
||
});
|
||
|
||
const data = await response.json();
|
||
return data;
|
||
} catch (error) {
|
||
console.error('注册请求失败:', error);
|
||
throw new Error('网络请求失败,请检查网络连接');
|
||
}
|
||
}
|
||
|
||
// 处理表单提交
|
||
async function handleSubmit(e) {
|
||
e.preventDefault();
|
||
|
||
// 清除之前的错误信息
|
||
document.getElementById('errorAlert').classList.remove('show');
|
||
document.getElementById('successMessage').classList.remove('show');
|
||
|
||
// 验证表单
|
||
if (!validateForm()) {
|
||
return;
|
||
}
|
||
|
||
const inviteCode = document.getElementById('inviteCode').value.trim();
|
||
const email = document.getElementById('email').value.trim();
|
||
const emailCode = document.getElementById('emailCode').value.trim();
|
||
const password = document.getElementById('password').value;
|
||
|
||
// 邀请码为选填,可以为空
|
||
|
||
// 禁用提交按钮
|
||
const submitBtn = document.getElementById('submitBtn');
|
||
submitBtn.disabled = true;
|
||
submitBtn.classList.add('loading');
|
||
|
||
try {
|
||
const result = await register(email, emailCode, password, inviteCode);
|
||
|
||
if (result.code === 0 || result.success) {
|
||
showMessage('successMessage', '注册成功!请使用邮箱和密码登录系统。');
|
||
|
||
// 清空表单
|
||
document.getElementById('registerForm').reset();
|
||
|
||
// 3秒后可以提示跳转(如果需要)
|
||
setTimeout(() => {
|
||
// 可以在这里添加跳转到登录页的逻辑
|
||
// window.location.href = '/login.html';
|
||
}, 3000);
|
||
} else {
|
||
showMessage('errorAlert', result.message || '注册失败,请重试', true);
|
||
}
|
||
} catch (error) {
|
||
showMessage('errorAlert', error.message || '注册失败,请稍后重试', true);
|
||
} finally {
|
||
submitBtn.disabled = false;
|
||
submitBtn.classList.remove('loading');
|
||
}
|
||
}
|
||
|
||
// 初始化
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const inviteCodeFromUrl = getInviteCodeFromUrl();
|
||
|
||
// 自动填充邀请码
|
||
autoFillInviteCode(inviteCodeFromUrl);
|
||
|
||
// 显示邀请码徽章
|
||
if (inviteCodeFromUrl) {
|
||
displayInviteCodeBadge(inviteCodeFromUrl);
|
||
}
|
||
|
||
// 绑定表单提交事件
|
||
document.getElementById('registerForm').addEventListener('submit', handleSubmit);
|
||
|
||
// 发送验证码按钮事件
|
||
document.getElementById('sendCodeBtn').addEventListener('click', async function() {
|
||
const email = document.getElementById('email').value.trim();
|
||
|
||
// 验证邮箱
|
||
if (!email) {
|
||
showFieldError('email', '请先输入邮箱地址');
|
||
return;
|
||
}
|
||
|
||
if (!validateEmail(email)) {
|
||
showFieldError('email', '邮箱格式不正确');
|
||
return;
|
||
}
|
||
|
||
clearFieldError('email');
|
||
|
||
// 禁用按钮
|
||
const sendBtn = document.getElementById('sendCodeBtn');
|
||
sendBtn.disabled = true;
|
||
sendBtn.textContent = '发送中...';
|
||
|
||
try {
|
||
const result = await sendEmailCode(email);
|
||
|
||
if (result.code === 0 || result.success) {
|
||
showMessage('successMessage', '验证码已发送到您的邮箱,请查收');
|
||
startCountdown(60);
|
||
} else {
|
||
showMessage('errorAlert', result.message || '发送验证码失败,请重试', true);
|
||
sendBtn.disabled = false;
|
||
sendBtn.textContent = '发送验证码';
|
||
}
|
||
} catch (error) {
|
||
showMessage('errorAlert', error.message || '发送验证码失败,请稍后重试', true);
|
||
sendBtn.disabled = false;
|
||
sendBtn.textContent = '发送验证码';
|
||
}
|
||
});
|
||
|
||
// 实时验证
|
||
document.getElementById('email').addEventListener('blur', function() {
|
||
const email = this.value.trim();
|
||
if (email && !validateEmail(email)) {
|
||
showFieldError('email', '邮箱格式不正确');
|
||
} else {
|
||
clearFieldError('email');
|
||
}
|
||
});
|
||
|
||
document.getElementById('password').addEventListener('blur', function() {
|
||
const password = this.value;
|
||
if (password && password.length < 6) {
|
||
showFieldError('password', '密码长度不能少于6位');
|
||
} else {
|
||
clearFieldError('password');
|
||
}
|
||
});
|
||
|
||
document.getElementById('confirmPassword').addEventListener('blur', function() {
|
||
const password = document.getElementById('password').value;
|
||
const confirmPassword = this.value;
|
||
if (confirmPassword && password !== confirmPassword) {
|
||
showFieldError('confirmPassword', '两次输入的密码不一致');
|
||
} else {
|
||
clearFieldError('confirmPassword');
|
||
}
|
||
});
|
||
|
||
// 输入时清除错误
|
||
document.getElementById('email').addEventListener('input', function() {
|
||
if (!this.classList.contains('error')) return;
|
||
const email = this.value.trim();
|
||
if (email && validateEmail(email)) {
|
||
clearFieldError('email');
|
||
}
|
||
});
|
||
|
||
document.getElementById('password').addEventListener('input', function() {
|
||
if (!this.classList.contains('error')) return;
|
||
const password = this.value;
|
||
if (password && password.length >= 6) {
|
||
clearFieldError('password');
|
||
}
|
||
|
||
// 如果确认密码已输入,重新验证
|
||
const confirmPassword = document.getElementById('confirmPassword').value;
|
||
if (confirmPassword) {
|
||
if (password === confirmPassword) {
|
||
clearFieldError('confirmPassword');
|
||
} else {
|
||
showFieldError('confirmPassword', '两次输入的密码不一致');
|
||
}
|
||
}
|
||
});
|
||
|
||
document.getElementById('confirmPassword').addEventListener('input', function() {
|
||
if (!this.classList.contains('error')) return;
|
||
const password = document.getElementById('password').value;
|
||
const confirmPassword = this.value;
|
||
if (confirmPassword && password === confirmPassword) {
|
||
clearFieldError('confirmPassword');
|
||
}
|
||
});
|
||
|
||
document.getElementById('emailCode').addEventListener('input', function() {
|
||
if (!this.classList.contains('error')) return;
|
||
const emailCode = this.value.trim();
|
||
if (emailCode && /^\d{6}$/.test(emailCode)) {
|
||
clearFieldError('emailCode');
|
||
}
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|