feat: 更新动态相关数据模型及视图组件

- 在DynamicsModels.swift中为动态响应结构和列表数据添加Sendable协议,提升并发安全性。
- 在FeedListFeature.swift中实现动态内容的加载逻辑,集成API请求以获取最新动态。
- 在FeedListView.swift中新增动态内容列表展示,优化用户交互体验。
- 在MeView.swift中添加设置按钮,支持弹出设置视图。
- 在SettingView.swift中新增COS上传测试功能,允许用户测试图片上传至腾讯云COS。
- 在OptimizedDynamicCardView.swift中实现优化的动态卡片组件,提升动态展示效果。
This commit is contained in:
edwinQQQ
2025-07-22 17:17:21 +08:00
parent 6c363ea884
commit c8ff40cac1
9 changed files with 1007 additions and 520 deletions

View File

@@ -1,5 +1,6 @@
import Foundation
import ComposableArchitecture
import QCloudCOSXML
// MARK: - COS
@@ -15,6 +16,26 @@ class COSManager: ObservableObject {
private init() {}
//
private static var isCOSInitialized = false
//
private func ensureCOSInitialized(tokenData: TcTokenData) {
guard !Self.isCOSInitialized else { return }
let configuration = QCloudServiceConfiguration()
let endpoint = QCloudCOSXMLEndPoint()
endpoint.regionName = tokenData.region
endpoint.useHTTPS = true
if tokenData.accelerate {
endpoint.suffix = "cos.accelerate.myqcloud.com"
}
configuration.endpoint = endpoint
QCloudCOSXMLService.registerDefaultCOSXML(with: configuration)
QCloudCOSTransferMangerService.registerDefaultCOSTransferManger(with: configuration)
Self.isCOSInitialized = true
debugInfoSync("✅ COS服务已初始化region: \(tokenData.region)")
}
// MARK: - Token
/// Token
@@ -102,13 +123,83 @@ class COSManager: ObservableObject {
/// Token
func getTokenStatus() -> String {
if let cached = cachedToken, let expiration = tokenExpirationDate {
if let _ = cachedToken, let expiration = tokenExpirationDate {
let isExpired = Date() >= expiration
return "Token 状态: \(isExpired ? "已过期" : "有效"), 过期时间: \(expiration)"
} else {
return "Token 状态: 未缓存"
}
}
// MARK: -
/// COS
/// - Parameters:
/// - imageData:
/// - apiService: API
/// - Returns: nil
func uploadImage(_ imageData: Data, apiService: any APIServiceProtocol & Sendable) async -> String? {
guard let tokenData = await getToken(apiService: apiService) else {
debugInfoSync("❌ 无法获取 COS Token")
return nil
}
// COS
ensureCOSInitialized(tokenData: tokenData)
// COS
let credential = QCloudCredential()
credential.secretID = tokenData.secretId
// secretKey
let rawSecretKey = tokenData.secretKey.trimmingCharacters(in: .whitespacesAndNewlines)
debugInfoSync("secretKey原始内容: [\(rawSecretKey)]")
credential.secretKey = rawSecretKey
credential.token = tokenData.sessionToken
credential.startDate = tokenData.startDate
credential.expirationDate = tokenData.expirationDate
let request = QCloudCOSXMLUploadObjectRequest<AnyObject>()
request.bucket = tokenData.bucket
request.regionName = tokenData.region
request.credential = credential
// key
let fileExtension = "jpg" // JPG
let key = "images/\(UUID().uuidString).\(fileExtension)"
request.object = key
request.body = imageData as AnyObject
//
request.sendProcessBlock = { (bytesSent, totalBytesSent,
totalBytesExpectedToSend) in
debugInfoSync("\(bytesSent), \(totalBytesSent), \(totalBytesExpectedToSend)")
// bytesSent
// totalBytesSent
// totalBytesExpectedToSend
};
//
if tokenData.accelerate {
request.enableQuic = true
// endpoint "cos.accelerate.myqcloud.com"
}
// 使 async/await
return await withCheckedContinuation { continuation in
request.setFinish { result, error in
if let error = error {
debugInfoSync("❌ 图片上传失败: \(error.localizedDescription)")
continuation.resume(returning: " ?????????? ")
} else {
//
let domain = tokenData.customDomain.isEmpty ? "\(tokenData.bucket).cos.\(tokenData.region).myqcloud.com" : tokenData.customDomain
let cloudURL = "https://\(domain)/\(key)"
debugInfoSync("✅ 图片上传成功: \(cloudURL)")
continuation.resume(returning: cloudURL)
}
}
QCloudCOSTransferMangerService.defaultCOSTransferManager().uploadObject(request)
}
}
}
// MARK: -
@@ -134,4 +225,4 @@ extension COSManager {
debugInfoSync("✅ 腾讯云 COS Token 测试完成\n")
#endif
}
}
}