1. 前端改为vue单体程序
2. 增加设备管理相关接口
This commit is contained in:
		| @@ -3,270 +3,12 @@ | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>猪场管理系统 - 登录</title> | ||||
|     <style> | ||||
|         * { | ||||
|             margin: 0; | ||||
|             padding: 0; | ||||
|             box-sizing: border-box; | ||||
|         } | ||||
|  | ||||
|         body { | ||||
|             font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | ||||
|             background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | ||||
|             min-height: 100vh; | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|         } | ||||
|  | ||||
|         .login-container { | ||||
|             background: rgba(255, 255, 255, 0.95); | ||||
|             backdrop-filter: blur(10px); | ||||
|             border-radius: 20px; | ||||
|             box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2); | ||||
|             padding: 40px; | ||||
|             width: 100%; | ||||
|             max-width: 400px; | ||||
|             text-align: center; | ||||
|             animation: fadeIn 0.5s ease-out; | ||||
|         } | ||||
|  | ||||
|         @keyframes fadeIn { | ||||
|             from { | ||||
|                 opacity: 0; | ||||
|                 transform: translateY(-20px); | ||||
|             } | ||||
|             to { | ||||
|                 opacity: 1; | ||||
|                 transform: translateY(0); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         .logo { | ||||
|             width: 80px; | ||||
|             height: 80px; | ||||
|             background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | ||||
|             border-radius: 50%; | ||||
|             margin: 0 auto 20px; | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|             color: white; | ||||
|             font-size: 30px; | ||||
|             font-weight: bold; | ||||
|         } | ||||
|  | ||||
|         h1 { | ||||
|             color: #333; | ||||
|             margin-bottom: 10px; | ||||
|             font-size: 28px; | ||||
|         } | ||||
|  | ||||
|         .subtitle { | ||||
|             color: #666; | ||||
|             margin-bottom: 30px; | ||||
|             font-size: 14px; | ||||
|         } | ||||
|  | ||||
|         .form-group { | ||||
|             margin-bottom: 20px; | ||||
|             text-align: left; | ||||
|         } | ||||
|  | ||||
|         label { | ||||
|             display: block; | ||||
|             margin-bottom: 8px; | ||||
|             color: #555; | ||||
|             font-weight: 500; | ||||
|         } | ||||
|  | ||||
|         input { | ||||
|             width: 100%; | ||||
|             padding: 15px; | ||||
|             border: 2px solid #e1e1e1; | ||||
|             border-radius: 10px; | ||||
|             font-size: 16px; | ||||
|             transition: all 0.3s ease; | ||||
|             outline: none; | ||||
|         } | ||||
|  | ||||
|         input:focus { | ||||
|             border-color: #667eea; | ||||
|             box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); | ||||
|         } | ||||
|  | ||||
|         button { | ||||
|             width: 100%; | ||||
|             padding: 15px; | ||||
|             background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | ||||
|             color: white; | ||||
|             border: none; | ||||
|             border-radius: 10px; | ||||
|             font-size: 16px; | ||||
|             font-weight: 600; | ||||
|             cursor: pointer; | ||||
|             transition: all 0.3s ease; | ||||
|             margin-top: 10px; | ||||
|         } | ||||
|  | ||||
|         button:hover { | ||||
|             transform: translateY(-2px); | ||||
|             box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3); | ||||
|         } | ||||
|  | ||||
|         button:active { | ||||
|             transform: translateY(0); | ||||
|         } | ||||
|  | ||||
|         button:disabled { | ||||
|             opacity: 0.7; | ||||
|             cursor: not-allowed; | ||||
|             transform: none; | ||||
|             box-shadow: none; | ||||
|         } | ||||
|  | ||||
|         .error-message { | ||||
|             color: #e74c3c; | ||||
|             margin-top: 15px; | ||||
|             padding: 10px; | ||||
|             border-radius: 5px; | ||||
|             background-color: #fdf2f2; | ||||
|             border: 1px solid #f5c6cb; | ||||
|             display: none; | ||||
|         } | ||||
|  | ||||
|         .success-message { | ||||
|             color: #27ae60; | ||||
|             margin-top: 15px; | ||||
|             padding: 10px; | ||||
|             border-radius: 5px; | ||||
|             background-color: #f2fdf2; | ||||
|             border: 1px solid #c6f5cb; | ||||
|             display: none; | ||||
|         } | ||||
|  | ||||
|         .loading { | ||||
|             display: none; | ||||
|             margin: 20px auto; | ||||
|         } | ||||
|  | ||||
|         .loading-spinner { | ||||
|             border: 3px solid #f3f3f3; | ||||
|             border-top: 3px solid #667eea; | ||||
|             border-radius: 50%; | ||||
|             width: 30px; | ||||
|             height: 30px; | ||||
|             animation: spin 1s linear infinite; | ||||
|             margin: 0 auto; | ||||
|         } | ||||
|  | ||||
|         @keyframes spin { | ||||
|             0% { transform: rotate(0deg); } | ||||
|             100% { transform: rotate(360deg); } | ||||
|         } | ||||
|  | ||||
|         @media (max-width: 480px) { | ||||
|             .login-container { | ||||
|                 margin: 20px; | ||||
|                 padding: 30px 20px; | ||||
|             } | ||||
|              | ||||
|             h1 { | ||||
|                 font-size: 24px; | ||||
|             } | ||||
|         } | ||||
|     </style> | ||||
|     <title>猪场管理系统</title> | ||||
| </head> | ||||
| <body> | ||||
|     <div class="login-container"> | ||||
|         <div class="logo">🐷</div> | ||||
|         <h1>猪场管理系统</h1> | ||||
|         <p class="subtitle">请登录您的账户</p> | ||||
|          | ||||
|         <form id="loginForm"> | ||||
|             <div class="form-group"> | ||||
|                 <label for="username">用户名</label> | ||||
|                 <input type="text" id="username" name="username" required placeholder="请输入用户名"> | ||||
|             </div> | ||||
|              | ||||
|             <div class="form-group"> | ||||
|                 <label for="password">密码</label> | ||||
|                 <input type="password" id="password" name="password" required placeholder="请输入密码"> | ||||
|             </div> | ||||
|              | ||||
|             <button type="submit" id="loginBtn">登录</button> | ||||
|         </form> | ||||
|          | ||||
|         <div class="loading" id="loading"> | ||||
|             <div class="loading-spinner"></div> | ||||
|             <p>登录中...</p> | ||||
|         </div> | ||||
|          | ||||
|         <div class="error-message" id="errorMessage"></div> | ||||
|         <div class="success-message" id="successMessage"></div> | ||||
|     </div> | ||||
|  | ||||
|     <script> | ||||
|         document.getElementById('loginForm').addEventListener('submit', async function(e) { | ||||
|             e.preventDefault(); | ||||
|              | ||||
|             const username = document.getElementById('username').value; | ||||
|             const password = document.getElementById('password').value; | ||||
|             const loginBtn = document.getElementById('loginBtn'); | ||||
|             const loading = document.getElementById('loading'); | ||||
|             const errorMessage = document.getElementById('errorMessage'); | ||||
|             const successMessage = document.getElementById('successMessage'); | ||||
|              | ||||
|             // 隐藏之前的消息 | ||||
|             errorMessage.style.display = 'none'; | ||||
|             successMessage.style.display = 'none'; | ||||
|              | ||||
|             // 显示加载状态 | ||||
|             loginBtn.disabled = true; | ||||
|             loading.style.display = 'block'; | ||||
|              | ||||
|             try { | ||||
|                 const response = await fetch('/api/v1/user/login', { | ||||
|                     method: 'POST', | ||||
|                     headers: { | ||||
|                         'Content-Type': 'application/json' | ||||
|                     }, | ||||
|                     body: JSON.stringify({ username, password }) | ||||
|                 }); | ||||
|                  | ||||
|                 const data = await response.json(); | ||||
|                  | ||||
|                 if (response.ok && data.code === 0) { | ||||
|                     // 登录成功 | ||||
|                     successMessage.textContent = data.message; | ||||
|                     successMessage.style.display = 'block'; | ||||
|                      | ||||
|                     // 保存token到localStorage | ||||
|                     localStorage.setItem('authToken', data.data.token); | ||||
|                     localStorage.setItem('userId', data.data.id); | ||||
|                     localStorage.setItem('username', data.data.username); | ||||
|                      | ||||
|                     // 跳转到主页面(这里暂时只是显示成功信息) | ||||
|                     setTimeout(() => { | ||||
|                         alert('登录成功!将跳转到主页面。'); | ||||
|                         // 这里可以重定向到主页面 | ||||
|                         // window.location.href = '/dashboard.html'; | ||||
|                     }, 1000); | ||||
|                 } else { | ||||
|                     // 登录失败 | ||||
|                     errorMessage.textContent = data.message || '登录失败'; | ||||
|                     errorMessage.style.display = 'block'; | ||||
|                 } | ||||
|             } catch (error) { | ||||
|                 errorMessage.textContent = '网络错误,请稍后重试'; | ||||
|                 errorMessage.style.display = 'block'; | ||||
|             } finally { | ||||
|                 // 恢复按钮状态 | ||||
|                 loginBtn.disabled = false; | ||||
|                 loading.style.display = 'none'; | ||||
|             } | ||||
|         }); | ||||
|     </script> | ||||
|     <div id="app"></div> | ||||
|     <!-- Vue应用将挂载到这个div上 --> | ||||
|     <script type="module" src="/src/main.js"></script> | ||||
| </body> | ||||
| </html> | ||||
| </html> | ||||
| ``` | ||||
		Reference in New Issue
	
	Block a user