449 lines
14 KiB
HTML
Executable File
449 lines
14 KiB
HTML
Executable File
<!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> |