Files
xbxs/templates/login.html

116 lines
4.1 KiB
HTML

{% extends "auth.html" %}
{% block title %}登录{% endblock %}
{% block content %}
<div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
<div class="w-full max-w-sm bg-white rounded-2xl shadow-xl p-8 relative">
<!-- Logo / 标题 -->
<div class="text-center mb-6">
<div
class="mx-auto w-14 h-14 flex items-center justify-center rounded-full bg-blue-600 text-white text-xl font-bold shadow">
</div>
<h2 class="text-2xl font-bold mt-4">小北学生系统</h2>
<p class="text-sm text-gray-500 mt-1">
校园签到 · 数据可视化 · 自动化
</p>
</div>
<!-- 表单 -->
<div class="space-y-4">
<!-- 用户名 -->
<div class="relative">
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">
👤
</span>
<input id="username" type="text" placeholder="用户名"
class="w-full pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring focus:ring-blue-200" />
</div>
<!-- 密码 -->
<div class="relative">
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">
🔒
</span>
<input id="password" type="password" placeholder="密码"
class="w-full pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring focus:ring-blue-200" />
</div>
<!-- 登录按钮 -->
<button id="login-btn"
class="w-full bg-blue-600 text-white py-2 rounded-lg hover:bg-blue-700 transition disabled:opacity-60 flex items-center justify-center gap-2">
<span id="btn-text">登录</span>
<svg id="loading" class="hidden w-5 h-5 animate-spin text-white" xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" />
</svg>
</button>
</div>
<!-- 错误提示 -->
<p id="error" class="text-red-500 text-sm mt-4 text-center hidden animate-pulse"></p>
<!-- 底部 -->
<div class="mt-6 text-center text-xs text-gray-400">
&copy; {{ year }} 小北 · 学生服务系统
</div>
</div>
</div>
<script>
const btn = document.getElementById("login-btn")
const btnText = document.getElementById("btn-text")
const loading = document.getElementById("loading")
const errorBox = document.getElementById("error")
async function login() {
const username = document.getElementById("username").value.trim()
const password = document.getElementById("password").value.trim()
if (!username || !password) {
showError("请输入用户名和密码")
return
}
btn.disabled = true
btnText.innerText = "登录中"
loading.classList.remove("hidden")
try {
const res = await fetch("/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }),
})
if (res.ok) {
window.location.href = "/home"
} else {
showError("用户名或密码错误")
}
} catch {
showError("网络异常,请稍后再试")
} finally {
btn.disabled = false
btnText.innerText = "登录"
loading.classList.add("hidden")
}
}
function showError(msg) {
errorBox.innerText = msg
errorBox.classList.remove("hidden")
}
// 事件绑定
btn.addEventListener("click", login)
document.addEventListener("keydown", e => {
if (e.key === "Enter") login()
})
</script>
{% endblock %}