erp-frontend/simple-login.html
2026-04-06 21:14:31 +08:00

449 lines
14 KiB
HTML
Executable File
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>ERP系统登录</title>
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.login-container {
width: 100%;
max-width: 420px;
}
.login-box {
background: white;
border-radius: 16px;
padding: 40px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
}
.login-header {
text-align: center;
margin-bottom: 40px;
}
.login-title {
font-size: 28px;
font-weight: 700;
color: #333;
margin-bottom: 8px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.login-subtitle {
font-size: 14px;
color: #666;
margin: 0;
}
.login-form {
margin-bottom: 30px;
}
.form-group {
margin-bottom: 24px;
}
.form-label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #333;
}
.form-input {
width: 100%;
padding: 12px 16px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s;
}
.form-input:focus {
outline: none;
border-color: #667eea;
}
.form-input.error {
border-color: #f56c6c;
}
.error-message {
color: #f56c6c;
font-size: 12px;
margin-top: 4px;
display: none;
}
.login-options {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.remember-me {
display: flex;
align-items: center;
gap: 8px;
}
.forgot-password {
color: #667eea;
text-decoration: none;
font-size: 14px;
}
.forgot-password:hover {
text-decoration: underline;
}
.login-btn {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.login-btn:hover {
transform: translateY(-1px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.login-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.register-link {
text-align: center;
margin-top: 24px;
font-size: 14px;
color: #666;
}
.register-link a {
color: #667eea;
text-decoration: none;
font-weight: 500;
}
.register-link a:hover {
text-decoration: underline;
}
.login-footer {
border-top: 1px solid #eee;
padding-top: 20px;
text-align: center;
}
.test-account {
background: #f8f9fa;
border-radius: 8px;
padding: 12px;
margin-bottom: 20px;
font-size: 12px;
color: #666;
line-height: 1.5;
}
.test-account p {
margin: 4px 0;
}
.copyright {
font-size: 12px;
color: #999;
}
.message {
padding: 12px;
border-radius: 8px;
margin-bottom: 20px;
display: none;
}
.message.success {
background: #f0f9eb;
color: #67c23a;
border: 1px solid #e1f3d8;
}
.message.error {
background: #fef0f0;
color: #f56c6c;
border: 1px solid #fde2e2;
}
@media (max-width: 480px) {
.login-box {
padding: 30px 20px;
}
.login-title {
font-size: 24px;
}
.login-options {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
}
</style>
</head>
<body>
<div class="login-container">
<div class="login-box">
<div class="login-header">
<h1 class="login-title">ERP管理系统</h1>
<p class="login-subtitle">欢迎回来,请登录您的账户</p>
</div>
<div id="message" class="message"></div>
<form id="loginForm" class="login-form">
<div class="form-group">
<label class="form-label">邮箱</label>
<input
type="email"
id="email"
class="form-input"
placeholder="请输入邮箱"
value="admin@erp.com"
required
>
<div id="emailError" class="error-message">请输入有效的邮箱地址</div>
</div>
<div class="form-group">
<label class="form-label">密码</label>
<input
type="password"
id="password"
class="form-input"
placeholder="请输入密码"
value="password123"
required
>
<div id="passwordError" class="error-message">密码不能少于6位</div>
</div>
<div class="login-options">
<div class="remember-me">
<input type="checkbox" id="rememberMe">
<label for="rememberMe">记住我</label>
</div>
<a href="#" class="forgot-password">忘记密码?</a>
</div>
<button type="submit" class="login-btn" id="loginBtn">
登录
</button>
</form>
<div class="register-link">
还没有账号? <a href="/register">立即注册</a>
</div>
<div class="login-footer">
<div class="test-account">
<p><strong>测试账号:</strong> admin@erp.com / password123</p>
<p><strong>API地址:</strong> <span id="apiUrl">/api</span></p>
</div>
<div class="copyright">
© 2024 ERP管理系统. All rights reserved.
</div>
</div>
</div>
</div>
<script>
// 显示API地址
document.getElementById('apiUrl').textContent = window.location.origin + '/api';
// 表单验证
function validateForm() {
let isValid = true;
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
// 验证邮箱
const emailError = document.getElementById('emailError');
const emailInput = document.getElementById('email');
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
emailError.style.display = 'block';
emailInput.classList.add('error');
isValid = false;
} else {
emailError.style.display = 'none';
emailInput.classList.remove('error');
}
// 验证密码
const passwordError = document.getElementById('passwordError');
const passwordInput = document.getElementById('password');
if (!password || password.length < 6) {
passwordError.style.display = 'block';
passwordInput.classList.add('error');
isValid = false;
} else {
passwordError.style.display = 'none';
passwordInput.classList.remove('error');
}
return isValid;
}
// 显示消息
function showMessage(text, type = 'success') {
const messageEl = document.getElementById('message');
messageEl.textContent = text;
messageEl.className = `message ${type}`;
messageEl.style.display = 'block';
if (type === 'success') {
setTimeout(() => {
messageEl.style.display = 'none';
}, 3000);
}
}
// 处理登录
async function handleLogin(event) {
event.preventDefault();
if (!validateForm()) {
return;
}
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const rememberMe = document.getElementById('rememberMe').checked;
const loginBtn = document.getElementById('loginBtn');
loginBtn.disabled = true;
loginBtn.textContent = '登录中...';
try {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
remember: rememberMe
})
});
const data = await response.json();
if (response.ok && data.code === 200) {
showMessage('登录成功!正在跳转...', 'success');
// 保存token
localStorage.setItem('erp_token', data.data.token);
localStorage.setItem('current_user', JSON.stringify(data.data.user));
if (rememberMe) {
localStorage.setItem('remember_me', 'true');
}
// 跳转到首页
setTimeout(() => {
window.location.href = '/';
}, 1500);
} else {
showMessage(data.message || '登录失败', 'error');
loginBtn.disabled = false;
loginBtn.textContent = '登录';
}
} catch (error) {
console.error('登录失败:', error);
showMessage('网络错误请检查API服务', 'error');
loginBtn.disabled = false;
loginBtn.textContent = '登录';
}
}
// 绑定事件
document.getElementById('loginForm').addEventListener('submit', handleLogin);
// 实时验证
document.getElementById('email').addEventListener('input', validateForm);
document.getElementById('password').addEventListener('input', validateForm);
// 检查是否已登录
window.addEventListener('load', () => {
const token = localStorage.getItem('erp_token');
if (token) {
// 如果已登录,跳转到首页
window.location.href = '/';
}
// 测试API连接
testApiConnection();
});
// 测试API连接
async function testApiConnection() {
try {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'test', password: 'test' })
});
console.log('API测试响应:', response.status);
if (response.status === 401) {
console.log('✅ Mock API正常工作 (返回401表示Mock已启用)');
} else {
const data = await response.json();
console.log('API响应数据:', data);
}
} catch (error) {
console.error('❌ API连接测试失败:', error);
showMessage('API服务连接失败请检查服务状态', 'error');
}
}
// 回车键登录
document.addEventListener('keydown', (event) => {
if (event.key === 'Enter' && !document.getElementById('loginBtn').disabled) {
handleLogin(event);
}
});
</script>
</body>
</html>