feat: 完善相册 AI 修图模板选择流程

This commit is contained in:
2026-08-11 15:22:08 +08:00
parent 43c75c8e36
commit e64dcec094
11 changed files with 261 additions and 202 deletions
@@ -13,6 +13,7 @@ final class TravelAlbumAIRetouchTemplateViewModel {
private(set) var selectedRefinedTemplateId: Int?
private(set) var selectedAtmosphereTemplateId: Int?
private(set) var selectedCoverTemplateId: Int?
private(set) var remainingQuota: Int?
private(set) var isLoading = false
private(set) var isSubmitting = false
private(set) var loadErrorMessage: String?
@@ -56,6 +57,22 @@ final class TravelAlbumAIRetouchTemplateViewModel {
workflow.isOptional(category)
}
/// 当前选择预计消耗的修图次数;封面模板免费,不计入额度。
var requiredQuota: Int {
switch workflow {
case .initial(_, let materialIds):
let outputCount = 1 + (selectedAtmosphereTemplateId == nil ? 0 : 1)
return materialIds.count * outputCount
case .reretouch(_, _, let type):
switch type {
case .refined, .atmosphere:
return 1
case .all:
return 1 + (selectedAtmosphereTemplateId == nil ? 0 : 1)
}
}
}
/// 当前必选模板或业务参数缺失时用于底部提示的文案。
var validationMessage: String? {
guard !isLoading, loadErrorMessage == nil else { return nil }
@@ -70,6 +87,12 @@ final class TravelAlbumAIRetouchTemplateViewModel {
return unavailableMessage(for: category)
}
}
guard let remainingQuota else {
return "剩余修图次数获取失败,请刷新后重试"
}
if requiredQuota > remainingQuota {
return "剩余修图次数不足,需要\(requiredQuota)次,当前剩余\(remainingQuota)次"
}
return nil
}
@@ -92,6 +115,7 @@ final class TravelAlbumAIRetouchTemplateViewModel {
guard !isLoading else { return }
isLoading = true
loadErrorMessage = nil
remainingQuota = nil
notifyStateChange()
do {
@@ -99,6 +123,7 @@ final class TravelAlbumAIRetouchTemplateViewModel {
refinedTemplates = response.refinedTemplates
atmosphereTemplates = response.atmosphereTemplates
coverTemplates = response.coverTemplates
remainingQuota = response.remainingQuota
selectedRefinedTemplateId = visibleCategories.contains(.refined) ? refinedTemplates.first?.id : nil
selectedAtmosphereTemplateId = visibleCategories.contains(.atmosphere) && !isOptional(.atmosphere)
? atmosphereTemplates.first?.id
@@ -116,6 +141,7 @@ final class TravelAlbumAIRetouchTemplateViewModel {
selectedRefinedTemplateId = nil
selectedAtmosphereTemplateId = nil
selectedCoverTemplateId = nil
remainingQuota = nil
isLoading = false
loadErrorMessage = error.localizedDescription.isEmpty ? "模板加载失败" : error.localizedDescription
notifyStateChange()