import Foundation import ComposableArchitecture @Reducer struct FeedFeature { @ObservableState struct State: Equatable { var moments: [MomentsInfo] = [] var isLoading = false var hasMoreData = true var error: String? var nextDynamicId: Int = 0 // 是否已初始化 var isInitialized = false // CreateFeedView 相关状态 var isShowingCreateFeed = false var createFeedState: CreateFeedFeature.State? = nil } enum Action { case onAppear case loadLatestMoments case loadMoreMoments case momentsResponse(TaskResult) case clearError case retryLoad // CreateFeedView 相关 Action case showCreateFeed case dismissCreateFeed case createFeedCompleted indirect case createFeed(CreateFeedFeature.Action) } @Dependency(\.apiService) var apiService var body: some ReducerOf { Reduce { state, action in switch action { case .onAppear: #if DEBUG return .none #endif // 只在首次出现时触发加载 guard !state.isInitialized else { return .none } state.isInitialized = true return .send(.loadLatestMoments) case .loadLatestMoments: // 加载最新数据(下拉刷新) state.isLoading = true state.error = nil let request = LatestDynamicsRequest( dynamicId: "", // 首次加载传空字符串 pageSize: 20, types: [.text, .picture] ) return .run { send in await send(.momentsResponse(TaskResult { try await apiService.request(request) })) } case .loadMoreMoments: // 加载更多数据(分页加载) guard !state.isLoading && state.hasMoreData else { return .none } state.isLoading = true state.error = nil let request = LatestDynamicsRequest( dynamicId: state.nextDynamicId == 0 ? "" : String(state.nextDynamicId), pageSize: 20, types: [.text, .picture] ) return .run { send in await send(.momentsResponse(TaskResult { try await apiService.request(request) })) } case let .momentsResponse(.success(response)): state.isLoading = false // 添加调试日志 debugInfoSync("📱 FeedFeature: API 响应成功") debugInfoSync("📱 FeedFeature: response.code = \(response.code)") debugInfoSync("📱 FeedFeature: response.message = \(response.message)") debugInfoSync("📱 FeedFeature: response.data = \(response.data != nil ? "有数据" : "无数据")") // 检查响应状态 guard response.code == 200, let data = response.data else { let errorMsg = response.message.isEmpty ? "获取动态失败" : response.message state.error = errorMsg debugErrorSync("❌ FeedFeature: API 响应失败 - code: \(response.code), message: \(errorMsg)") return .none } // 添加数据调试日志 debugInfoSync("📱 FeedFeature: data.dynamicList.count = \(data.dynamicList.count)") debugInfoSync("📱 FeedFeature: data.nextDynamicId = \(data.nextDynamicId)") // 判断是刷新还是加载更多 let isRefresh = state.nextDynamicId == 0 debugInfoSync("📱 FeedFeature: isRefresh = \(isRefresh)") if isRefresh { // 刷新:替换所有数据 state.moments = data.dynamicList debugInfoSync(" FeedFeature: 刷新数据,moments.count = \(state.moments.count)") } else { // 加载更多:追加到现有数据 let oldCount = state.moments.count state.moments.append(contentsOf: data.dynamicList) debugInfoSync(" FeedFeature: 加载更多,moments.count: \(oldCount) -> \(state.moments.count)") } // 更新分页状态 state.nextDynamicId = data.nextDynamicId state.hasMoreData = !data.dynamicList.isEmpty debugInfoSync("📱 FeedFeature: 更新完成 - nextDynamicId: \(state.nextDynamicId), hasMoreData: \(state.hasMoreData)") return .none case let .momentsResponse(.failure(error)): state.isLoading = false state.error = error.localizedDescription debugErrorSync("❌ FeedFeature: API 请求失败 - \(error.localizedDescription)") return .none case .clearError: state.error = nil return .none case .retryLoad: // 重试加载 if state.moments.isEmpty { return .send(.loadLatestMoments) } else { return .send(.loadMoreMoments) } case .showCreateFeed: state.isShowingCreateFeed = true // 初始化 createFeedState state.createFeedState = CreateFeedFeature.State() return .none case .dismissCreateFeed: state.isShowingCreateFeed = false state.createFeedState = nil return .none case .createFeedCompleted: state.isShowingCreateFeed = false state.createFeedState = nil // 发布完成后刷新动态列表 return .send(.loadLatestMoments) case .createFeed: // 子模块 Action 由作用域 reducer 处理 return .none } } // 子模块作用域 reducer ifLet(\State.createFeedState, action: /Action.createFeed) { CreateFeedFeature() } } }