// // ProfileInfoRowView.swift // suixinkan // import SnapKit import UIKit /// 个人信息卡片行,展示左侧标题与右侧内容,可选点击与箭头。 final class ProfileInfoRowView: UIControl { enum AccessoryStyle { case none case chevron case action(String) } private let titleLabel = UILabel() private let valueLabel = UILabel() private let accessoryLabel = UILabel() private let chevronView = UIImageView() private let divider = UIView() private let badgeContainer = UIView() private var badgeView: ProfileStatusBadgeView? private let rightStack = UIStackView() private let stackNameLabel = UILabel() private let stackTypeTag = UILabel() private var rowHeightConstraint: Constraint? var showsDivider = true { didSet { divider.isHidden = !showsDivider } } init(title: String) { super.init(frame: .zero) titleLabel.text = title setupUI() } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func configure( value: String?, valueColor: UIColor = AppColor.text333, accessory: AccessoryStyle = .none, badge: ProfileStatusBadgeView.Style? = nil ) { setStackedModeEnabled(false) valueLabel.text = value valueLabel.textColor = valueColor valueLabel.isHidden = badge != nil badgeContainer.isHidden = badge == nil if let badge { if badgeView == nil { let view = ProfileStatusBadgeView() badgeContainer.addSubview(view) view.snp.makeConstraints { make in make.edges.equalToSuperview() } badgeView = view } badgeView?.apply(style: badge, text: value ?? "") } accessoryLabel.isHidden = true chevronView.isHidden = true switch accessory { case .none: break case .chevron: chevronView.isHidden = false case .action(let text): accessoryLabel.text = text accessoryLabel.isHidden = false chevronView.isHidden = false } updateContentConstraints(for: accessory) } /// 右侧竖排展示店铺名称与账号类型标识,可选右侧箭头。 func configureAccountInfo( storeName: String, accountTypeLabel: String, isStoreAccount: Bool, showsChevron: Bool = true ) { setStackedModeEnabled(true, showsChevron: showsChevron) stackNameLabel.text = storeName stackTypeTag.text = accountTypeLabel if isStoreAccount { stackTypeTag.textColor = UIColor(hex: 0x0F9F6E) stackTypeTag.backgroundColor = UIColor(hex: 0xE8F8F1) } else { stackTypeTag.textColor = UIColor(hex: 0x7C3AED) stackTypeTag.backgroundColor = UIColor(hex: 0xF3ECFF) } updateStackedConstraints(showsChevron: showsChevron) } private func setStackedModeEnabled(_ enabled: Bool, showsChevron: Bool = false) { rightStack.isHidden = !enabled accessoryLabel.isHidden = true chevronView.isHidden = !enabled || !showsChevron if enabled { valueLabel.isHidden = true badgeContainer.isHidden = true rowHeightConstraint?.update(offset: 64) } else { rowHeightConstraint?.update(offset: 52) } } private func updateStackedConstraints(showsChevron: Bool) { rightStack.snp.remakeConstraints { make in make.centerY.equalToSuperview() make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(8) if showsChevron { make.trailing.equalTo(chevronView.snp.leading).offset(-4) } else { make.trailing.equalToSuperview() } } } private func updateContentConstraints(for accessory: AccessoryStyle) { valueLabel.snp.remakeConstraints { make in make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(8) make.centerY.equalToSuperview() switch accessory { case .action: make.trailing.equalTo(accessoryLabel.snp.leading).offset(-8) case .chevron: make.trailing.equalTo(chevronView.snp.leading).offset(-4) case .none: make.trailing.equalToSuperview() } } badgeContainer.snp.remakeConstraints { make in make.leading.equalTo(titleLabel.snp.trailing).offset(8) make.centerY.equalToSuperview() switch accessory { case .action: make.trailing.lessThanOrEqualTo(accessoryLabel.snp.leading).offset(-8) case .chevron: make.trailing.lessThanOrEqualTo(chevronView.snp.leading).offset(-8) case .none: make.trailing.lessThanOrEqualToSuperview() } } } private func setupUI() { titleLabel.font = .systemFont(ofSize: 14) titleLabel.textColor = UIColor(hex: 0x4B5563) titleLabel.setContentHuggingPriority(.required, for: .horizontal) valueLabel.font = .systemFont(ofSize: 14) valueLabel.textAlignment = .right valueLabel.numberOfLines = 1 valueLabel.lineBreakMode = .byTruncatingTail valueLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) accessoryLabel.font = .systemFont(ofSize: 14) accessoryLabel.textColor = AppColor.primary accessoryLabel.setContentHuggingPriority(.required, for: .horizontal) accessoryLabel.setContentCompressionResistancePriority(.required, for: .horizontal) chevronView.image = UIImage(systemName: "chevron.right") chevronView.tintColor = AppColor.text666 chevronView.contentMode = .scaleAspectFit chevronView.setContentHuggingPriority(.required, for: .horizontal) stackNameLabel.font = .systemFont(ofSize: 14) stackNameLabel.textColor = AppColor.text333 stackNameLabel.textAlignment = .right stackNameLabel.numberOfLines = 1 stackNameLabel.lineBreakMode = .byTruncatingTail stackTypeTag.font = .systemFont(ofSize: 11, weight: .semibold) stackTypeTag.textAlignment = .center stackTypeTag.layer.cornerRadius = 4 stackTypeTag.clipsToBounds = true rightStack.axis = .vertical rightStack.alignment = .trailing rightStack.spacing = 4 rightStack.isUserInteractionEnabled = false rightStack.addArrangedSubview(stackNameLabel) rightStack.addArrangedSubview(stackTypeTag) rightStack.isHidden = true badgeContainer.isUserInteractionEnabled = false divider.backgroundColor = UIColor(hex: 0xE5E7EB) divider.isUserInteractionEnabled = false addSubview(titleLabel) addSubview(valueLabel) addSubview(badgeContainer) addSubview(accessoryLabel) addSubview(chevronView) addSubview(rightStack) addSubview(divider) snp.makeConstraints { make in rowHeightConstraint = make.height.equalTo(52).constraint } titleLabel.snp.makeConstraints { make in make.leading.equalToSuperview() make.centerY.equalToSuperview() make.width.equalTo(102) } chevronView.snp.makeConstraints { make in make.trailing.equalToSuperview() make.centerY.equalToSuperview() make.width.height.equalTo(16) } accessoryLabel.snp.makeConstraints { make in make.trailing.equalTo(chevronView.snp.leading).offset(-4) make.centerY.equalToSuperview() } rightStack.snp.makeConstraints { make in make.trailing.equalToSuperview() make.centerY.equalToSuperview() make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(8) } stackTypeTag.snp.makeConstraints { make in make.height.equalTo(22) make.width.greaterThanOrEqualTo(56) } updateContentConstraints(for: .none) divider.snp.makeConstraints { make in make.leading.trailing.bottom.equalToSuperview() make.height.equalTo(0.5) } } }