xianyu-auto-reply/static/register.html
2025-07-25 17:24:29 +08:00

570 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>
<link rel="stylesheet" href="/static/lib/bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="/static/lib/bootstrap-icons/bootstrap-icons.css">
<style>
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 10px;
}
.register-container {
background: white;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
overflow: hidden;
max-width: 420px;
width: 100%;
max-height: 95vh;
overflow-y: auto;
}
.register-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1.2rem;
text-align: center;
}
.register-header h2 {
margin-bottom: 0.3rem;
font-size: 1.4rem;
}
.register-header p {
margin-bottom: 0;
font-size: 0.85rem;
}
.register-body {
padding: 1.2rem;
}
.form-control {
border-radius: 8px;
border: 1px solid #e9ecef;
padding: 8px 12px;
transition: all 0.3s ease;
font-size: 0.9rem;
}
.form-control:focus {
border-color: #667eea;
box-shadow: 0 0 0 0.15rem rgba(102, 126, 234, 0.2);
}
.btn-register {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 8px;
padding: 10px;
font-weight: 600;
transition: all 0.3s ease;
font-size: 0.9rem;
}
.btn-register:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.btn-code {
border-radius: 8px;
border: 1px solid #667eea;
color: #667eea;
font-weight: 600;
transition: all 0.3s ease;
padding: 8px 12px;
font-size: 0.85rem;
}
.btn-code:hover {
background: #667eea;
color: white;
}
.btn-code:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.login-link {
text-align: center;
margin-top: 0.8rem;
}
.login-link a {
color: #667eea;
text-decoration: none;
font-weight: 600;
font-size: 0.9rem;
}
.login-link a:hover {
text-decoration: underline;
}
.alert {
border-radius: 8px;
border: none;
padding: 0.6rem 1rem;
font-size: 0.85rem;
}
.input-group {
margin-bottom: 0.8rem;
}
.countdown {
color: #6c757d;
font-size: 0.8rem;
}
.mb-3 {
margin-bottom: 0.8rem !important;
}
.form-label {
margin-bottom: 0.3rem;
font-weight: 600;
font-size: 0.85rem;
color: #495057;
}
.form-text {
margin-top: 0.2rem;
font-size: 0.75rem;
}
.captcha-container img {
height: 32px !important;
}
/* 响应式优化 */
@media (max-height: 700px) {
.register-header {
padding: 1rem;
}
.register-header h2 {
font-size: 1.2rem;
margin-bottom: 0.2rem;
}
.register-header p {
font-size: 0.8rem;
}
.register-body {
padding: 1rem;
}
.mb-3 {
margin-bottom: 0.6rem !important;
}
.form-control {
padding: 6px 10px;
}
.btn-code {
padding: 6px 10px;
font-size: 0.8rem;
}
}
@media (max-width: 480px) {
.register-container {
margin: 5px;
max-width: none;
}
.row.g-2 > * {
padding-left: 0.25rem;
padding-right: 0.25rem;
}
}
</style>
</head>
<body>
<div class="register-container">
<div class="register-header">
<h2 class="mb-0">
<i class="bi bi-person-plus-fill me-2"></i>
用户注册
</h2>
<p class="mb-0 mt-2 opacity-75">创建您的闲鱼自动回复账号</p>
</div>
<div class="register-body">
<div id="alertContainer"></div>
<form id="registerForm">
<div class="mb-3">
<label for="username" class="form-label">
<i class="bi bi-person me-1"></i>用户名
</label>
<input type="text" class="form-control" id="username" name="username"
placeholder="3-20个字符支持字母、数字、下划线" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">
<i class="bi bi-envelope me-1"></i>邮箱地址
</label>
<input type="email" class="form-control" id="email" name="email"
placeholder="用于接收验证码和重要通知" required>
</div>
<div class="mb-3">
<label for="captchaCode" class="form-label">
<i class="bi bi-shield-lock me-1"></i>图形验证码
</label>
<div class="row g-2">
<div class="col-7">
<input type="text" class="form-control" id="captchaCode" name="captchaCode"
placeholder="输入4位验证码" maxlength="4" required>
</div>
<div class="col-5">
<div class="captcha-container" style="position: relative;">
<img id="captchaImage" src="" alt="图形验证码"
style="width: 100%; height: 32px; border: 1px solid #ddd; border-radius: 5px; cursor: pointer;"
onclick="refreshCaptcha()">
<div id="captchaLoading" class="text-center" style="display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">
<div class="spinner-border spinner-border-sm" role="status"></div>
</div>
</div>
</div>
</div>
<div class="form-text">
<span id="captchaStatus">请输入图形验证码,点击图片可刷新</span>
</div>
</div>
<div class="mb-3">
<label for="verificationCode" class="form-label">
<i class="bi bi-shield-check me-1"></i>邮箱验证码
</label>
<div class="input-group">
<input type="text" class="form-control" id="verificationCode" name="verificationCode"
placeholder="输入6位验证码" maxlength="6" required>
<button type="button" class="btn btn-code" id="sendCodeBtn" onclick="sendVerificationCode()" disabled>
发送验证码
</button>
</div>
<div class="form-text">
<span id="codeStatus">请先验证图形验证码</span>
</div>
</div>
<div class="mb-3">
<label for="password" class="form-label">
<i class="bi bi-lock me-1"></i>设置密码
</label>
<input type="password" class="form-control" id="password" name="password"
placeholder="至少6个字符" required>
</div>
<div class="mb-3">
<label for="confirmPassword" class="form-label">
<i class="bi bi-lock-fill me-1"></i>确认密码
</label>
<input type="password" class="form-control" id="confirmPassword" name="confirmPassword"
placeholder="再次输入密码" required>
</div>
<button type="submit" class="btn btn-register btn-primary w-100 mt-2">
<i class="bi bi-person-plus me-1"></i>立即注册
</button>
</form>
<div class="login-link">
<span class="text-muted">已有账号?</span>
<a href="/login.html">立即登录</a>
</div>
</div>
</div>
<script src="/static/lib/bootstrap/bootstrap.bundle.min.js"></script>
<script>
let countdownTimer = null;
let countdownSeconds = 0;
let sessionId = generateSessionId();
let captchaVerified = false;
function generateSessionId() {
return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
}
function showAlert(message, type = 'danger') {
const alertContainer = document.getElementById('alertContainer');
const alertHtml = `
<div class="alert alert-${type} alert-dismissible fade show" role="alert">
<i class="bi bi-${type === 'success' ? 'check-circle' : 'exclamation-triangle'}-fill me-2"></i>
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
`;
alertContainer.innerHTML = alertHtml;
}
function validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
async function loadCaptcha() {
const captchaImage = document.getElementById('captchaImage');
const captchaLoading = document.getElementById('captchaLoading');
const captchaStatus = document.getElementById('captchaStatus');
try {
captchaLoading.style.display = 'block';
captchaImage.style.display = 'none';
const response = await fetch('/generate-captcha', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ session_id: sessionId })
});
const result = await response.json();
if (result.success) {
captchaImage.src = result.captcha_image;
captchaStatus.textContent = '请输入图形验证码,点击图片可刷新';
captchaVerified = false;
updateSendCodeButton();
} else {
captchaStatus.textContent = '图形验证码加载失败,请刷新页面重试';
}
} catch (error) {
console.error('加载图形验证码失败:', error);
captchaStatus.textContent = '图形验证码加载失败,请检查网络连接';
} finally {
captchaLoading.style.display = 'none';
captchaImage.style.display = 'block';
}
}
function refreshCaptcha() {
sessionId = generateSessionId(); // 生成新的session ID
loadCaptcha();
document.getElementById('captchaCode').value = ''; // 清空输入
}
async function verifyCaptcha() {
const captchaCode = document.getElementById('captchaCode').value.trim();
const captchaStatus = document.getElementById('captchaStatus');
if (!captchaCode) {
captchaStatus.textContent = '请输入图形验证码';
captchaVerified = false;
updateSendCodeButton();
return;
}
try {
const response = await fetch('/verify-captcha', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
session_id: sessionId,
captcha_code: captchaCode
})
});
const result = await response.json();
if (result.success) {
captchaStatus.innerHTML = '<span style="color: green;">✓ 图形验证码验证成功</span>';
captchaVerified = true;
} else {
captchaStatus.innerHTML = '<span style="color: red;">✗ 图形验证码错误,请重新输入</span>';
captchaVerified = false;
refreshCaptcha(); // 自动刷新验证码
}
updateSendCodeButton();
} catch (error) {
console.error('验证图形验证码失败:', error);
captchaStatus.innerHTML = '<span style="color: red;">验证失败,请检查网络连接</span>';
captchaVerified = false;
updateSendCodeButton();
}
}
function updateSendCodeButton() {
const sendCodeBtn = document.getElementById('sendCodeBtn');
const email = document.getElementById('email').value.trim();
const codeStatus = document.getElementById('codeStatus');
if (captchaVerified && email && validateEmail(email)) {
sendCodeBtn.disabled = false;
codeStatus.textContent = '图形验证码已验证,可以发送邮箱验证码';
} else {
sendCodeBtn.disabled = true;
if (!captchaVerified) {
codeStatus.textContent = '请先验证图形验证码';
} else if (!email) {
codeStatus.textContent = '请先输入邮箱地址';
} else if (!validateEmail(email)) {
codeStatus.textContent = '请输入有效的邮箱地址';
}
}
}
function startCountdown() {
countdownSeconds = 60;
const sendCodeBtn = document.getElementById('sendCodeBtn');
const codeStatus = document.getElementById('codeStatus');
sendCodeBtn.disabled = true;
countdownTimer = setInterval(() => {
countdownSeconds--;
sendCodeBtn.textContent = `重新发送 (${countdownSeconds}s)`;
codeStatus.innerHTML = `<span class="countdown">验证码已发送,${countdownSeconds}秒后可重新发送</span>`;
if (countdownSeconds <= 0) {
clearInterval(countdownTimer);
sendCodeBtn.disabled = false;
sendCodeBtn.textContent = '发送验证码';
codeStatus.textContent = '可以重新发送验证码';
}
}, 1000);
}
async function sendVerificationCode() {
const email = document.getElementById('email').value.trim();
if (!captchaVerified) {
showAlert('请先验证图形验证码');
return;
}
if (!email) {
showAlert('请先输入邮箱地址');
return;
}
if (!validateEmail(email)) {
showAlert('请输入有效的邮箱地址');
return;
}
try {
const response = await fetch('/send-verification-code', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
session_id: sessionId
})
});
const result = await response.json();
if (result.success) {
showAlert(result.message, 'success');
startCountdown();
} else {
showAlert(result.message);
}
} catch (error) {
console.error('发送验证码失败:', error);
showAlert('发送验证码失败,请检查网络连接');
}
}
document.getElementById('registerForm').addEventListener('submit', async function(e) {
e.preventDefault();
const formData = new FormData(this);
const username = formData.get('username').trim();
const email = formData.get('email').trim();
const captchaCode = formData.get('captchaCode').trim();
const verificationCode = formData.get('verificationCode').trim();
const password = formData.get('password');
const confirmPassword = formData.get('confirmPassword');
// 前端验证
if (!captchaVerified) {
showAlert('请先验证图形验证码');
return;
}
if (username.length < 3 || username.length > 20) {
showAlert('用户名长度必须在3-20个字符之间');
return;
}
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
showAlert('用户名只能包含字母、数字和下划线');
return;
}
if (!validateEmail(email)) {
showAlert('请输入有效的邮箱地址');
return;
}
if (verificationCode.length !== 6) {
showAlert('请输入6位验证码');
return;
}
if (password.length < 6) {
showAlert('密码长度至少6个字符');
return;
}
if (password !== confirmPassword) {
showAlert('两次输入的密码不一致');
return;
}
try {
const response = await fetch('/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
email: email,
verification_code: verificationCode,
password: password
})
});
const result = await response.json();
if (result.success) {
showAlert(result.message, 'success');
setTimeout(() => {
window.location.href = '/login.html';
}, 2000);
} else {
showAlert(result.message);
}
} catch (error) {
console.error('注册失败:', error);
showAlert('注册失败,请检查网络连接');
}
});
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
loadCaptcha();
});
// 图形验证码输入框事件
document.getElementById('captchaCode').addEventListener('input', function() {
if (this.value.length === 4) {
verifyCaptcha();
} else {
captchaVerified = false;
updateSendCodeButton();
document.getElementById('captchaStatus').textContent = '请输入4位图形验证码';
}
});
// 邮箱输入框事件
document.getElementById('email').addEventListener('input', function() {
updateSendCodeButton();
});
document.getElementById('email').addEventListener('blur', function() {
const email = this.value.trim();
updateSendCodeButton();
});
</script>
</body>
</html>