IdentityGateView.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //
  2. // RealNamePopupView.swift
  3. // RoderickRalph
  4. //
  5. // Created by Neoa on 2025/8/20.
  6. //
  7. import Foundation
  8. import UIKit
  9. class IdentityGateView: UIView, UITextFieldDelegate{
  10. // MARK: - UI Components
  11. private let backdropView: UIView = {
  12. let view = UIView()
  13. view.backgroundColor = UIColor.black.withAlphaComponent(0.5) // Semi-transparent gray background
  14. view.translatesAutoresizingMaskIntoConstraints = false
  15. return view
  16. }()
  17. private let cardImageView: UIImageView = {
  18. let imageView = UIImageView()
  19. imageView.image = UIImage(named: "res_ew6zkg25") // Background image for the pop-up
  20. imageView.contentMode = .scaleToFill
  21. imageView.translatesAutoresizingMaskIntoConstraints = false
  22. return imageView
  23. }()
  24. private let titleRibbon: UIButton = {
  25. let button = UIButton(type: .system)
  26. button.setBackgroundImage(UIImage(named: "res_x8brwne3"), for: .normal)
  27. button.setTitle("实名认证", for: .normal)
  28. button.setTitleColor(.white, for: .normal)
  29. button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
  30. button.translatesAutoresizingMaskIntoConstraints = false
  31. return button
  32. }()
  33. private let infoLabel: UILabel = {
  34. let label = UILabel()
  35. label.text = "根据国家相关法规规定,请使用有效身份证进行实名认证。(该信息仅用于实名登记,不会向任何第三方泄露)"
  36. label.font = UIFont.systemFont(ofSize: 11)
  37. label.textColor = .white
  38. label.numberOfLines = 0
  39. label.translatesAutoresizingMaskIntoConstraints = false
  40. return label
  41. }()
  42. private let nameCaption: UILabel = {
  43. let label = UILabel()
  44. label.text = "姓 名"
  45. label.font = UIFont.systemFont(ofSize: 12)
  46. label.textColor = .white
  47. label.translatesAutoresizingMaskIntoConstraints = false
  48. return label
  49. }()
  50. private let nameField: UITextField = {
  51. let textField = UITextField()
  52. textField.placeholder = "请输入真实姓名"
  53. textField.font = UIFont.systemFont(ofSize: 14)
  54. textField.borderStyle = .roundedRect
  55. textField.translatesAutoresizingMaskIntoConstraints = false
  56. return textField
  57. }()
  58. private let idCaption: UILabel = {
  59. let label = UILabel()
  60. label.text = "身份证号"
  61. label.font = UIFont.systemFont(ofSize: 12)
  62. label.textColor = .white
  63. label.translatesAutoresizingMaskIntoConstraints = false
  64. return label
  65. }()
  66. private let idField: UITextField = {
  67. let textField = UITextField()
  68. textField.placeholder = "请输入有效的身份证号"
  69. textField.font = UIFont.systemFont(ofSize: 14)
  70. textField.borderStyle = .roundedRect
  71. textField.translatesAutoresizingMaskIntoConstraints = false
  72. return textField
  73. }()
  74. private let confirmControl: UIButton = {
  75. let button = UIButton(type: .system)
  76. button.setBackgroundImage(UIImage(named: "res_ux9fin4y"), for: .normal)
  77. button.setTitle("认证", for: .normal)
  78. button.setTitleColor(.white, for: .normal)
  79. button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
  80. button.contentHorizontalAlignment = .center
  81. button.translatesAutoresizingMaskIntoConstraints = false
  82. return button
  83. }()
  84. private let dismissControl: UIButton = {
  85. let button = UIButton(type: .custom)
  86. button.setImage(UIImage(named: "res_9mx2yiyi"), for: .normal)
  87. button.addTarget(self, action: #selector(dismissPanel), for: .touchUpInside)
  88. button.translatesAutoresizingMaskIntoConstraints = false
  89. return button
  90. }()
  91. // MARK: - Initialization
  92. init() {
  93. super.init(frame: .zero)
  94. buildUI()
  95. applyConstraints()
  96. wireKeyboardDismissal() // Set up keyboard dismissal
  97. }
  98. required init?(coder: NSCoder) {
  99. fatalError("init(coder:) has not been implemented")
  100. }
  101. // MARK: - UI Setup
  102. private func buildUI() {
  103. addSubview(backdropView)
  104. addSubview(cardImageView)
  105. addSubview(titleRibbon)
  106. addSubview(infoLabel)
  107. addSubview(nameCaption)
  108. addSubview(nameField)
  109. addSubview(idCaption)
  110. addSubview(idField)
  111. addSubview(confirmControl)
  112. addSubview(dismissControl)
  113. // If you want the dimmed background to also close the popup, uncomment below:
  114. // let tapGesture = UITapGestureRecognizer(target: self, action: #selector(closePopup))
  115. // backgroundView.addGestureRecognizer(tapGesture)
  116. nameField.delegate = self
  117. idField.delegate = self
  118. confirmControl.addTarget(self, action: #selector(handleConfirmTap), for: .touchUpInside)
  119. }
  120. private func applyConstraints() {
  121. NSLayoutConstraint.activate([
  122. // Background view
  123. backdropView.topAnchor.constraint(equalTo: topAnchor),
  124. backdropView.bottomAnchor.constraint(equalTo: bottomAnchor),
  125. backdropView.leadingAnchor.constraint(equalTo: leadingAnchor),
  126. backdropView.trailingAnchor.constraint(equalTo: trailingAnchor),
  127. cardImageView.centerXAnchor.constraint(equalTo: centerXAnchor),
  128. cardImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
  129. cardImageView.widthAnchor.constraint(equalToConstant: 333),
  130. cardImageView.heightAnchor.constraint(equalToConstant: 266),
  131. titleRibbon.topAnchor.constraint(equalTo: cardImageView.topAnchor, constant: 10),
  132. titleRibbon.centerXAnchor.constraint(equalTo: cardImageView.centerXAnchor, constant: 0),
  133. titleRibbon.widthAnchor.constraint(equalToConstant: 132),
  134. titleRibbon.heightAnchor.constraint(equalToConstant: 37),
  135. infoLabel.topAnchor.constraint(equalTo: titleRibbon.bottomAnchor, constant: 14),
  136. infoLabel.centerXAnchor.constraint(equalTo: cardImageView.centerXAnchor, constant: 0),
  137. infoLabel.leadingAnchor.constraint(equalTo: cardImageView.leadingAnchor, constant: 35),
  138. infoLabel.trailingAnchor.constraint(equalTo: cardImageView.trailingAnchor, constant: -35),
  139. nameField.topAnchor.constraint(equalTo: infoLabel.bottomAnchor, constant: 17),
  140. nameField.trailingAnchor.constraint(equalTo: cardImageView.trailingAnchor, constant: -30),
  141. nameField.widthAnchor.constraint(equalToConstant: 204),
  142. nameField.heightAnchor.constraint(equalToConstant: 24),
  143. nameCaption.centerYAnchor.constraint(equalTo: nameField.centerYAnchor, constant: 0),
  144. nameCaption.trailingAnchor.constraint(equalTo: nameField.leadingAnchor, constant: -11),
  145. idField.topAnchor.constraint(equalTo: nameField.bottomAnchor, constant: 8),
  146. idField.trailingAnchor.constraint(equalTo: nameField.trailingAnchor, constant: 0),
  147. idField.widthAnchor.constraint(equalToConstant: 204),
  148. idField.heightAnchor.constraint(equalToConstant: 24),
  149. idCaption.centerYAnchor.constraint(equalTo: idField.centerYAnchor, constant: 0),
  150. idCaption.trailingAnchor.constraint(equalTo: idField.leadingAnchor, constant: -11),
  151. confirmControl.topAnchor.constraint(equalTo: idField.bottomAnchor, constant: 20),
  152. confirmControl.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0),
  153. confirmControl.widthAnchor.constraint(equalToConstant: 211),
  154. confirmControl.heightAnchor.constraint(equalToConstant: 42),
  155. dismissControl.topAnchor.constraint(equalTo: cardImageView.topAnchor, constant: -12),
  156. dismissControl.trailingAnchor.constraint(equalTo: cardImageView.trailingAnchor, constant: 12),
  157. dismissControl.widthAnchor.constraint(equalToConstant: 24),
  158. dismissControl.heightAnchor.constraint(equalToConstant: 24),
  159. ])
  160. }
  161. // MARK: - Actions
  162. @objc private func dismissPanel() {
  163. removeFromSuperview()
  164. }
  165. @objc private func handleConfirmTap() {
  166. // Perform validation checks
  167. if nameField.text?.isEmpty ?? true {
  168. flashToast(message: "姓名不能为空")
  169. } else if idField.text?.isEmpty ?? true {
  170. flashToast(message: "身份证号不能为空")
  171. } else {
  172. // Show success message
  173. flashToast(message: "认证成功")
  174. }
  175. }
  176. // MARK: - Keyboard Dismissal
  177. private func wireKeyboardDismissal() {
  178. // Tap gesture to dismiss keyboard when tapping outside the text fields
  179. let tapGesture = UITapGestureRecognizer(target: self, action: #selector(resignKeyboard))
  180. self.addGestureRecognizer(tapGesture)
  181. }
  182. @objc private func resignKeyboard() {
  183. nameField.resignFirstResponder()
  184. idField.resignFirstResponder()
  185. }
  186. // MARK: - UITextFieldDelegate
  187. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  188. // Dismiss the keyboard when the return key is pressed
  189. textField.resignFirstResponder()
  190. return true
  191. }
  192. // 通用 Toast
  193. private func flashToast(message: String) {
  194. let toastLabel = UILabel()
  195. toastLabel.text = message
  196. toastLabel.font = UIFont.systemFont(ofSize: 14)
  197. toastLabel.textColor = .white
  198. toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.7)
  199. toastLabel.textAlignment = .center
  200. toastLabel.alpha = 0.0
  201. toastLabel.layer.cornerRadius = 8
  202. toastLabel.clipsToBounds = true
  203. toastLabel.translatesAutoresizingMaskIntoConstraints = false
  204. addSubview(toastLabel)
  205. NSLayoutConstraint.activate([
  206. toastLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
  207. toastLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
  208. toastLabel.widthAnchor.constraint(equalToConstant: 160),
  209. toastLabel.heightAnchor.constraint(equalToConstant: 40)
  210. ])
  211. UIView.animate(withDuration: 0.3) {
  212. toastLabel.alpha = 1.0
  213. } completion: { _ in
  214. DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
  215. UIView.animate(withDuration: 0.3) {
  216. toastLabel.alpha = 0.0
  217. } completion: { _ in
  218. toastLabel.removeFromSuperview()
  219. }
  220. }
  221. }
  222. }
  223. }