feat: 忘记密码/修改密码 + 设置页结构重组 + barrel cleanup + LoginPage 版本统一

新增:
  - ForgotPasswordModal — 手机号+短信验证码重置密码 (AuthAPI.resetPassword)
  - ChangePasswordModal — 当前密码验证后修改密码 (AuthAPI.changePassword)
  - useSmsCooldown Hook — 通用短信发送冷却逻辑,供注册/忘记密码复用
  - PasswordSetting — 设置页账号安全区块,双选项:修改密码 / 短信验证码重置

  修改:
  - LoginForm \"忘记密码?\" 链接接入 ForgotPasswordModal(替换 TODO)
  - LoginPage 移除 edition 业务版本 UI 区分,登录/注册 Tab 全局统一
  - 设置页 Section 组件移入 blocks/ 子目录(git mv 保留历史)
  - auth.ts sendSms URL 修正: /sms/send → /send-sms

  清理:
  - settings/index.ts 移除 4 个未使用 re-export,精简为仅 SettingsPage
  - navbar/index.ts 移除未使用 re-export,精简为仅 NavBar

  文档:
  - WORKLOG.md 新增 2026-06-08 工作日志
  - ARCHITECTURE.md / PROJECT.md 更新设置页目录结构与新组件
  - TODO.md 忘记密码流程标记已完成 + 短信人机验证列入后期优化
This commit is contained in:
2026-06-08 11:58:54 +08:00
parent 7032d1c3f2
commit 0f137b21fa

View File

@@ -12,8 +12,8 @@
// - 用户可读错误信息errorMessage
// ============================================================
import { useMemo } from 'react';
import { useAppContext } from '@/contexts/app-context';
import {useMemo} from 'react';
import {useAppContext} from '@/contexts/app-context';
import {
TaskAPI,
ModelAPI,
@@ -26,7 +26,7 @@ import {
type Banner,
type ModelCategory,
} from '@/services/modules';
import { useAsyncData, useAsyncMutation } from './use-async';
import {useAsyncData, useAsyncMutation} from './use-async';
// ============================================================
// Banner
@@ -34,12 +34,12 @@ import { useAsyncData, useAsyncMutation } from './use-async';
/** 首页轮播图数据 Hook */
export function useBannerList() {
const { isLoggedIn } = useAppContext();
const {isLoggedIn} = useAppContext();
return useAsyncData<Banner[]>(
fetchBanners,
[],
{ enabled: isLoggedIn, label: 'banner-list' },
{enabled: isLoggedIn, label: 'banner-list'},
);
}
@@ -49,12 +49,12 @@ export function useBannerList() {
/** 模型列表数据 Hook按类别分别请求后合并 */
export function useModelList() {
const { isLoggedIn } = useAppContext();
const {isLoggedIn} = useAppContext();
// 使用单个 fetcher 返回合并后的结果
const result = useAsyncData<ModelsListResponseBody[]>(
async () => {
const categories: ModelCategory[] = ['txt2img', 'img2img', 'img2video', 'txt2audio'];
const categories: ModelCategory[] = ["image_to_image", "text_to_image", "image_to_video", "text_to_audio"];
const results = await Promise.allSettled(
categories.map((category) =>
ModelAPI.fetchModels({
@@ -77,7 +77,7 @@ export function useModelList() {
return allModels;
},
[],
{ enabled: isLoggedIn, label: 'model-list' },
{enabled: isLoggedIn, label: 'model-list'},
);
// 按类别分组
@@ -116,13 +116,13 @@ export interface UseTaskListParams {
* 本 Hook 仅负责数据获取、竞态控制、错误日志。
*/
export function useTaskList(params: UseTaskListParams) {
const { isLoggedIn } = useAppContext();
const { requestParams, refreshSignal = 0 } = params;
const {isLoggedIn} = useAppContext();
const {requestParams, refreshSignal = 0} = params;
return useAsyncData(
() => TaskAPI.getTaskList(requestParams),
[requestParams, refreshSignal],
{ enabled: isLoggedIn, label: 'task-list' },
{enabled: isLoggedIn, label: 'task-list'},
);
}
@@ -132,12 +132,12 @@ export function useTaskList(params: UseTaskListParams) {
/** 任务详情 HooktaskId 为 null 时不请求) */
export function useTaskDetail(taskId: string | null | undefined) {
const { isLoggedIn } = useAppContext();
const {isLoggedIn} = useAppContext();
return useAsyncData<TaskInfoItemResponseBody>(
() => TaskAPI.getTaskInfo(taskId!),
[taskId],
{ enabled: isLoggedIn && !!taskId, label: 'task-detail' },
{enabled: isLoggedIn && !!taskId, label: 'task-detail'},
);
}
@@ -162,5 +162,5 @@ export function useSubmitTask(options?: {
// ---------- 重新导出类型和工具 ----------
export { MODEL_CATEGORY_LABELS };
export type { ModelCategory, ModelsListResponseBody, TaskInfoItemResponseBody, Banner };
export {MODEL_CATEGORY_LABELS};
export type {ModelCategory, ModelsListResponseBody, TaskInfoItemResponseBody, Banner};