Add sample management and upload flows to Assets module.

Extend media library for sample kind with project selection, wire home routing for sample entries, and expand Assets tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-24 10:06:16 +08:00
parent 607130ade0
commit c772b25897
13 changed files with 523 additions and 111 deletions

View File

@ -8,7 +8,7 @@
import Foundation
import Observation
/// 便 ViewModel
/// 便 ViewModel
@MainActor
protocol AssetsServing {
///
@ -35,27 +35,30 @@ protocol AssetsServing {
///
func checkCloudUploadPermission() async throws -> CheckCloudUploadResponse
///
///
func mediaAlbumList(kind: MediaLibraryKind, keyword: String, status: Int?, page: Int, pageSize: Int) async throws -> MediaLibraryListResponse
///
func mediaAlbumDetail(id: Int) async throws -> MediaLibraryDetail
///
func mediaAlbumDetail(id: Int, kind: MediaLibraryKind) async throws -> MediaLibraryDetail
///
///
func mediaAlbumOperation(_ request: MediaAlbumOperationRequest) async throws
///
///
func mediaAlbumDelete(_ request: MediaAlbumDeleteRequest) async throws
///
func mediaAlbumAddTag(_ request: MediaAlbumAddTagRequest) async throws
///
///
func mediaAlbumUpload(_ request: MediaAlbumUploadRequest) async throws
///
func mediaAlbumEdit(_ request: MediaAlbumEditRequest) async throws
///
func projectList(scenicId: Int, name: String?, page: Int, pageSize: Int) async throws -> ListPayload<PhotographerProjectItem>
///
func albumFolderList(scenicId: Int, page: Int, pageSize: Int, name: String, startTime: String?, endTime: String?) async throws -> ListPayload<AlbumFolderItem>
@ -163,7 +166,7 @@ final class AssetsAPI: AssetsServing {
)
}
///
///
func mediaAlbumList(
kind: MediaLibraryKind = .material,
keyword: String = "",
@ -185,25 +188,28 @@ final class AssetsAPI: AssetsServing {
)
}
///
func mediaAlbumDetail(id: Int) async throws -> MediaLibraryDetail {
///
func mediaAlbumDetail(id: Int, kind: MediaLibraryKind = .material) async throws -> MediaLibraryDetail {
try await client.send(
APIRequest(
method: .get,
path: "/api/app/media-album/detail",
queryItems: [URLQueryItem(name: "id", value: "\(id)")]
queryItems: [
URLQueryItem(name: "id", value: "\(id)"),
URLQueryItem(name: "type", value: "\(kind.rawValue)")
]
)
)
}
///
///
func mediaAlbumOperation(_ request: MediaAlbumOperationRequest) async throws {
_ = try await client.send(
APIRequest(method: .post, path: "/api/app/media-album/operation", body: request)
) as EmptyPayload
}
///
///
func mediaAlbumDelete(_ request: MediaAlbumDeleteRequest) async throws {
_ = try await client.send(
APIRequest(method: .post, path: "/api/app/media-album/delete", body: request)
@ -217,7 +223,7 @@ final class AssetsAPI: AssetsServing {
) as EmptyPayload
}
///
///
func mediaAlbumUpload(_ request: MediaAlbumUploadRequest) async throws {
_ = try await client.send(
APIRequest(method: .post, path: "/api/app/media-album/upload", body: request)
@ -231,6 +237,26 @@ final class AssetsAPI: AssetsServing {
) as EmptyPayload
}
///
func projectList(
scenicId: Int,
name: String? = nil,
page: Int = 1,
pageSize: Int = 50
) async throws -> ListPayload<PhotographerProjectItem> {
var query = [
URLQueryItem(name: "scenic_id", value: "\(scenicId)"),
URLQueryItem(name: "page", value: "\(max(page, 1))"),
URLQueryItem(name: "page_size", value: "\(max(pageSize, 1))")
]
if let name, !name.isEmpty {
query.append(URLQueryItem(name: "name", value: name))
}
return try await client.send(
APIRequest(method: .get, path: "/api/yf-handset-app/photog/project/list", queryItems: query)
)
}
///
func albumFolderList(
scenicId: Int,