From 5a2b7b60979287935a030a8da1fbc6c10a7cd088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=89=E7=A7=8B?= <497055328@qq.com> Date: Tue, 7 Jul 2026 11:14:57 +0800 Subject: [PATCH] Fix image preview presentation when order source sheet is open. Present previews from the top of the presentation chain so tapping lead images inside the sheet no longer conflicts with the already-presented picker. Co-authored-by: Cursor --- suixinkan/Base/BaseViewController.swift | 24 +++++++++++++++++++ .../OrderSourceLeadListViewController.swift | 9 ++++--- .../OrderSourcePickerViewController.swift | 8 ++----- .../UI/Orders/OrdersViewController.swift | 10 +------- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/suixinkan/Base/BaseViewController.swift b/suixinkan/Base/BaseViewController.swift index 66a47d7..e7bdf43 100644 --- a/suixinkan/Base/BaseViewController.swift +++ b/suixinkan/Base/BaseViewController.swift @@ -119,6 +119,30 @@ class BaseViewController: UIViewController { navigationController?.popViewController(animated: true) } + /// 沿 presentation 链找到当前最顶层控制器,避免 Sheet 已展示时 present 冲突。 + func topMostPresentedViewController() -> UIViewController { + var top: UIViewController = self + while let presented = top.presentedViewController { + top = presented + } + return top + } + + /// 在当前可见 presentation 链顶端弹出页面。 + func presentOnTop( + _ viewController: UIViewController, + animated: Bool = true, + completion: (() -> Void)? = nil + ) { + topMostPresentedViewController().present(viewController, animated: animated, completion: completion) + } + + /// 全屏预览网络图片。 + func presentImagePreview(imageURLs: [String], startIndex: Int) { + guard !imageURLs.isEmpty else { return } + presentOnTop(ImagePreviewViewController(imageURLs: imageURLs, startIndex: startIndex)) + } + // MARK: - Notifications private func registerBaseNotifications() { diff --git a/suixinkan/UI/Orders/OrderSourceLeadListViewController.swift b/suixinkan/UI/Orders/OrderSourceLeadListViewController.swift index 7d37332..08311e3 100644 --- a/suixinkan/UI/Orders/OrderSourceLeadListViewController.swift +++ b/suixinkan/UI/Orders/OrderSourceLeadListViewController.swift @@ -16,7 +16,6 @@ final class OrderSourceLeadListViewController: BaseViewController, UITableViewDa private let loadLeads: (OrderSourcePerson) async -> Void private let onLeadBound: (OrderSourceSelection) -> Void private let onCallPhone: (String) -> Void - private let onPreviewImages: ([String], Int) -> Void private let phoneRow = UIStackView() private let phoneLabel = UILabel() @@ -32,8 +31,7 @@ final class OrderSourceLeadListViewController: BaseViewController, UITableViewDa referralOrder: BoundReferralOrderEntity?, loadLeads: @escaping (OrderSourcePerson) async -> Void, onLeadBound: @escaping (OrderSourceSelection) -> Void, - onCallPhone: @escaping (String) -> Void, - onPreviewImages: @escaping ([String], Int) -> Void + onCallPhone: @escaping (String) -> Void ) { self.person = person self.orderNumber = orderNumber @@ -42,7 +40,6 @@ final class OrderSourceLeadListViewController: BaseViewController, UITableViewDa self.loadLeads = loadLeads self.onLeadBound = onLeadBound self.onCallPhone = onCallPhone - self.onPreviewImages = onPreviewImages super.init(nibName: nil, bundle: nil) } @@ -178,7 +175,9 @@ final class OrderSourceLeadListViewController: BaseViewController, UITableViewDa && currentSelection?.lead.key == lead.key cell.configure(lead: lead, selected: selected) cell.onCallPhone = onCallPhone - cell.onImageTap = onPreviewImages + cell.onImageTap = { [weak self] urls, index in + self?.presentImagePreview(imageURLs: urls, startIndex: index) + } cell.onSelect = { [weak self] in guard let self else { return } let selection = OrderSourceSelection(person: self.person, lead: lead) diff --git a/suixinkan/UI/Orders/OrderSourcePickerViewController.swift b/suixinkan/UI/Orders/OrderSourcePickerViewController.swift index d947b7f..6a7912f 100644 --- a/suixinkan/UI/Orders/OrderSourcePickerViewController.swift +++ b/suixinkan/UI/Orders/OrderSourcePickerViewController.swift @@ -15,7 +15,6 @@ final class OrderSourcePickerViewController: UIViewController, UITableViewDataSo private let loadLeads: (OrderSourcePerson) async -> Void private let onLeadBound: (OrderSourceSelection) -> Void private let onCallPhone: (String) -> Void - private let onPreviewImages: ([String], Int) -> Void private let titleLabel = UILabel() private let subtitleLabel = UILabel() @@ -29,8 +28,7 @@ final class OrderSourcePickerViewController: UIViewController, UITableViewDataSo referralOrder: BoundReferralOrderEntity?, loadLeads: @escaping (OrderSourcePerson) async -> Void, onLeadBound: @escaping (OrderSourceSelection) -> Void, - onCallPhone: @escaping (String) -> Void, - onPreviewImages: @escaping ([String], Int) -> Void + onCallPhone: @escaping (String) -> Void ) { self.orderNumber = orderNumber self.viewModel = viewModel @@ -38,7 +36,6 @@ final class OrderSourcePickerViewController: UIViewController, UITableViewDataSo self.loadLeads = loadLeads self.onLeadBound = onLeadBound self.onCallPhone = onCallPhone - self.onPreviewImages = onPreviewImages super.init(nibName: nil, bundle: nil) } @@ -157,8 +154,7 @@ final class OrderSourcePickerViewController: UIViewController, UITableViewDataSo referralOrder: referralOrder, loadLeads: loadLeads, onLeadBound: onLeadBound, - onCallPhone: onCallPhone, - onPreviewImages: onPreviewImages + onCallPhone: onCallPhone ) navigationController?.setNavigationBarHidden(false, animated: true) navigationController?.pushViewController(leadController, animated: true) diff --git a/suixinkan/UI/Orders/OrdersViewController.swift b/suixinkan/UI/Orders/OrdersViewController.swift index 7b3877f..87db859 100644 --- a/suixinkan/UI/Orders/OrdersViewController.swift +++ b/suixinkan/UI/Orders/OrdersViewController.swift @@ -377,7 +377,7 @@ final class OrdersViewController: BaseViewController, UITableViewDataSource, UIT self?.presentOrderSourcePicker(for: order) } actions.onOrderSourceImageTap = { [weak self] images, index in - self?.presentImagePreview(images: images, startIndex: index) + self?.presentImagePreview(imageURLs: images, startIndex: index) } if let travel = order.photoTravel, travel.canGiftRetouch { actions.onSendGift = { [weak self] in @@ -492,9 +492,6 @@ final class OrdersViewController: BaseViewController, UITableViewDataSource, UIT }, onCallPhone: { [weak self] phone in self?.callPhone(phone) - }, - onPreviewImages: { [weak self] urls, index in - self?.presentImagePreview(images: urls, startIndex: index) } ) self.orderSourcePicker = controller @@ -524,9 +521,4 @@ final class OrdersViewController: BaseViewController, UITableViewDataSource, UIT guard !trimmed.isEmpty, let url = URL(string: "tel://\(trimmed)") else { return } UIApplication.shared.open(url) } - - private func presentImagePreview(images: [String], startIndex: Int) { - guard !images.isEmpty else { return } - present(ImagePreviewViewController(imageURLs: images, startIndex: startIndex), animated: true) - } }