feat: 新增相册自动修图与OTG状态预览
支持相册修图配置、模板选择和传输模式选择;上传后自动提交修图并展示状态角标及精修预览。补充接口文档与相关测试。
This commit is contained in:
+105
@@ -0,0 +1,105 @@
|
||||
import Foundation
|
||||
|
||||
/// 自动修图设置状态,负责加载真实精修模板、单选和配置校验,不直接创建修图任务。
|
||||
final class TravelAlbumAutoRetouchSettingViewModel {
|
||||
/// 设置页当前层级。
|
||||
enum Stage: Sendable, Equatable {
|
||||
case mode
|
||||
case templates
|
||||
}
|
||||
|
||||
let scenicId: Int
|
||||
let startsWithModeSelection: Bool
|
||||
private(set) var stage: Stage
|
||||
private(set) var templates: [TravelAlbumAIRetouchTemplate] = []
|
||||
private(set) var selectedTemplateId: Int?
|
||||
private(set) var isEnabled: Bool
|
||||
private(set) var isLoading = false
|
||||
private(set) var errorMessage: String?
|
||||
|
||||
var onStateChange: (() -> Void)?
|
||||
|
||||
/// 创建自动修图配置状态。
|
||||
init(
|
||||
scenicId: Int,
|
||||
configuration: TravelAlbumAutoRetouchConfiguration,
|
||||
startsWithModeSelection: Bool
|
||||
) {
|
||||
self.scenicId = scenicId
|
||||
self.startsWithModeSelection = startsWithModeSelection
|
||||
self.stage = startsWithModeSelection ? .mode : .templates
|
||||
self.isEnabled = configuration.enabled
|
||||
self.selectedTemplateId = configuration.refinedTemplateId
|
||||
}
|
||||
|
||||
/// 当前可提交配置;启用状态必须已经选择服务端模板。
|
||||
var pendingConfiguration: TravelAlbumAutoRetouchConfiguration? {
|
||||
if !isEnabled { return .disabled }
|
||||
guard let selectedTemplateId,
|
||||
templates.contains(where: { $0.id == selectedTemplateId }) else {
|
||||
return nil
|
||||
}
|
||||
return TravelAlbumAutoRetouchConfiguration(
|
||||
enabled: true,
|
||||
refinedTemplateId: selectedTemplateId
|
||||
)
|
||||
}
|
||||
|
||||
/// 拉取当前景区的真实精修模板。
|
||||
func loadTemplates(api: any TravelAlbumServing) async {
|
||||
guard scenicId > 0 else {
|
||||
errorMessage = "请先选择景区"
|
||||
notify()
|
||||
return
|
||||
}
|
||||
guard !isLoading else { return }
|
||||
isLoading = true
|
||||
errorMessage = nil
|
||||
notify()
|
||||
defer {
|
||||
isLoading = false
|
||||
notify()
|
||||
}
|
||||
do {
|
||||
let response = try await api.aiRetouchTemplates(scenicId: scenicId)
|
||||
templates = response.refinedTemplates
|
||||
if !templates.contains(where: { $0.id == selectedTemplateId }) {
|
||||
selectedTemplateId = nil
|
||||
}
|
||||
if templates.isEmpty { errorMessage = "暂无可用的原图精修模板" }
|
||||
} catch is CancellationError {
|
||||
return
|
||||
} catch {
|
||||
templates = []
|
||||
errorMessage = error.localizedDescription.isEmpty ? "模板加载失败" : error.localizedDescription
|
||||
}
|
||||
}
|
||||
|
||||
/// 选择一级修图方式。
|
||||
func selectMode(enabled: Bool) {
|
||||
isEnabled = enabled
|
||||
if enabled {
|
||||
stage = .templates
|
||||
} else {
|
||||
selectedTemplateId = nil
|
||||
}
|
||||
notify()
|
||||
}
|
||||
|
||||
/// 选择一个真实精修模板。
|
||||
func selectTemplate(id: Int) {
|
||||
guard templates.contains(where: { $0.id == id }) else { return }
|
||||
isEnabled = true
|
||||
selectedTemplateId = id
|
||||
notify()
|
||||
}
|
||||
|
||||
/// 从模板列表返回修图方式层级。
|
||||
func returnToModeSelection() {
|
||||
guard startsWithModeSelection else { return }
|
||||
stage = .mode
|
||||
notify()
|
||||
}
|
||||
|
||||
private func notify() { onStateChange?() }
|
||||
}
|
||||
Reference in New Issue
Block a user