291 lines
11 KiB
HTML
291 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" />
|
||
<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>
|