registry/public/login.html
jif2.zhang 1765caba50
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 21s
feat: 账号认证、用户管理与 API Token 管理
- 后端: Auth(登录/登出/me + session 中间件)、Users、Tokens 路由与 Service,
  scrypt 哈希+timingSafeEqual 校验、requireAdmin 保护、admin 用户自动初始化
- 前端: login.html(登录页, 无账号密码提示)、admin.html(用户+Token 管理,
  令牌明文显隐/复制/吊销/重置密码)、标题栏用户信息+系统管理入口
- 持久化: jsonAdapter 支持 users/api-tokens,运行时数据忽略入库
- 文档: 需求.md/原型设计.md 同步
2026-09-11 17:12:37 +08:00

96 lines
3.8 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录 - Registry 配置管理中心</title>
<link rel="stylesheet" href="/css/style.css">
<style>
body.login-page {
background: linear-gradient(135deg, #003a70 0%, #0a4a86 48%, #0b63a8 100%);
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.login-wrap { width: 400px; max-width: calc(100vw - 32px); }
.login-card { background: #fff; border-radius: 8px; box-shadow: 0 18px 50px rgba(0,0,0,0.35); overflow: hidden; }
.login-card-header { background: linear-gradient(to bottom, #0a4a86, #003a70); color: #fff; padding: 28px 24px 22px; text-align: center; }
.login-logo { font-size: 36px; line-height: 1; }
.login-card-header h1 { font-size: 18px; font-weight: 600; margin-top: 10px; }
.login-card-header p { font-size: 12px; color: #cfe3f7; margin-top: 4px; }
.login-card-body { padding: 24px; }
.login-card-body .form-group { margin-bottom: 16px; }
.login-card-body .form-group input { height: 36px; }
.login-error { display: none; margin-bottom: 14px; padding: 8px 12px; border: 1px solid #f2b8b5; background: #fdecea; color: #c62828; border-radius: 3px; font-size: 12px; }
.login-error.show { display: block; }
.login-btn { width: 100%; height: 38px; font-size: 14px; font-weight: 600; }
.login-footer { margin-top: 16px; text-align: center; font-size: 11px; color: rgba(255,255,255,0.65); }
</style>
</head>
<body class="login-page">
<div class="login-wrap">
<div class="login-card">
<div class="login-card-header">
<div class="login-logo">📋</div>
<h1>Registry 配置管理中心</h1>
<p>微服务配置集中化 · 可视化 · 规范化管理</p>
</div>
<div class="login-card-body">
<div class="login-error" id="login-error"></div>
<form id="login-form" autocomplete="off">
<div class="form-group">
<label>用户名 <span class="required">*</span></label>
<input type="text" id="username" placeholder="请输入用户名" autofocus>
</div>
<div class="form-group">
<label>密码 <span class="required">*</span></label>
<input type="password" id="password" placeholder="请输入密码">
</div>
<button type="submit" class="btn btn-primary login-btn" id="btn-login">登 录</button>
</form>
</div>
</div>
<div class="login-footer">Registry Config Center</div>
</div>
<script>
// 已登录则直接跳转
if (localStorage.getItem("registry_token")) {
window.location.href = "/projects.html";
}
document.getElementById("login-form").addEventListener("submit", async function (e) {
e.preventDefault();
var error = document.getElementById("login-error");
var btn = document.getElementById("btn-login");
var username = document.getElementById("username").value.trim();
var password = document.getElementById("password").value;
error.classList.remove("show");
if (!username || !password) {
error.textContent = "请输入用户名和密码";
error.classList.add("show");
return;
}
btn.disabled = true;
btn.textContent = "登录中...";
try {
var data = await API.login(username, password);
localStorage.setItem("registry_token", data.token);
localStorage.setItem("registry_user", JSON.stringify(data.user));
window.location.href = "/projects.html";
} catch (err) {
error.textContent = err.message || "登录失败";
error.classList.add("show");
btn.disabled = false;
btn.textContent = "登 录";
}
});
</script>
<script src="/js/api.js"></script>
</body>
</html>