feat: 阶段2 Python后端、用户管理、统计、单词收藏与响应式适配

This commit is contained in:
guoqingshan
2026-08-01 17:46:04 +08:00
parent a2e705aa30
commit 55705683ff
26 changed files with 1929 additions and 42 deletions
+92
View File
@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录 — Mi Diario 西班牙语日记</title>
<link rel="stylesheet" href="style.css">
<style>
body { align-items: center; justify-content: center; min-height: 100vh; padding: 1rem; }
#auth-box {
width: 100%; max-width: 380px;
background: var(--panel-bg); border: 1px solid var(--border);
border-radius: var(--radius); box-shadow: var(--shadow);
padding: 1.5rem;
}
#auth-box h1 { font-size: 1.25rem; margin-bottom: 0.25rem; }
#auth-box p { color: var(--text-muted); font-size: 0.85rem; margin-bottom: 1rem; }
#auth-box label { display: block; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.25rem; }
#auth-box input {
width: 100%; border: 1px solid var(--border); border-radius: 6px;
padding: 0.55rem 0.7rem; font-size: 0.9rem; margin-bottom: 0.75rem;
background: var(--bg); color: var(--text); outline: none;
}
#auth-box input:focus { border-color: var(--accent); }
#auth-box button {
width: 100%; background: var(--accent); color: #fff; border: none;
padding: 0.6rem; border-radius: 6px; font-size: 0.95rem; cursor: pointer;
}
#auth-box button:hover { background: var(--accent-hover); }
#auth-error { color: var(--danger); font-size: 0.85rem; min-height: 1.2em; margin-bottom: 0.5rem; }
#auth-switch { margin-top: 1rem; font-size: 0.85rem; text-align: center; color: var(--text-muted); }
#auth-switch a { color: var(--accent); cursor: pointer; text-decoration: none; }
#display-name-field { display: none; }
#back-home { display: block; text-align: center; margin-top: 0.75rem; font-size: 0.8rem; color: var(--text-muted); text-decoration: none; }
</style>
</head>
<body>
<div id="auth-box">
<h1 id="auth-title">登录</h1>
<p>Mi Diario 西班牙语日记</p>
<div id="auth-error"></div>
<form id="auth-form">
<label for="auth-username">用户名</label>
<input id="auth-username" type="text" autocomplete="username" required>
<div id="display-name-field">
<label for="auth-display-name">显示名</label>
<input id="auth-display-name" type="text" autocomplete="nickname">
</div>
<label for="auth-password">密码</label>
<input id="auth-password" type="password" autocomplete="current-password" required>
<button type="submit" id="auth-submit">登录</button>
</form>
<div id="auth-switch"><a id="auth-toggle">还没有账号?注册</a></div>
<a id="back-home" href="index.html">返回首页</a>
</div>
<script src="api.js"></script>
<script>
var isRegister = false;
var title = document.getElementById('auth-title');
var submit = document.getElementById('auth-submit');
var toggle = document.getElementById('auth-toggle');
var displayNameField = document.getElementById('display-name-field');
var errorBox = document.getElementById('auth-error');
function setMode(register) {
isRegister = register;
title.textContent = register ? '注册' : '登录';
submit.textContent = register ? '注册并登录' : '登录';
toggle.textContent = register ? '已有账号?登录' : '还没有账号?注册';
displayNameField.style.display = register ? 'block' : 'none';
errorBox.textContent = '';
}
toggle.addEventListener('click', function() { setMode(!isRegister); });
document.getElementById('auth-form').addEventListener('submit', function(e) {
e.preventDefault();
errorBox.textContent = '';
var username = document.getElementById('auth-username').value.trim();
var password = document.getElementById('auth-password').value;
var displayName = document.getElementById('auth-display-name').value.trim();
var action = isRegister ? apiRegister(username, password, displayName || username) : apiLogin(username, password);
action.then(function() {
location.href = 'index.html';
}).catch(function(err) {
errorBox.textContent = err.message || '操作失败';
});
});
</script>
</body>
</html>