feat: 优化线下收款展示细节

This commit is contained in:
2026-08-26 10:47:43 +08:00
parent 825a0448cc
commit 4351c26e74
10 changed files with 55 additions and 59 deletions
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "payment_method_alipay_generated.png",
"filename" : "payment_method_alipay_official.png",
"idiom" : "universal"
}
],
Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "payment_method_wechat_generated.png",
"filename" : "payment_method_wechat_official.png",
"idiom" : "universal"
}
],
Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

@@ -332,7 +332,14 @@ enum OfflineCollectionMoney {
static func responseFen(_ value: String) -> Int? { parseFen(value) }
static func apiAmount(_ fen: Int) -> String { "\(fen / 100).\(String(format: "%02d", fen % 100))" }
static func display(_ fen: Int) -> String { "¥\(apiAmount(fen))" }
static func displayAmount(_ fen: Int) -> String {
let whole = fen / 100
let cents = fen % 100
if cents == 0 { return "\(whole)" }
if cents.isMultiple(of: 10) { return "\(whole).\(cents / 10)" }
return "\(whole).\(String(format: "%02d", cents))"
}
static func display(_ fen: Int) -> String { "¥\(displayAmount(fen))" }
}
/// 线下收款统一使用的营业日工具。
@@ -30,7 +30,6 @@ final class OfflineCollectionDailyViewController: BaseViewController {
private let countValue = UILabel()
private let settledValue = UILabel()
private let pendingValue = UILabel()
private let pendingStatusLabel = UILabel()
private let statusButton = UIButton(type: .system)
private let bottomContainer = UIView()
private let settlementButton = OfflineCollectionGradientButton(
@@ -99,7 +98,7 @@ final class OfflineCollectionDailyViewController: BaseViewController {
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 82
tableView.estimatedRowHeight = 96
tableView.showsVerticalScrollIndicator = false
tableView.contentInset.bottom = 12
tableView.register(OfflineCollectionRecordCell.self, forCellReuseIdentifier: OfflineCollectionRecordCell.reuseIdentifier)
@@ -151,13 +150,13 @@ final class OfflineCollectionDailyViewController: BaseViewController {
summaryCard.layer.shadowRadius = 10
summaryCard.layer.shadowOffset = CGSize(width: 0, height: 4)
summaryDateLabel.font = .systemFont(ofSize: 18, weight: .bold)
summaryDateLabel.font = .systemFont(ofSize: 17, weight: .bold)
summaryDateLabel.textColor = UIColor(hex: 0x081739)
let topLeft = metric(title: "线下收款总额", value: totalValue)
let topRight = metric(title: "登记笔数", value: countValue)
let bottomLeft = metric(title: "已补缴", value: settledValue)
let bottomRight = metric(title: "待补缴", value: pendingValue, badge: pendingStatusLabel)
let bottomRight = metric(title: "待补缴", value: pendingValue)
let grid = UIView()
[topLeft, topRight, bottomLeft, bottomRight].forEach(grid.addSubview)
topLeft.snp.makeConstraints { make in
@@ -196,25 +195,26 @@ final class OfflineCollectionDailyViewController: BaseViewController {
summaryCard.addSubview(summaryDateLabel)
summaryCard.addSubview(grid)
summaryDateLabel.snp.makeConstraints { make in
make.top.leading.trailing.equalToSuperview().inset(16)
make.height.equalTo(24)
make.top.equalToSuperview().offset(14)
make.leading.trailing.equalToSuperview().inset(16)
make.height.equalTo(22)
}
grid.snp.makeConstraints { make in
make.top.equalTo(summaryDateLabel.snp.bottom).offset(8)
make.top.equalTo(summaryDateLabel.snp.bottom).offset(6)
make.leading.trailing.equalToSuperview().inset(10)
make.bottom.equalToSuperview().inset(10)
make.bottom.equalToSuperview().inset(8)
}
summaryCard.snp.makeConstraints { make in make.height.equalTo(238) }
summaryCard.snp.makeConstraints { make in make.height.equalTo(196) }
}
private func metric(title: String, value: UILabel, badge: UILabel? = nil) -> UIView {
private func metric(title: String, value: UILabel) -> UIView {
let titleLabel = UILabel()
titleLabel.text = title
titleLabel.font = .systemFont(ofSize: 13)
titleLabel.font = .systemFont(ofSize: 12)
titleLabel.textColor = UIColor(hex: 0x7B8494)
titleLabel.textAlignment = .center
value.font = .systemFont(ofSize: 22, weight: .bold)
value.font = .systemFont(ofSize: 20, weight: .bold)
value.textColor = UIColor(hex: 0x081739)
value.textAlignment = .center
value.adjustsFontSizeToFitWidth = true
@@ -223,23 +223,7 @@ final class OfflineCollectionDailyViewController: BaseViewController {
let stack = UIStackView(arrangedSubviews: [titleLabel, value])
stack.axis = .vertical
stack.alignment = .fill
stack.spacing = 8
if let badge {
badge.text = "未结清"
badge.font = .systemFont(ofSize: 12, weight: .medium)
badge.textColor = UIColor(hex: 0xFF7600)
badge.textAlignment = .center
badge.backgroundColor = UIColor(hex: 0xFFF0E2)
badge.layer.cornerRadius = 7
badge.clipsToBounds = true
badge.snp.makeConstraints { make in make.width.equalTo(72); make.height.equalTo(26) }
let badgeContainer = UIView()
badgeContainer.addSubview(badge)
badge.snp.makeConstraints { make in make.center.equalToSuperview() }
stack.addArrangedSubview(badgeContainer)
badgeContainer.snp.makeConstraints { make in make.height.equalTo(26) }
stack.spacing = 5
}
stack.spacing = 6
let container = UIView()
container.addSubview(stack)
@@ -286,7 +270,6 @@ final class OfflineCollectionDailyViewController: BaseViewController {
settledValue.text = OfflineCollectionMoney.display(viewModel.summary.settledAmountFen)
pendingValue.text = OfflineCollectionMoney.display(viewModel.summary.pendingAmountFen)
pendingValue.textColor = viewModel.summary.pendingCount > 0 ? UIColor(hex: 0xFF7600) : UIColor(hex: 0x081739)
pendingStatusLabel.isHidden = viewModel.summary.pendingCount == 0
if let error = viewModel.errorMessage, !viewModel.isLoading {
statusButton.isHidden = false
@@ -469,12 +452,11 @@ private final class OfflineCollectionRecordCell: UITableViewCell {
idLabel.font = .systemFont(ofSize: 9.5, weight: .medium)
idLabel.textColor = UIColor(hex: 0x6F7B8F)
idLabel.backgroundColor = UIColor(hex: 0xF0F2F6)
idLabel.layer.cornerRadius = 5
idLabel.clipsToBounds = true
idLabel.textAlignment = .center
idLabel.adjustsFontSizeToFitWidth = true
idLabel.minimumScaleFactor = 0.7
idLabel.textAlignment = .left
idLabel.numberOfLines = 0
idLabel.lineBreakMode = .byCharWrapping
idLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
idLabel.setContentCompressionResistancePriority(.required, for: .vertical)
amountLabel.font = .systemFont(ofSize: 16, weight: .bold)
amountLabel.textColor = UIColor(hex: 0x081739)
@@ -493,18 +475,17 @@ private final class OfflineCollectionRecordCell: UITableViewCell {
separator.backgroundColor = UIColor(hex: 0xE7EBF1)
let idContainer = UIView()
idContainer.backgroundColor = UIColor(hex: 0xF0F2F6)
idContainer.layer.cornerRadius = 5
idContainer.clipsToBounds = true
idContainer.addSubview(idLabel)
idLabel.snp.makeConstraints { make in
make.leading.top.bottom.equalToSuperview()
make.trailing.lessThanOrEqualToSuperview()
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 3, left: 6, bottom: 3, right: 6))
}
idContainer.snp.makeConstraints { make in make.height.equalTo(20) }
let leftStack = UIStackView(arrangedSubviews: [titleLabel, idContainer])
leftStack.axis = .vertical
leftStack.spacing = 4
card.addSubview(iconView)
card.addSubview(leftStack)
card.addSubview(titleLabel)
card.addSubview(idContainer)
card.addSubview(amountLabel)
card.addSubview(statusLabel)
card.addSubview(timeLabel)
@@ -514,34 +495,39 @@ private final class OfflineCollectionRecordCell: UITableViewCell {
card.snp.makeConstraints { make in
make.top.bottom.equalToSuperview()
make.leading.trailing.equalToSuperview().inset(16)
make.height.greaterThanOrEqualTo(78)
make.height.greaterThanOrEqualTo(90)
}
iconView.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(12)
make.centerY.equalToSuperview()
make.top.equalToSuperview().offset(10)
make.width.height.equalTo(38)
}
leftStack.snp.makeConstraints { make in
titleLabel.snp.makeConstraints { make in
make.leading.equalTo(iconView.snp.trailing).offset(10)
make.centerY.equalToSuperview()
make.width.equalTo(106)
make.centerY.equalTo(iconView)
}
amountLabel.snp.makeConstraints { make in
make.leading.greaterThanOrEqualTo(leftStack.snp.trailing).offset(4)
make.centerY.equalToSuperview()
make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(4)
make.centerY.equalTo(iconView)
make.width.equalTo(68)
}
statusLabel.snp.makeConstraints { make in
make.leading.equalTo(amountLabel.snp.trailing).offset(4)
make.centerY.equalToSuperview()
make.trailing.equalToSuperview().inset(12)
make.centerY.equalTo(iconView)
make.width.equalTo(50)
make.height.equalTo(27)
}
timeLabel.snp.makeConstraints { make in
make.leading.equalTo(statusLabel.snp.trailing).offset(2)
make.trailing.equalToSuperview().inset(10)
make.centerY.equalToSuperview()
make.width.greaterThanOrEqualTo(34)
make.trailing.equalToSuperview().inset(12)
make.centerY.equalTo(idContainer)
make.width.equalTo(40)
}
idContainer.snp.makeConstraints { make in
make.leading.equalTo(iconView)
make.top.equalTo(iconView.snp.bottom).offset(6)
make.trailing.lessThanOrEqualTo(timeLabel.snp.leading).offset(-8)
make.bottom.equalToSuperview().inset(10)
}
separator.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(12)
@@ -363,7 +363,7 @@ extension OfflineCollectionRegistrationViewController: UITextFieldDelegate {
}
}
/// 登记页的收款方式单选卡,展示生成的品牌图标和右上角选中标记。
/// 登记页的收款方式单选卡,展示官方品牌图标和右上角选中标记。
@MainActor
final class OfflinePaymentMethodButton: UIControl {
let method: OfflineCollectionPaymentMethod