同步已迁移的 iOS 模块
This commit is contained in:
@ -0,0 +1,100 @@
|
||||
//
|
||||
// StatisticsViewModel.swift
|
||||
// suixinkan
|
||||
//
|
||||
// Created by Codex on 2026/6/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
/// 数据统计页面 ViewModel,管理时间段、汇总数据、每日明细和分页状态。
|
||||
final class StatisticsViewModel {
|
||||
var selectedPeriod: StatisticsPeriod = .today
|
||||
private(set) var loading = false
|
||||
private(set) var loadingMore = false
|
||||
private(set) var summary = StatisticsSummaryResponse()
|
||||
private(set) var dailyItems: [StatisticsDailyItem] = []
|
||||
private(set) var totalDailyCount = 0
|
||||
private(set) var lastRefreshAt: Date?
|
||||
|
||||
private var page = 1
|
||||
private let pageSize = 15
|
||||
|
||||
/// 当前日数据是否还有下一页。
|
||||
var hasMore: Bool {
|
||||
dailyItems.count < totalDailyCount
|
||||
}
|
||||
|
||||
/// 切换统计时间段,并重置分页重新加载。
|
||||
func selectPeriod(_ period: StatisticsPeriod, api: StatisticsServing, scenicId: Int?, roleId: Int?) async throws {
|
||||
selectedPeriod = period
|
||||
try await reload(api: api, scenicId: scenicId, roleId: roleId)
|
||||
}
|
||||
|
||||
/// 刷新统计汇总和第一页日数据,缺少景区时清空旧状态。
|
||||
func reload(api: StatisticsServing, scenicId: Int?, roleId: Int?, showLoading: Bool = true) async throws {
|
||||
guard let scenicId else {
|
||||
reset()
|
||||
return
|
||||
}
|
||||
|
||||
if showLoading { loading = true }
|
||||
defer { if showLoading { loading = false } }
|
||||
|
||||
let isScenicAdmin = roleId == 53
|
||||
async let summaryResult = api.summary(
|
||||
scenicId: scenicId,
|
||||
range: selectedPeriod.apiRange,
|
||||
isScenicAdmin: isScenicAdmin
|
||||
)
|
||||
async let dailyResult = api.dailyList(
|
||||
scenicId: scenicId,
|
||||
startTime: selectedPeriod.apiStartTime,
|
||||
endTime: selectedPeriod.apiEndTime,
|
||||
page: 1,
|
||||
pageSize: pageSize,
|
||||
isScenicAdmin: isScenicAdmin
|
||||
)
|
||||
let (summaryData, dailyData) = try await (summaryResult, dailyResult)
|
||||
summary = summaryData
|
||||
dailyItems = dailyData.data
|
||||
totalDailyCount = dailyData.total
|
||||
page = 1
|
||||
lastRefreshAt = Date()
|
||||
}
|
||||
|
||||
/// 加载每日统计下一页。
|
||||
func loadMore(api: StatisticsServing, scenicId: Int?, roleId: Int?) async throws {
|
||||
guard !loadingMore, hasMore, let scenicId else { return }
|
||||
|
||||
loadingMore = true
|
||||
defer { loadingMore = false }
|
||||
|
||||
let nextPage = page + 1
|
||||
let result = try await api.dailyList(
|
||||
scenicId: scenicId,
|
||||
startTime: selectedPeriod.apiStartTime,
|
||||
endTime: selectedPeriod.apiEndTime,
|
||||
page: nextPage,
|
||||
pageSize: pageSize,
|
||||
isScenicAdmin: roleId == 53
|
||||
)
|
||||
dailyItems.append(contentsOf: result.data)
|
||||
totalDailyCount = result.total
|
||||
page = nextPage
|
||||
}
|
||||
|
||||
/// 清空统计状态。
|
||||
private func reset() {
|
||||
summary = StatisticsSummaryResponse()
|
||||
dailyItems = []
|
||||
totalDailyCount = 0
|
||||
page = 1
|
||||
lastRefreshAt = nil
|
||||
loading = false
|
||||
loadingMore = false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user