feat: 接通图片预览 AI 修图流程

This commit is contained in:
2026-08-11 09:52:15 +08:00
parent 5704531f3a
commit 43c75c8e36
14 changed files with 814 additions and 169 deletions
+33 -11
View File
@@ -33,6 +33,7 @@ final class TravelAlbumModelsTests: XCTestCase {
fileUrl: "https://cdn.example.com/original.jpg",
fileSize: 4096,
coverUrl: "https://cdn.example.com/cover.jpg",
aiRetouchBatchId: 55,
aiRefinedURL: " https://cdn.example.com/refined.jpg ",
aiAtmosphereURL: "https://cdn.example.com/atmosphere.jpg"
)
@@ -50,6 +51,7 @@ final class TravelAlbumModelsTests: XCTestCase {
)
XCTAssertNil(project.asset(for: .cover))
XCTAssertTrue(project.hasVariants)
XCTAssertEqual(project.aiRetouchBatchId, 55)
}
func testPreviewProjectIgnoresBlankAIResultURLs() {
@@ -161,24 +163,40 @@ final class TravelAlbumModelsTests: XCTestCase {
)
}
func testPlaceholderPreviewActionsReturnUnavailableWithoutMutation() async {
let handler = PlaceholderTravelAlbumPreviewActionHandler()
let aiResult = await handler.requestAIRetouch(originalMaterialId: 9)
let deleteResult = await handler.deleteProject(originalMaterialId: 9)
let refreshResult = await handler.refreshProject(originalMaterialId: 9)
func testPreviewProjectMapsCurrentTabToMinimalAIRetouchWorkflow() {
let originalOnly = makePreviewProject(id: 9, kinds: [.original])
let variants = TravelAlbumPreviewProject(
originalMaterialId: 10,
aiRetouchBatchId: 88,
assets: makePreviewProject(id: 10, kinds: [.original, .retouched, .atmosphere]).assets
)
XCTAssertEqual(
aiResult,
.unavailable("AI修图功能待接口接入")
originalOnly.aiRetouchWorkflow(albumId: 7, selectedKind: .original),
.initial(albumId: 7, materialIds: [9])
)
XCTAssertEqual(
variants.aiRetouchWorkflow(albumId: 7, selectedKind: .original),
.reretouch(materialId: 10, batchId: 88, type: .all)
)
XCTAssertEqual(
variants.aiRetouchWorkflow(albumId: 7, selectedKind: .retouched),
.reretouch(materialId: 10, batchId: 88, type: .refined)
)
XCTAssertEqual(
variants.aiRetouchWorkflow(albumId: 7, selectedKind: .atmosphere),
.reretouch(materialId: 10, batchId: 88, type: .atmosphere)
)
XCTAssertNil(variants.aiRetouchWorkflow(albumId: 7, selectedKind: .cover))
}
func testPlaceholderPreviewDeleteReturnsUnavailableWithoutMutation() async {
let handler = PlaceholderTravelAlbumPreviewActionHandler()
let deleteResult = await handler.deleteProject(originalMaterialId: 9)
XCTAssertEqual(
deleteResult,
.unavailable("项目删除接口待接入")
)
XCTAssertEqual(
refreshResult,
.unavailable("关联图片刷新接口待接入")
)
}
func testTravelAlbumDecodesSnakeCaseFields() throws {
@@ -225,6 +243,7 @@ final class TravelAlbumModelsTests: XCTestCase {
"is_purchased": false,
"ai_retouch_status": 3,
"ai_retouch_status_name": "AI已修",
"ai_retouch_batch_id": 66,
"ai_refined_url": "https://cdn/refined.jpg",
"ai_atmosphere_url": "https://cdn/atmosphere.jpg",
"created_at": "",
@@ -238,6 +257,7 @@ final class TravelAlbumModelsTests: XCTestCase {
XCTAssertFalse(material.isPurchased)
XCTAssertEqual(material.aiRetouchStatus, 3)
XCTAssertEqual(material.aiRetouchStatusName, "AI已修")
XCTAssertEqual(material.aiRetouchBatchId, 66)
XCTAssertEqual(material.aiRefinedURL, "https://cdn/refined.jpg")
XCTAssertEqual(material.aiAtmosphereURL, "https://cdn/atmosphere.jpg")
}
@@ -258,6 +278,7 @@ final class TravelAlbumModelsTests: XCTestCase {
"is_purchased": false,
"ai_retouch_status": "invalid",
"ai_retouch_status_name": null,
"ai_retouch_batch_id": "invalid",
"ai_refined_url": 123,
"created_at": "",
"updated_at": ""
@@ -268,6 +289,7 @@ final class TravelAlbumModelsTests: XCTestCase {
XCTAssertEqual(material.aiRetouchStatus, 0)
XCTAssertEqual(material.aiRetouchStatusName, "")
XCTAssertEqual(material.aiRetouchBatchId, 0)
XCTAssertEqual(material.aiRefinedURL, "")
XCTAssertEqual(material.aiAtmosphereURL, "")
}