login.html 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>登录 - 网络拓扑发现系统</title>
  7. <style>
  8. * { margin: 0; padding: 0; box-sizing: border-box; }
  9. body {
  10. font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  11. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  12. min-height: 100vh;
  13. display: flex;
  14. align-items: center;
  15. justify-content: center;
  16. }
  17. .login-card {
  18. background: white;
  19. border-radius: 12px;
  20. box-shadow: 0 20px 60px rgba(0,0,0,0.3);
  21. padding: 50px 40px;
  22. width: 400px;
  23. max-width: 90vw;
  24. }
  25. .login-card h1 {
  26. text-align: center;
  27. margin-bottom: 10px;
  28. font-size: 24px;
  29. color: #333;
  30. }
  31. .login-card p {
  32. text-align: center;
  33. color: #999;
  34. margin-bottom: 30px;
  35. font-size: 14px;
  36. }
  37. .form-group {
  38. margin-bottom: 20px;
  39. }
  40. .form-group label {
  41. display: block;
  42. margin-bottom: 6px;
  43. color: #555;
  44. font-weight: 500;
  45. }
  46. .form-group input {
  47. width: 100%;
  48. padding: 12px 16px;
  49. border: 2px solid #e0e0e0;
  50. border-radius: 8px;
  51. font-size: 15px;
  52. transition: border-color 0.3s;
  53. outline: none;
  54. }
  55. .form-group input:focus {
  56. border-color: #667eea;
  57. }
  58. .login-btn {
  59. width: 100%;
  60. padding: 14px;
  61. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  62. color: white;
  63. border: none;
  64. border-radius: 8px;
  65. font-size: 16px;
  66. font-weight: 600;
  67. cursor: pointer;
  68. transition: opacity 0.3s;
  69. }
  70. .login-btn:hover {
  71. opacity: 0.9;
  72. }
  73. .login-btn:disabled {
  74. opacity: 0.6;
  75. cursor: not-allowed;
  76. }
  77. .error-msg {
  78. color: #f44336;
  79. text-align: center;
  80. margin-top: 15px;
  81. font-size: 14px;
  82. display: none;
  83. }
  84. </style>
  85. </head>
  86. <body>
  87. <div class="login-card">
  88. <h1>🌐 网络拓扑发现系统</h1>
  89. <p>请登录以继续</p>
  90. <form id="login-form">
  91. <div class="form-group">
  92. <label for="username">用户名</label>
  93. <input type="text" id="username" name="username" required autofocus placeholder="请输入用户名">
  94. </div>
  95. <div class="form-group">
  96. <label for="password">密码</label>
  97. <input type="password" id="password" name="password" required placeholder="请输入密码">
  98. </div>
  99. <button type="submit" class="login-btn" id="login-btn">登 录</button>
  100. <div class="error-msg" id="error-msg"></div>
  101. </form>
  102. </div>
  103. <script>
  104. document.getElementById('login-form').addEventListener('submit', async function(e) {
  105. e.preventDefault();
  106. var btn = document.getElementById('login-btn');
  107. var errEl = document.getElementById('error-msg');
  108. btn.disabled = true;
  109. btn.textContent = '登录中...';
  110. errEl.style.display = 'none';
  111. var username = document.getElementById('username').value;
  112. var password = document.getElementById('password').value;
  113. try {
  114. var resp = await fetch('/api/login', {
  115. method: 'POST',
  116. headers: { 'Content-Type': 'application/json' },
  117. body: JSON.stringify({ username: username, password: password })
  118. });
  119. var data = await resp.json();
  120. if (resp.ok && data.success) {
  121. window.location.href = '/';
  122. } else {
  123. errEl.textContent = data.message || '登录失败';
  124. errEl.style.display = 'block';
  125. }
  126. } catch (err) {
  127. errEl.textContent = '网络错误,请重试';
  128. errEl.style.display = 'block';
  129. }
  130. btn.disabled = false;
  131. btn.textContent = '登 录';
  132. });
  133. </script>
  134. </body>
  135. </html>