Advance UIKit rewrite with AMap integration and core UI modules.

Integrate高德 SDK with simulator-safe build flags, add map views for operating area and punch points, refactor main tabs and key feature screens to UIKit with Diffable lists, and document Swift concurrency defaults in AGENTS.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 15:16:12 +08:00
parent 9edf993432
commit d99a5b1bf8
124 changed files with 5195 additions and 1536 deletions

View File

@ -130,6 +130,7 @@ final class ProjectManagementViewModel {
return value.isEmpty ? nil : value
}
/// List
private func resetList() {
items = []
loading = false
@ -139,6 +140,7 @@ final class ProjectManagementViewModel {
total = 0
}
/// sorted
private func sorted(_ values: [PhotographerProjectItem]) -> [PhotographerProjectItem] {
values.sorted { lhs, rhs in
if lhs.status != rhs.status { return lhs.status < rhs.status }
@ -146,6 +148,7 @@ final class ProjectManagementViewModel {
}
}
/// deduplicated
private func deduplicated(_ values: [PhotographerProjectItem]) -> [PhotographerProjectItem] {
var result: [Int: PhotographerProjectItem] = [:]
values.forEach { result[$0.id] = $0 }
@ -278,6 +281,7 @@ final class ProjectEditorViewModel {
return labels.isEmpty ? nil : labels
}
/// resolveCover
private func resolveCoverURL(scenicId: Int, uploadService: any OSSUploadServing) async throws -> String {
if let coverImage {
return try await uploadService.uploadProjectImage(data: coverImage.data, fileName: coverImage.fileName, scenicId: scenicId) { [weak self] progress in
@ -287,6 +291,7 @@ final class ProjectEditorViewModel {
return existingCoverURL
}
/// resolveCarouselURLs
private func resolveCarouselURLs(scenicId: Int, uploadService: any OSSUploadServing) async throws -> [String] {
var urls = existingCarouselURLs
for image in carouselImages {
@ -298,11 +303,13 @@ final class ProjectEditorViewModel {
return urls
}
/// dMoney
private func normalizedMoney(_ value: String) -> String? {
let amount = Double(value.trimmingCharacters(in: .whitespacesAndNewlines)) ?? 0
return amount > 0 ? String(format: "%.2f", amount) : nil
}
/// false
private func fail(_ error: ProjectEditorError) -> Bool {
errorMessage = error.localizedDescription
return false
@ -511,6 +518,7 @@ final class StoreProjectEditorViewModel {
return nil
}
/// resolveCover
private func resolveCoverURL(scenicId: Int, uploadService: any OSSUploadServing) async throws -> String {
if let coverImage {
return try await uploadService.uploadProjectImage(data: coverImage.data, fileName: coverImage.fileName, scenicId: scenicId) { _ in }
@ -518,6 +526,7 @@ final class StoreProjectEditorViewModel {
return existingCoverURL
}
/// resolveCarouselURLs
private func resolveCarouselURLs(scenicId: Int, uploadService: any OSSUploadServing) async throws -> [String] {
var urls = existingCarouselURLs
for image in carouselImages {
@ -527,6 +536,7 @@ final class StoreProjectEditorViewModel {
return urls
}
/// MultiPointProject
private func submitMultiPointProject(
userId: Int,
api: any ProjectServing,
@ -586,6 +596,7 @@ final class StoreProjectEditorViewModel {
}
}
/// OfflineProject
private func submitOfflineProject(api: any ProjectServing, name: String, description: String, coverURL: String, carouselURLs: [String]) async throws {
let scenicId = selectedScenicIds.first ?? 0
let storeId = selectedStoreId ?? 0
@ -617,6 +628,7 @@ final class StoreProjectEditorViewModel {
}
}
/// false
private func fail(_ error: ProjectEditorError) -> Bool {
errorMessage = error.localizedDescription
return false