feat: 优化线下收款展示细节
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "payment_method_alipay_generated.png",
|
"filename" : "payment_method_alipay_official.png",
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 221 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "payment_method_wechat_generated.png",
|
"filename" : "payment_method_wechat_official.png",
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 268 KiB |
BIN
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 responseFen(_ value: String) -> Int? { parseFen(value) }
|
||||||
static func apiAmount(_ fen: Int) -> String { "\(fen / 100).\(String(format: "%02d", fen % 100))" }
|
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 countValue = UILabel()
|
||||||
private let settledValue = UILabel()
|
private let settledValue = UILabel()
|
||||||
private let pendingValue = UILabel()
|
private let pendingValue = UILabel()
|
||||||
private let pendingStatusLabel = UILabel()
|
|
||||||
private let statusButton = UIButton(type: .system)
|
private let statusButton = UIButton(type: .system)
|
||||||
private let bottomContainer = UIView()
|
private let bottomContainer = UIView()
|
||||||
private let settlementButton = OfflineCollectionGradientButton(
|
private let settlementButton = OfflineCollectionGradientButton(
|
||||||
@@ -99,7 +98,7 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
|||||||
tableView.backgroundColor = .clear
|
tableView.backgroundColor = .clear
|
||||||
tableView.separatorStyle = .none
|
tableView.separatorStyle = .none
|
||||||
tableView.rowHeight = UITableView.automaticDimension
|
tableView.rowHeight = UITableView.automaticDimension
|
||||||
tableView.estimatedRowHeight = 82
|
tableView.estimatedRowHeight = 96
|
||||||
tableView.showsVerticalScrollIndicator = false
|
tableView.showsVerticalScrollIndicator = false
|
||||||
tableView.contentInset.bottom = 12
|
tableView.contentInset.bottom = 12
|
||||||
tableView.register(OfflineCollectionRecordCell.self, forCellReuseIdentifier: OfflineCollectionRecordCell.reuseIdentifier)
|
tableView.register(OfflineCollectionRecordCell.self, forCellReuseIdentifier: OfflineCollectionRecordCell.reuseIdentifier)
|
||||||
@@ -151,13 +150,13 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
|||||||
summaryCard.layer.shadowRadius = 10
|
summaryCard.layer.shadowRadius = 10
|
||||||
summaryCard.layer.shadowOffset = CGSize(width: 0, height: 4)
|
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)
|
summaryDateLabel.textColor = UIColor(hex: 0x081739)
|
||||||
|
|
||||||
let topLeft = metric(title: "线下收款总额", value: totalValue)
|
let topLeft = metric(title: "线下收款总额", value: totalValue)
|
||||||
let topRight = metric(title: "登记笔数", value: countValue)
|
let topRight = metric(title: "登记笔数", value: countValue)
|
||||||
let bottomLeft = metric(title: "已补缴", value: settledValue)
|
let bottomLeft = metric(title: "已补缴", value: settledValue)
|
||||||
let bottomRight = metric(title: "待补缴", value: pendingValue, badge: pendingStatusLabel)
|
let bottomRight = metric(title: "待补缴", value: pendingValue)
|
||||||
let grid = UIView()
|
let grid = UIView()
|
||||||
[topLeft, topRight, bottomLeft, bottomRight].forEach(grid.addSubview)
|
[topLeft, topRight, bottomLeft, bottomRight].forEach(grid.addSubview)
|
||||||
topLeft.snp.makeConstraints { make in
|
topLeft.snp.makeConstraints { make in
|
||||||
@@ -196,25 +195,26 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
|||||||
summaryCard.addSubview(summaryDateLabel)
|
summaryCard.addSubview(summaryDateLabel)
|
||||||
summaryCard.addSubview(grid)
|
summaryCard.addSubview(grid)
|
||||||
summaryDateLabel.snp.makeConstraints { make in
|
summaryDateLabel.snp.makeConstraints { make in
|
||||||
make.top.leading.trailing.equalToSuperview().inset(16)
|
make.top.equalToSuperview().offset(14)
|
||||||
make.height.equalTo(24)
|
make.leading.trailing.equalToSuperview().inset(16)
|
||||||
|
make.height.equalTo(22)
|
||||||
}
|
}
|
||||||
grid.snp.makeConstraints { make in
|
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.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()
|
let titleLabel = UILabel()
|
||||||
titleLabel.text = title
|
titleLabel.text = title
|
||||||
titleLabel.font = .systemFont(ofSize: 13)
|
titleLabel.font = .systemFont(ofSize: 12)
|
||||||
titleLabel.textColor = UIColor(hex: 0x7B8494)
|
titleLabel.textColor = UIColor(hex: 0x7B8494)
|
||||||
titleLabel.textAlignment = .center
|
titleLabel.textAlignment = .center
|
||||||
|
|
||||||
value.font = .systemFont(ofSize: 22, weight: .bold)
|
value.font = .systemFont(ofSize: 20, weight: .bold)
|
||||||
value.textColor = UIColor(hex: 0x081739)
|
value.textColor = UIColor(hex: 0x081739)
|
||||||
value.textAlignment = .center
|
value.textAlignment = .center
|
||||||
value.adjustsFontSizeToFitWidth = true
|
value.adjustsFontSizeToFitWidth = true
|
||||||
@@ -223,23 +223,7 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
|||||||
let stack = UIStackView(arrangedSubviews: [titleLabel, value])
|
let stack = UIStackView(arrangedSubviews: [titleLabel, value])
|
||||||
stack.axis = .vertical
|
stack.axis = .vertical
|
||||||
stack.alignment = .fill
|
stack.alignment = .fill
|
||||||
stack.spacing = 8
|
stack.spacing = 6
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
let container = UIView()
|
let container = UIView()
|
||||||
container.addSubview(stack)
|
container.addSubview(stack)
|
||||||
@@ -286,7 +270,6 @@ final class OfflineCollectionDailyViewController: BaseViewController {
|
|||||||
settledValue.text = OfflineCollectionMoney.display(viewModel.summary.settledAmountFen)
|
settledValue.text = OfflineCollectionMoney.display(viewModel.summary.settledAmountFen)
|
||||||
pendingValue.text = OfflineCollectionMoney.display(viewModel.summary.pendingAmountFen)
|
pendingValue.text = OfflineCollectionMoney.display(viewModel.summary.pendingAmountFen)
|
||||||
pendingValue.textColor = viewModel.summary.pendingCount > 0 ? UIColor(hex: 0xFF7600) : UIColor(hex: 0x081739)
|
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 {
|
if let error = viewModel.errorMessage, !viewModel.isLoading {
|
||||||
statusButton.isHidden = false
|
statusButton.isHidden = false
|
||||||
@@ -469,12 +452,11 @@ private final class OfflineCollectionRecordCell: UITableViewCell {
|
|||||||
|
|
||||||
idLabel.font = .systemFont(ofSize: 9.5, weight: .medium)
|
idLabel.font = .systemFont(ofSize: 9.5, weight: .medium)
|
||||||
idLabel.textColor = UIColor(hex: 0x6F7B8F)
|
idLabel.textColor = UIColor(hex: 0x6F7B8F)
|
||||||
idLabel.backgroundColor = UIColor(hex: 0xF0F2F6)
|
idLabel.textAlignment = .left
|
||||||
idLabel.layer.cornerRadius = 5
|
idLabel.numberOfLines = 0
|
||||||
idLabel.clipsToBounds = true
|
idLabel.lineBreakMode = .byCharWrapping
|
||||||
idLabel.textAlignment = .center
|
idLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
||||||
idLabel.adjustsFontSizeToFitWidth = true
|
idLabel.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||||
idLabel.minimumScaleFactor = 0.7
|
|
||||||
|
|
||||||
amountLabel.font = .systemFont(ofSize: 16, weight: .bold)
|
amountLabel.font = .systemFont(ofSize: 16, weight: .bold)
|
||||||
amountLabel.textColor = UIColor(hex: 0x081739)
|
amountLabel.textColor = UIColor(hex: 0x081739)
|
||||||
@@ -493,18 +475,17 @@ private final class OfflineCollectionRecordCell: UITableViewCell {
|
|||||||
separator.backgroundColor = UIColor(hex: 0xE7EBF1)
|
separator.backgroundColor = UIColor(hex: 0xE7EBF1)
|
||||||
|
|
||||||
let idContainer = UIView()
|
let idContainer = UIView()
|
||||||
|
idContainer.backgroundColor = UIColor(hex: 0xF0F2F6)
|
||||||
|
idContainer.layer.cornerRadius = 5
|
||||||
|
idContainer.clipsToBounds = true
|
||||||
idContainer.addSubview(idLabel)
|
idContainer.addSubview(idLabel)
|
||||||
idLabel.snp.makeConstraints { make in
|
idLabel.snp.makeConstraints { make in
|
||||||
make.leading.top.bottom.equalToSuperview()
|
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 3, left: 6, bottom: 3, right: 6))
|
||||||
make.trailing.lessThanOrEqualToSuperview()
|
|
||||||
}
|
}
|
||||||
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(iconView)
|
||||||
card.addSubview(leftStack)
|
card.addSubview(titleLabel)
|
||||||
|
card.addSubview(idContainer)
|
||||||
card.addSubview(amountLabel)
|
card.addSubview(amountLabel)
|
||||||
card.addSubview(statusLabel)
|
card.addSubview(statusLabel)
|
||||||
card.addSubview(timeLabel)
|
card.addSubview(timeLabel)
|
||||||
@@ -514,34 +495,39 @@ private final class OfflineCollectionRecordCell: UITableViewCell {
|
|||||||
card.snp.makeConstraints { make in
|
card.snp.makeConstraints { make in
|
||||||
make.top.bottom.equalToSuperview()
|
make.top.bottom.equalToSuperview()
|
||||||
make.leading.trailing.equalToSuperview().inset(16)
|
make.leading.trailing.equalToSuperview().inset(16)
|
||||||
make.height.greaterThanOrEqualTo(78)
|
make.height.greaterThanOrEqualTo(90)
|
||||||
}
|
}
|
||||||
iconView.snp.makeConstraints { make in
|
iconView.snp.makeConstraints { make in
|
||||||
make.leading.equalToSuperview().offset(12)
|
make.leading.equalToSuperview().offset(12)
|
||||||
make.centerY.equalToSuperview()
|
make.top.equalToSuperview().offset(10)
|
||||||
make.width.height.equalTo(38)
|
make.width.height.equalTo(38)
|
||||||
}
|
}
|
||||||
leftStack.snp.makeConstraints { make in
|
titleLabel.snp.makeConstraints { make in
|
||||||
make.leading.equalTo(iconView.snp.trailing).offset(10)
|
make.leading.equalTo(iconView.snp.trailing).offset(10)
|
||||||
make.centerY.equalToSuperview()
|
make.centerY.equalTo(iconView)
|
||||||
make.width.equalTo(106)
|
|
||||||
}
|
}
|
||||||
amountLabel.snp.makeConstraints { make in
|
amountLabel.snp.makeConstraints { make in
|
||||||
make.leading.greaterThanOrEqualTo(leftStack.snp.trailing).offset(4)
|
make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(4)
|
||||||
make.centerY.equalToSuperview()
|
make.centerY.equalTo(iconView)
|
||||||
make.width.equalTo(68)
|
make.width.equalTo(68)
|
||||||
}
|
}
|
||||||
statusLabel.snp.makeConstraints { make in
|
statusLabel.snp.makeConstraints { make in
|
||||||
make.leading.equalTo(amountLabel.snp.trailing).offset(4)
|
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.width.equalTo(50)
|
||||||
make.height.equalTo(27)
|
make.height.equalTo(27)
|
||||||
}
|
}
|
||||||
timeLabel.snp.makeConstraints { make in
|
timeLabel.snp.makeConstraints { make in
|
||||||
make.leading.equalTo(statusLabel.snp.trailing).offset(2)
|
make.trailing.equalToSuperview().inset(12)
|
||||||
make.trailing.equalToSuperview().inset(10)
|
make.centerY.equalTo(idContainer)
|
||||||
make.centerY.equalToSuperview()
|
make.width.equalTo(40)
|
||||||
make.width.greaterThanOrEqualTo(34)
|
}
|
||||||
|
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
|
separator.snp.makeConstraints { make in
|
||||||
make.leading.equalToSuperview().offset(12)
|
make.leading.equalToSuperview().offset(12)
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ extension OfflineCollectionRegistrationViewController: UITextFieldDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 登记页的收款方式单选卡,展示生成的品牌图标和右上角选中标记。
|
/// 登记页的收款方式单选卡,展示官方品牌图标和右上角选中标记。
|
||||||
@MainActor
|
@MainActor
|
||||||
final class OfflinePaymentMethodButton: UIControl {
|
final class OfflinePaymentMethodButton: UIControl {
|
||||||
let method: OfflineCollectionPaymentMethod
|
let method: OfflineCollectionPaymentMethod
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ final class OfflineCollectionAPITests: XCTestCase {
|
|||||||
XCTAssertEqual(OfflineCollectionMoney.parseFen("0.01"), 1)
|
XCTAssertEqual(OfflineCollectionMoney.parseFen("0.01"), 1)
|
||||||
XCTAssertEqual(OfflineCollectionMoney.parseFen("12.3"), 1_230)
|
XCTAssertEqual(OfflineCollectionMoney.parseFen("12.3"), 1_230)
|
||||||
XCTAssertEqual(OfflineCollectionMoney.apiAmount(9_999_999), "99999.99")
|
XCTAssertEqual(OfflineCollectionMoney.apiAmount(9_999_999), "99999.99")
|
||||||
|
XCTAssertEqual(OfflineCollectionMoney.displayAmount(200), "2")
|
||||||
|
XCTAssertEqual(OfflineCollectionMoney.displayAmount(210), "2.1")
|
||||||
|
XCTAssertEqual(OfflineCollectionMoney.displayAmount(222), "2.22")
|
||||||
XCTAssertNil(OfflineCollectionMoney.parseFen("0"))
|
XCTAssertNil(OfflineCollectionMoney.parseFen("0"))
|
||||||
XCTAssertNil(OfflineCollectionMoney.parseFen("100000.00"))
|
XCTAssertNil(OfflineCollectionMoney.parseFen("100000.00"))
|
||||||
XCTAssertNil(OfflineCollectionMoney.parseFen("1.001"))
|
XCTAssertNil(OfflineCollectionMoney.parseFen("1.001"))
|
||||||
|
|||||||
Reference in New Issue
Block a user