Files
pdnode-account/public/index.html
2025-07-29 15:36:25 -07:00

245 lines
11 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>OAuth认证系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.auth-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 15px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
.btn-primary {
background: linear-gradient(45deg, #667eea, #764ba2);
border: none;
}
.btn-primary:hover {
background: linear-gradient(45deg, #5a6fd8, #6a4190);
}
</style>
</head>
<body>
<div class="container">
<div class="row justify-content-center align-items-center min-vh-100">
<div class="col-md-6 col-lg-4">
<div class="auth-card p-4">
<div class="text-center mb-4">
<i class="fas fa-user-circle fa-3x text-primary mb-3"></i>
<h2 id="page-title">登录</h2>
<p class="text-muted" id="page-subtitle">欢迎回来,请登录您的账户</p>
</div>
<div id="alert-container"></div>
<form id="auth-form">
<div class="mb-3" id="username-field">
<label for="username" class="form-label">用户名</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3" id="email-field" style="display: none;">
<label for="email" class="form-label">邮箱</label>
<input type="email" class="form-control" id="email" name="email">
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<div class="input-group">
<input type="password" class="form-control" id="password" name="password" required>
<button class="btn btn-outline-secondary" type="button" id="toggle-password">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="mb-3" id="confirm-password-field" style="display: none;">
<label for="confirm-password" class="form-label">确认密码</label>
<div class="input-group">
<input type="password" class="form-control" id="confirm-password" name="confirm-password">
<button class="btn btn-outline-secondary" type="button" id="toggle-confirm-password">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<button type="submit" class="btn btn-primary w-100 mb-3" id="submit-btn">
<span id="submit-text">登录</span>
<span id="loading-spinner" style="display: none;">
<i class="fas fa-spinner fa-spin"></i>
</span>
</button>
<div class="text-center">
<p class="mb-0">
<span id="switch-text">还没有账户?</span>
<a href="#" id="switch-link">立即注册</a>
</p>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
const API_BASE = 'http://localhost:3000/api';
let isLoginMode = true;
// 切换密码可见性
document.getElementById('toggle-password').addEventListener('click', function() {
const passwordInput = document.getElementById('password');
const icon = this.querySelector('i');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
icon.className = 'fas fa-eye-slash';
} else {
passwordInput.type = 'password';
icon.className = 'fas fa-eye';
}
});
document.getElementById('toggle-confirm-password').addEventListener('click', function() {
const confirmPasswordInput = document.getElementById('confirm-password');
const icon = this.querySelector('i');
if (confirmPasswordInput.type === 'password') {
confirmPasswordInput.type = 'text';
icon.className = 'fas fa-eye-slash';
} else {
confirmPasswordInput.type = 'password';
icon.className = 'fas fa-eye';
}
});
// 切换登录/注册模式
document.getElementById('switch-link').addEventListener('click', function(e) {
e.preventDefault();
toggleMode();
});
function toggleMode() {
isLoginMode = !isLoginMode;
if (isLoginMode) {
// 切换到登录模式
document.getElementById('page-title').textContent = '登录';
document.getElementById('page-subtitle').textContent = '欢迎回来,请登录您的账户';
document.getElementById('submit-text').textContent = '登录';
document.getElementById('switch-text').textContent = '还没有账户?';
document.getElementById('switch-link').textContent = '立即注册';
document.getElementById('email-field').style.display = 'none';
document.getElementById('confirm-password-field').style.display = 'none';
document.getElementById('email').required = false;
document.getElementById('confirm-password').required = false;
} else {
// 切换到注册模式
document.getElementById('page-title').textContent = '注册';
document.getElementById('page-subtitle').textContent = '创建您的账户';
document.getElementById('submit-text').textContent = '注册';
document.getElementById('switch-text').textContent = '已有账户?';
document.getElementById('switch-link').textContent = '立即登录';
document.getElementById('email-field').style.display = 'block';
document.getElementById('confirm-password-field').style.display = 'block';
document.getElementById('email').required = true;
document.getElementById('confirm-password').required = true;
}
clearForm();
hideAlert();
}
// 表单提交
document.getElementById('auth-form').addEventListener('submit', async function(e) {
e.preventDefault();
const submitBtn = document.getElementById('submit-btn');
const submitText = document.getElementById('submit-text');
const loadingSpinner = document.getElementById('loading-spinner');
submitBtn.disabled = true;
submitText.style.display = 'none';
loadingSpinner.style.display = 'inline';
try {
const formData = new FormData(this);
const data = Object.fromEntries(formData);
if (!isLoginMode) {
// 注册模式
if (data.password !== data['confirm-password']) {
showAlert('两次输入的密码不一致', 'danger');
return;
}
if (data.password.length < 6) {
showAlert('密码长度至少6位', 'danger');
return;
}
}
const endpoint = isLoginMode ? '/auth/login' : '/auth/register';
const response = await fetch(`${API_BASE}${endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: data.username,
password: data.password,
...(isLoginMode ? {} : { email: data.email })
})
});
const result = await response.json();
if (result.success) {
localStorage.setItem('token', result.data.token);
showAlert('操作成功!正在跳转...', 'success');
setTimeout(() => {
window.location.href = '/dashboard.html';
}, 1000);
} else {
showAlert(result.message || '操作失败', 'danger');
}
} catch (error) {
showAlert('网络错误,请稍后重试', 'danger');
} finally {
submitBtn.disabled = false;
submitText.style.display = 'inline';
loadingSpinner.style.display = 'none';
}
});
function showAlert(message, type) {
const alertContainer = document.getElementById('alert-container');
alertContainer.innerHTML = `
<div class="alert alert-${type} alert-dismissible fade show" role="alert">
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
`;
}
function hideAlert() {
document.getElementById('alert-container').innerHTML = '';
}
function clearForm() {
document.getElementById('auth-form').reset();
}
// 检查是否已登录
const token = localStorage.getItem('token');
if (token) {
window.location.href = '/dashboard.html';
}
</script>
</body>
</html>