feat: 优化自动修图设置与模板网格交互

同页切换修图方式并展开三列模板,复用模板卡片与对比预览,保留草稿和滚动位置,统一卡片与固定底栏样式并补充回归测试。
This commit is contained in:
2026-08-27 17:15:50 +08:00
parent d04641b623
commit 396597a160
6 changed files with 538 additions and 259 deletions
+47 -2
View File
@@ -455,6 +455,51 @@ final class TravelAlbumDetailViewModelTests: XCTestCase {
/// 自动修图配置 ViewModel 测试。
@MainActor
final class TravelAlbumAutoRetouchSettingViewModelTests: XCTestCase {
func testModeToggleRetainsDraftButDisabledSubmissionOmitsTemplate() async {
let api = TravelAlbumMockAPI()
api.aiRetouchTemplatesResponse = TravelAlbumAIRetouchTemplatesResponse(refinedTemplates: [
TravelAlbumAIRetouchTemplate(id: 12, name: "清透", previewURL: ""),
])
let viewModel = TravelAlbumAutoRetouchSettingViewModel(scenicId: 18, configuration: .disabled, allowsModeSelection: true)
await viewModel.loadTemplates(api: api)
viewModel.selectMode(enabled: true)
XCTAssertFalse(viewModel.canConfirm)
viewModel.selectTemplate(id: 12)
viewModel.selectMode(enabled: false)
XCTAssertEqual(viewModel.pendingConfiguration, .disabled)
XCTAssertEqual(viewModel.selectedTemplateId, 12)
viewModel.selectMode(enabled: true)
XCTAssertEqual(viewModel.pendingConfiguration?.refinedTemplateId, 12)
XCTAssertEqual(viewModel.selectedTemplateName, "清透")
XCTAssertTrue(viewModel.canConfirm)
}
func testOriginalModeRemainsConfirmableDuringTemplateLoadingAndFailure() async {
let api = TravelAlbumMockAPI()
api.aiRetouchTemplatesError = APIError.httpStatus(500, "模板服务不可用")
let viewModel = TravelAlbumAutoRetouchSettingViewModel(scenicId: 18, configuration: .disabled, allowsModeSelection: true)
var couldConfirmWhileLoading = false
viewModel.onStateChange = {
if viewModel.isLoading { couldConfirmWhileLoading = viewModel.canConfirm }
}
await viewModel.loadTemplates(api: api)
viewModel.onStateChange = nil
XCTAssertTrue(couldConfirmWhileLoading)
XCTAssertTrue(viewModel.canConfirm)
XCTAssertEqual(viewModel.pendingConfiguration, .disabled)
viewModel.selectMode(enabled: true)
XCTAssertFalse(viewModel.canConfirm)
}
func testTemplateOnlyEntryRequiresAISelectionAndCannotDisable() {
let viewModel = TravelAlbumAutoRetouchSettingViewModel(scenicId: 18, configuration: .disabled, allowsModeSelection: false)
XCTAssertTrue(viewModel.isEnabled)
XCTAssertFalse(viewModel.canConfirm)
XCTAssertNil(viewModel.pendingConfiguration)
viewModel.selectMode(enabled: false)
XCTAssertTrue(viewModel.isEnabled)
}
func testLoadsOnlyRefinedTemplatesAndKeepsSingleSelection() async {
let api = TravelAlbumMockAPI()
api.aiRetouchTemplatesResponse = TravelAlbumAIRetouchTemplatesResponse(
@@ -470,7 +515,7 @@ final class TravelAlbumAutoRetouchSettingViewModelTests: XCTestCase {
let viewModel = TravelAlbumAutoRetouchSettingViewModel(
scenicId: 18,
configuration: .disabled,
startsWithModeSelection: true
allowsModeSelection: true
)
viewModel.selectMode(enabled: true)
@@ -490,7 +535,7 @@ final class TravelAlbumAutoRetouchSettingViewModelTests: XCTestCase {
let viewModel = TravelAlbumAutoRetouchSettingViewModel(
scenicId: 18,
configuration: TravelAlbumAutoRetouchConfiguration(enabled: true, refinedTemplateId: 12),
startsWithModeSelection: false
allowsModeSelection: false
)
await viewModel.loadTemplates(api: api)