Add role-based analyse APIs, summary/daily UI with date range sheet, and flexible parsing for string refund amounts from the backend. Co-authored-by: Cursor <cursoragent@cursor.com>
109 lines
3.8 KiB
Swift
109 lines
3.8 KiB
Swift
//
|
||
// StatisticsDailyCell.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import SnapKit
|
||
import UIKit
|
||
|
||
/// 数据统计日明细行,对齐 Android `DailyDataBox`。
|
||
final class StatisticsDailyCell: UITableViewCell {
|
||
|
||
static let reuseIdentifier = "StatisticsDailyCell"
|
||
|
||
private let dateLabel = UILabel()
|
||
private let orderCountTitle = UILabel()
|
||
private let orderCountValue = UILabel()
|
||
private let averageTitle = UILabel()
|
||
private let averageValue = UILabel()
|
||
private let refundTitle = UILabel()
|
||
private let refundValue = UILabel()
|
||
private let receivedTitle = UILabel()
|
||
private let receivedValue = UILabel()
|
||
private let divider = UIView()
|
||
|
||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||
setupUI()
|
||
}
|
||
|
||
@available(*, unavailable)
|
||
required init?(coder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
|
||
func configure(with item: StatisticsDailyItem, showsDivider: Bool) {
|
||
dateLabel.text = item.date
|
||
orderCountValue.text = "\(item.orderCount)"
|
||
averageValue.text = "¥\(item.orderPrice)"
|
||
refundValue.text = "¥\(item.refund)"
|
||
receivedValue.text = "¥\(item.received)"
|
||
divider.isHidden = !showsDivider
|
||
}
|
||
|
||
private func setupUI() {
|
||
selectionStyle = .none
|
||
backgroundColor = .clear
|
||
|
||
dateLabel.font = .systemFont(ofSize: 14)
|
||
dateLabel.textColor = .black
|
||
|
||
let metricColor = UIColor(hex: 0x4B5563)
|
||
[orderCountTitle, averageTitle, refundTitle, receivedTitle].forEach {
|
||
$0.font = .systemFont(ofSize: 14)
|
||
$0.textColor = metricColor
|
||
}
|
||
orderCountTitle.text = "订单数"
|
||
averageTitle.text = "客单价"
|
||
refundTitle.text = "退款"
|
||
receivedTitle.text = "实收"
|
||
|
||
[orderCountValue, averageValue].forEach {
|
||
$0.font = .systemFont(ofSize: 14, weight: .semibold)
|
||
$0.textColor = .black
|
||
}
|
||
refundValue.font = .systemFont(ofSize: 14, weight: .semibold)
|
||
refundValue.textColor = UIColor(hex: 0xEF4444)
|
||
receivedValue.font = .systemFont(ofSize: 14, weight: .semibold)
|
||
receivedValue.textColor = UIColor(hex: 0x22C55E)
|
||
|
||
divider.backgroundColor = UIColor(hex: 0xF4F4F4)
|
||
|
||
let metricsRow = UIStackView()
|
||
metricsRow.axis = .horizontal
|
||
metricsRow.distribution = .fillEqually
|
||
metricsRow.alignment = .fill
|
||
metricsRow.spacing = 8
|
||
|
||
metricsRow.addArrangedSubview(metricColumn(title: orderCountTitle, value: orderCountValue))
|
||
metricsRow.addArrangedSubview(metricColumn(title: averageTitle, value: averageValue))
|
||
metricsRow.addArrangedSubview(metricColumn(title: refundTitle, value: refundValue))
|
||
metricsRow.addArrangedSubview(metricColumn(title: receivedTitle, value: receivedValue))
|
||
|
||
contentView.addSubview(dateLabel)
|
||
contentView.addSubview(metricsRow)
|
||
contentView.addSubview(divider)
|
||
|
||
dateLabel.snp.makeConstraints { make in
|
||
make.top.leading.trailing.equalToSuperview().inset(UIEdgeInsets(top: 12, left: 0, bottom: 0, right: 0))
|
||
}
|
||
metricsRow.snp.makeConstraints { make in
|
||
make.top.equalTo(dateLabel.snp.bottom).offset(12)
|
||
make.leading.trailing.equalToSuperview()
|
||
make.bottom.equalToSuperview().inset(12)
|
||
}
|
||
divider.snp.makeConstraints { make in
|
||
make.leading.trailing.bottom.equalToSuperview()
|
||
make.height.equalTo(1)
|
||
}
|
||
}
|
||
|
||
private func metricColumn(title: UILabel, value: UILabel) -> UIStackView {
|
||
let stack = UIStackView(arrangedSubviews: [title, value])
|
||
stack.axis = .vertical
|
||
stack.spacing = 4
|
||
stack.alignment = .leading
|
||
return stack
|
||
}
|
||
}
|