Files
autoAiWorkSys/admin/public/register.html
张成 cfbcbc39fd 11
2025-12-19 15:54:52 +08:00

763 lines
21 KiB
HTML
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.
<!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>