新增 CooperationOrder 模块(双 Tab 列表、获客员绑定、主 Tab 扫码)、订单来源/带客单绑定及配套 API 测试;同步引入 roleCode 权限匹配与相关单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
124 lines
4.7 KiB
Swift
124 lines
4.7 KiB
Swift
//
|
||
// CooperationOrderListView.swift
|
||
// suixinkan
|
||
//
|
||
// Created by Codex on 2026/6/29.
|
||
//
|
||
|
||
import SwiftUI
|
||
|
||
/// 合作订单主页,展示获客线索与获客订单双 Tab 列表。
|
||
struct CooperationOrderListView: View {
|
||
@Environment(\.cooperationOrderAPI) private var cooperationOrderAPI
|
||
@Environment(\.globalLoading) private var globalLoading
|
||
@StateObject private var viewModel = CooperationOrderListViewModel()
|
||
@State private var route: CooperationOrderRoute?
|
||
|
||
var body: some View {
|
||
VStack(spacing: 0) {
|
||
CooperationOrderTabs(
|
||
selectedTab: viewModel.selectedTab,
|
||
onTabSelected: { viewModel.onTabSelected($0) }
|
||
)
|
||
|
||
if viewModel.selectedTab == 1 {
|
||
CooperationOrderSearchBar(searchText: $viewModel.searchText) {
|
||
Task { await searchOrders(showLoading: true) }
|
||
}
|
||
}
|
||
|
||
ScrollView {
|
||
LazyVStack(spacing: 12) {
|
||
if viewModel.selectedTab == 0 {
|
||
if viewModel.hasLoadedLeadsOnce && viewModel.leads.isEmpty {
|
||
emptyState("暂无获客员线索")
|
||
} else {
|
||
ForEach(Array(viewModel.leads.enumerated()), id: \.element.id) { index, lead in
|
||
ReferralLeadCard(lead: lead)
|
||
.onAppear {
|
||
guard index >= viewModel.leads.count - 3 else { return }
|
||
Task { await viewModel.loadMore(api: cooperationOrderAPI) }
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if viewModel.hasLoadedOrdersOnce && viewModel.orders.isEmpty {
|
||
emptyState("暂无相关合作订单")
|
||
} else {
|
||
ForEach(Array(viewModel.orders.enumerated()), id: \.element.id) { index, order in
|
||
AcquisitionOrderCard(order: order)
|
||
.onAppear {
|
||
guard index >= viewModel.orders.count - 3 else { return }
|
||
Task { await viewModel.loadMore(api: cooperationOrderAPI) }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if viewModel.isLoadingMore {
|
||
ProgressView()
|
||
.tint(CooperationOrderColors.primary)
|
||
.frame(width: 24, height: 24)
|
||
.padding(16)
|
||
}
|
||
}
|
||
.padding(.horizontal, 14)
|
||
.padding(.vertical, 12)
|
||
}
|
||
.refreshable {
|
||
await reloadCurrentTab(showLoading: false)
|
||
}
|
||
}
|
||
.navigationTitle("合作订单")
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
.toolbar {
|
||
ToolbarItem(placement: .topBarTrailing) {
|
||
Button("合作获客员") {
|
||
route = .acquirer
|
||
}
|
||
.font(.system(size: 14))
|
||
.foregroundStyle(CooperationOrderColors.primary)
|
||
}
|
||
}
|
||
.background(CooperationOrderColors.pageBg.ignoresSafeArea())
|
||
.appNavigationDestination(item: $route) { destination in
|
||
switch destination {
|
||
case .acquirer:
|
||
CooperationAcquirerView(onBind: { saleUserId in
|
||
route = .bind(saleUserId: saleUserId)
|
||
})
|
||
case let .bind(saleUserId):
|
||
BindAcquirerView(saleUserId: saleUserId, onSuccess: {
|
||
route = .acquirer
|
||
})
|
||
}
|
||
}
|
||
.task {
|
||
await reloadCurrentTab(showLoading: true)
|
||
}
|
||
.onChange(of: viewModel.selectedTab) { _ in
|
||
Task { await reloadCurrentTab(showLoading: true) }
|
||
}
|
||
}
|
||
|
||
private func reloadCurrentTab(showLoading: Bool) async {
|
||
await globalLoading.withOptionalLoading(showLoading) {
|
||
await viewModel.refreshCurrentTab(api: cooperationOrderAPI)
|
||
}
|
||
}
|
||
|
||
private func searchOrders(showLoading: Bool) async {
|
||
await globalLoading.withOptionalLoading(showLoading) {
|
||
await viewModel.searchOrders(api: cooperationOrderAPI)
|
||
}
|
||
}
|
||
|
||
private func emptyState(_ text: String) -> some View {
|
||
Text(text)
|
||
.font(.system(size: 14))
|
||
.foregroundStyle(CooperationOrderColors.text999)
|
||
.frame(maxWidth: .infinity)
|
||
.padding(.vertical, 48)
|
||
}
|
||
}
|