feat: 管理端板块管理与旧版数据导入,补充部署运营文档
- 新增管理端板块管理页面与后端接口(admin_board) - 新增旧版数据导入:legacyimport 服务、导入面板、importusers 命令行工具 - 聊天用户卡片、板块图标等 UI 组件与界面优化 - 补充 about/公告/1Panel 部署等文档 - gitignore 排除 dist/ 构建产物与 .agents/ 本地工具目录
This commit is contained in:
@@ -38,6 +38,14 @@ export default function LoginPage() {
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [retryAfter, setRetryAfter] = useState(0);
|
||||
|
||||
// 登录限流倒计时:窗口期内禁用提交,避免无意义请求与提示条消失重现的闪烁
|
||||
useEffect(() => {
|
||||
if (retryAfter <= 0) return;
|
||||
const t = setTimeout(() => setRetryAfter((s) => s - 1), 1000);
|
||||
return () => clearTimeout(t);
|
||||
}, [retryAfter]);
|
||||
|
||||
// 已登录用户访问登录页:直接回落到安全的跳转目标
|
||||
useEffect(() => {
|
||||
@@ -52,7 +60,7 @@ export default function LoginPage() {
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setError("");
|
||||
// 提交不清空 error:提示条消失又重现会造成表单跳动(闪烁),输入时再清除
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await apiLogin(username, password);
|
||||
@@ -63,6 +71,9 @@ export default function LoginPage() {
|
||||
router.refresh();
|
||||
} else {
|
||||
setError(res.error || "登录失败");
|
||||
if (typeof res.retry_after === "number" && res.retry_after > 0) {
|
||||
setRetryAfter(res.retry_after);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
@@ -96,7 +107,10 @@ export default function LoginPage() {
|
||||
id="login-username"
|
||||
type="text"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setUsername(e.target.value);
|
||||
setError("");
|
||||
}}
|
||||
required
|
||||
autoFocus
|
||||
autoComplete="username"
|
||||
@@ -110,15 +124,18 @@ export default function LoginPage() {
|
||||
id="login-password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setPassword(e.target.value);
|
||||
setError("");
|
||||
}}
|
||||
required
|
||||
autoComplete="current-password"
|
||||
className="field"
|
||||
placeholder="输入密码"
|
||||
/>
|
||||
</div>
|
||||
<button type="submit" disabled={loading} className="btn btn-primary w-full justify-center mt-2">
|
||||
{loading ? "登录中..." : "登录"}
|
||||
<button type="submit" disabled={loading || retryAfter > 0} className="btn btn-primary w-full justify-center mt-2">
|
||||
{loading ? "登录中..." : retryAfter > 0 ? `${retryAfter} 秒后可重试` : "登录"}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user