
- 在DynamicsModels.swift中新增MyMomentInfo结构,专门用于处理/dynamic/getMyDynamic接口的响应数据。 - 更新MyMomentsResponse结构以使用MyMomentInfo,确保数据类型一致性。 - 在LoginModels.swift中重构IDLoginAPIRequest和EmailLoginRequest,优化queryParameters的实现方式,提升代码可读性。 - 在RecoverPasswordFeature中重构ResetPasswordRequest,优化queryParameters的实现方式,确保一致性。 - 在多个视图中添加调试信息,增强调试能力和用户体验。 - 更新Localizable.strings文件,新增动态列表为空时的提示信息,提升用户交互体验。
108 lines
3.8 KiB
Swift
108 lines
3.8 KiB
Swift
import Foundation
|
|
import ComposableArchitecture
|
|
|
|
@Reducer
|
|
struct MeDynamicFeature: Reducer {
|
|
struct State: Equatable {
|
|
var uid: Int
|
|
var dynamics: [MomentsInfo] = []
|
|
var page: Int = 1
|
|
var pageSize: Int = 20
|
|
var isLoading: Bool = false
|
|
var isRefreshing: Bool = false
|
|
var isLoadingMore: Bool = false
|
|
var hasMore: Bool = true
|
|
var error: String?
|
|
var isInitialized: Bool = false // 首次加载标记
|
|
|
|
init(uid: Int = 0) {
|
|
self.uid = uid
|
|
}
|
|
}
|
|
|
|
enum Action: Equatable {
|
|
case onAppear
|
|
case refresh
|
|
case loadMore
|
|
case fetchResponse(Result<MyMomentsResponse, APIError>)
|
|
}
|
|
|
|
@Dependency(\.apiService) var apiService
|
|
|
|
func reduce(into state: inout State, action: Action) async -> Effect<Action> {
|
|
switch action {
|
|
case .onAppear:
|
|
guard !state.isInitialized else { return .none }
|
|
state.isInitialized = true
|
|
state.page = 1
|
|
state.dynamics = []
|
|
state.hasMore = true
|
|
state.isLoading = true
|
|
state.error = nil
|
|
return fetchDynamics(uid: state.uid, page: 1, pageSize: state.pageSize)
|
|
case .refresh:
|
|
state.page = 1
|
|
state.hasMore = true
|
|
state.isRefreshing = true
|
|
state.error = nil
|
|
state.isInitialized = false // 允许刷新后重新加载
|
|
return fetchDynamics(
|
|
uid: state.uid,
|
|
page: 1,
|
|
pageSize: state.pageSize
|
|
)
|
|
case .loadMore:
|
|
guard !state.isLoadingMore, state.hasMore else { return .none }
|
|
state.isLoadingMore = true
|
|
return fetchDynamics(uid: state.uid, page: state.page + 1, pageSize: state.pageSize)
|
|
case let .fetchResponse(result):
|
|
state.isLoading = false
|
|
state.isRefreshing = false
|
|
state.isLoadingMore = false
|
|
switch result {
|
|
case let .success(resp):
|
|
let myMoments = resp.data ?? []
|
|
// 将 MyMomentInfo 转换为 MomentsInfo
|
|
let newDynamics = myMoments.map { $0.toMomentsInfo() }
|
|
if state.page == 1 {
|
|
state.dynamics = newDynamics
|
|
} else {
|
|
state.dynamics += newDynamics
|
|
}
|
|
state.hasMore = newDynamics.count == state.pageSize
|
|
if state.hasMore { state.page += 1 }
|
|
state.error = nil
|
|
case let .failure(error):
|
|
state.error = error.localizedDescription
|
|
}
|
|
return .none
|
|
}
|
|
}
|
|
|
|
private func fetchDynamics(uid: Int, page: Int, pageSize: Int) -> Effect<Action> {
|
|
let apiService = self.apiService
|
|
return .run { send in
|
|
debugInfoSync("🔄 MeDynamicFeature: 开始获取动态")
|
|
debugInfoSync(" UID: \(uid)")
|
|
debugInfoSync(" 页码: \(page)")
|
|
debugInfoSync(" 页大小: \(pageSize)")
|
|
|
|
do {
|
|
let req = GetMyDynamicRequest(fromUid: uid, uid: uid, page: page, pageSize: pageSize)
|
|
let resp = try await apiService.request(req)
|
|
debugInfoSync("✅ MeDynamicFeature: API 请求成功")
|
|
debugInfoSync(" 响应码: \(resp.code)")
|
|
debugInfoSync(" 消息: \(resp.message)")
|
|
debugInfoSync(" 数据数量: \(resp.data?.count ?? 0)")
|
|
await send(.fetchResponse(.success(resp)))
|
|
} catch {
|
|
debugErrorSync("❌ MeDynamicFeature: API 请求失败: \(error.localizedDescription)")
|
|
await send(.fetchResponse(.failure(error as? APIError ?? .unknown(error.localizedDescription))))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|