refactor: 重组 components/ 和 pages/ 文件结构,按职责分层

components/ 拆为三层:
  - providers/   — 状态管理(App/Theme/SettingsProvider)
  - shell/       — 应用外壳(Layout/NavBar/PageDispatcher)
  - ui/          — 通用 UI 原子(FloatingPanel/LegalTextModal)

pages/ 重命名 + 重组:
  - headers/ → panels/        NavBar 触发的面板页
  - login/   → auth/          认证模块(含注册/忘记密码)
  - settings/blocks/ → sections/
  - home/components/ → panels/ features/ controls/ hooks/
    按职责分:panels(布局壳) + features(功能面板) + controls(表单控件) + hooks

其他清理:
  - 删除空占位 Test3.tsx
  - HomeContext 从 HomeContent 拆出独立文件
  - uploadValidation 内联到 ImageInput
  - 修复过时注释(useUI → controls)
This commit is contained in:
2026-06-15 11:19:06 +08:00
parent bc33b81121
commit 0e6d996718
63 changed files with 123 additions and 123 deletions

View File

@@ -0,0 +1,57 @@
// ============================================================
// useSmsCooldown — 短信验证码发送冷却 Hook
//
// 从 RegisterForm 提取,供所有需要短信验证码的场景复用:
// - 注册RegisterForm
// - 忘记密码ForgotPasswordModal
// ============================================================
import { useState, useCallback, useRef, useEffect } from 'react';
export interface SmsCooldownState {
/** 是否在冷却中 */
cooldown: boolean;
/** 冷却剩余秒数 */
secondsLeft: number;
/** 开始冷却 */
startCooldown: () => void;
}
export function useSmsCooldown(cooldownSeconds: number = 60): SmsCooldownState {
const [cooldown, setCooldown] = useState(false);
const [secondsLeft, setSecondsLeft] = useState(0);
const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
const startCooldown = useCallback(() => {
// 清理之前的计时器(防止重复点击导致多个计时器叠加)
if (timerRef.current) {
clearInterval(timerRef.current);
}
setCooldown(true);
setSecondsLeft(cooldownSeconds);
timerRef.current = setInterval(() => {
setSecondsLeft((prev) => {
if (prev <= 1) {
if (timerRef.current) {
clearInterval(timerRef.current);
timerRef.current = null;
}
setCooldown(false);
return 0;
}
return prev - 1;
});
}, 1000);
}, [cooldownSeconds]);
// 组件卸载时清理计时器
useEffect(() => {
return () => {
if (timerRef.current) {
clearInterval(timerRef.current);
}
};
}, []);
return { cooldown, secondsLeft, startCooldown };
}