完成主页, 作品页,作品编辑页
> 未对接后端接口

Change-Id: I5d62663602656da4940707e00f76bfe09d824c2c
diff --git a/src/feature/home/categorySlice.ts b/src/feature/home/categorySlice.ts
new file mode 100644
index 0000000..31482cc
--- /dev/null
+++ b/src/feature/home/categorySlice.ts
@@ -0,0 +1,167 @@
+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;
\ No newline at end of file