v1.0.0提交

This commit is contained in:
2026-03-31 15:54:32 +08:00
parent 79bfeb0e18
commit 314e53bf9c
16 changed files with 2110 additions and 1 deletions

216
login.php Normal file
View File

@@ -0,0 +1,216 @@
<?php
/**
* PerToolBox Front - 登录/注册页面
*
* Copyright (C) 2024 Sea Network Technology Studio
* Author: Canglan <admin@sea-studio.top>
* License: AGPL v3
*/
require_once 'config.php';
include_once 'header.php';
include_once 'sidebar.php';
?>
<div class="main-content">
<div class="max-w-md mx-auto">
<div class="card">
<div class="flex border-b mb-6">
<button id="tabLogin" class="flex-1 py-2 text-center font-semibold text-blue-600 border-b-2 border-blue-600">登录</button>
<button id="tabRegister" class="flex-1 py-2 text-center text-gray-500">注册</button>
</div>
<!-- 登录表单 -->
<div id="loginForm">
<div class="mb-4">
<label class="form-label">手机号 / 邮箱</label>
<input type="text" id="loginAccount" class="form-input" placeholder="请输入手机号或邮箱">
</div>
<div class="mb-4">
<label class="form-label">密码 / 验证码</label>
<div class="flex gap-2">
<input type="text" id="loginPassword" class="form-input flex-1" placeholder="密码或验证码">
<button id="loginCodeBtn" class="btn btn-secondary whitespace-nowrap">获取验证码</button>
</div>
</div>
<button id="loginBtn" class="btn btn-primary w-full">登录</button>
</div>
<!-- 注册表单 -->
<div id="registerForm" style="display: none;">
<div class="mb-4">
<label class="form-label">手机号 / 邮箱</label>
<input type="text" id="registerAccount" class="form-input" placeholder="请输入手机号或邮箱">
</div>
<div class="mb-4">
<label class="form-label">验证码</label>
<div class="flex gap-2">
<input type="text" id="registerCode" class="form-input flex-1" placeholder="验证码">
<button id="registerCodeBtn" class="btn btn-secondary whitespace-nowrap">获取验证码</button>
</div>
</div>
<div class="mb-4">
<label class="form-label">密码</label>
<input type="password" id="registerPassword" class="form-input" placeholder="6-20位密码">
</div>
<button id="registerBtn" class="btn btn-primary w-full">注册</button>
</div>
</div>
</div>
</div>
<script>
let loginTimer = null;
let registerTimer = null;
// 切换选项卡
document.getElementById('tabLogin').addEventListener('click', () => {
document.getElementById('loginForm').style.display = 'block';
document.getElementById('registerForm').style.display = 'none';
document.getElementById('tabLogin').className = 'flex-1 py-2 text-center font-semibold text-blue-600 border-b-2 border-blue-600';
document.getElementById('tabRegister').className = 'flex-1 py-2 text-center text-gray-500';
});
document.getElementById('tabRegister').addEventListener('click', () => {
document.getElementById('loginForm').style.display = 'none';
document.getElementById('registerForm').style.display = 'block';
document.getElementById('tabRegister').className = 'flex-1 py-2 text-center font-semibold text-blue-600 border-b-2 border-blue-600';
document.getElementById('tabLogin').className = 'flex-1 py-2 text-center text-gray-500';
});
// 获取验证码
function startCountdown(btn, timerVar, seconds = 60) {
let count = seconds;
btn.disabled = true;
btn.textContent = `${count}秒后重试`;
const interval = setInterval(() => {
count--;
if (count <= 0) {
clearInterval(interval);
btn.disabled = false;
btn.textContent = '获取验证码';
} else {
btn.textContent = `${count}秒后重试`;
}
}, 1000);
return interval;
}
// 登录获取验证码
document.getElementById('loginCodeBtn').addEventListener('click', async () => {
const account = document.getElementById('loginAccount').value.trim();
if (!account) {
showToast('请输入手机号或邮箱', 'error');
return;
}
const type = /^1[3-9]\d{9}$/.test(account) ? 'phone' : 'email';
try {
await apiRequest('/auth/send-code', {
method: 'POST',
body: JSON.stringify({ account, type })
});
showToast('验证码已发送');
if (loginTimer) clearInterval(loginTimer);
loginTimer = startCountdown(document.getElementById('loginCodeBtn'), loginTimer);
} catch (error) {
showToast(error.message, 'error');
}
});
// 注册获取验证码
document.getElementById('registerCodeBtn').addEventListener('click', async () => {
const account = document.getElementById('registerAccount').value.trim();
if (!account) {
showToast('请输入手机号或邮箱', 'error');
return;
}
const type = /^1[3-9]\d{9}$/.test(account) ? 'phone' : 'email';
try {
await apiRequest('/auth/send-code', {
method: 'POST',
body: JSON.stringify({ account, type })
});
showToast('验证码已发送');
if (registerTimer) clearInterval(registerTimer);
registerTimer = startCountdown(document.getElementById('registerCodeBtn'), registerTimer);
} catch (error) {
showToast(error.message, 'error');
}
});
// 登录
document.getElementById('loginBtn').addEventListener('click', async () => {
const account = document.getElementById('loginAccount').value.trim();
const password = document.getElementById('loginPassword').value.trim();
if (!account) {
showToast('请输入账号', 'error');
return;
}
if (!password) {
showToast('请输入密码或验证码', 'error');
return;
}
try {
const result = await apiRequest('/auth/login', {
method: 'POST',
body: JSON.stringify({ account, password })
});
if (result.token) {
setToken(result.token);
showToast('登录成功');
setTimeout(() => {
window.location.href = '/';
}, 1000);
}
} catch (error) {
showToast(error.message, 'error');
}
});
// 注册
document.getElementById('registerBtn').addEventListener('click', async () => {
const account = document.getElementById('registerAccount').value.trim();
const code = document.getElementById('registerCode').value.trim();
const password = document.getElementById('registerPassword').value.trim();
if (!account) {
showToast('请输入账号', 'error');
return;
}
if (!code) {
showToast('请输入验证码', 'error');
return;
}
if (!password || password.length < 6) {
showToast('密码长度至少6位', 'error');
return;
}
try {
const result = await apiRequest('/auth/register', {
method: 'POST',
body: JSON.stringify({ account, code, password })
});
if (result.token) {
setToken(result.token);
showToast('注册成功');
setTimeout(() => {
window.location.href = '/';
}, 1000);
}
} catch (error) {
showToast(error.message, 'error');
}
});
</script>
<?php include_once 'footer.php'; ?>