接入首页位置上报与在线倒计时,并优化上报交互体验。
持久化服务端 expired 过期时间戳以正确恢复倒计时,切换在线/离线与上报时展示定位 Loading,移除重复的成功 Alert,并将 Toast 调整为居中半透明样式。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -8,28 +8,16 @@
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
/// 位置上报 ViewModel,负责页面内在线状态、坐标、倒计时和提交动作。
|
||||
/// 位置上报 ViewModel,负责页面内坐标、标记点和提交表单。
|
||||
@MainActor
|
||||
final class LocationReportViewModel: ObservableObject {
|
||||
@Published var isOnline = false
|
||||
@Published var reminderMinutes = 30
|
||||
@Published var secondsUntilReport = 0
|
||||
@Published var currentCoordinate: LocationCoordinate?
|
||||
@Published var markedCoordinate: LocationCoordinate?
|
||||
@Published var currentAddress = ""
|
||||
@Published var markedAddress = ""
|
||||
@Published var lastReportText = ""
|
||||
@Published var errorMessage: String?
|
||||
@Published var isSubmitting = false
|
||||
|
||||
/// 倒计时展示文案。
|
||||
var countdownText: String {
|
||||
guard secondsUntilReport > 0 else { return "可立即上报" }
|
||||
let hours = secondsUntilReport / 3600
|
||||
let minutes = (secondsUntilReport % 3600) / 60
|
||||
return "\(hours)小时\(minutes)分钟后可再次提醒"
|
||||
}
|
||||
|
||||
/// 设置当前位置。
|
||||
func applyCurrentLocation(latitude: Double, longitude: Double, address: String) {
|
||||
currentCoordinate = LocationCoordinate(latitude: latitude, longitude: longitude)
|
||||
@ -42,24 +30,13 @@ final class LocationReportViewModel: ObservableObject {
|
||||
markedAddress = address
|
||||
}
|
||||
|
||||
/// 切换在线状态;切到在线时会提交一次状态上报。
|
||||
func setOnline(
|
||||
_ value: Bool,
|
||||
staffId: Int?,
|
||||
scenicId: Int?,
|
||||
api: any LocationReportServing
|
||||
) async -> Bool {
|
||||
isOnline = value
|
||||
guard value else { return true }
|
||||
return await submit(type: .onlineStatus, staffId: staffId, scenicId: scenicId, api: api)
|
||||
}
|
||||
|
||||
/// 提交指定类型的位置上报。
|
||||
func submit(
|
||||
type: LocationReportType,
|
||||
staffId: Int?,
|
||||
scenicId: Int?,
|
||||
api: any LocationReportServing
|
||||
homeLocationViewModel: HomeLocationViewModel,
|
||||
toast: ToastCenter
|
||||
) async -> Bool {
|
||||
guard !isSubmitting else { return false }
|
||||
guard let staffId, staffId > 0 else {
|
||||
@ -86,28 +63,19 @@ final class LocationReportViewModel: ObservableObject {
|
||||
errorMessage = nil
|
||||
defer { isSubmitting = false }
|
||||
|
||||
do {
|
||||
let response = try await api.reportLocation(
|
||||
staffId: staffId,
|
||||
latitude: coordinate.latitude,
|
||||
longitude: coordinate.longitude,
|
||||
address: address,
|
||||
type: type,
|
||||
scenicId: scenicId
|
||||
)
|
||||
secondsUntilReport = response.expired > 0 ? response.expired : 7200
|
||||
lastReportText = LocationReportViewModel.displayFormatter.string(from: Date())
|
||||
return true
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
return false
|
||||
let success = await homeLocationViewModel.reportCoordinate(
|
||||
latitude: coordinate.latitude,
|
||||
longitude: coordinate.longitude,
|
||||
address: address,
|
||||
type: type,
|
||||
staffId: staffId,
|
||||
scenicId: scenicId,
|
||||
toast: toast
|
||||
)
|
||||
if !success, errorMessage == nil {
|
||||
errorMessage = "上报失败"
|
||||
}
|
||||
}
|
||||
|
||||
/// 页面内倒计时每秒递减。
|
||||
func tick() {
|
||||
guard secondsUntilReport > 0 else { return }
|
||||
secondsUntilReport -= 1
|
||||
return success
|
||||
}
|
||||
|
||||
/// 根据上报类型选择当前坐标或标记点坐标。
|
||||
@ -115,16 +83,10 @@ final class LocationReportViewModel: ObservableObject {
|
||||
switch type {
|
||||
case .marked:
|
||||
(markedCoordinate ?? currentCoordinate, markedAddress.isEmpty ? currentAddress : markedAddress)
|
||||
case .all, .immediate, .onlineStatus:
|
||||
case .all, .immediate, .offlineReport:
|
||||
(currentCoordinate, currentAddress)
|
||||
}
|
||||
}
|
||||
|
||||
private static let displayFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
||||
return formatter
|
||||
}()
|
||||
}
|
||||
|
||||
/// 位置上报历史 ViewModel,负责筛选、日期和分页加载。
|
||||
|
||||
Reference in New Issue
Block a user