Files
e-party-iOS/yana/Features/MeDynamicFeature.swift
edwinQQQ 99a53d7274 feat: 新增我的动态信息结构和相关API请求逻辑
- 在DynamicsModels.swift中新增MyMomentInfo结构,专门用于处理/dynamic/getMyDynamic接口的响应数据。
- 更新MyMomentsResponse结构以使用MyMomentInfo,确保数据类型一致性。
- 在LoginModels.swift中重构IDLoginAPIRequest和EmailLoginRequest,优化queryParameters的实现方式,提升代码可读性。
- 在RecoverPasswordFeature中重构ResetPasswordRequest,优化queryParameters的实现方式,确保一致性。
- 在多个视图中添加调试信息,增强调试能力和用户体验。
- 更新Localizable.strings文件,新增动态列表为空时的提示信息,提升用户交互体验。
2025-08-04 19:12:31 +08:00

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))))
}
}
}
}