feat: 使用旅拍相册批量删除接口

This commit is contained in:
2026-08-11 15:57:19 +08:00
parent e64dcec094
commit aca19a53fb
6 changed files with 61 additions and 18 deletions
+16
View File
@@ -104,6 +104,22 @@ final class TravelAlbumAPITests: XCTestCase {
XCTAssertEqual(query?.first { $0.name == "material_id" }?.value, "6")
}
func testBatchDeleteMaterialsBuildsPathAndBody() async throws {
let session = MockURLSession(responses: [envelopeJSON("{}")])
let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))
try await api.batchDeleteMaterials(ids: [2031, 2032, 2033])
let request = try XCTUnwrap(session.requests.first)
XCTAssertEqual(request.httpMethod, "POST")
XCTAssertEqual(
request.url?.path,
"/api/yf-handset-app/photog/travel-album/batch-delete-material"
)
let body = try JSONSerialization.jsonObject(with: try XCTUnwrap(request.httpBody)) as? [String: Any]
XCTAssertEqual(body?["ids"] as? [Int], [2031, 2032, 2033])
}
func testUploadMaterialBuildsPathAndBody() async throws {
let material = envelopeJSON(#"{"id":6,"user_equity_travel_id":3,"status":1,"order_number":"","user_id":9,"file_name":"A.JPG","file_type":1,"file_url":"https://cdn/a.jpg","file_size":1024,"cover_url":"","is_purchased":false,"created_at":"2026-07-08 10:00:00","updated_at":"2026-07-08 10:00:00"}"#)
let session = MockURLSession(responses: [material])
@@ -57,13 +57,13 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
let success = await handler.deleteProject(originalMaterialId: 8)
XCTAssertEqual(api.deletedMaterialIds, [8])
XCTAssertEqual(api.deletedMaterialIDBatches, [[8]])
XCTAssertEqual(success, .success("删除成功"))
api.deleteMaterialError = APIError.serverCode(500, "服务暂不可用")
let failure = await handler.deleteProject(originalMaterialId: 9)
XCTAssertEqual(api.deletedMaterialIds, [8, 9])
XCTAssertEqual(api.deletedMaterialIDBatches, [[8], [9]])
XCTAssertEqual(failure, .failure("服务暂不可用"))
}
@@ -92,7 +92,7 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
controller.view.allAccessibilityLabels().contains("第 1 张,共 2 张")
}
XCTAssertEqual(api.deletedMaterialIds, [1])
XCTAssertEqual(api.deletedMaterialIDBatches, [[1]])
XCTAssertEqual(deletedIds, [1])
XCTAssertTrue(
controller.view.allLabels().contains { $0.text == "第二张.jpg" }
@@ -120,7 +120,7 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
controller.view.allAccessibilityLabels().contains("第 2 张,共 2 张")
}
XCTAssertEqual(api.deletedMaterialIds, [3])
XCTAssertEqual(api.deletedMaterialIDBatches, [[3]])
XCTAssertTrue(
controller.view.allLabels().contains { $0.text == "第二张.jpg" }
)
@@ -146,7 +146,7 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
controller.deleteCurrentProjectAfterConfirmation()
await waitUntil { host.presentedViewController == nil }
XCTAssertEqual(api.deletedMaterialIds, [1])
XCTAssertEqual(api.deletedMaterialIDBatches, [[1]])
XCTAssertNil(host.presentedViewController)
window.isHidden = true
}
+23 -3
View File
@@ -242,6 +242,26 @@ final class TravelAlbumDetailViewModelTests: XCTestCase {
XCTAssertEqual(api.deletedAlbumIds, [5])
XCTAssertEqual(deletedId, 5)
}
func testDeleteSelectedMaterialsUsesSingleBatchRequest() async {
let api = TravelAlbumMockAPI()
api.materialListResponses = [
TravelAlbumListResponse(total: 0, list: []),
TravelAlbumListResponse(total: 0, list: []),
TravelAlbumListResponse(total: 0, list: []),
]
let viewModel = TravelAlbumDetailViewModel(albumId: 5)
viewModel.toggleSelectionMode()
viewModel.toggleMaterialSelection(TravelAlbumMaterial(id: 2033, status: 1))
viewModel.toggleMaterialSelection(TravelAlbumMaterial(id: 2031, status: 1))
viewModel.toggleMaterialSelection(TravelAlbumMaterial(id: 2032, status: 1))
await viewModel.deleteSelectedMaterials(api: api)
XCTAssertEqual(api.deletedMaterialIDBatches, [[2031, 2032, 2033]])
XCTAssertFalse(viewModel.isSelectionMode)
XCTAssertTrue(viewModel.selectedMaterialIds.isEmpty)
}
}
/// 有线传输 ViewModel 测试。
@@ -1097,7 +1117,7 @@ final class TravelAlbumMockAPI: TravelAlbumServing {
private(set) var uploadMaterialRequests: [TravelAlbumUploadMaterialRequest] = []
private(set) var materialClientPhotoIdsCallCount = 0
private(set) var deletedAlbumIds: [Int] = []
private(set) var deletedMaterialIds: [Int] = []
private(set) var deletedMaterialIDBatches: [[Int]] = []
private(set) var aiRetouchTemplateScenicIds: [Int] = []
private(set) var aiRetouchRequests: [TravelAlbumAIRetouchRequest] = []
private(set) var aiReretouchRequests: [TravelAlbumAIReretouchRequest] = []
@@ -1167,8 +1187,8 @@ final class TravelAlbumMockAPI: TravelAlbumServing {
deletedAlbumIds.append(id)
}
func deleteMaterial(id: Int) async throws {
deletedMaterialIds.append(id)
func batchDeleteMaterials(ids: [Int]) async throws {
deletedMaterialIDBatches.append(ids)
if deleteMaterialDelayNanoseconds > 0 {
try await Task.sleep(nanoseconds: deleteMaterialDelayNanoseconds)
}