| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- <!doctype html>
- <html lang="zh-CN">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>登录</title>
- <style>
- body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, PingFang SC, Microsoft YaHei, sans-serif; background: #0b1020; color: #e8ecf1; }
- .container { min-height: 100vh; display: flex; align-items: center; justify-content: center; }
- .card { width: 360px; background: #121a2a; border: 1px solid #1e2a44; border-radius: 12px; padding: 28px; box-shadow: 0 10px 30px rgba(0,0,0,.35); }
- .title { font-size: 20px; font-weight: 600; margin-bottom: 18px; }
- label { font-size: 13px; color: #9fb0ca; display: block; margin: 12px 0 6px; }
- input { width: 100%; height: 40px; border-radius: 8px; border: 1px solid #2a3b5f; background: #0e1424; color: #e8ecf1; padding: 0 12px; outline: none; }
- input:focus { border-color: #3c7bff; box-shadow: 0 0 0 3px rgba(60,123,255,.2); }
- .btn { margin-top: 16px; width: 100%; height: 40px; border-radius: 8px; border: none; background: linear-gradient(135deg, #2a6bff, #6b9dff); color: #fff; font-weight: 600; cursor: pointer; }
- .btn:disabled { background: #2a3b5f; cursor: not-allowed; }
- .error { color: #ff6b6b; font-size: 13px; margin-top: 8px; min-height: 18px; }
- </style>
- <script>
- async function handleLogin(event) {
- event.preventDefault();
- const btn = document.getElementById('submitBtn');
- btn.disabled = true;
- const username = document.getElementById('username').value.trim();
- const password = document.getElementById('password').value;
- const errorEl = document.getElementById('error');
- errorEl.textContent = '';
- try {
- const resp = await fetch('/api/v1/auth/login', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username, password })
- });
- if (!resp.ok) {
- const msg = await resp.text();
- throw new Error(msg || '登录失败');
- }
- const data = await resp.json();
- const token = data.access_token;
- if (!token) throw new Error('未获取到token');
- localStorage.setItem('access_token', token);
- window.location.href = '/dashboard';
- } catch (e) {
- errorEl.textContent = e.message;
- } finally {
- btn.disabled = false;
- }
- }
- </script>
- </head>
- <body>
- <div class="container">
- <form class="card" onsubmit="handleLogin(event)">
- <div class="title">系统登录</div>
- <label for="username">用户名</label>
- <input id="username" name="username" placeholder="请输入用户名" required />
- <label for="password">密码</label>
- <input id="password" name="password" type="password" placeholder="请输入密码" required />
- <button id="submitBtn" class="btn" type="submit">登录</button>
- <div id="error" class="error"></div>
- </form>
- </div>
- </body>
- </html>
|