同步订单详情与扫码核销流程
This commit is contained in:
@ -0,0 +1,71 @@
|
||||
//
|
||||
// OrderDetailViewModel.swift
|
||||
// suixinkan
|
||||
//
|
||||
// Created by Codex on 2026/6/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
/// 订单详情 ViewModel,负责加载门店订单详情并保留列表摘要兜底展示。
|
||||
final class OrderDetailViewModel {
|
||||
private(set) var detail: StoreOrderDetailResponse?
|
||||
private(set) var loading = false
|
||||
private(set) var errorMessage: String?
|
||||
private(set) var contextMessage: String?
|
||||
|
||||
/// 当前页面用于展示的订单信息,详情接口成功时优先使用详情数据。
|
||||
var display: StoreOrderDetailDisplay {
|
||||
if let detail {
|
||||
return StoreOrderDetailDisplay(detail: detail)
|
||||
}
|
||||
return StoreOrderDetailDisplay(item: item)
|
||||
}
|
||||
|
||||
/// 详情中的项目配置。
|
||||
var projectInfo: StoreOrderProjectInfo? {
|
||||
detail?.multiTravel?.projectInfo
|
||||
}
|
||||
|
||||
/// 详情中的拍摄点列表。
|
||||
var shootingList: [StoreOrderShootingListItem] {
|
||||
detail?.multiTravel?.shootingList ?? []
|
||||
}
|
||||
|
||||
private let item: OrderEntity
|
||||
|
||||
/// 初始化详情 ViewModel,并注入列表订单作为兜底数据。
|
||||
init(item: OrderEntity) {
|
||||
self.item = item
|
||||
}
|
||||
|
||||
/// 加载门店订单详情,缺少门店 ID 时只保留列表摘要展示。
|
||||
func load(api: OrderServing, fallbackStoreId: Int?) async {
|
||||
guard detail == nil, !loading else { return }
|
||||
|
||||
guard let storeId = item.storeId ?? fallbackStoreId, storeId > 0 else {
|
||||
contextMessage = "缺少门店上下文,当前展示订单摘要。"
|
||||
return
|
||||
}
|
||||
|
||||
loading = true
|
||||
errorMessage = nil
|
||||
contextMessage = nil
|
||||
defer { loading = false }
|
||||
|
||||
do {
|
||||
detail = try await api.storeOrderDetail(storeId: storeId, orderNumber: item.orderNumber)
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
contextMessage = "详情加载失败,当前展示订单摘要。"
|
||||
}
|
||||
}
|
||||
|
||||
/// 清理当前错误提示。
|
||||
func clearError() {
|
||||
errorMessage = nil
|
||||
}
|
||||
}
|
||||
@ -39,12 +39,12 @@ final class OrdersViewModel {
|
||||
}
|
||||
|
||||
/// 根据当前子入口刷新对应列表。
|
||||
func reload(api: OrderServing, scenicId: Int?, roleId: Int?, showLoading: Bool = true) async throws {
|
||||
func reload(api: OrderServing, scenicId: Int?, storeId: Int? = nil, roleId: Int?, showLoading: Bool = true) async throws {
|
||||
switch selectedEntry {
|
||||
case .storeOrders:
|
||||
try await reloadStoreOrders(api: api, scenicId: scenicId, roleId: roleId, showLoading: showLoading)
|
||||
case .verificationOrders:
|
||||
try await reloadWriteOffOrders(api: api, scenicId: scenicId, showLoading: showLoading)
|
||||
try await reloadWriteOffOrders(api: api, scenicId: scenicId, storeId: storeId, showLoading: showLoading)
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ final class OrdersViewModel {
|
||||
}
|
||||
|
||||
/// 刷新核销订单列表,缺少景区时清空旧数据。
|
||||
func reloadWriteOffOrders(api: OrderServing, scenicId: Int?, showLoading: Bool = true) async throws {
|
||||
func reloadWriteOffOrders(api: OrderServing, scenicId: Int?, storeId: Int? = nil, showLoading: Bool = true) async throws {
|
||||
guard let scenicId else {
|
||||
writeOffOrders = []
|
||||
writeOffTotal = 0
|
||||
@ -115,7 +115,7 @@ final class OrdersViewModel {
|
||||
if showLoading { loading = true }
|
||||
defer { if showLoading { loading = false } }
|
||||
|
||||
let result = try await api.writeOffList(scenicId: scenicId, page: 1, pageSize: pageSize)
|
||||
let result = try await api.writeOffList(scenicId: scenicId, storeId: storeId, page: 1, pageSize: pageSize)
|
||||
writeOffOrders = result.list
|
||||
writeOffTotal = result.total
|
||||
writeOffPage = 1
|
||||
@ -123,13 +123,13 @@ final class OrdersViewModel {
|
||||
}
|
||||
|
||||
/// 加载核销订单下一页。
|
||||
func loadMoreWriteOffOrders(api: OrderServing, scenicId: Int?) async throws {
|
||||
func loadMoreWriteOffOrders(api: OrderServing, scenicId: Int?, storeId: Int? = nil) async throws {
|
||||
guard !loadingMore, writeOffHasMore, let scenicId else { return }
|
||||
loadingMore = true
|
||||
defer { loadingMore = false }
|
||||
|
||||
let nextPage = writeOffPage + 1
|
||||
let result = try await api.writeOffList(scenicId: scenicId, page: nextPage, pageSize: pageSize)
|
||||
let result = try await api.writeOffList(scenicId: scenicId, storeId: storeId, page: nextPage, pageSize: pageSize)
|
||||
writeOffOrders.append(contentsOf: result.list)
|
||||
writeOffTotal = result.total
|
||||
writeOffPage = nextPage
|
||||
@ -137,7 +137,7 @@ final class OrdersViewModel {
|
||||
}
|
||||
|
||||
/// 手动核销订单,并在成功后刷新核销列表。
|
||||
func verify(api: OrderServing, scenicId: Int, orderNumber: String) async throws {
|
||||
func verify(api: OrderServing, scenicId: Int, storeId: Int? = nil, orderNumber: String) async throws {
|
||||
guard !isVerifying else { return }
|
||||
|
||||
isVerifying = true
|
||||
@ -148,13 +148,31 @@ final class OrdersViewModel {
|
||||
}
|
||||
|
||||
try await api.writeOff(orderNumber: orderNumber)
|
||||
let refreshed = try await api.writeOffList(scenicId: scenicId, page: 1, pageSize: pageSize)
|
||||
let refreshed = try await api.writeOffList(scenicId: scenicId, storeId: storeId, page: 1, pageSize: pageSize)
|
||||
writeOffOrders = refreshed.list
|
||||
writeOffTotal = refreshed.total
|
||||
writeOffPage = 1
|
||||
writeOffHasMore = writeOffOrders.count < refreshed.total && !refreshed.list.isEmpty
|
||||
}
|
||||
|
||||
/// 解析扫码结果并返回当前核销列表中的匹配订单。
|
||||
func matchedWriteOffOrder(for rawCode: String) -> (orderNumber: String, matched: WriteOffOrderItem?)? {
|
||||
guard let orderNumber = OrderNumberParser.parse(rawCode) else {
|
||||
return nil
|
||||
}
|
||||
let matched = writeOffOrders.first {
|
||||
$0.orderNumber.caseInsensitiveCompare(orderNumber) == .orderedSame
|
||||
}
|
||||
return (matched?.orderNumber ?? orderNumber, matched)
|
||||
}
|
||||
|
||||
/// 根据订单号查找当前核销列表中的订单。
|
||||
func writeOffOrder(matching orderNumber: String) -> WriteOffOrderItem? {
|
||||
writeOffOrders.first {
|
||||
$0.orderNumber.caseInsensitiveCompare(orderNumber) == .orderedSame
|
||||
}
|
||||
}
|
||||
|
||||
/// 用于测试重复提交场景的内部状态设置。
|
||||
func markVerifyingForTests(orderNumber: String) {
|
||||
isVerifying = true
|
||||
|
||||
Reference in New Issue
Block a user