Add location report map page and history list aligned with Android.

Extract shared LocationReportService, wire location_report menu routing, and add unit tests for reporting cooldown and history pagination.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-07 11:34:54 +08:00
co-authored by Cursor
parent 5a2b7b6097
commit d2879ad7e2
17 changed files with 1974 additions and 151 deletions
@@ -46,14 +46,8 @@ final class HomeLocationProvider: NSObject, CLLocationManagerDelegate {
)
}
private func requestCoordinate() async throws -> CLLocationCoordinate2D {
try await withCheckedThrowingContinuation { continuation in
self.coordinateContinuation = continuation
manager.requestLocation()
}
}
private func reverseGeocode(latitude: Double, longitude: Double) async -> String {
/// 逆地理编码,供地图标记使用。
func reverseGeocode(latitude: Double, longitude: Double) async -> String {
let location = CLLocation(latitude: latitude, longitude: longitude)
let geocoder = CLGeocoder()
do {
@@ -64,6 +58,13 @@ final class HomeLocationProvider: NSObject, CLLocationManagerDelegate {
}
}
private func requestCoordinate() async throws -> CLLocationCoordinate2D {
try await withCheckedThrowingContinuation { continuation in
self.coordinateContinuation = continuation
manager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
coordinateContinuation?.resume(returning: location.coordinate)
@@ -82,7 +83,7 @@ enum HomeLocationProviderError: LocalizedError {
var errorDescription: String? {
switch self {
case .permissionDenied: "需要位置权限才能上线"
case .permissionDenied: "需要定位权限才能使用此功能"
}
}
}
@@ -80,6 +80,15 @@ final class HomeLocationStateStore {
notifyChange()
}
var countdownDisplayText: String {
formattedCountdown(from: nextReportCountdownSeconds)
}
/// Android 独立页倒计时格式 `H:MM:SS`。
var countdownDisplayTextSingleHour: String {
formattedCountdownSingleHour(from: nextReportCountdownSeconds)
}
/// 格式化倒计时文本 `HH:MM:SS`。
func formattedCountdown(from seconds: Int64) -> String {
let hours = seconds / 3600
@@ -88,8 +97,12 @@ final class HomeLocationStateStore {
return String(format: "%02d:%02d:%02d", hours, minutes, secs)
}
var countdownDisplayText: String {
formattedCountdown(from: nextReportCountdownSeconds)
/// 格式化倒计时文本 `H:MM:SS`。
func formattedCountdownSingleHour(from seconds: Int64) -> String {
let hours = seconds / 3600
let minutes = (seconds % 3600) / 60
let secs = seconds % 60
return String(format: "%d:%02d:%02d", hours, minutes, secs)
}
/// 是否到达提前提醒窗口。
@@ -48,6 +48,8 @@ enum HomeRouteHandler {
return
}
viewController.navigationController?.pushViewController(CooperationOrderListViewController(), animated: true)
case "location_report":
viewController.navigationController?.pushViewController(LocationReportViewController(), animated: true)
case "task_management", "task_management_editor":
viewController.navigationController?.pushViewController(TaskAddViewController(), animated: true)
default: