diff --git a/src/components/AppProvider.tsx b/src/components/AppProvider.tsx index 4fa2a8c..f5ad76c 100644 --- a/src/components/AppProvider.tsx +++ b/src/components/AppProvider.tsx @@ -12,11 +12,10 @@ import type { Platform, Edition } from '@shared/types'; import { getPlatform, isDev } from '@/utils/platform'; import { safeIpcOn, safeIpcOff } from '@/utils/ipc'; -import type { LoginResponseBody } from '@/services/modules'; +import { AuthAPI, type LoginResponseBody } from '@/services/modules/auth'; import { setToken, clearToken, initTokenStore } from '@/services/request'; import { emit, EVENTS } from '@/utils/event-bus'; import { logger } from '@/utils/logger'; -import { AuthAPI } from '@/services/modules'; import { getAutoLoginFlag, clearAutoLoginFlag } from '@/services/auth-persistence'; import { initAuthRefresh, diff --git a/src/components/PageDispatcher.tsx b/src/components/PageDispatcher.tsx index b7b2275..ee06041 100644 --- a/src/components/PageDispatcher.tsx +++ b/src/components/PageDispatcher.tsx @@ -7,21 +7,18 @@ // - floating → FloatingPanel(非模态浮动面板,可拖拽,不阻断交互) // // 支持多面板共存(floating 类型可同时打开多个) +// +// PAGE_MAP 集中注册所有可调度页面: +// 有真实组件 → { component: XxxPage } +// 占位页面 → 只写 label,自动渲染 PlaceholderPage +// 新增页面只需在这里加一行,无需创建独立文件 // ============================================================ -import {useState, useEffect, useCallback, useRef, type ComponentType} from 'react'; -import {Modal, Drawer} from 'antd'; -import {on, off, EVENTS} from '@/utils/event-bus'; -import {FloatingPanel} from '@/components/ui/FloatingPanel'; -import {ComplianceAssetsPage} from '@/pages/compliance-assets/ComplianceAssetsPage'; -import {AccountPage} from '@/pages/account/AccountPage'; -import {VipPage} from '@/pages/vip/VipPage'; -import {RechargePage} from '@/pages/recharge/RechargePage'; -import {BillingPage} from '@/pages/billing/BillingPage'; -import {OrdersPage} from '@/pages/orders/OrdersPage'; -import {ProjectsPage} from '@/pages/projects/ProjectsPage'; -import {QuotaPage} from '@/pages/quota/QuotaPage'; -import {WechatWorkPage} from '@/pages/wechat-work/WechatWorkPage'; +import { useState, useEffect, useCallback, useRef, type ComponentType } from 'react'; +import { Modal, Drawer } from 'antd'; +import { on, off, EVENTS } from '@/utils/event-bus'; +import { FloatingPanel } from '@/components/ui/FloatingPanel'; +import { WechatWorkPage } from '@/pages/wechat-work/WechatWorkPage'; // ---------- 类型 ---------- @@ -39,20 +36,54 @@ interface ActivePanel { label: string; } -// ---------- target → 页面组件映射 ---------- +interface PageConfig { + /** 页面组件(未提供则使用占位组件) */ + component?: ComponentType; + /** 页面标签(显示在容器标题栏) */ + label: string; +} -const PAGE_MAP: Record = { - '/compliance-assets': ComplianceAssetsPage, - '/account': AccountPage, - '/vip': VipPage, - '/recharge': RechargePage, - '/billing': BillingPage, - '/orders': OrdersPage, - '/projects': ProjectsPage, - '/quota': QuotaPage, - '/wechat-work': WechatWorkPage, +// ---------- 占位组件 ---------- + +function PlaceholderPage({ label }: { label: string }) { + return ( +
+

{label} — 页面开发中

+
+ ); +} + +/** 创建一个包装了 label 的稳定占位组件(模块级,避免渲染时重建) */ +function makePlaceholder(label: string): ComponentType { + const Placeholder = () => ; + return Placeholder; +} + +// ---------- target → 页面组件映射 ---------- +// +// 新增页面只需在此加一行 —— +// 有自定义组件:{ component: XxxPage, label: '页面标题' } +// 占位页面: { label: '页面标题' } ← 自动渲染 "页面标题 — 页面开发中" + +const PAGE_MAP: Record = { + '/wechat-work': { component: WechatWorkPage, label: '企业微信' }, + '/compliance-assets': { label: '合规素材库' }, + '/account': { label: '查帐户' }, + '/vip': { label: '开会员/激活' }, + '/recharge': { label: '充值积分' }, + '/billing': { label: '消费记录' }, + '/orders': { label: '订单明细' }, + '/projects': { label: '项目管理' }, + '/quota': { label: '查配额' }, }; +/** 解析页面组件:有自定义组件用自定义,否则用占位 */ +function resolvePage(target: string): ComponentType | null { + const config = PAGE_MAP[target]; + if (!config) return null; + return config.component || makePlaceholder(config.label); +} + // ---------- 组件 ---------- export function PageDispatcher() { @@ -66,7 +97,7 @@ export function PageDispatcher() { // 监听 OPEN_PAGE 事件 useEffect(() => { const handler = (payload: unknown) => { - const {target, modalType, label} = payload as PageEventPayload; + const { target, modalType, label } = payload as PageEventPayload; if (!target || !PAGE_MAP[target]) { console.warn(`[PageDispatcher] 未找到页面组件: ${target}`); @@ -76,10 +107,10 @@ export function PageDispatcher() { if (modalType === 'floating') { // 浮动面板:追加到列表 const id = `fp-${nextIdRef.current++}`; - setFloatingPanels((prev) => [...prev, {id, target, label}]); + setFloatingPanels((prev) => [...prev, { id, target, label }]); } else { // modal / drawer:单实例,覆盖之前的 - setSingleton({target, modalType, label}); + setSingleton({ target, modalType, label }); } }; @@ -98,7 +129,7 @@ export function PageDispatcher() { }, []); // 单实例对应的页面组件 - const SingletonPage = singleton ? PAGE_MAP[singleton.target] : null; + const SingletonPage = singleton ? resolvePage(singleton.target) : null; return ( <> @@ -111,9 +142,7 @@ export function PageDispatcher() { onCancel={closeSingleton} footer={null} destroyOnHidden={true} - mask={{ - closable: true, - }} + mask={{ closable: true }} width={640} > @@ -135,7 +164,7 @@ export function PageDispatcher() { {/* ======== Floating Panels ======== */} {floatingPanels.map((panel) => { - const PageContent = PAGE_MAP[panel.target]; + const PageContent = resolvePage(panel.target); if (!PageContent) return null; return ( diff --git a/src/components/navbar/AnnouncementDrawer.tsx b/src/components/navbar/AnnouncementDrawer.tsx index 85074aa..9d37eb3 100644 --- a/src/components/navbar/AnnouncementDrawer.tsx +++ b/src/components/navbar/AnnouncementDrawer.tsx @@ -7,7 +7,7 @@ import {useEffect, useState, useCallback} from 'react'; import {Drawer, Card, Typography, Empty, Tag, Spin, Modal, Tooltip} from 'antd'; import {NotificationOutlined} from '@ant-design/icons'; -import {fetchAnnouncements, type Announcement, AnnouncementListResponse} from '@/services/modules'; +import { fetchAnnouncements, type Announcement, type AnnouncementListResponse } from '@/services/modules/announcement'; const {Text, Paragraph} = Typography; diff --git a/src/hooks/use-api.ts b/src/hooks/use-api.ts index 7735354..c1814fa 100644 --- a/src/hooks/use-api.ts +++ b/src/hooks/use-api.ts @@ -14,18 +14,9 @@ import {useMemo} from 'react'; import {useAppContext} from '@/components/AppProvider'; -import { - TaskAPI, - ModelAPI, - fetchBanners, - MODEL_CATEGORY_LABELS, - type TaskListRequestParams, - type TaskInfoItemResponseBody, - type CreatTaskRequestBody, - type ModelsListResponseBody, - type Banner, - type ModelCategoryStringEnum, -} from '@/services/modules'; +import { TaskAPI, type TaskListRequestParams, type TaskInfoItemResponseBody, type CreatTaskRequestBody } from '@/services/modules/task'; +import { ModelAPI, MODEL_CATEGORY_LABELS, type ModelsListResponseBody, type ModelCategoryStringEnum } from '@/services/modules/models'; +import { fetchBanners, type Banner } from '@/services/modules/banner'; import {useAsyncData, UseAsyncDataReturn, useAsyncMutation} from './use-async'; // ============================================================ diff --git a/src/pages/account/AccountPage.tsx b/src/pages/account/AccountPage.tsx deleted file mode 100644 index 5a012c5..0000000 --- a/src/pages/account/AccountPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================ -// AccountPage — 查帐户(占位组件,后续实现具体功能) -// ============================================================ - -export function AccountPage() { - return ( -
-

查帐户 — 页面开发中

-
- ); -} diff --git a/src/pages/billing/BillingPage.tsx b/src/pages/billing/BillingPage.tsx deleted file mode 100644 index d491b00..0000000 --- a/src/pages/billing/BillingPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================ -// BillingPage — 消费记录(占位组件,后续实现具体功能) -// ============================================================ - -export function BillingPage() { - return ( -
-

消费记录 — 页面开发中

-
- ); -} diff --git a/src/pages/compliance-assets/ComplianceAssetsPage.tsx b/src/pages/compliance-assets/ComplianceAssetsPage.tsx deleted file mode 100644 index 8503865..0000000 --- a/src/pages/compliance-assets/ComplianceAssetsPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================ -// ComplianceAssetsPage — 合规素材库(占位组件,后续实现具体功能) -// ============================================================ - -export function ComplianceAssetsPage() { - return ( -
-

合规素材库 — 页面开发中

-
- ); -} diff --git a/src/pages/home/HomeContent.tsx b/src/pages/home/HomeContent.tsx index 5699b9e..1270a12 100644 --- a/src/pages/home/HomeContent.tsx +++ b/src/pages/home/HomeContent.tsx @@ -7,7 +7,8 @@ import { createContext, useContext, useState, useCallback, useRef, useEffect, us import { theme as antTheme, Empty } from 'antd'; import { useAppContext } from '@/components/AppProvider'; -import type { ModelsListResponseBody, TaskInfoItemResponseBody } from '@/services/modules'; +import type { ModelsListResponseBody } from '@/services/modules/models'; +import type { TaskInfoItemResponseBody } from '@/services/modules/task'; import { LeftPanel } from './components/LeftPanel'; import { CenterPanel } from './components/CenterPanel'; import { RightPanel } from './components/RightPanel'; diff --git a/src/pages/home/components/BannerCarousel.tsx b/src/pages/home/components/BannerCarousel.tsx index 3654bc1..cb23e32 100644 --- a/src/pages/home/components/BannerCarousel.tsx +++ b/src/pages/home/components/BannerCarousel.tsx @@ -14,7 +14,7 @@ import { CloseOutlined } from '@ant-design/icons'; import type { CarouselRef } from 'antd/es/carousel'; import { useBannerList } from '@/hooks/use-api'; -import type { Banner } from '@/services/modules'; +import type { Banner } from '@/services/modules/banner'; // ---------- 组件 Props ---------- diff --git a/src/pages/home/components/ModelInputForm.tsx b/src/pages/home/components/ModelInputForm.tsx index 8cd80a7..7693c00 100644 --- a/src/pages/home/components/ModelInputForm.tsx +++ b/src/pages/home/components/ModelInputForm.tsx @@ -29,7 +29,8 @@ import { useHomeContext } from '@/pages/home/HomeContent'; import { useAppContext } from '@/components/AppProvider'; import { useSubmitTask } from '@/hooks/use-api'; import { emit, EVENTS } from '@/utils/event-bus'; -import type { ModelsListResponseBody, TaskInfoItemResponseBody } from '@/services/modules'; +import type { ModelsListResponseBody } from '@/services/modules/models'; +import type { TaskInfoItemResponseBody } from '@/services/modules/task'; const { Text, Title } = Typography; const { TextArea } = Input; diff --git a/src/pages/home/components/ModelSelector.tsx b/src/pages/home/components/ModelSelector.tsx index edada3c..3f209ef 100644 --- a/src/pages/home/components/ModelSelector.tsx +++ b/src/pages/home/components/ModelSelector.tsx @@ -9,8 +9,7 @@ import { AppstoreOutlined } from '@ant-design/icons'; import { useModelList } from '@/hooks/use-api'; import { useHomeContext } from '@/pages/home/HomeContent'; -import { resolveCategoryLabel, MODEL_CATEGORIES } from '@/services/modules'; -import type { ModelsListResponseBody, ModelCategoryStringEnum } from '@/services/modules'; +import { resolveCategoryLabel, MODEL_CATEGORIES, type ModelsListResponseBody, type ModelCategoryStringEnum } from '@/services/modules/models'; const { Text } = Typography; diff --git a/src/pages/home/components/OutputPreview.tsx b/src/pages/home/components/OutputPreview.tsx index 4adae40..e8654f0 100644 --- a/src/pages/home/components/OutputPreview.tsx +++ b/src/pages/home/components/OutputPreview.tsx @@ -13,7 +13,7 @@ import { import { useHomeContext } from '@/pages/home/HomeContent'; import { useTaskDetail } from '@/hooks/use-api'; -import type { TaskStatusString } from '@/services/modules'; +import type { TaskStatusString } from '@/services/modules/task'; const { Text } = Typography; diff --git a/src/pages/home/components/TaskHistory.tsx b/src/pages/home/components/TaskHistory.tsx index 79b6b7e..0dd3476 100644 --- a/src/pages/home/components/TaskHistory.tsx +++ b/src/pages/home/components/TaskHistory.tsx @@ -26,8 +26,8 @@ import type { TaskInfoItemResponseBody, TaskListRequestParams, TaskStatusString, -} from '@/services/modules'; -import { TaskStatusMap, OutputTypeMap } from '@/services/modules'; +} from '@/services/modules/task'; +import { TaskStatusMap, OutputTypeMap } from '@/services/modules/task'; const { Text } = Typography; diff --git a/src/pages/login/components/ChangePasswordModal.tsx b/src/pages/login/components/ChangePasswordModal.tsx index 954839b..72b0c8f 100644 --- a/src/pages/login/components/ChangePasswordModal.tsx +++ b/src/pages/login/components/ChangePasswordModal.tsx @@ -13,7 +13,7 @@ import { Modal, Input, Button, Typography, App } from 'antd'; import { LockOutlined, KeyOutlined, SafetyOutlined } from '@ant-design/icons'; import { useTheme } from '@/components/ThemeProvider'; -import { AuthAPI } from '@/services/modules'; +import { AuthAPI } from '@/services/modules/auth'; import { validatePassword, validateConfirmPassword } from '../config/validators'; const { Text, Title } = Typography; diff --git a/src/pages/login/components/ForgotPasswordModal.tsx b/src/pages/login/components/ForgotPasswordModal.tsx index 485a2b1..5c622bd 100644 --- a/src/pages/login/components/ForgotPasswordModal.tsx +++ b/src/pages/login/components/ForgotPasswordModal.tsx @@ -19,7 +19,7 @@ import { } from '@ant-design/icons'; import { useTheme } from '@/components/ThemeProvider'; -import { AuthAPI } from '@/services/modules'; +import { AuthAPI } from '@/services/modules/auth'; import { validatePhone, validateSmsCode, diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index 10f2246..211a097 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -16,7 +16,7 @@ import { LoginForm } from './components/LoginForm'; import { RegisterForm } from './components/RegisterForm'; import { ForgotPasswordModal } from './components/ForgotPasswordModal'; import { useAuthState } from './hooks/use-auth-state'; -import { AuthAPI, LoginResponseBody } from '@/services/modules'; +import { AuthAPI, type LoginResponseBody } from '@/services/modules/auth'; import { getDeviceId } from '@/utils/device'; import type { LoginFormValues, RegisterFormValues } from './types'; diff --git a/src/pages/orders/OrdersPage.tsx b/src/pages/orders/OrdersPage.tsx deleted file mode 100644 index 57277ba..0000000 --- a/src/pages/orders/OrdersPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================ -// OrdersPage — 订单明细(占位组件,后续实现具体功能) -// ============================================================ - -export function OrdersPage() { - return ( -
-

订单明细 — 页面开发中

-
- ); -} diff --git a/src/pages/projects/ProjectsPage.tsx b/src/pages/projects/ProjectsPage.tsx deleted file mode 100644 index 61d55fa..0000000 --- a/src/pages/projects/ProjectsPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================ -// ProjectsPage — 项目管理(占位组件,后续实现具体功能) -// ============================================================ - -export function ProjectsPage() { - return ( -
-

项目管理 — 页面开发中

-
- ); -} diff --git a/src/pages/quota/QuotaPage.tsx b/src/pages/quota/QuotaPage.tsx deleted file mode 100644 index 62e5e3c..0000000 --- a/src/pages/quota/QuotaPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================ -// QuotaPage — 查配额(占位组件,后续实现具体功能) -// ============================================================ - -export function QuotaPage() { - return ( -
-

查配额 — 页面开发中

-
- ); -} diff --git a/src/pages/recharge/RechargePage.tsx b/src/pages/recharge/RechargePage.tsx deleted file mode 100644 index d6c8907..0000000 --- a/src/pages/recharge/RechargePage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================ -// RechargePage — 充值积分(占位组件,后续实现具体功能) -// ============================================================ - -export function RechargePage() { - return ( -
-

充值积分 — 页面开发中

-
- ); -} diff --git a/src/pages/vip/VipPage.tsx b/src/pages/vip/VipPage.tsx deleted file mode 100644 index 65a9e47..0000000 --- a/src/pages/vip/VipPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================ -// VipPage — 开会员/激活(占位组件,后续实现具体功能) -// ============================================================ - -export function VipPage() { - return ( -
-

开会员/激活 — 页面开发中

-
- ); -} diff --git a/src/pages/wechat-work/WechatWorkPage.tsx b/src/pages/wechat-work/WechatWorkPage.tsx index 78bfbed..39bbbac 100644 --- a/src/pages/wechat-work/WechatWorkPage.tsx +++ b/src/pages/wechat-work/WechatWorkPage.tsx @@ -11,7 +11,7 @@ import { useEffect, useState, useCallback } from 'react'; import { Spin, Empty } from 'antd'; import { WechatOutlined } from '@ant-design/icons'; -import { fetchBanners, type Banner } from '@/services/modules'; +import { fetchBanners, type Banner } from '@/services/modules/banner'; export function WechatWorkPage() { const [banner, setBanner] = useState(null); diff --git a/src/services/auth-token.ts b/src/services/auth-token.ts index 3202de5..1e82f98 100644 --- a/src/services/auth-token.ts +++ b/src/services/auth-token.ts @@ -12,8 +12,7 @@ // ============================================================ import { setToken, setTokenRefreshHandler } from './request'; -import { AuthAPI } from './modules'; -import type { RefreshTokenResponseBody } from './modules'; +import { AuthAPI, type RefreshTokenResponseBody } from './modules/auth'; import { getSafeStore, setSafeStore, diff --git a/src/services/modules/index.ts b/src/services/modules/index.ts deleted file mode 100644 index 5b398e3..0000000 --- a/src/services/modules/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -// ============================================================ -// API 模块统一导出 -// ============================================================ - -export { - fetchAnnouncements, - type Announcement, - type AnnouncementType, - type AnnouncementListResponse, -} from './announcement'; - -export { - AuthAPI, - type SendSMSRequestBody, - type RegisterRequestBody, - type RegisterResponseBody, - type LoginRequestBody, - type LoginResponseBody, - type RefreshTokenRequestBody, - type RefreshTokenResponseBody, - type UserInfoBody, - type ChangePasswordRequestBody, - type UsePhoneResetPasswordRequestBody, -} from './auth'; - -export { - fetchBanners, - type Banner, - type BannerListResponse, -} from './banner'; - -export { - ModelAPI, - MODEL_CATEGORIES, - MODEL_CATEGORY_LABELS, - CATEGORY_SLUG_MAP, - resolveCategoryLabel, - toCategorySlug, - type ModelsListReqeustParams, - type ModelsListResponseBody, - type ModelInfoRequestParams, - type ModelInfoResponseBody, - type ModelCategoryStringEnum, - type ParamSchemaItem, -} from './models'; - -export { - TaskAPI, - OutputTypeMap, - TaskStatusMap, - type OutputTypeString, - type TaskStatusString, - type TaskListRequestParams, - type CreatTaskRequestBody, - type ExportTaskCSVParams, - type ContentItem, - type ImageUiParams, - type VideoUiParams, - type AudioUiParams, - type TaskInfoItemResponseBody, - type TaskInfoDataResponseBody, - type TaskStatusResponseBody, -} from './task';