commit remaining frontend updates
This commit is contained in:
+18
-1
@@ -12,7 +12,7 @@ body {
|
|||||||
.page { display: none; }
|
.page { display: none; }
|
||||||
.page.active { display: flex; flex-direction: column; }
|
.page.active { display: flex; flex-direction: column; }
|
||||||
|
|
||||||
#loginPage {
|
#loginPage, #registerPage {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -68,6 +68,12 @@ body {
|
|||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
.btn-secondary {
|
||||||
|
background: transparent;
|
||||||
|
color: #667eea;
|
||||||
|
border: 1px solid #667eea;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
.login-error {
|
.login-error {
|
||||||
color: #e74c3c;
|
color: #e74c3c;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -76,6 +82,17 @@ body {
|
|||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-register-link {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-register-link a {
|
||||||
|
color: #667eea;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
/* 首页 */
|
/* 首页 */
|
||||||
#homePage {
|
#homePage {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|||||||
+24
-1
@@ -21,10 +21,33 @@
|
|||||||
<input type="password" id="loginPass" placeholder="请输入密码" autocomplete="current-password">
|
<input type="password" id="loginPass" placeholder="请输入密码" autocomplete="current-password">
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary" onclick="doLogin()">登 录</button>
|
<button class="btn btn-primary" onclick="doLogin()">登 录</button>
|
||||||
|
<button class="btn btn-secondary" onclick="showRegisterPage()">注册账号</button>
|
||||||
<div class="login-error" id="loginError"></div>
|
<div class="login-error" id="loginError"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 注册页 -->
|
||||||
|
<div id="registerPage" class="page">
|
||||||
|
<div class="login-box">
|
||||||
|
<h1>注册账号</h1>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>用户名</label>
|
||||||
|
<input type="text" id="registerUser" placeholder="请输入用户名" autocomplete="username">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>密码</label>
|
||||||
|
<input type="password" id="registerPass" placeholder="请输入密码" autocomplete="new-password">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>确认密码</label>
|
||||||
|
<input type="password" id="registerPassConfirm" placeholder="请再次输入密码" autocomplete="new-password">
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary" onclick="doRegister()">注 册</button>
|
||||||
|
<button class="btn btn-secondary" onclick="showLoginPage()">返回登录</button>
|
||||||
|
<div class="login-error" id="registerError"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 首页 -->
|
<!-- 首页 -->
|
||||||
<div id="homePage" class="page">
|
<div id="homePage" class="page">
|
||||||
<div class="home-header">
|
<div class="home-header">
|
||||||
@@ -457,7 +480,7 @@
|
|||||||
<div class="toast" id="toast"></div>
|
<div class="toast" id="toast"></div>
|
||||||
|
|
||||||
<script src="js/app.js?v=20260224"></script>
|
<script src="js/app.js?v=20260224"></script>
|
||||||
<script src="js/auth.js"></script>
|
<script src="js/auth.js?v=20260428b"></script>
|
||||||
<script src="js/autocomplete.js"></script>
|
<script src="js/autocomplete.js"></script>
|
||||||
<script src="js/month-picker.js"></script>
|
<script src="js/month-picker.js"></script>
|
||||||
<script src="js/stats.js?v=20260326"></script>
|
<script src="js/stats.js?v=20260326"></script>
|
||||||
|
|||||||
@@ -20,6 +20,40 @@ async function doLogin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function doRegister() {
|
||||||
|
const user = document.getElementById('registerUser').value.trim();
|
||||||
|
const pass = document.getElementById('registerPass').value.trim();
|
||||||
|
const passConfirm = document.getElementById('registerPassConfirm').value.trim();
|
||||||
|
if (!user || !pass) { document.getElementById('registerError').textContent = '请输入用户名和密码'; return; }
|
||||||
|
if (pass !== passConfirm) { document.getElementById('registerError').textContent = '两次密码输入不一致'; return; }
|
||||||
|
try {
|
||||||
|
const res = await fetch(API + '/api/register', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ username: user, password: pass })
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (!res.ok) { document.getElementById('registerError').textContent = data.error; return; }
|
||||||
|
showToast('注册成功,请登录');
|
||||||
|
showLoginPage();
|
||||||
|
} catch (e) {
|
||||||
|
document.getElementById('registerError').textContent = '网络错误';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showRegisterPage() {
|
||||||
|
document.getElementById('registerError').textContent = '';
|
||||||
|
document.getElementById('registerUser').value = '';
|
||||||
|
document.getElementById('registerPass').value = '';
|
||||||
|
document.getElementById('registerPassConfirm').value = '';
|
||||||
|
showPage('registerPage');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showLoginPage() {
|
||||||
|
document.getElementById('loginError').textContent = '';
|
||||||
|
showPage('loginPage');
|
||||||
|
}
|
||||||
|
|
||||||
function doLogout() {
|
function doLogout() {
|
||||||
token = null;
|
token = null;
|
||||||
username = null;
|
username = null;
|
||||||
|
|||||||
@@ -135,9 +135,8 @@ async function saveEditRecord() {
|
|||||||
if (time) body.created_at = new Date(time).toISOString();
|
if (time) body.created_at = new Date(time).toISOString();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(API + '/api/records/' + id, {
|
const res = await apiFetch(API + '/api/records/' + id, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: headers(),
|
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
});
|
});
|
||||||
if (!res.ok) { showToast('保存失败'); return; }
|
if (!res.ok) { showToast('保存失败'); return; }
|
||||||
@@ -152,7 +151,7 @@ async function deleteEditRecord() {
|
|||||||
const id = document.getElementById('editId').value;
|
const id = document.getElementById('editId').value;
|
||||||
if (!confirm('确定删除这条记录?')) return;
|
if (!confirm('确定删除这条记录?')) return;
|
||||||
try {
|
try {
|
||||||
const res = await fetch(API + '/api/records/' + id, { method: 'DELETE', headers: headers() });
|
const res = await apiFetch(API + '/api/records/' + id, { method: 'DELETE' });
|
||||||
if (!res.ok) { showToast('删除失败'); return; }
|
if (!res.ok) { showToast('删除失败'); return; }
|
||||||
showToast('已删除');
|
showToast('已删除');
|
||||||
closeEditModal();
|
closeEditModal();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ async function doExport(format) {
|
|||||||
closeExportModal();
|
closeExportModal();
|
||||||
showToast('正在导出...');
|
showToast('正在导出...');
|
||||||
try {
|
try {
|
||||||
const res = await fetch(API + '/api/export?format=' + format, { headers: headers() });
|
const res = await apiFetch(API + '/api/export?format=' + format);
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const err = await res.json();
|
const err = await res.json();
|
||||||
showToast(err.error || '导出失败');
|
showToast(err.error || '导出失败');
|
||||||
@@ -88,9 +88,9 @@ async function confirmImport() {
|
|||||||
if (!pendingImportContent) return;
|
if (!pendingImportContent) return;
|
||||||
showToast('正在导入...');
|
showToast('正在导入...');
|
||||||
try {
|
try {
|
||||||
const res = await fetch(API + '/api/import', {
|
const res = await apiFetch(API + '/api/import', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'text/plain; charset=utf-8', 'Authorization': 'Bearer ' + token },
|
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
|
||||||
body: pendingImportContent
|
body: pendingImportContent
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|||||||
@@ -159,9 +159,8 @@ async function submitRecord() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(API + '/api/records', {
|
const res = await apiFetch(API + '/api/records', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: headers(),
|
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
});
|
});
|
||||||
if (!res.ok) { showToast('保存失败'); return; }
|
if (!res.ok) { showToast('保存失败'); return; }
|
||||||
|
|||||||
Reference in New Issue
Block a user