Add scenic selection and cooperation order flows aligned with Android.
Upgrade scenic picker with search, location sorting, permission apply/status, and blocking home dialog; add cooperation order module and order source picker improvements with unit tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
196
suixinkan/UI/CooperationOrder/BindAcquirerViewController.swift
Normal file
196
suixinkan/UI/CooperationOrder/BindAcquirerViewController.swift
Normal file
@ -0,0 +1,196 @@
|
||||
//
|
||||
// BindAcquirerViewController.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import SnapKit
|
||||
import UIKit
|
||||
|
||||
/// 接受邀请 / 绑定获客员页,对齐 Android `BindAcquirerScreen`。
|
||||
final class BindAcquirerViewController: BaseViewController {
|
||||
|
||||
var onBindSuccess: (() -> Void)?
|
||||
|
||||
private let saleUserId: Int
|
||||
private let viewModel = BindAcquirerViewModel()
|
||||
private let orderAPI = NetworkServices.shared.orderAPI
|
||||
|
||||
private let scrollView = UIScrollView()
|
||||
private let contentStack = UIStackView()
|
||||
private let headerCard = UIView()
|
||||
private let headerIcon = UIImageView()
|
||||
private let headerTitleLabel = UILabel()
|
||||
private let infoCard = UIView()
|
||||
private let salerRow = CooperationInfoRowView(label: "获客员")
|
||||
private let phoneRow = CooperationInfoRowView(label: "手机号")
|
||||
private let commissionField = UITextField()
|
||||
private let acceptButton = AppButton(title: "接受邀请")
|
||||
private let loadingIndicator = UIActivityIndicatorView(style: .large)
|
||||
private let bottomBar = UIView()
|
||||
|
||||
init(saleUserId: Int) {
|
||||
self.saleUserId = saleUserId
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func setupNavigationBar() {
|
||||
title = "接受邀请"
|
||||
}
|
||||
|
||||
override func setupUI() {
|
||||
contentStack.axis = .vertical
|
||||
contentStack.spacing = AppSpacing.sm
|
||||
|
||||
headerCard.backgroundColor = AppColor.primary
|
||||
headerCard.layer.cornerRadius = AppRadius.md
|
||||
headerIcon.image = UIImage(systemName: "person.fill")
|
||||
headerIcon.tintColor = .white
|
||||
headerTitleLabel.text = "邀请信息"
|
||||
headerTitleLabel.font = .systemFont(ofSize: 16, weight: .bold)
|
||||
headerTitleLabel.textColor = .white
|
||||
|
||||
infoCard.backgroundColor = .white
|
||||
infoCard.layer.cornerRadius = AppRadius.md
|
||||
|
||||
commissionField.placeholder = "请输入分账比例(0-100)"
|
||||
commissionField.keyboardType = .numberPad
|
||||
commissionField.borderStyle = .roundedRect
|
||||
commissionField.font = .systemFont(ofSize: 15)
|
||||
|
||||
bottomBar.backgroundColor = .white
|
||||
acceptButton.addTarget(self, action: #selector(acceptTapped), for: .touchUpInside)
|
||||
|
||||
loadingIndicator.hidesWhenStopped = true
|
||||
loadingIndicator.color = AppColor.primary
|
||||
|
||||
view.addSubview(scrollView)
|
||||
view.addSubview(bottomBar)
|
||||
scrollView.addSubview(contentStack)
|
||||
bottomBar.addSubview(acceptButton)
|
||||
scrollView.addSubview(loadingIndicator)
|
||||
|
||||
contentStack.addArrangedSubview(headerCard)
|
||||
contentStack.addArrangedSubview(infoCard)
|
||||
|
||||
headerCard.addSubview(headerIcon)
|
||||
headerCard.addSubview(headerTitleLabel)
|
||||
|
||||
let infoStack = UIStackView(arrangedSubviews: [salerRow, phoneRow, commissionField])
|
||||
infoStack.axis = .vertical
|
||||
infoStack.spacing = AppSpacing.sm
|
||||
infoCard.addSubview(infoStack)
|
||||
infoStack.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(AppSpacing.md)
|
||||
}
|
||||
|
||||
headerIcon.snp.makeConstraints { make in
|
||||
make.leading.equalToSuperview().offset(AppSpacing.md)
|
||||
make.centerY.equalToSuperview()
|
||||
make.size.equalTo(24)
|
||||
}
|
||||
headerTitleLabel.snp.makeConstraints { make in
|
||||
make.leading.equalTo(headerIcon.snp.trailing).offset(AppSpacing.sm)
|
||||
make.trailing.equalToSuperview().inset(AppSpacing.md)
|
||||
make.top.bottom.equalToSuperview().inset(AppSpacing.md)
|
||||
}
|
||||
headerCard.snp.makeConstraints { make in
|
||||
make.height.greaterThanOrEqualTo(56)
|
||||
}
|
||||
commissionField.snp.makeConstraints { make in
|
||||
make.height.equalTo(44)
|
||||
}
|
||||
}
|
||||
|
||||
override func setupConstraints() {
|
||||
bottomBar.snp.makeConstraints { make in
|
||||
make.leading.trailing.bottom.equalToSuperview()
|
||||
}
|
||||
acceptButton.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(AppSpacing.md)
|
||||
}
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
|
||||
make.bottom.equalTo(bottomBar.snp.top)
|
||||
}
|
||||
contentStack.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(AppSpacing.md)
|
||||
make.width.equalTo(scrollView.snp.width).offset(-AppSpacing.md * 2)
|
||||
}
|
||||
loadingIndicator.snp.makeConstraints { make in
|
||||
make.center.equalTo(scrollView)
|
||||
}
|
||||
}
|
||||
|
||||
override func bindActions() {
|
||||
viewModel.onStateChange = { [weak self] in
|
||||
Task { @MainActor in self?.applyViewModel() }
|
||||
}
|
||||
viewModel.onShowMessage = { [weak self] message in
|
||||
Task { @MainActor in self?.showToast(message) }
|
||||
}
|
||||
viewModel.onBindSuccess = { [weak self] in
|
||||
Task { @MainActor in
|
||||
if let callback = self?.onBindSuccess {
|
||||
callback()
|
||||
} else {
|
||||
self?.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModel.onShouldPop = { [weak self] in
|
||||
Task { @MainActor in self?.navigationController?.popViewController(animated: true) }
|
||||
}
|
||||
commissionField.addTarget(self, action: #selector(commissionChanged), for: .editingChanged)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
guard CooperationOrderFeature.hasPermission(in: AppStore.shared.permissionItems()) else {
|
||||
showToast("暂无合作订单权限")
|
||||
navigationController?.popViewController(animated: false)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
viewModel.initSaleUserId(saleUserId)
|
||||
Task { await viewModel.loadInviteInfo(api: orderAPI) }
|
||||
}
|
||||
|
||||
@objc private func commissionChanged() {
|
||||
viewModel.updateCommissionRateDraft(commissionField.text ?? "")
|
||||
}
|
||||
|
||||
@objc private func acceptTapped() {
|
||||
Task { await viewModel.acceptBind(api: orderAPI) }
|
||||
}
|
||||
|
||||
private func applyViewModel() {
|
||||
if viewModel.isLoading, viewModel.inviteInfo == nil {
|
||||
loadingIndicator.startAnimating()
|
||||
contentStack.isHidden = true
|
||||
bottomBar.isHidden = true
|
||||
return
|
||||
}
|
||||
loadingIndicator.stopAnimating()
|
||||
contentStack.isHidden = false
|
||||
bottomBar.isHidden = false
|
||||
|
||||
if let info = viewModel.inviteInfo {
|
||||
title = info.title.isEmpty ? "接受邀请" : info.title
|
||||
salerRow.setValue(info.salerName.isEmpty ? "—" : info.salerName)
|
||||
phoneRow.setValue(info.salerPhone.isEmpty ? "—" : info.salerPhone)
|
||||
}
|
||||
|
||||
commissionField.text = viewModel.commissionRateDraft
|
||||
commissionField.isEnabled = !viewModel.isAlreadyBound
|
||||
acceptButton.isEnabled = !viewModel.isAlreadyBound
|
||||
acceptButton.setTitle(viewModel.isAlreadyBound ? "已绑定获客员" : "接受邀请", for: .normal)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user