feat: add wild photographer report mock flow
This commit is contained in:
@ -0,0 +1,128 @@
|
||||
//
|
||||
// WildReportSupplementEvidenceViewController.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import SnapKit
|
||||
import UIKit
|
||||
|
||||
/// 补充证据页面,允许为已有举报追加说明和 Mock 附件。
|
||||
final class WildReportSupplementEvidenceViewController: BaseViewController {
|
||||
private let viewModel: WildReportSupplementEvidenceViewModel
|
||||
private let scrollView = UIScrollView()
|
||||
private let stack = UIStackView()
|
||||
private let textView = UITextView()
|
||||
private let submitButton = AppButton(title: "提交补充证据")
|
||||
|
||||
init(reportID: String, homeViewModel: WildPhotographerReportHomeViewModel) {
|
||||
self.viewModel = WildReportSupplementEvidenceViewModel(reportID: reportID, homeViewModel: homeViewModel)
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func setupNavigationBar() {
|
||||
title = "补充证据"
|
||||
}
|
||||
|
||||
override func setupUI() {
|
||||
view.backgroundColor = AppColor.pageBackgroundSoft
|
||||
scrollView.keyboardDismissMode = .interactive
|
||||
stack.axis = .vertical
|
||||
stack.spacing = AppSpacing.sm
|
||||
textView.font = .app(.body)
|
||||
textView.textColor = AppColor.textPrimary
|
||||
textView.backgroundColor = AppColor.inputBackground
|
||||
textView.layer.cornerRadius = AppRadius.md
|
||||
textView.textContainerInset = UIEdgeInsets(top: 12, left: 10, bottom: 12, right: 10)
|
||||
textView.delegate = self
|
||||
submitButton.addTarget(self, action: #selector(submitTapped), for: .touchUpInside)
|
||||
|
||||
view.addSubview(scrollView)
|
||||
scrollView.addSubview(stack)
|
||||
view.addSubview(submitButton)
|
||||
rebuildContent()
|
||||
}
|
||||
|
||||
override func setupConstraints() {
|
||||
submitButton.snp.makeConstraints { make in
|
||||
make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
|
||||
make.bottom.equalTo(view.safeAreaLayoutGuide).inset(AppSpacing.sm)
|
||||
}
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
|
||||
make.bottom.equalTo(submitButton.snp.top).offset(-AppSpacing.sm)
|
||||
}
|
||||
stack.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(UIEdgeInsets(top: AppSpacing.sm, left: AppSpacing.md, bottom: AppSpacing.lg, right: AppSpacing.md))
|
||||
make.width.equalTo(scrollView.snp.width).offset(-AppSpacing.md * 2)
|
||||
}
|
||||
}
|
||||
|
||||
override func bindActions() {
|
||||
viewModel.onStateChange = { [weak self] in
|
||||
Task { @MainActor in self?.rebuildContent() }
|
||||
}
|
||||
viewModel.onShowMessage = { [weak self] message in
|
||||
Task { @MainActor in self?.showToast(message) }
|
||||
}
|
||||
viewModel.onSubmitSuccess = { [weak self] in
|
||||
Task { @MainActor in
|
||||
self?.showToast("补充证据已提交")
|
||||
self?.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func rebuildContent() {
|
||||
stack.arrangedSubviews.forEach { view in
|
||||
stack.removeArrangedSubview(view)
|
||||
view.removeFromSuperview()
|
||||
}
|
||||
let textCard = WildReportCardView(spacing: AppSpacing.sm)
|
||||
textCard.stack.addArrangedSubview(WildReportUI.label("补充说明", font: .app(.title), color: AppColor.textPrimary))
|
||||
textView.text = viewModel.text
|
||||
textCard.stack.addArrangedSubview(textView)
|
||||
textView.snp.makeConstraints { make in make.height.equalTo(150) }
|
||||
let count = WildReportUI.label("\(viewModel.text.count)/500", font: .app(.caption), color: AppColor.textTertiary)
|
||||
count.textAlignment = .right
|
||||
textCard.stack.addArrangedSubview(count)
|
||||
stack.addArrangedSubview(textCard)
|
||||
|
||||
let attachmentCard = WildReportCardView(spacing: AppSpacing.sm)
|
||||
attachmentCard.stack.addArrangedSubview(WildReportUI.label("补充材料", font: .app(.title), color: AppColor.textPrimary))
|
||||
let row = UIStackView()
|
||||
row.axis = .horizontal
|
||||
row.spacing = AppSpacing.sm
|
||||
row.distribution = .fillEqually
|
||||
let imageButton = WildReportUI.iconButton(title: "添加图片", imageName: "photo", style: .secondary)
|
||||
imageButton.addTarget(self, action: #selector(addImageTapped), for: .touchUpInside)
|
||||
let videoButton = WildReportUI.iconButton(title: "添加视频", imageName: "video", style: .secondary)
|
||||
videoButton.addTarget(self, action: #selector(addVideoTapped), for: .touchUpInside)
|
||||
[imageButton, videoButton].forEach { button in
|
||||
button.snp.makeConstraints { make in make.height.equalTo(44) }
|
||||
row.addArrangedSubview(button)
|
||||
}
|
||||
attachmentCard.stack.addArrangedSubview(row)
|
||||
(viewModel.images + viewModel.videos).forEach { attachment in
|
||||
let chip = WildReportAttachmentChipView(attachment: attachment)
|
||||
chip.onRemove = { [weak self] in self?.viewModel.removeAttachment(attachment) }
|
||||
attachmentCard.stack.addArrangedSubview(chip)
|
||||
}
|
||||
stack.addArrangedSubview(attachmentCard)
|
||||
}
|
||||
|
||||
@objc private func addImageTapped() { viewModel.addImage() }
|
||||
@objc private func addVideoTapped() { viewModel.addVideo() }
|
||||
@objc private func submitTapped() { viewModel.submit() }
|
||||
}
|
||||
|
||||
extension WildReportSupplementEvidenceViewController: UITextViewDelegate {
|
||||
func textViewDidChange(_ textView: UITextView) {
|
||||
viewModel.updateText(textView.text)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user