修复合作获客扫码绑定崩溃与 Toast 层级,并接入分成比例修改。

将扫码页提升到列表层弹出并补齐 AppDelegate.window,避免扫码时 UIKit 取主窗口崩溃;Toast 改用独立 UIWindow 显示在 sheet 之上;合作获客员支持短信验证修改分成比例,同时优化冷启动根视图创建时机并补充相关测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-03 20:37:24 +08:00
parent 00c3cd0a93
commit 49e997ddba
20 changed files with 905 additions and 70 deletions

View File

@ -15,6 +15,7 @@ final class BindAcquirerViewModel: ObservableObject {
@Published var isLoading = false
@Published var isAlreadyBound = false
@Published var errorMessage: String?
@Published var commissionRateDraft = ""
private var saleUserId = 0
@ -27,6 +28,7 @@ final class BindAcquirerViewModel: ObservableObject {
if self.saleUserId == saleUserId && (inviteInfo != nil || isAlreadyBound) { return }
self.saleUserId = saleUserId
isAlreadyBound = false
commissionRateDraft = ""
isLoading = true
errorMessage = nil
defer { isLoading = false }
@ -54,10 +56,21 @@ final class BindAcquirerViewModel: ObservableObject {
}
}
/// 3
func updateCommissionRateDraft(_ text: String) {
commissionRateDraft = String(text.filter(\.isNumber).prefix(3))
}
///
func acceptBind(api: CooperationOrderServing) async throws {
guard saleUserId > 0, !isAlreadyBound else { return }
try await api.saleUserAcceptBind(saleUserId: saleUserId)
guard let commissionRate = Int(commissionRateDraft.trimmingCharacters(in: .whitespacesAndNewlines)) else {
throw CooperationOrderCommissionRateValidationError(message: "请输入分账比例")
}
guard (0...100).contains(commissionRate) else {
throw CooperationOrderCommissionRateValidationError(message: "分账比例需在0到100之间")
}
try await api.saleUserAcceptBind(saleUserId: saleUserId, commissionRate: commissionRate)
}
///

View File

@ -13,6 +13,10 @@ import Combine
final class CooperationAcquirerViewModel: ObservableObject {
@Published var acquirers: [CooperativeSaler] = []
@Published private(set) var hasLoadedOnce = false
@Published var commissionEditingAcquirer: CooperativeSaler?
@Published var commissionRateDraft = ""
@Published var commissionSmsCodeDraft = ""
@Published var commissionSmsCountdown = 0
///
func reload(api: CooperationOrderServing, storeId: Int?) async {
@ -45,6 +49,82 @@ final class CooperationAcquirerViewModel: ObservableObject {
return acquirer.withPhotogRemarkName(trimmedRemark)
}
}
///
func startEditCommissionRate(_ acquirer: CooperativeSaler) {
commissionEditingAcquirer = acquirer
commissionRateDraft = "\(acquirer.commissionRate)"
commissionSmsCodeDraft = ""
commissionSmsCountdown = 0
}
/// 3
func updateCommissionRateDraft(_ text: String) {
commissionRateDraft = String(text.filter(\.isNumber).prefix(3))
}
/// 6
func updateCommissionSmsCodeDraft(_ text: String) {
commissionSmsCodeDraft = String(text.filter(\.isNumber).prefix(6))
}
///
func dismissCommissionRateDialog() {
commissionEditingAcquirer = nil
commissionRateDraft = ""
commissionSmsCodeDraft = ""
commissionSmsCountdown = 0
}
/// 60
func sendCommissionRateSms(api: CooperationOrderServing) async throws {
guard commissionSmsCountdown == 0 else {
throw CooperationOrderCommissionRateValidationError(message: "请在倒计时结束后重新获取")
}
guard let acquirer = commissionEditingAcquirer else { return }
let phone = acquirer.salerPhone.cooperationNonEmptyOrDefault(acquirer.displayPhone)
.trimmingCharacters(in: .whitespacesAndNewlines)
guard !phone.isEmpty else {
throw CooperationOrderCommissionRateValidationError(message: "获客员手机号为空")
}
try await api.saleUserCommissionRateSendSmsCode(phone: phone)
commissionSmsCountdown = 60
}
///
func saveCommissionRate(api: CooperationOrderServing) async throws {
guard let acquirer = commissionEditingAcquirer else { return }
guard acquirer.saleUserId > 0 else { return }
guard let commissionRate = Int(commissionRateDraft.trimmingCharacters(in: .whitespacesAndNewlines)) else {
throw CooperationOrderCommissionRateValidationError(message: "请输入分成比例")
}
guard (0...100).contains(commissionRate) else {
throw CooperationOrderCommissionRateValidationError(message: "分成比例需在0到100之间")
}
let smsCode = commissionSmsCodeDraft.trimmingCharacters(in: .whitespacesAndNewlines)
guard !smsCode.isEmpty else {
throw CooperationOrderCommissionRateValidationError(message: "请输入验证码")
}
let updated = try await api.saleUserUpdateCommissionRate(
saleUserId: acquirer.saleUserId,
commissionRate: commissionRate,
smsCode: smsCode
)
if updated.saleUserId > 0 {
acquirers = acquirers.map { item in
item.saleUserId == updated.saleUserId ? updated : item
}
}
dismissCommissionRateDialog()
}
///
func tickCommissionSmsCountdown() {
if commissionSmsCountdown > 0 {
commissionSmsCountdown -= 1
}
}
}
///
@ -53,3 +133,10 @@ struct CooperationOrderRemarkValidationError: LocalizedError {
var errorDescription: String? { message }
}
///
struct CooperationOrderCommissionRateValidationError: LocalizedError {
let message: String
var errorDescription: String? { message }
}