login.html 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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>登录 - CJYDocs</title>
  7. <link rel="stylesheet" href="css/style.css">
  8. <style>
  9. .login-container {
  10. min-height: 100vh;
  11. display: flex;
  12. align-items: center;
  13. justify-content: center;
  14. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  15. padding: 20px;
  16. }
  17. .login-box {
  18. background: white;
  19. border-radius: 12px;
  20. box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
  21. padding: 40px;
  22. width: 100%;
  23. max-width: 400px;
  24. }
  25. .login-header {
  26. text-align: center;
  27. margin-bottom: 30px;
  28. }
  29. .login-title {
  30. font-size: 2rem;
  31. font-weight: 700;
  32. color: var(--text-color);
  33. margin-bottom: 8px;
  34. }
  35. .login-subtitle {
  36. color: #6b7280;
  37. font-size: 0.95rem;
  38. }
  39. .form-group {
  40. margin-bottom: 20px;
  41. }
  42. .form-label {
  43. display: block;
  44. font-weight: 500;
  45. margin-bottom: 8px;
  46. color: var(--text-color);
  47. }
  48. .form-input {
  49. width: 100%;
  50. padding: 12px 16px;
  51. border: 2px solid var(--border-color);
  52. border-radius: 8px;
  53. font-size: 1rem;
  54. transition: border-color 0.2s;
  55. }
  56. .form-input:focus {
  57. outline: none;
  58. border-color: var(--primary-color);
  59. }
  60. .login-btn {
  61. width: 100%;
  62. padding: 12px;
  63. background: var(--primary-color);
  64. color: white;
  65. border: none;
  66. border-radius: 8px;
  67. font-size: 1rem;
  68. font-weight: 600;
  69. cursor: pointer;
  70. transition: background-color 0.2s;
  71. }
  72. .login-btn:hover {
  73. background: var(--primary-hover);
  74. }
  75. .login-btn:disabled {
  76. background: #9ca3af;
  77. cursor: not-allowed;
  78. }
  79. .error-message {
  80. background: #fee2e2;
  81. color: #dc2626;
  82. padding: 12px;
  83. border-radius: 8px;
  84. margin-bottom: 20px;
  85. display: none;
  86. text-align: center;
  87. font-size: 0.9rem;
  88. }
  89. .error-message.show {
  90. display: block;
  91. }
  92. .password-toggle {
  93. position: relative;
  94. }
  95. .toggle-btn {
  96. position: absolute;
  97. right: 12px;
  98. top: 50%;
  99. transform: translateY(-50%);
  100. background: none;
  101. border: none;
  102. color: #6b7280;
  103. cursor: pointer;
  104. padding: 4px 8px;
  105. font-size: 0.85rem;
  106. }
  107. .toggle-btn:hover {
  108. color: var(--primary-color);
  109. }
  110. </style>
  111. </head>
  112. <body>
  113. <div class="login-container">
  114. <div class="login-box">
  115. <div class="login-header">
  116. <h1 class="login-title">CJYDocs</h1>
  117. <p class="login-subtitle">请输入密码访问文档系统</p>
  118. </div>
  119. <div id="error-message" class="error-message"></div>
  120. <form id="login-form">
  121. <div class="form-group">
  122. <label for="password" class="form-label">密码</label>
  123. <div class="password-toggle">
  124. <input
  125. type="password"
  126. id="password"
  127. class="form-input"
  128. placeholder="请输入密码"
  129. required
  130. autocomplete="current-password"
  131. >
  132. <button type="button" class="toggle-btn" id="toggle-password">显示</button>
  133. </div>
  134. </div>
  135. <button type="submit" class="login-btn" id="login-btn">
  136. 登录
  137. </button>
  138. </form>
  139. </div>
  140. </div>
  141. <script>
  142. const loginForm = document.getElementById('login-form');
  143. const passwordInput = document.getElementById('password');
  144. const loginBtn = document.getElementById('login-btn');
  145. const errorMessage = document.getElementById('error-message');
  146. const togglePasswordBtn = document.getElementById('toggle-password');
  147. // 切换密码显示/隐藏
  148. togglePasswordBtn.addEventListener('click', () => {
  149. if (passwordInput.type === 'password') {
  150. passwordInput.type = 'text';
  151. togglePasswordBtn.textContent = '隐藏';
  152. } else {
  153. passwordInput.type = 'password';
  154. togglePasswordBtn.textContent = '显示';
  155. }
  156. });
  157. // 显示错误信息
  158. function showError(message) {
  159. errorMessage.textContent = message;
  160. errorMessage.classList.add('show');
  161. setTimeout(() => {
  162. errorMessage.classList.remove('show');
  163. }, 3000);
  164. }
  165. // 登录表单提交
  166. loginForm.addEventListener('submit', async (e) => {
  167. e.preventDefault();
  168. const password = passwordInput.value.trim();
  169. if (!password) {
  170. showError('请输入密码');
  171. return;
  172. }
  173. // 禁用按钮,防止重复提交
  174. loginBtn.disabled = true;
  175. loginBtn.textContent = '登录中...';
  176. try {
  177. const response = await fetch('/api/login', {
  178. method: 'POST',
  179. headers: {
  180. 'Content-Type': 'application/json'
  181. },
  182. body: JSON.stringify({ password })
  183. });
  184. const data = await response.json();
  185. if (response.ok && data.success) {
  186. // 登录成功,跳转到首页
  187. window.location.href = '/';
  188. } else {
  189. // 登录失败
  190. showError(data.error || '密码错误,请重试');
  191. passwordInput.value = '';
  192. passwordInput.focus();
  193. }
  194. } catch (error) {
  195. console.error('Login error:', error);
  196. showError('登录失败,请稍后重试');
  197. } finally {
  198. // 恢复按钮状态
  199. loginBtn.disabled = false;
  200. loginBtn.textContent = '登录';
  201. }
  202. });
  203. // 页面加载时聚焦到密码输入框
  204. passwordInput.focus();
  205. </script>
  206. </body>
  207. </html>