feat: 增强发布动态功能,支持图片上传与进度显示

- 在PublishFeedRequest中新增resList属性,支持上传图片资源信息。
- 在EditFeedFeature中实现图片上传逻辑,处理图片选择与上传进度。
- 更新EditFeedView以显示图片上传进度,提升用户体验。
- 在COSManager中新增UIImage上传方法,优化图片上传流程。
- 在FeedListView中添加通知以刷新动态列表,确保数据同步。
This commit is contained in:
edwinQQQ
2025-07-22 19:02:48 +08:00
parent fd6e44c6f9
commit ed3e7100c3
5 changed files with 161 additions and 30 deletions

View File

@@ -19,8 +19,12 @@ struct EditFeedFeature {
}
var canPublish: Bool {
!content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !isLoading
(!content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || !processedImages.isEmpty) && !isLoading && !isUploadingImages
}
//
var isUploadingImages: Bool = false
var imageUploadProgress: Double = 0.0 // 0.0~1.0
var uploadedResList: [ResListItem] = []
// EquatableselectedImagesPhotosPickerItemEquatable
static func == (lhs: State, rhs: State) -> Bool {
lhs.content == rhs.content &&
@@ -28,7 +32,10 @@ struct EditFeedFeature {
lhs.errorMessage == rhs.errorMessage &&
lhs.shouldDismiss == rhs.shouldDismiss &&
lhs.processedImages == rhs.processedImages &&
lhs.selectedImages.count == rhs.selectedImages.count
lhs.selectedImages.count == rhs.selectedImages.count &&
lhs.isUploadingImages == rhs.isUploadingImages &&
lhs.imageUploadProgress == rhs.imageUploadProgress &&
lhs.uploadedResList == rhs.uploadedResList
}
}
@@ -44,6 +51,11 @@ struct EditFeedFeature {
case processPhotosPickerItems([PhotosPickerItem])
case updateProcessedImages([UIImage])
case removeImage(Int)
// Action
case uploadImages
case uploadImagesResponse(Result<[ResListItem], Error>)
//
case updateImageUploadProgress(Double)
}
@Dependency(\.apiService) var apiService
@@ -62,24 +74,85 @@ struct EditFeedFeature {
state.errorMessage = "请输入内容"
return .none
}
state.isLoading = true
state.errorMessage = nil
return .run { [content = state.content] send in
let userId = await UserInfoManager.getCurrentUserId() ?? ""
let request = await PublishFeedRequest.make(
content: content.trimmingCharacters(in: .whitespacesAndNewlines),
uid: userId,
type: "0"
)
do {
let response = try await apiService.request(request)
await send(.publishResponse(.success(response)))
} catch {
await send(.publishResponse(.failure(error)))
//
if !state.processedImages.isEmpty {
state.isUploadingImages = true
state.imageUploadProgress = 0.0
state.errorMessage = nil
return .send(.uploadImages)
} else {
state.isLoading = true
state.errorMessage = nil
return .run { [content = state.content] send in
let userId = await UserInfoManager.getCurrentUserId() ?? ""
let type = content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "2" : "0"
let request = await PublishFeedRequest.make(
content: content.trimmingCharacters(in: .whitespacesAndNewlines),
uid: userId,
type: type,
resList: nil
)
do {
let response = try await apiService.request(request)
await send(.publishResponse(.success(response)))
} catch {
await send(.publishResponse(.failure(error)))
}
}
}
case .uploadImages:
let images = state.processedImages
return .run { send in
var resList: [ResListItem] = []
for (idx, image) in images.enumerated() {
guard let data = image.jpegData(compressionQuality: 0.9) else { continue }
if let url = await COSManager.shared.uploadImage(data, apiService: apiService),
let cgImage = image.cgImage {
let width = cgImage.width
let height = cgImage.height
let format = "jpeg"
let item = ResListItem(resUrl: url, width: width, height: height, format: format)
resList.append(item)
}
//
await MainActor.run {
send(.updateImageUploadProgress(Double(idx + 1) / Double(images.count)))
}
}
if resList.count == images.count {
await send(.uploadImagesResponse(.success(resList)))
} else {
await send(.uploadImagesResponse(.failure(NSError(domain: "COSUpload", code: -1, userInfo: [NSLocalizedDescriptionKey: "部分图片上传失败"])) ))
}
}
case .uploadImagesResponse(let result):
state.isUploadingImages = false
state.imageUploadProgress = 1.0
switch result {
case .success(let resList):
state.uploadedResList = resList
state.isLoading = true
return .run { [content = state.content, resList] send in
let userId = await UserInfoManager.getCurrentUserId() ?? ""
// type: 2 /
let type = resList.isEmpty ? "0" : (content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "2" : "2")
let request = await PublishFeedRequest.make(
content: content.trimmingCharacters(in: .whitespacesAndNewlines),
uid: userId,
type: type,
resList: resList
)
do {
let response = try await apiService.request(request)
await send(.publishResponse(.success(response)))
} catch {
await send(.publishResponse(.failure(error)))
}
}
case .failure(let error):
state.errorMessage = error.localizedDescription
return .none
}
case .publishResponse(.success(let response)):
state.isLoading = false
if response.code == 200 {
@@ -88,16 +161,13 @@ struct EditFeedFeature {
state.errorMessage = response.message.isEmpty ? "发布失败" : response.message
return .none
}
case .publishResponse(.failure(let error)):
state.isLoading = false
state.errorMessage = error.localizedDescription
return .none
case .clearError:
state.errorMessage = nil
return .none
case .dismissView:
state.shouldDismiss = true
return .none
@@ -134,6 +204,10 @@ struct EditFeedFeature {
state.selectedImages.remove(at: index)
}
return .none
//
case .updateImageUploadProgress(let progress):
state.imageUploadProgress = progress
return .none
}
}
}