Implement task creation with cloud/local media, order linking, and OSS upload; wire home entry and move profile nickname/avatar editing to ProfileEditViewController. Co-authored-by: Cursor <cursoragent@cursor.com>
71 lines
1.9 KiB
Swift
71 lines
1.9 KiB
Swift
//
|
||
// TaskOrderSelectViewModel.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import Foundation
|
||
|
||
/// 任务关联订单选择 ViewModel,对齐 Android `OrderSelectViewModel`。
|
||
final class TaskOrderSelectViewModel {
|
||
|
||
private(set) var orders: [AvailableOrder] = []
|
||
private(set) var selectedOrderNumber: String?
|
||
private(set) var isLoading = false
|
||
|
||
var onStateChange: (() -> Void)?
|
||
var onShowMessage: ((String) -> Void)?
|
||
|
||
private let appStore: AppStore
|
||
|
||
init(appStore: AppStore = .shared, initialOrderNumber: String? = nil) {
|
||
self.appStore = appStore
|
||
let trimmed = initialOrderNumber?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||
selectedOrderNumber = trimmed.isEmpty ? nil : trimmed
|
||
}
|
||
|
||
/// 拉取可选订单列表。
|
||
func loadOrders(api: TaskAPI) async {
|
||
isLoading = true
|
||
notifyStateChange()
|
||
defer {
|
||
isLoading = false
|
||
notifyStateChange()
|
||
}
|
||
|
||
let scenicId = appStore.currentScenicId
|
||
guard scenicId > 0 else {
|
||
orders = []
|
||
onShowMessage?("请先选择景区")
|
||
return
|
||
}
|
||
|
||
do {
|
||
orders = try await api.availableOrders(scenicId: scenicId)
|
||
} catch is CancellationError {
|
||
return
|
||
} catch {
|
||
orders = []
|
||
onShowMessage?(error.localizedDescription)
|
||
}
|
||
}
|
||
|
||
/// 切换订单选中状态,再次点击同一项则取消。
|
||
func toggleSelection(orderNumber: String) {
|
||
if selectedOrderNumber == orderNumber {
|
||
selectedOrderNumber = nil
|
||
} else {
|
||
selectedOrderNumber = orderNumber
|
||
}
|
||
notifyStateChange()
|
||
}
|
||
|
||
/// 确认选择并返回订单号。
|
||
func confirmedOrderNumber() -> String? {
|
||
selectedOrderNumber
|
||
}
|
||
|
||
private func notifyStateChange() {
|
||
onStateChange?()
|
||
}
|
||
}
|