feat: add wild photographer report mock flow
This commit is contained in:
@ -0,0 +1,209 @@
|
||||
//
|
||||
// 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")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user