22301014 | 356527a | 2025-06-09 17:46:56 +0800 | [diff] [blame^] | 1 | import { createSlice, type PayloadAction } from '@reduxjs/toolkit'; |
| 2 | import type{ WorkListState, Artwork, Section } from './types'; |
| 3 | |
| 4 | // 初始状态 |
| 5 | const initialState: WorkListState = { |
| 6 | artworks: [], |
| 7 | searchTerm: '', |
| 8 | loading: false, |
| 9 | error: null, |
| 10 | }; |
| 11 | |
| 12 | // 创建slice |
| 13 | const workListSlice = createSlice({ |
| 14 | name: 'workList', |
| 15 | initialState, |
| 16 | reducers: { |
| 17 | // 设置加载状态 |
| 18 | setLoading: (state, action: PayloadAction<boolean>) => { |
| 19 | state.loading = action.payload; |
| 20 | if (action.payload) { |
| 21 | state.error = null; |
| 22 | } |
| 23 | }, |
| 24 | |
| 25 | // 设置错误信息 |
| 26 | setError: (state, action: PayloadAction<string>) => { |
| 27 | state.error = action.payload; |
| 28 | state.loading = false; |
| 29 | }, |
| 30 | |
| 31 | // 设置作品列表 |
| 32 | setArtworks: (state, action: PayloadAction<Artwork[]>) => { |
| 33 | state.artworks = action.payload; |
| 34 | state.loading = false; |
| 35 | state.error = null; |
| 36 | }, |
| 37 | |
| 38 | // 添加单个作品 |
| 39 | addArtwork: (state, action: PayloadAction<Artwork>) => { |
| 40 | state.artworks.push(action.payload); |
| 41 | }, |
| 42 | |
| 43 | // 更新作品 |
| 44 | updateArtwork: (state, action: PayloadAction<Artwork>) => { |
| 45 | const index = state.artworks.findIndex(artwork => artwork.id === action.payload.id); |
| 46 | if (index !== -1) { |
| 47 | state.artworks[index] = action.payload; |
| 48 | } |
| 49 | }, |
| 50 | |
| 51 | // 删除作品 |
| 52 | removeArtwork: (state, action: PayloadAction<number>) => { |
| 53 | state.artworks = state.artworks.filter(artwork => artwork.id !== action.payload); |
| 54 | }, |
| 55 | |
| 56 | // 设置搜索词 |
| 57 | setSearchTerm: (state, action: PayloadAction<string>) => { |
| 58 | state.searchTerm = action.payload; |
| 59 | }, |
| 60 | |
| 61 | // 清空搜索 |
| 62 | clearSearch: (state) => { |
| 63 | state.searchTerm = ''; |
| 64 | }, |
| 65 | |
| 66 | // 重置状态 |
| 67 | resetState: () => { |
| 68 | return initialState; |
| 69 | }, |
| 70 | |
| 71 | // 初始化数据(用于设置示例数据) |
| 72 | initializeArtworks: (state, action: PayloadAction<Artwork[]>) => { |
| 73 | state.artworks = action.payload; |
| 74 | state.loading = false; |
| 75 | state.error = null; |
| 76 | }, |
| 77 | }, |
| 78 | }); |
| 79 | |
| 80 | // 导出actions |
| 81 | export const { |
| 82 | setLoading, |
| 83 | setError, |
| 84 | setArtworks, |
| 85 | addArtwork, |
| 86 | updateArtwork, |
| 87 | removeArtwork, |
| 88 | setSearchTerm, |
| 89 | clearSearch, |
| 90 | resetState, |
| 91 | initializeArtworks, |
| 92 | } = workListSlice.actions; |
| 93 | |
| 94 | // 选择器函数 |
| 95 | export const selectArtworks = (state: { workList: WorkListState }) => state.workList.artworks; |
| 96 | export const selectSearchTerm = (state: { workList: WorkListState }) => state.workList.searchTerm; |
| 97 | export const selectWorkListLoading = (state: { workList: WorkListState }) => state.workList.loading; |
| 98 | export const selectWorkListError = (state: { workList: WorkListState }) => state.workList.error; |
| 99 | |
| 100 | // 过滤后的作品选择器 |
| 101 | export const selectFilteredArtworks = (state: { workList: WorkListState }) => { |
| 102 | const { artworks, searchTerm } = state.workList; |
| 103 | |
| 104 | if (!searchTerm.trim()) { |
| 105 | return artworks; |
| 106 | } |
| 107 | |
| 108 | return artworks.filter(artwork => |
| 109 | artwork.title.toLowerCase().includes(searchTerm.toLowerCase()) || |
| 110 | artwork.author.toLowerCase().includes(searchTerm.toLowerCase()) || |
| 111 | artwork.category.name.toLowerCase().includes(searchTerm.toLowerCase()) || |
| 112 | artwork.category.children.some(child => |
| 113 | child.toLowerCase().includes(searchTerm.toLowerCase()) |
| 114 | ) |
| 115 | ); |
| 116 | }; |
| 117 | |
| 118 | // 根据分区获取作品的选择器 |
| 119 | export const selectArtworksBySection = (sectionId: number) => (state: { |
| 120 | workList: WorkListState; |
| 121 | category: { sections: Section[] } |
| 122 | }) => { |
| 123 | const section = state.category.sections.find(s => s.id === sectionId); |
| 124 | const filteredArtworks = selectFilteredArtworks(state); |
| 125 | |
| 126 | if (!section) return []; |
| 127 | |
| 128 | return filteredArtworks.filter(artwork => section.childrenid.includes(artwork.id)); |
| 129 | }; |
| 130 | |
| 131 | export default workListSlice.reducer; |