// // LocationReportHistoryViews.swift // suixinkan // import SnapKit import UIKit /// 历史上报列表卡片。 final class LocationReportHistoryCell: UITableViewCell { static let reuseIdentifier = "LocationReportHistoryCell" private let typeBadge = UILabel() private let timeLabel = UILabel() private let coordinateLabel = UILabel() private let addressLabel = UILabel() private let remarkLabel = UILabel() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) selectionStyle = .none backgroundColor = .clear let card = UIView() card.backgroundColor = .white card.layer.cornerRadius = 10 typeBadge.font = .systemFont(ofSize: 12, weight: .medium) typeBadge.textAlignment = .center typeBadge.layer.cornerRadius = 4 typeBadge.clipsToBounds = true timeLabel.font = .systemFont(ofSize: 14, weight: .medium) timeLabel.textColor = AppColor.textPrimary coordinateLabel.font = .systemFont(ofSize: 12) coordinateLabel.textColor = AppColor.textSecondary addressLabel.font = .systemFont(ofSize: 13) addressLabel.textColor = AppColor.textPrimary addressLabel.numberOfLines = 2 remarkLabel.font = .systemFont(ofSize: 12) remarkLabel.textColor = AppColor.textTertiary remarkLabel.numberOfLines = 2 let stack = UIStackView(arrangedSubviews: [timeLabel, coordinateLabel, addressLabel, remarkLabel]) stack.axis = .vertical stack.spacing = 6 card.addSubview(typeBadge) card.addSubview(stack) contentView.addSubview(card) card.snp.makeConstraints { make in make.edges.equalToSuperview().inset(UIEdgeInsets(top: 6, left: 16, bottom: 6, right: 16)) } typeBadge.snp.makeConstraints { make in make.top.leading.equalToSuperview().offset(12) make.height.equalTo(22) make.width.greaterThanOrEqualTo(64) } stack.snp.makeConstraints { make in make.top.equalTo(typeBadge.snp.bottom).offset(8) make.leading.trailing.bottom.equalToSuperview().inset(12) } } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func apply(item: LocationReportHistoryItem) { let filterType = item.filterType typeBadge.text = " \(filterType.displayName) " typeBadge.textColor = UIColor(hex: filterType.tagColorHex) typeBadge.backgroundColor = UIColor(hex: filterType.tagColorHex).withAlphaComponent(0.12) timeLabel.text = item.createdAt.isEmpty ? "--" : item.createdAt coordinateLabel.text = "经纬度:\(item.latitude), \(item.longitude)" addressLabel.text = item.address.isEmpty ? "--" : item.address if item.remark.isEmpty { remarkLabel.isHidden = true } else { remarkLabel.isHidden = false remarkLabel.text = "备注:\(item.remark)" } } } /// 筛选与日期工具栏。 final class LocationReportHistoryFilterBar: UIView { var onFilterTap: (() -> Void)? var onDateFilterTap: (() -> Void)? var onClearDates: (() -> Void)? private let filterButton = UIButton(type: .system) private let dateButton = UIButton(type: .system) private let startLabel = UILabel() private let endLabel = UILabel() private let clearButton = UIButton(type: .system) private let dateRangeStack = UIStackView() override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .white filterButton.setTitle("全部", for: .normal) filterButton.setTitleColor(AppColor.textPrimary, for: .normal) filterButton.titleLabel?.font = .systemFont(ofSize: 14) filterButton.setImage(UIImage(systemName: "chevron.down"), for: .normal) filterButton.semanticContentAttribute = .forceRightToLeft filterButton.addTarget(self, action: #selector(filterTapped), for: .touchUpInside) dateButton.setTitle("时间筛选", for: .normal) dateButton.setTitleColor(AppColor.primary, for: .normal) dateButton.titleLabel?.font = .systemFont(ofSize: 14) dateButton.addTarget(self, action: #selector(dateTapped), for: .touchUpInside) startLabel.font = .systemFont(ofSize: 13) endLabel.font = .systemFont(ofSize: 13) startLabel.textColor = AppColor.textSecondary endLabel.textColor = AppColor.textSecondary clearButton.setTitle("清除", for: .normal) clearButton.setTitleColor(AppColor.danger, for: .normal) clearButton.titleLabel?.font = .systemFont(ofSize: 13) clearButton.addTarget(self, action: #selector(clearTapped), for: .touchUpInside) dateRangeStack.axis = .horizontal dateRangeStack.spacing = 8 dateRangeStack.alignment = .center dateRangeStack.addArrangedSubview(startLabel) dateRangeStack.addArrangedSubview(UILabel(text: "至")) dateRangeStack.addArrangedSubview(endLabel) dateRangeStack.addArrangedSubview(clearButton) dateRangeStack.isHidden = true let topRow = UIStackView(arrangedSubviews: [filterButton, UIView(), dateButton]) topRow.axis = .horizontal let stack = UIStackView(arrangedSubviews: [topRow, dateRangeStack]) stack.axis = .vertical stack.spacing = 8 addSubview(stack) stack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(12) } } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func apply(filterTitle: String, startText: String, endText: String, showsDateRange: Bool) { filterButton.setTitle(filterTitle, for: .normal) startLabel.text = startText endLabel.text = endText dateRangeStack.isHidden = !showsDateRange } @objc private func filterTapped() { onFilterTap?() } @objc private func dateTapped() { onDateFilterTap?() } @objc private func clearTapped() { onClearDates?() } } private extension UILabel { convenience init(text: String) { self.init() self.text = text font = .systemFont(ofSize: 13) textColor = AppColor.textSecondary } }