feat: 优化线下收款日历交互与选中态
This commit is contained in:
@@ -24,6 +24,8 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
||||
private let headerContainer = UIView()
|
||||
private let headerStack = UIStackView()
|
||||
private let calendarView = OfflineCollectionCalendarView()
|
||||
private var calendarHeightConstraint: Constraint?
|
||||
private var isAnimatingHeaderResize = false
|
||||
private let summaryCard = UIView()
|
||||
private let summaryDateLabel = UILabel()
|
||||
private let totalValue = UILabel()
|
||||
@@ -75,7 +77,7 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
||||
guard let self else { return }
|
||||
Task { await self.viewModel.selectBusinessDate(date) }
|
||||
}
|
||||
calendarView.onModeChanged = { [weak self] in self?.resizeHeader() }
|
||||
calendarView.onModeChanged = { [weak self] animated in self?.resizeHeader(animated: animated) }
|
||||
viewModel.onStateChange = { [weak self] in Task { @MainActor in self?.applyState() } }
|
||||
}
|
||||
|
||||
@@ -91,7 +93,9 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
resizeHeader()
|
||||
if !isAnimatingHeaderResize {
|
||||
resizeHeader()
|
||||
}
|
||||
}
|
||||
|
||||
private func configureTableView() {
|
||||
@@ -116,6 +120,9 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
||||
make.leading.trailing.equalToSuperview().inset(16)
|
||||
}
|
||||
headerStack.addArrangedSubview(calendarView)
|
||||
calendarView.snp.makeConstraints { make in
|
||||
calendarHeightConstraint = make.height.equalTo(calendarView.preferredHeight).constraint
|
||||
}
|
||||
configureSummaryCard()
|
||||
headerStack.addArrangedSubview(summaryCard)
|
||||
|
||||
@@ -351,9 +358,41 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private func resizeHeader() {
|
||||
private func resizeHeader(animated: Bool = false) {
|
||||
guard tableView.bounds.width > 0 else { return }
|
||||
if isAnimatingHeaderResize, !animated { return }
|
||||
headerContainer.frame.size.width = tableView.bounds.width
|
||||
|
||||
let targetCalendarHeight = calendarView.preferredHeight
|
||||
if animated,
|
||||
!UIAccessibility.isReduceMotionEnabled,
|
||||
headerContainer.frame.height > 0,
|
||||
calendarView.bounds.height > 0 {
|
||||
let targetHeaderHeight = headerContainer.frame.height + targetCalendarHeight - calendarView.bounds.height
|
||||
guard abs(headerContainer.frame.height - targetHeaderHeight) > 0.5 else { return }
|
||||
calendarHeightConstraint?.update(offset: targetCalendarHeight)
|
||||
isAnimatingHeaderResize = true
|
||||
UIView.animate(
|
||||
withDuration: 0.3,
|
||||
delay: 0,
|
||||
options: [.curveEaseInOut, .beginFromCurrentState],
|
||||
animations: { [weak self] in
|
||||
guard let self else { return }
|
||||
headerContainer.frame.size.height = targetHeaderHeight
|
||||
headerContainer.layoutIfNeeded()
|
||||
tableView.tableHeaderView = headerContainer
|
||||
tableView.layoutIfNeeded()
|
||||
},
|
||||
completion: { [weak self] _ in
|
||||
guard let self else { return }
|
||||
isAnimatingHeaderResize = false
|
||||
resizeHeader()
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
calendarHeightConstraint?.update(offset: targetCalendarHeight)
|
||||
headerContainer.setNeedsLayout()
|
||||
headerContainer.layoutIfNeeded()
|
||||
let height = headerContainer.systemLayoutSizeFitting(
|
||||
@@ -362,8 +401,13 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
||||
verticalFittingPriority: .fittingSizeLevel
|
||||
).height
|
||||
guard abs(headerContainer.frame.height - height) > 0.5 else { return }
|
||||
headerContainer.frame.size.height = height
|
||||
tableView.tableHeaderView = headerContainer
|
||||
let updates = { [weak self] in
|
||||
guard let self else { return }
|
||||
headerContainer.frame.size.height = height
|
||||
tableView.tableHeaderView = headerContainer
|
||||
tableView.layoutIfNeeded()
|
||||
}
|
||||
updates()
|
||||
}
|
||||
|
||||
@MainActor private func presentFeedbackIfNeeded() {
|
||||
@@ -371,15 +415,9 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
||||
switch viewModel.settlementState {
|
||||
case .idle, .processing:
|
||||
return
|
||||
case let .success(result):
|
||||
feedbackPresented = true
|
||||
let alert = UIAlertController(
|
||||
title: "补缴成功",
|
||||
message: "营业日:\(result.date)\n共结清 \(result.updatedCount) 笔",
|
||||
preferredStyle: .alert
|
||||
)
|
||||
alert.addAction(UIAlertAction(title: "完成", style: .default) { [weak self] _ in self?.finishFeedback() })
|
||||
present(alert, animated: true)
|
||||
case .success:
|
||||
// 成功后页面数据已经刷新,直接清理反馈状态,不再阻断用户操作。
|
||||
viewModel.clearSettlementFeedback()
|
||||
case let .failed(message, canRetry):
|
||||
feedbackPresented = true
|
||||
let alert = UIAlertController(title: "补缴失败", message: message, preferredStyle: .alert)
|
||||
|
||||
Reference in New Issue
Block a user