10 KiB
10 KiB
Design Document: 代码拆分重构
Overview
本设计文档描述如何将三个大型代码文件拆分为更小、更可维护的模块。采用 React 自定义 Hooks 和组件拆分的方式,遵循单一职责原则。
Architecture
components/
├── upload/ # 上传相关组件(已有部分)
│ ├── UploadModal.tsx # 主组件(重构后)
│ ├── UploadForm.tsx # 新增:表单字段组件
│ ├── SpecialBatchUploadUI.tsx # 新增:特殊批量上传UI
│ └── ... (已有文件保持不变)
├── admin/ # 新增:管理后台组件
│ ├── UserManagement.tsx
│ ├── MaterialManagement.tsx
│ ├── CategoryManagement.tsx
│ ├── SystemSettings.tsx
│ └── AdminStats.tsx
└── home/ # 新增:首页组件
├── FilterPanel.tsx
├── MaterialGrid.tsx
├── MaterialDetailModal.tsx
├── SearchBar.tsx
└── Pagination.tsx
hooks/
├── useUploadState.ts # 新增:上传状态管理
├── useCategoryData.ts # 新增:分类数据获取
├── useBatchUpload.ts # 新增:批量上传逻辑
├── useDragHandlers.ts # 新增:拖拽处理
├── useAdminState.ts # 新增:管理后台状态
├── useHomeState.ts # 新增:首页状态
└── useMaterials.ts # 新增:素材数据获取
Components and Interfaces
1. UploadModal 拆分
useUploadState Hook
// hooks/useUploadState.ts
interface UploadState {
// 文件状态
previewImages: File[]
previewUrls: string[]
displayImage: File | null
displayImageUrl: string
modelImages: File[]
modelImageUrls: string[]
zipFile: File | null
// 表单状态
productModel: string
categoryName: string
sceneName: string
platformName: string
productCategoryName: string
materialType: string
renderer: string
// 上传状态
uploading: boolean
uploadProgress: number
uploadSpeed: number
isProcessing: boolean
error: string
// 批量上传状态
batchFiles: BatchFileItem[]
isBatchMode: boolean
batchUploadStatus: BatchUploadStatus | null
}
export function useUploadState(): {
state: UploadState
actions: UploadStateActions
}
useCategoryData Hook
// hooks/useCategoryData.ts
interface CategoryData {
categories: Array<{ id: string; name: string }>
scenes: Array<{ id: string; name: string }>
platforms: Array<{ id: string; name: string }>
productCategories: Array<{ id: string; name: string }>
}
export function useCategoryData(): {
data: CategoryData
loading: boolean
refresh: () => Promise<void>
}
useBatchUpload Hook
// hooks/useBatchUpload.ts
export function useBatchUpload(materialType: string): {
// 特殊类型批量文件
batchMusicFiles: Array<{ file: File; productModel: string }>
batchVideoFiles: Array<{ file: File; productModel: string }>
batch3DFiles: Array<{ file: File; productModel: string; previewImage?: File }>
batchBrandVIFiles: Array<{ file: File; productModel: string }>
batchBuyerShowFiles: Array<{ productModel: string; images: File[] }>
batchXiaohongshuFiles: Array<{ productModel: string; images: File[] }>
// 操作函数
handleBatchFileSelect: (e: React.ChangeEvent<HTMLInputElement>) => void
handleBatchMusicUpload: () => Promise<void>
handleCancelBatchUpload: () => Promise<void>
// ... 其他批量上传函数
}
useDragHandlers Hook
// hooks/useDragHandlers.ts
export function useDragHandlers(): {
isDragging: boolean
isPreviewDragging: boolean
isDisplayImageDragging: boolean
handleDragEnter: (e: React.DragEvent) => void
handleDragLeave: (e: React.DragEvent) => void
handleDragOver: (e: React.DragEvent) => void
handleDrop: (e: React.DragEvent) => void
handlePreviewDrop: (e: React.DragEvent) => void
handleDisplayImageDrop: (e: React.DragEvent) => void
}
UploadForm Component
// components/upload/UploadForm.tsx
interface UploadFormProps {
materialType: string
productModel: string
categoryName: string
sceneName: string
platformName: string
productCategoryName: string
renderer: string
categories: Array<{ id: string; name: string }>
scenes: Array<{ id: string; name: string }>
platforms: Array<{ id: string; name: string }>
productCategories: Array<{ id: string; name: string }>
onProductModelChange: (value: string) => void
onCategoryChange: (value: string) => void
onSceneChange: (value: string) => void
onPlatformChange: (value: string) => void
onProductCategoryChange: (value: string) => void
onRendererChange: (value: string) => void
onAddCategory: (name: string) => Promise<void>
onAddScene: (name: string) => Promise<void>
}
2. AdminPage 拆分
useAdminState Hook
// hooks/useAdminState.ts
interface AdminState {
activeTab: 'materials' | 'users' | 'categories' | 'departments' | 'permissions' | 'superAdmins'
materials: Material[]
users: User[]
categories: Category[]
scenes: Scene[]
platforms: Platform[]
productCategories: ProductCategory[]
loading: boolean
// ... 其他状态
}
export function useAdminState(): {
state: AdminState
actions: AdminStateActions
}
Admin Components
// components/admin/UserManagement.tsx
interface UserManagementProps {
users: User[]
departments: Department[]
onUpdateUser: (userId: string, data: Partial<User>) => Promise<void>
onDeleteUser: (userId: string) => Promise<void>
}
// components/admin/MaterialManagement.tsx
interface MaterialManagementProps {
materials: Material[]
showRecycleBin: boolean
onDelete: (ids: string[]) => Promise<void>
onRestore: (ids: string[]) => Promise<void>
onSearch: (keyword: string) => void
}
// components/admin/CategoryManagement.tsx
interface CategoryManagementProps {
categories: Category[]
scenes: Scene[]
platforms: Platform[]
productCategories: ProductCategory[]
onAdd: (type: string, name: string) => Promise<void>
onEdit: (type: string, id: string, name: string) => Promise<void>
onDelete: (type: string, id: string) => Promise<void>
}
3. HomePage 拆分
useHomeState Hook
// hooks/useHomeState.ts
interface HomeState {
searchKeyword: string
selectedCategory: string
selectedScene: string
selectedMaterialType: string
selectedPlatform: string
selectedProductCategory: string
selectedMonth: string
sortBy: string
sortOrder: 'asc' | 'desc'
isFilterCollapsed: boolean
}
export function useHomeState(): {
state: HomeState
actions: HomeStateActions
}
useMaterials Hook
// hooks/useMaterials.ts
interface UseMaterialsOptions {
searchKeyword: string
selectedCategory: string
selectedScene: string
selectedMaterialType: string
selectedPlatform: string
selectedProductCategory: string
selectedMonth: string
sortBy: string
sortOrder: 'asc' | 'desc'
}
export function useMaterials(options: UseMaterialsOptions): {
materials: Material[]
loading: boolean
hasMore: boolean
totalCount: number
loadMore: () => Promise<void>
refresh: () => Promise<void>
}
Home Components
// components/home/FilterPanel.tsx
interface FilterPanelProps {
categories: Category[]
scenes: Scene[]
platforms: Platform[]
productCategories: ProductCategory[]
materialTypes: MaterialType[]
months: Month[]
selectedCategory: string
selectedScene: string
selectedMaterialType: string
selectedPlatform: string
selectedProductCategory: string
selectedMonth: string
sortBy: string
sortOrder: 'asc' | 'desc'
isCollapsed: boolean
onCategoryChange: (value: string) => void
onSceneChange: (value: string) => void
onMaterialTypeChange: (value: string) => void
onPlatformChange: (value: string) => void
onProductCategoryChange: (value: string) => void
onMonthChange: (value: string) => void
onSortByChange: (value: string) => void
onSortOrderChange: (value: 'asc' | 'desc') => void
onToggleCollapse: () => void
}
// components/home/MaterialGrid.tsx
interface MaterialGridProps {
materials: Material[]
loading: boolean
onMaterialClick: (material: Material) => void
onDownload: (material: Material) => void
onLike: (material: Material) => void
onFavorite: (material: Material) => void
onShare: (material: Material) => void
}
// components/home/SearchBar.tsx
interface SearchBarProps {
value: string
onChange: (value: string) => void
placeholder?: string
}
// components/home/Pagination.tsx
interface PaginationProps {
hasMore: boolean
isLoading: boolean
onLoadMore: () => void
}
Data Models
数据模型保持不变,继续使用现有的 Prisma 模型和 TypeScript 接口。
Correctness Properties
A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.
由于本次重构主要是代码组织优化,不涉及业务逻辑变更,因此主要通过以下方式验证正确性:
- 构建验证: 重构后代码能够成功通过 TypeScript 编译和 Next.js 构建
- 行数验证: 主文件行数符合目标要求
- 功能验证: 通过手动测试确保所有功能正常工作
Error Handling
- 拆分后的 Hooks 和组件应保持原有的错误处理逻辑
- 新增的 Hooks 应提供统一的错误状态和错误处理回调
- 组件间通过 props 传递错误信息,保持错误边界清晰
Testing Strategy
验证方式
- TypeScript 类型检查: 运行
npx tsc --noEmit确保无类型错误 - ESLint 检查: 运行
npm run lint确保代码风格一致 - 构建测试: 运行
npm run build确保能够成功构建 - 手动功能测试:
- 测试上传弹窗的所有上传类型
- 测试管理后台的所有功能标签页
- 测试首页的筛选、搜索、分页功能
回归测试清单
- 单个文件上传(各种素材类型)
- 批量文件上传(音乐、视频、3D场景等)
- 拖拽上传
- 分类/场景/平台筛选
- 搜索功能
- 分页加载
- 用户管理
- 素材管理(删除、恢复)
- 分类管理(增删改)