| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- //
- // FeedbackViewController.swift
- // VenusKitto
- //
- // Created by Neoa on 2025/8/27.
- //
- import Foundation
- import UIKit
- final class VKWhistleBoardController: UIViewController {
-
- // MARK: - UI Elements
-
- // 问题描述部分
- private let bx_wrap: UIView = {
- let view = UIView()
- view.translatesAutoresizingMaskIntoConstraints = false
- return view
- }()
-
- private let bx_bar: UIView = {
- let view = UIView()
- view.backgroundColor = UIColor(hex: "#FFE059")
- view.translatesAutoresizingMaskIntoConstraints = false
- return view
- }()
-
- private let bx_title: UILabel = {
- let label = UILabel()
- label.translatesAutoresizingMaskIntoConstraints = false
-
- // 创建属性字符串
- let mainString = "问题描述(必填)"
- let attributedString = NSMutableAttributedString(string: mainString)
-
- // 设置整体样式
- attributedString.addAttributes([
- .font: UIFont.systemFont(ofSize: 15),
- .foregroundColor: UIColor.black
- ], range: NSRange(location: 0, length: mainString.count))
-
- // 将"(必填)"设置为红色
- if let range = mainString.range(of: "(必填)") {
- let nsRange = NSRange(range, in: mainString)
- attributedString.addAttributes([
- .foregroundColor: UIColor.red
- ], range: nsRange)
- }
-
- label.attributedText = attributedString
- return label
- }()
-
- private let bx_hint: UILabel = {
- let label = UILabel()
- label.text = "请尽量将问题描述详细"
- label.font = UIFont.boldSystemFont(ofSize: 14)
- label.textAlignment = .left
- label.textColor = .lightGray
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
-
- private let bx_text: UITextView = {
- let textView = UITextView()
- textView.font = UIFont.systemFont(ofSize: 16)
- textView.text = ""
- textView.textColor = .lightGray
- textView.layer.borderWidth = 0.5
- textView.layer.borderColor = UIColor.lightGray.cgColor
- textView.layer.cornerRadius = 4
- textView.translatesAutoresizingMaskIntoConstraints = false
- return textView
- }()
-
- // 联系方式部分
- private let cx_wrap: UIView = {
- let view = UIView()
- view.translatesAutoresizingMaskIntoConstraints = false
- return view
- }()
-
- private let cx_bar: UIView = {
- let view = UIView()
- view.backgroundColor = UIColor(hex: "#FFE059")
- view.translatesAutoresizingMaskIntoConstraints = false
- return view
- }()
-
- private let cx_title: UILabel = {
- let label = UILabel()
- label.text = "联系方式(选填)"
- label.font = UIFont.systemFont(ofSize: 15)
- label.textColor = .black
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
-
- private let cx_hint: UILabel = {
- let label = UILabel()
- label.text = "请输入手机号或QQ号"
- label.font = UIFont.systemFont(ofSize: 14)
- label.textColor = .lightGray
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
- private let cx_text: UITextView = {
- let textView = UITextView()
- textView.font = UIFont.systemFont(ofSize: 16)
- textView.text = ""
- textView.textColor = .lightGray
- textView.layer.borderWidth = 0.5
- textView.layer.borderColor = UIColor.lightGray.cgColor
- textView.layer.cornerRadius = 4
- textView.translatesAutoresizingMaskIntoConstraints = false
- return textView
- }()
-
- private let mx_commit: UIButton = {
- let button = UIButton(type: .system)
- button.setTitle("提交反馈", for: .normal)
- button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
- button.setTitleColor(.black, for: .normal)
- button.backgroundColor = UIColor(hex: "#FFE059")
- button.layer.cornerRadius = 25
- button.translatesAutoresizingMaskIntoConstraints = false
- return button
- }()
-
- // MARK: - Lifecycle
- override func viewDidLoad() {
- super.viewDidLoad()
- buildUI()
- wireConstraints()
- hookDelegates()
- installGestures()
-
-
- navigationItem.title = "意见反馈"
- navigationItem.leftBarButtonItem = UIBarButtonItem(
- image: UIImage(systemName: "chevron.left"),
- style: .plain,
- target: self,
- action: #selector(ax_back)
- )
- navigationController?.navigationBar.tintColor = .black
- mx_commit.addTarget(self, action: #selector(ax_submit), for: .touchUpInside)
- }
-
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
- navigationController?.setNavigationBarHidden(false, animated: animated)
- }
-
- @objc private func ax_submit() {
- // 验证问题描述是否为空
- if bx_text.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
- vx_emit("请填写问题描述")
- return
- }
- // TODO: 在此处添加提交反馈的逻辑
- vx_emit("提交成功")
- // 延迟后返回上一页
- DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
- self.navigationController?.popViewController(animated: true)
- }
- }
- private func vx_emit(_ message: String) {
- let toastLabel = UILabel()
- toastLabel.text = message
- toastLabel.font = UIFont.systemFont(ofSize: 14)
- toastLabel.textColor = .white
- toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.7)
- toastLabel.textAlignment = .center
- toastLabel.alpha = 0.0
- toastLabel.layer.cornerRadius = 8
- toastLabel.clipsToBounds = true
- toastLabel.translatesAutoresizingMaskIntoConstraints = false
-
- view.addSubview(toastLabel)
-
- NSLayoutConstraint.activate([
- toastLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
- toastLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -100),
- toastLabel.widthAnchor.constraint(equalToConstant: 160),
- toastLabel.heightAnchor.constraint(equalToConstant: 40)
- ])
-
- UIView.animate(withDuration: 0.3) {
- toastLabel.alpha = 1.0
- } completion: { _ in
- DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
- UIView.animate(withDuration: 0.3) {
- toastLabel.alpha = 0.0
- } completion: { _ in
- toastLabel.removeFromSuperview()
- }
- }
- }
- }
- // MARK: - Setup
- private func buildUI() {
- view.backgroundColor = .white
-
- // 添加主要视图组件
- view.addSubview(bx_wrap)
- view.addSubview(bx_hint)
- view.addSubview(cx_wrap)
- view.addSubview(mx_commit)
-
- // 问题描述容器内的组件
- bx_wrap.addSubview(bx_bar)
- bx_wrap.addSubview(bx_title)
- bx_wrap.addSubview(bx_text)
-
- // 联系方式容器内的组件
- cx_wrap.addSubview(cx_bar)
- cx_wrap.addSubview(cx_title)
- cx_wrap.addSubview(cx_hint)
- cx_wrap.addSubview(cx_text)
- }
-
- private func wireConstraints() {
- // 问题描述容器
- NSLayoutConstraint.activate([
- bx_wrap.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
- bx_wrap.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
- bx_wrap.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
- ])
-
- // 蓝色分割线
- NSLayoutConstraint.activate([
- bx_bar.leadingAnchor.constraint(equalTo: bx_wrap.leadingAnchor),
- bx_bar.topAnchor.constraint(equalTo: bx_title.topAnchor),
- bx_bar.bottomAnchor.constraint(equalTo: bx_title.bottomAnchor),
- bx_bar.widthAnchor.constraint(equalToConstant: 3),
- ])
-
- // 问题描述标题和文本框
- NSLayoutConstraint.activate([
- bx_title.leadingAnchor.constraint(equalTo: bx_bar.trailingAnchor, constant: 8),
- bx_title.trailingAnchor.constraint(equalTo: bx_wrap.trailingAnchor),
- bx_title.topAnchor.constraint(equalTo: bx_wrap.topAnchor),
-
- bx_hint.leadingAnchor.constraint(equalTo: bx_title.leadingAnchor, constant: 0),
- bx_hint.topAnchor.constraint(equalTo: bx_title.bottomAnchor, constant: 8),
-
- bx_text.topAnchor.constraint(equalTo: bx_hint.bottomAnchor, constant: 8),
- bx_text.leadingAnchor.constraint(equalTo: bx_wrap.leadingAnchor, constant: 8),
- bx_text.trailingAnchor.constraint(equalTo: bx_wrap.trailingAnchor, constant: -8),
- bx_text.heightAnchor.constraint(equalToConstant: 150),
- bx_text.bottomAnchor.constraint(equalTo: bx_wrap.bottomAnchor),
- ])
-
- // 联系方式容器
- NSLayoutConstraint.activate([
- cx_wrap.topAnchor.constraint(equalTo: bx_wrap.bottomAnchor),
- cx_wrap.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
- cx_wrap.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
- ])
-
- // 蓝色分割线
- NSLayoutConstraint.activate([
- cx_bar.leadingAnchor.constraint(equalTo: cx_wrap.leadingAnchor),
- cx_bar.topAnchor.constraint(equalTo: cx_title.topAnchor),
- cx_bar.bottomAnchor.constraint(equalTo: cx_title.bottomAnchor),
- cx_bar.widthAnchor.constraint(equalToConstant: 3),
- ])
-
- // 联系方式标题和文本框
- NSLayoutConstraint.activate([
- cx_title.leadingAnchor.constraint(equalTo: cx_bar.trailingAnchor, constant: 8),
- cx_title.trailingAnchor.constraint(equalTo: cx_wrap.trailingAnchor),
- cx_title.topAnchor.constraint(equalTo: cx_wrap.topAnchor, constant: 16),
-
- cx_hint.leadingAnchor.constraint(equalTo: cx_title.leadingAnchor, constant: 0),
- cx_hint.topAnchor.constraint(equalTo: cx_title.bottomAnchor, constant: 8),
-
- cx_text.topAnchor.constraint(equalTo: cx_hint.bottomAnchor, constant: 8),
- cx_text.leadingAnchor.constraint(equalTo: cx_wrap.leadingAnchor, constant: 8),
- cx_text.trailingAnchor.constraint(equalTo: cx_wrap.trailingAnchor, constant: -8),
- cx_text.heightAnchor.constraint(equalToConstant: 150),
- cx_text.bottomAnchor.constraint(equalTo: cx_wrap.bottomAnchor),
- ])
-
- // 提交按钮
- NSLayoutConstraint.activate([
- mx_commit.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -50),
- mx_commit.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
- mx_commit.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
- mx_commit.heightAnchor.constraint(equalToConstant: 50)
- ])
- }
-
- private func hookDelegates() {
- bx_text.delegate = self
- cx_text.delegate = self
- }
-
- private func installGestures() {
- let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ax_hideKB))
- view.addGestureRecognizer(tapGesture)
- }
-
- @objc private func ax_hideKB() {
- view.endEditing(true)
- }
-
- @objc private func ax_back() {
- if presentingViewController != nil {
- dismiss(animated: true, completion: nil)
- } else {
- navigationController?.popViewController(animated: true)
- }
- }
- }
- // MARK: - TextView Delegate
- extension VKWhistleBoardController: UITextViewDelegate {
- func textViewDidBeginEditing(_ textView: UITextView) {
- if textView.textColor == .lightGray {
- textView.text = nil
- textView.textColor = .black
- }
- }
-
- func textViewDidEndEditing(_ textView: UITextView) {
- if textView.text.isEmpty {
- textView.text = ""
- textView.textColor = .lightGray
- }
- }
- }
- // MARK: - TextField Delegate
- extension VKWhistleBoardController: UITextFieldDelegate {
- func textFieldShouldReturn(_ textField: UITextField) -> Bool {
- textField.resignFirstResponder()
- return true
- }
- }
- // Compatibility alias for legacy code
- typealias FeedbackViewController = VKWhistleBoardController
|