新增 CooperationOrder 模块(双 Tab 列表、获客员绑定、主 Tab 扫码)、订单来源/带客单绑定及配套 API 测试;同步引入 roleCode 权限匹配与相关单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
131 lines
3.9 KiB
Swift
131 lines
3.9 KiB
Swift
//
|
||
// CooperationOrderListViewModel.swift
|
||
// suixinkan
|
||
//
|
||
// Created by Codex on 2026/6/29.
|
||
//
|
||
|
||
import Foundation
|
||
import Combine
|
||
|
||
/// 合作订单列表 ViewModel,管理获客线索与获客订单双 Tab 分页。
|
||
@MainActor
|
||
final class CooperationOrderListViewModel: ObservableObject {
|
||
@Published var selectedTab = 0
|
||
@Published var searchText = ""
|
||
@Published var leads: [ReferralLead] = []
|
||
@Published var orders: [AcquisitionOrder] = []
|
||
@Published var isLoadingMore = false
|
||
@Published var canLoadMore = false
|
||
@Published private(set) var hasLoadedLeadsOnce = false
|
||
@Published private(set) var hasLoadedOrdersOnce = false
|
||
|
||
private var leadsPage = 1
|
||
private var ordersPage = 1
|
||
private var leadsTotal = 0
|
||
private var ordersTotal = 0
|
||
private var isReloading = false
|
||
private let pageSize = 10
|
||
|
||
/// 切换 Tab 并触发对应列表刷新。
|
||
func onTabSelected(_ index: Int) {
|
||
guard selectedTab != index else { return }
|
||
selectedTab = index
|
||
}
|
||
|
||
/// 刷新当前 Tab 列表。
|
||
func refreshCurrentTab(api: CooperationOrderServing) async {
|
||
if selectedTab == 0 {
|
||
await refreshLeads(api: api)
|
||
} else {
|
||
await refreshOrders(api: api)
|
||
}
|
||
}
|
||
|
||
/// 刷新获客线索列表。
|
||
func refreshLeads(api: CooperationOrderServing) async {
|
||
guard !isReloading else { return }
|
||
isReloading = true
|
||
defer { isReloading = false }
|
||
leadsPage = 1
|
||
isLoadingMore = false
|
||
await loadLeads(api: api)
|
||
}
|
||
|
||
/// 刷新获客订单列表。
|
||
func refreshOrders(api: CooperationOrderServing) async {
|
||
guard !isReloading else { return }
|
||
isReloading = true
|
||
defer { isReloading = false }
|
||
ordersPage = 1
|
||
isLoadingMore = false
|
||
await loadOrders(api: api)
|
||
}
|
||
|
||
/// 加载更多当前 Tab 数据。
|
||
func loadMore(api: CooperationOrderServing) async {
|
||
guard !isReloading, !isLoadingMore, canLoadMore else { return }
|
||
isLoadingMore = true
|
||
if selectedTab == 0 {
|
||
leadsPage += 1
|
||
await loadLeads(api: api)
|
||
} else {
|
||
ordersPage += 1
|
||
await loadOrders(api: api)
|
||
}
|
||
}
|
||
|
||
/// 按关键词搜索获客订单。
|
||
func searchOrders(api: CooperationOrderServing) async {
|
||
guard selectedTab == 1 else { return }
|
||
await refreshOrders(api: api)
|
||
}
|
||
|
||
private func loadLeads(api: CooperationOrderServing) async {
|
||
do {
|
||
let data = try await api.saleUserReferralLeads(page: leadsPage, pageSize: pageSize)
|
||
leadsTotal = data.total
|
||
if leadsPage == 1 {
|
||
leads = data.list
|
||
} else {
|
||
leads.append(contentsOf: data.list)
|
||
}
|
||
canLoadMore = leads.count < leadsTotal
|
||
} catch {
|
||
if leadsPage == 1, !hasLoadedLeadsOnce {
|
||
leads = []
|
||
}
|
||
}
|
||
if leadsPage == 1 {
|
||
hasLoadedLeadsOnce = true
|
||
}
|
||
isLoadingMore = false
|
||
}
|
||
|
||
private func loadOrders(api: CooperationOrderServing) async {
|
||
do {
|
||
let keyword = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||
let data = try await api.saleUserAcquisitionOrders(
|
||
keyword: keyword.isEmpty ? nil : keyword,
|
||
page: ordersPage,
|
||
pageSize: pageSize
|
||
)
|
||
ordersTotal = data.total
|
||
if ordersPage == 1 {
|
||
orders = data.list
|
||
} else {
|
||
orders.append(contentsOf: data.list)
|
||
}
|
||
canLoadMore = orders.count < ordersTotal
|
||
} catch {
|
||
if ordersPage == 1, !hasLoadedOrdersOnce {
|
||
orders = []
|
||
}
|
||
}
|
||
if ordersPage == 1 {
|
||
hasLoadedOrdersOnce = true
|
||
}
|
||
isLoadingMore = false
|
||
}
|
||
}
|