Files
suixinkan_uikit/suixinkan/Features/LocationReport/ViewModels/LocationReportHistoryViewModel.swift
汉秋 005349f8e6 模块化 AppStore 并完善素材管理与个人空间设置。
将会话、权限、位置、收款与排队存储拆分为独立模块,同步更新各 ViewModel 与单元测试,并补充素材管理 UI 与个人空间设置交互。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-13 11:01:08 +08:00

125 lines
3.8 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// LocationReportHistoryViewModel.swift
// suixinkan
//
import Foundation
/// ViewModel Android `LocationReportHistoryViewModel`
final class LocationReportHistoryViewModel {
private(set) var reportList: [LocationReportHistoryItem] = []
private(set) var selectedFilter: LocationReportFilterType = .all
private(set) var isRefreshing = false
private(set) var canLoadMore = false
private(set) var startDate: Date?
private(set) var endDate: Date?
var onStateChange: (() -> Void)?
var onShowMessage: ((String) -> Void)?
private let appStore: AppStore
private var currentPage = 1
private let pageSize = 10
private var isLoading = false
init(appStore: AppStore = .shared) {
self.appStore = appStore
}
var startDateText: String { formattedDate(startDate) }
var endDateText: String { formattedDate(endDate) }
var hasDateFilter: Bool { startDate != nil || endDate != nil }
///
func loadReportList(api: HomeAPI, refresh: Bool = false) async {
guard !isLoading || refresh else { return }
let staffId = appStore.session.userId.trimmingCharacters(in: .whitespacesAndNewlines)
guard !staffId.isEmpty else {
onShowMessage?("获取用户ID失败")
return
}
if refresh {
currentPage = 1
isRefreshing = true
notifyStateChange()
}
isLoading = true
defer {
isLoading = false
isRefreshing = false
notifyStateChange()
}
do {
let response = try await api.locationReportList(
staffId: staffId,
page: currentPage,
pageSize: pageSize,
type: selectedFilter.typeCode,
startDate: apiDateString(startDate),
endDate: apiDateString(endDate)
)
if refresh || currentPage == 1 {
reportList = response.list
} else {
reportList.append(contentsOf: response.list)
}
currentPage += 1
canLoadMore = reportList.count < response.total
notifyStateChange()
} catch is CancellationError {
return
} catch {
onShowMessage?(error.localizedDescription)
}
}
func selectFilter(_ filter: LocationReportFilterType, api: HomeAPI) async {
selectedFilter = filter
currentPage = 1
await loadReportList(api: api, refresh: true)
}
func setDateRange(start: Date?, end: Date?, api: HomeAPI) async {
startDate = start
endDate = end
currentPage = 1
await loadReportList(api: api, refresh: true)
}
func clearDateRange(api: HomeAPI) async {
startDate = nil
endDate = nil
currentPage = 1
await loadReportList(api: api, refresh: true)
}
func loadMoreIfNeeded(currentIndex: Int, api: HomeAPI) async {
guard canLoadMore, !isLoading else { return }
guard currentIndex >= reportList.count - 2 else { return }
await loadReportList(api: api, refresh: false)
}
private func apiDateString(_ date: Date?) -> String? {
guard let date else { return nil }
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "zh_CN")
formatter.dateFormat = "yyyy-MM-dd"
return formatter.string(from: date)
}
private func formattedDate(_ date: Date?) -> String {
guard let date else { return "请选择" }
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "zh_CN")
formatter.dateFormat = "yyyy-MM-dd"
return formatter.string(from: date)
}
private func notifyStateChange() {
onStateChange?()
}
}