ERP/frontend/login.html

291 lines
11 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" />
<title>登录 - 韬智生产管理系统</title>
<link rel="icon" type="image/svg+xml" href="./assets/favicon.svg" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="./assets/login.css" />
</head>
<body>
<div class="login-container">
<div class="login-background"></div>
<div class="login-card">
<div class="login-header">
<div class="logo-container">
<div class="logo-icon bitcoin-coin">
<div class="coin-face front">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4091.27 4091.73" width="100%" height="100%">
<path fill="#F7931A" d="M4030.06 2540.77c-273.24,1096.01 -1383.32,1763.02 -2479.46,1489.71 -1095.68,-273.24 -1762.69,-1383.39 -1489.33,-2479.31 273.12,-1096.13 1383.2,-1763.19 2479,-1489.95 1096.06,273.24 1763.03,1383.51 1489.76,2479.57l0.02 -0.02z"/>
<path fill="white" d="M2947.77 1754.38c40.72,-272.26 -166.56,-418.61 -450,-516.24l91.95 -368.8 -224.5 -55.94 -89.51 359.09c-59.02,-14.72 -119.63,-28.59 -179.87,-42.34l90.16 -361.46 -224.36 -55.94 -92 368.68c-48.84,-11.12 -96.81,-22.11 -143.35,-33.69l0.26 -1.16 -309.59 -77.31 -59.72 239.78c0,0 166.56,38.18 163.05,40.53 90.91,22.69 107.35,82.87 104.62,130.57l-104.74 420.15c6.26,1.59 14.38,3.89 23.34,7.49 -7.49,-1.86 -15.46,-3.89 -23.73,-5.87l-146.81 588.57c-11.11,27.62 -39.31,69.07 -102.87,53.33 2.25,3.26 -163.17,-40.72 -163.17,-40.72l-111.46 256.98 292.15 72.83c54.35,13.63 107.61,27.89 160.06,41.3l-92.9 373.03 224.24 55.94 92 -369.07c61.26,16.63 120.71,31.97 178.91,46.43l-91.69 367.33 224.51 55.94 92.89 -372.33c382.82,72.45 670.67,43.24 791.83,-303.02 97.63,-278.78 -4.86,-439.58 -206.26,-544.44 146.69,-33.83 257.18,-130.31 286.64,-329.61l-0.07 -0.05zm-512.93 719.26c-69.38,278.78 -538.76,128.08 -690.94,90.29l123.28 -494.2c152.17,37.99 640.17,113.17 567.67,403.91zm69.43 -723.3c-63.29,253.58 -453.96,124.75 -580.69,93.16l111.77 -448.21c126.73,31.59 534.85,90.55 468.94,355.05l-0.02 0z"/>
</svg>
</div>
<div class="coin-face back">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4091.27 4091.73" width="100%" height="100%" style="transform:scaleX(-1)">
<path fill="#F7931A" d="M4030.06 2540.77c-273.24,1096.01 -1383.32,1763.02 -2479.46,1489.71 -1095.68,-273.24 -1762.69,-1383.39 -1489.33,-2479.31 273.12,-1096.13 1383.2,-1763.19 2479,-1489.95 1096.06,273.24 1763.03,1383.51 1489.76,2479.57l0.02 -0.02z"/>
<path fill="white" d="M2947.77 1754.38c40.72,-272.26 -166.56,-418.61 -450,-516.24l91.95 -368.8 -224.5 -55.94 -89.51 359.09c-59.02,-14.72 -119.63,-28.59 -179.87,-42.34l90.16 -361.46 -224.36 -55.94 -92 368.68c-48.84,-11.12 -96.81,-22.11 -143.35,-33.69l0.26 -1.16 -309.59 -77.31 -59.72 239.78c0,0 166.56,38.18 163.05,40.53 90.91,22.69 107.35,82.87 104.62,130.57l-104.74 420.15c6.26,1.59 14.38,3.89 23.34,7.49 -7.49,-1.86 -15.46,-3.89 -23.73,-5.87l-146.81 588.57c-11.11,27.62 -39.31,69.07 -102.87,53.33 2.25,3.26 -163.17,-40.72 -163.17,-40.72l-111.46 256.98 292.15 72.83c54.35,13.63 107.61,27.89 160.06,41.3l-92.9 373.03 224.24 55.94 92 -369.07c61.26,16.63 120.71,31.97 178.91,46.43l-91.69 367.33 224.51 55.94 92.89 -372.33c382.82,72.45 670.67,43.24 791.83,-303.02 97.63,-278.78 -4.86,-439.58 -206.26,-544.44 146.69,-33.83 257.18,-130.31 286.64,-329.61l-0.07 -0.05zm-512.93 719.26c-69.38,278.78 -538.76,128.08 -690.94,90.29l123.28 -494.2c152.17,37.99 640.17,113.17 567.67,403.91zm69.43 -723.3c-63.29,253.58 -453.96,124.75 -580.69,93.16l111.77 -448.21c126.73,31.59 534.85,90.55 468.94,355.05l-0.02 0z"/>
</svg>
</div>
</div>
<h1 class="system-title">韬智生产管理系统</h1>
</div>
<p class="system-subtitle">Production Management System</p>
</div>
<div class="login-form">
<div class="form-group">
<label for="username">用户名</label>
<div class="input-wrapper">
<span class="input-icon">
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="8" r="4" stroke="currentColor" stroke-width="2"/>
<path d="M6 21c0-3.314 2.686-6 6-6s6 2.686 6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</span>
<input
type="text"
id="username"
class="form-input"
placeholder="请输入用户名"
autocomplete="username"
/>
</div>
</div>
<div class="form-group">
<label for="password">密码</label>
<div class="input-wrapper">
<span class="input-icon">
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="5" y="11" width="14" height="10" rx="2" stroke="currentColor" stroke-width="2"/>
<path d="M8 11V7a4 4 0 0 1 8 0v4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<circle cx="12" cy="16" r="1.5" fill="currentColor"/>
</svg>
</span>
<input
type="password"
id="password"
class="form-input"
placeholder="请输入密码"
autocomplete="current-password"
/>
</div>
</div>
<div class="form-group">
<label for="captcha">验证码</label>
<div class="captcha-wrapper">
<div class="input-wrapper" style="flex: 1;">
<span class="input-icon">
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="3" y="5" width="18" height="14" rx="2" stroke="currentColor" stroke-width="2"/>
<path d="M7 9h2m3 0h2m3 0h2M7 13h3m4 0h3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</span>
<input
type="text"
id="captcha"
class="form-input"
placeholder="请输入验证码"
maxlength="4"
autocomplete="off"
/>
</div>
<div class="captcha-image-wrapper" id="captcha-image-wrapper" title="点击刷新验证码">
<img id="captcha-image" class="captcha-image" alt="验证码" />
</div>
</div>
</div>
<div id="error-message" class="error-message" style="display:none;"></div>
<button id="login-btn" class="login-btn">
<span id="login-text">登录</span>
<span id="login-loader" class="btn-loader" style="display:none;">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</span>
</button>
</div>
<div class="login-footer">
<p>© 2025 韬智科技 · 智能制造</p>
</div>
</div>
</div>
<script>
// 检查是否已登录
async function checkAuth() {
try {
const response = await fetch('/api/auth/me', {
credentials: 'include'
});
if (response.ok) {
const user = await response.json();
if (user && user.username) {
window.location.replace('/index.html#/dashboard');
}
}
} catch(e) {
// 未登录,继续显示登录页面
console.log('未登录,显示登录页面');
}
}
checkAuth();
// 登录处理
const usernameInput = document.getElementById('username');
const passwordInput = document.getElementById('password');
const captchaInput = document.getElementById('captcha');
const captchaImage = document.getElementById('captcha-image');
const captchaImageWrapper = document.getElementById('captcha-image-wrapper');
const loginBtn = document.getElementById('login-btn');
const loginText = document.getElementById('login-text');
const loginLoader = document.getElementById('login-loader');
const errorMessage = document.getElementById('error-message');
function showError(message) {
errorMessage.textContent = message;
errorMessage.style.display = 'block';
setTimeout(() => {
errorMessage.style.display = 'none';
}, 3000);
}
function setLoading(loading) {
if (loading) {
loginBtn.disabled = true;
loginText.style.display = 'none';
loginLoader.style.display = 'flex';
} else {
loginBtn.disabled = false;
loginText.style.display = 'inline';
loginLoader.style.display = 'none';
}
}
// 加载验证码
async function loadCaptcha() {
try {
const response = await fetch('/api/auth/captcha', {
credentials: 'include'
});
if (response.ok) {
const data = await response.json();
if (data.image) {
captchaImage.src = data.image;
}
}
} catch(e) {
console.error('加载验证码失败:', e);
}
}
// 点击图片刷新验证码
captchaImageWrapper.addEventListener('click', () => {
captchaInput.value = '';
captchaImageWrapper.classList.add('refreshing');
loadCaptcha();
setTimeout(() => {
captchaImageWrapper.classList.remove('refreshing');
}, 300);
});
// 页面加载时获取验证码
loadCaptcha();
async function handleLogin() {
const username = usernameInput.value.trim();
const password = passwordInput.value.trim();
const captcha = captchaInput.value.trim();
if (!username) {
showError('请输入用户名');
usernameInput.focus();
return;
}
if (!password) {
showError('请输入密码');
passwordInput.focus();
return;
}
if (!captcha) {
showError('请输入验证码');
captchaInput.focus();
return;
}
if (captcha.length !== 4) {
showError('验证码为4位数字');
captchaInput.focus();
return;
}
setLoading(true);
try {
// 直接使用 fetch避免 API.login 的 overlay 问题
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ username, password, captcha })
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.error || '登录失败');
}
if (result.ok) {
// 登录成功,跳转到主页面
// 使用 replace 避免 Safari 缓存问题
window.location.replace('/index.html#/dashboard');
} else {
throw new Error('登录失败');
}
} catch(e) {
showError(e.message || '登录失败');
setLoading(false);
// 刷新验证码
captchaInput.value = '';
loadCaptcha();
}
}
loginBtn.addEventListener('click', handleLogin);
// 回车键登录
usernameInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
passwordInput.focus();
}
});
passwordInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
captchaInput.focus();
}
});
captchaInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
handleLogin();
}
});
// 自动聚焦用户名输入框
usernameInput.focus();
</script>
</body>
</html>