Files
suixinkan_ios_new/suixinkan/Features/Orders/ViewModels/WriteOffListViewModel.swift

142 lines
4.9 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.

//
// WriteOffListViewModel.swift
// suixinkan
//
// Created by Codex on 2026/6/29.
//
import Foundation
import Combine
@MainActor
/// ViewModel Android WriteOffListViewModel
final class WriteOffListViewModel: ObservableObject {
@Published var searchPhone = ""
@Published var selectedStatus = 0
@Published var filterStartDate: Date?
@Published var filterEndDate: Date?
@Published private(set) var orders: [WriteOffOrderItem] = []
@Published private(set) var loading = false
@Published private(set) var loadingMore = false
@Published private(set) var isVerifying = false
@Published private(set) var total = 0
@Published private(set) var page = 1
@Published private(set) var hasMore = false
private let pageSize = 20
///
var normalizedPhone: String? {
let text = searchPhone.trimmingCharacters(in: .whitespacesAndNewlines)
return text.isEmpty ? nil : text
}
///
func reload(api: OrderServing, scenicId: Int?, storeId: Int? = nil, showLoading: Bool = true) async throws {
guard let scenicId else {
orders = []
total = 0
page = 1
hasMore = false
return
}
if showLoading { loading = true }
defer { if showLoading { loading = false } }
let result = try await api.writeOffList(
scenicId: scenicId,
storeId: storeId,
page: 1,
pageSize: pageSize,
orderStatus: orderStatusQuery,
orderVerifyStatus: verifyStatusQuery,
startTime: OrderDateRangeFormatter.queryValue(from: filterStartDate),
endTime: OrderDateRangeFormatter.queryValue(from: filterEndDate),
userPhone: normalizedPhone
)
orders = result.list
total = result.total
page = 1
hasMore = orders.count < result.total && !result.list.isEmpty
}
///
func loadMore(api: OrderServing, scenicId: Int?, storeId: Int? = nil) async throws {
guard !loadingMore, hasMore, let scenicId else { return }
loadingMore = true
defer { loadingMore = false }
let nextPage = page + 1
let result = try await api.writeOffList(
scenicId: scenicId,
storeId: storeId,
page: nextPage,
pageSize: pageSize,
orderStatus: orderStatusQuery,
orderVerifyStatus: verifyStatusQuery,
startTime: OrderDateRangeFormatter.queryValue(from: filterStartDate),
endTime: OrderDateRangeFormatter.queryValue(from: filterEndDate),
userPhone: normalizedPhone
)
orders.append(contentsOf: result.list)
total = result.total
page = nextPage
hasMore = orders.count < result.total && !result.list.isEmpty
}
///
func verify(api: OrderServing, scenicId: Int, storeId: Int? = nil, orderNumber: String) async throws {
guard !isVerifying else { return }
isVerifying = true
defer { isVerifying = false }
try await api.writeOff(orderNumber: orderNumber)
try await reload(api: api, scenicId: scenicId, storeId: storeId, showLoading: false)
}
///
func matchedWriteOffOrder(for rawCode: String) -> (orderNumber: String, matched: WriteOffOrderItem?)? {
guard let orderNumber = OrderNumberParser.parse(rawCode) else { return nil }
let matched = orders.first {
$0.orderNumber.caseInsensitiveCompare(orderNumber) == .orderedSame
}
return (matched?.orderNumber ?? orderNumber, matched)
}
///
func writeOffOrder(matching orderNumber: String) -> WriteOffOrderItem? {
orders.first { $0.orderNumber.caseInsensitiveCompare(orderNumber) == .orderedSame }
}
///
func canVerify(_ item: WriteOffOrderItem) -> Bool {
let status = displayVerificationStatus(for: item)
return !status.contains("已核销") && !status.contains("已退款") && !status.contains("已完成")
}
///
func displayVerificationStatus(for item: WriteOffOrderItem) -> String {
let text = item.orderVerificationStatus.trimmingCharacters(in: .whitespacesAndNewlines)
return text.isEmpty ? "待核销" : text
}
private var orderStatusQuery: Int? {
switch selectedStatus {
case 18, 30:
return selectedStatus
default:
return nil
}
}
private var verifyStatusQuery: Int? {
switch selectedStatus {
case 1, 2:
return selectedStatus
default:
return nil
}
}
}