// // WildReportCommonViews.swift // suixinkan // import SnapKit import UIKit /// 举报摄影师模块 UI 工具,统一卡片、标签和按钮样式。 enum WildReportUI { static func label(_ text: String, font: UIFont, color: UIColor, lines: Int = 1) -> UILabel { let label = UILabel() label.text = text label.font = font label.textColor = color label.numberOfLines = lines return label } static func iconButton(title: String, imageName: String, style: AppButton.Style = .primary) -> UIButton { let button = UIButton(type: .system) button.titleLabel?.font = .app(.subtitle) button.setTitle(title, for: .normal) button.setImage(UIImage(systemName: imageName), for: .normal) button.tintColor = style == .primary ? .white : AppColor.primary button.setTitleColor(style == .primary ? .white : AppColor.primary, for: .normal) button.backgroundColor = style == .primary ? AppColor.primary : AppColor.primaryLight button.layer.cornerRadius = AppRadius.md button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -4, bottom: 0, right: 4) button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12) return button } } /// 举报模块白底卡片容器。 final class WildReportCardView: UIView { let stack = UIStackView() init(spacing: CGFloat = AppSpacing.sm, inset: CGFloat = AppSpacing.md) { super.init(frame: .zero) backgroundColor = .white layer.cornerRadius = AppRadius.lg layer.borderWidth = 1 layer.borderColor = AppColor.cardOutline.cgColor stack.axis = .vertical stack.spacing = max(0, spacing - AppSpacing.xxs) addSubview(stack) stack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(inset) } } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } /// 举报模块状态标签。 final class WildReportStatusView: UILabel { override init(frame: CGRect) { super.init(frame: frame) font = .app(.captionMedium) textAlignment = .center layer.cornerRadius = 12 clipsToBounds = true } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func apply(status: WildReportStatus) { text = status.rawValue textColor = status.displayColor backgroundColor = status.backgroundColor } } /// 举报模块左右信息行。 final class WildReportInfoRowView: UIView { private let titleLabel = UILabel() private let valueLabel = UILabel() init(title: String, value: String) { super.init(frame: .zero) titleLabel.font = .app(.body) titleLabel.textColor = AppColor.textSecondary titleLabel.text = title valueLabel.font = .app(.bodyMedium) valueLabel.textColor = AppColor.textPrimary valueLabel.textAlignment = .right valueLabel.numberOfLines = 0 valueLabel.text = value addSubview(titleLabel) addSubview(valueLabel) titleLabel.snp.makeConstraints { make in make.leading.top.equalToSuperview() make.width.greaterThanOrEqualTo(76) make.bottom.lessThanOrEqualToSuperview() } valueLabel.snp.makeConstraints { make in make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(AppSpacing.sm) make.trailing.top.bottom.equalToSuperview() } } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } /// 举报模块附件占位 chip。 final class WildReportAttachmentChipView: UIView { private let titleLabel = UILabel() private let iconView = UIImageView() var onRemove: (() -> Void)? init(attachment: WildReportAttachment, removable: Bool = true) { super.init(frame: .zero) backgroundColor = AppColor.pageBackgroundSoft layer.cornerRadius = AppRadius.md layer.borderWidth = 1 layer.borderColor = AppColor.cardOutline.cgColor iconView.image = UIImage(systemName: iconName(for: attachment.kind)) iconView.tintColor = AppColor.primary titleLabel.text = attachment.title titleLabel.font = .app(.captionMedium) titleLabel.textColor = AppColor.textPrimary addSubview(iconView) addSubview(titleLabel) iconView.snp.makeConstraints { make in make.leading.equalToSuperview().offset(AppSpacing.sm) make.centerY.equalToSuperview() make.size.equalTo(18) } titleLabel.snp.makeConstraints { make in make.leading.equalTo(iconView.snp.trailing).offset(AppSpacing.xs) make.centerY.equalToSuperview() make.trailing.lessThanOrEqualToSuperview().inset(removable ? 34 : AppSpacing.sm) } if removable { let button = UIButton(type: .system) button.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal) button.tintColor = AppColor.textTertiary button.addTarget(self, action: #selector(removeTapped), for: .touchUpInside) addSubview(button) button.snp.makeConstraints { make in make.trailing.equalToSuperview().inset(AppSpacing.xs) make.centerY.equalToSuperview() make.size.equalTo(28) } } snp.makeConstraints { make in make.height.equalTo(40) } } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func iconName(for kind: WildReportAttachmentKind) -> String { switch kind { case .image: return "photo.fill" case .video: return "video.fill" case .payment: return "creditcard.fill" } } @objc private func removeTapped() { onRemove?() } } /// 举报模块空状态视图。 final class WildReportEmptyView: UIView { init(text: String) { super.init(frame: .zero) let icon = UIImageView(image: UIImage(systemName: "tray")) icon.tintColor = AppColor.textTertiary let label = WildReportUI.label(text, font: .app(.body), color: AppColor.textSecondary, lines: 0) label.textAlignment = .center addSubview(icon) addSubview(label) icon.snp.makeConstraints { make in make.top.centerX.equalToSuperview() make.size.equalTo(42) } label.snp.makeConstraints { make in make.top.equalTo(icon.snp.bottom).offset(AppSpacing.sm) make.leading.trailing.bottom.equalToSuperview() } } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }