blob: 31482cc0e279dd4f6f7ff0489642e395a476458b [file] [log] [blame]
22301014356527a2025-06-09 17:46:56 +08001import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2import type { Section } from './types';
3
4// 分区状态类型
5export interface CategoryState {
6 sections: Section[];
7 loading: boolean;
8 error: string | null;
9 selectedCategoryId: number | null;
10}
11
12// 初始状态
13const initialState: CategoryState = {
14 sections: [],
15 loading: false,
16 error: null,
17 selectedCategoryId: null,
18};
19
20// 创建categorySlice
21const categorySlice = createSlice({
22 name: 'category',
23 initialState,
24 reducers: {
25 // 设置加载状态
26 setLoading: (state, action: PayloadAction<boolean>) => {
27 state.loading = action.payload;
28 if (action.payload) {
29 state.error = null;
30 }
31 },
32
33 // 设置错误信息
34 setError: (state, action: PayloadAction<string>) => {
35 state.error = action.payload;
36 state.loading = false;
37 },
38
39 // 设置分区列表
40 setSections: (state, action: PayloadAction<Section[]>) => {
41 state.sections = action.payload;
42 state.loading = false;
43 state.error = null;
44 },
45
46 // 添加单个分区
47 addSection: (state, action: PayloadAction<Section>) => {
48 state.sections.push(action.payload);
49 },
50
51 // 更新分区
52 updateSection: (state, action: PayloadAction<Section>) => {
53 const index = state.sections.findIndex(section => section.id === action.payload.id);
54 if (index !== -1) {
55 state.sections[index] = action.payload;
56 }
57 },
58
59 // 删除分区
60 removeSection: (state, action: PayloadAction<number>) => {
61 state.sections = state.sections.filter(section => section.id !== action.payload);
62 // 如果删除的是当前选中的分区,清空选中状态
63 if (state.selectedCategoryId === action.payload) {
64 state.selectedCategoryId = null;
65 }
66 },
67
68 // 设置选中的分区ID
69 setSelectedCategoryId: (state, action: PayloadAction<number | null>) => {
70 state.selectedCategoryId = action.payload;
71 },
72
73 // 向分区添加作品ID
74 addArtworkToSection: (state, action: PayloadAction<{ sectionId: number; artworkId: number }>) => {
75 const { sectionId, artworkId } = action.payload;
76 const section = state.sections.find(s => s.id === sectionId);
77 if (section && !section.childrenid.includes(artworkId)) {
78 section.childrenid.push(artworkId);
79 }
80 },
81
82 // 从分区移除作品ID
83 removeArtworkFromSection: (state, action: PayloadAction<{ sectionId: number; artworkId: number }>) => {
84 const { sectionId, artworkId } = action.payload;
85 const section = state.sections.find(s => s.id === sectionId);
86 if (section) {
87 section.childrenid = section.childrenid.filter(id => id !== artworkId);
88 }
89 },
90
91 // 重新排序分区
92 reorderSections: (state, action: PayloadAction<Section[]>) => {
93 state.sections = action.payload;
94 },
95
96 // 重置分区状态
97 resetCategoryState: () => {
98 return initialState;
99 },
100
101 // 初始化分区数据
102 initializeSections: (state, action: PayloadAction<Section[]>) => {
103 state.sections = action.payload;
104 state.loading = false;
105 state.error = null;
106 },
107 },
108});
109
110// 导出actions
111export const {
112 setLoading,
113 setError,
114 setSections,
115 addSection,
116 updateSection,
117 removeSection,
118 setSelectedCategoryId,
119 addArtworkToSection,
120 removeArtworkFromSection,
121 reorderSections,
122 resetCategoryState,
123 initializeSections,
124} = categorySlice.actions;
125
126// 选择器函数
127export const selectSections = (state: { category: CategoryState }): Section[] =>
128 state.category.sections;
129
130export const selectCategoryLoading = (state: { category: CategoryState }): boolean =>
131 state.category.loading;
132
133export const selectCategoryError = (state: { category: CategoryState }): string | null =>
134 state.category.error;
135
136export const selectSelectedCategoryId = (state: { category: CategoryState }): number | null =>
137 state.category.selectedCategoryId;
138
139// 根据ID获取分区
140export const selectSectionById = (sectionId: number) => (state: { category: CategoryState }) => {
141 return state.category.sections.find(section => section.id === sectionId);
142};
143
144// 获取分区数量
145export const selectSectionCount = (state: { category: CategoryState }) => state.category.sections.length;
146
147// 获取包含特定作品的分区
148export const selectSectionsByArtworkId = (artworkId: number) => (state: { category: CategoryState }) => {
149 return state.category.sections.filter(section => section.childrenid.includes(artworkId));
150};
151
152// 获取选中的分区
153export const selectSelectedSection = (state: { category: CategoryState }) => {
154 const { sections, selectedCategoryId } = state.category;
155 if (selectedCategoryId === null) return null;
156 return sections.find(section => section.id === selectedCategoryId) || null;
157};
158
159// 获取分区名称映射
160export const selectSectionNameMap = (state: { category: CategoryState }) => {
161 return state.category.sections.reduce((acc, section) => {
162 acc[section.id] = section.name;
163 return acc;
164 }, {} as Record<number, string>);
165};
166
167export default categorySlice.reducer;