| import { createSlice, type PayloadAction } from '@reduxjs/toolkit'; |
| import type { Section } from './types'; |
| |
| // 分区状态类型 |
| export interface CategoryState { |
| sections: Section[]; |
| loading: boolean; |
| error: string | null; |
| selectedCategoryId: number | null; |
| } |
| |
| // 初始状态 |
| const initialState: CategoryState = { |
| sections: [], |
| loading: false, |
| error: null, |
| selectedCategoryId: null, |
| }; |
| |
| // 创建categorySlice |
| const categorySlice = createSlice({ |
| name: 'category', |
| initialState, |
| reducers: { |
| // 设置加载状态 |
| setLoading: (state, action: PayloadAction<boolean>) => { |
| state.loading = action.payload; |
| if (action.payload) { |
| state.error = null; |
| } |
| }, |
| |
| // 设置错误信息 |
| setError: (state, action: PayloadAction<string>) => { |
| state.error = action.payload; |
| state.loading = false; |
| }, |
| |
| // 设置分区列表 |
| setSections: (state, action: PayloadAction<Section[]>) => { |
| state.sections = action.payload; |
| state.loading = false; |
| state.error = null; |
| }, |
| |
| // 添加单个分区 |
| addSection: (state, action: PayloadAction<Section>) => { |
| state.sections.push(action.payload); |
| }, |
| |
| // 更新分区 |
| updateSection: (state, action: PayloadAction<Section>) => { |
| const index = state.sections.findIndex(section => section.id === action.payload.id); |
| if (index !== -1) { |
| state.sections[index] = action.payload; |
| } |
| }, |
| |
| // 删除分区 |
| removeSection: (state, action: PayloadAction<number>) => { |
| state.sections = state.sections.filter(section => section.id !== action.payload); |
| // 如果删除的是当前选中的分区,清空选中状态 |
| if (state.selectedCategoryId === action.payload) { |
| state.selectedCategoryId = null; |
| } |
| }, |
| |
| // 设置选中的分区ID |
| setSelectedCategoryId: (state, action: PayloadAction<number | null>) => { |
| state.selectedCategoryId = action.payload; |
| }, |
| |
| // 向分区添加作品ID |
| addArtworkToSection: (state, action: PayloadAction<{ sectionId: number; artworkId: number }>) => { |
| const { sectionId, artworkId } = action.payload; |
| const section = state.sections.find(s => s.id === sectionId); |
| if (section && !section.childrenid.includes(artworkId)) { |
| section.childrenid.push(artworkId); |
| } |
| }, |
| |
| // 从分区移除作品ID |
| removeArtworkFromSection: (state, action: PayloadAction<{ sectionId: number; artworkId: number }>) => { |
| const { sectionId, artworkId } = action.payload; |
| const section = state.sections.find(s => s.id === sectionId); |
| if (section) { |
| section.childrenid = section.childrenid.filter(id => id !== artworkId); |
| } |
| }, |
| |
| // 重新排序分区 |
| reorderSections: (state, action: PayloadAction<Section[]>) => { |
| state.sections = action.payload; |
| }, |
| |
| // 重置分区状态 |
| resetCategoryState: () => { |
| return initialState; |
| }, |
| |
| // 初始化分区数据 |
| initializeSections: (state, action: PayloadAction<Section[]>) => { |
| state.sections = action.payload; |
| state.loading = false; |
| state.error = null; |
| }, |
| }, |
| }); |
| |
| // 导出actions |
| export const { |
| setLoading, |
| setError, |
| setSections, |
| addSection, |
| updateSection, |
| removeSection, |
| setSelectedCategoryId, |
| addArtworkToSection, |
| removeArtworkFromSection, |
| reorderSections, |
| resetCategoryState, |
| initializeSections, |
| } = categorySlice.actions; |
| |
| // 选择器函数 |
| export const selectSections = (state: { category: CategoryState }): Section[] => |
| state.category.sections; |
| |
| export const selectCategoryLoading = (state: { category: CategoryState }): boolean => |
| state.category.loading; |
| |
| export const selectCategoryError = (state: { category: CategoryState }): string | null => |
| state.category.error; |
| |
| export const selectSelectedCategoryId = (state: { category: CategoryState }): number | null => |
| state.category.selectedCategoryId; |
| |
| // 根据ID获取分区 |
| export const selectSectionById = (sectionId: number) => (state: { category: CategoryState }) => { |
| return state.category.sections.find(section => section.id === sectionId); |
| }; |
| |
| // 获取分区数量 |
| export const selectSectionCount = (state: { category: CategoryState }) => state.category.sections.length; |
| |
| // 获取包含特定作品的分区 |
| export const selectSectionsByArtworkId = (artworkId: number) => (state: { category: CategoryState }) => { |
| return state.category.sections.filter(section => section.childrenid.includes(artworkId)); |
| }; |
| |
| // 获取选中的分区 |
| export const selectSelectedSection = (state: { category: CategoryState }) => { |
| const { sections, selectedCategoryId } = state.category; |
| if (selectedCategoryId === null) return null; |
| return sections.find(section => section.id === selectedCategoryId) || null; |
| }; |
| |
| // 获取分区名称映射 |
| export const selectSectionNameMap = (state: { category: CategoryState }) => { |
| return state.category.sections.reduce((acc, section) => { |
| acc[section.id] = section.name; |
| return acc; |
| }, {} as Record<number, string>); |
| }; |
| |
| export default categorySlice.reducer; |