LNOrderRefundViewController.swift 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. //
  2. // LNOrderRefundViewController.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/12/23.
  6. //
  7. import Foundation
  8. import UIKit
  9. import SnapKit
  10. extension UIView {
  11. func pushToOrderRefund(_ orderId: String) {
  12. let vc = LNOrderRefundViewController(orderId: orderId)
  13. navigationController?.pushViewController(vc, animated: true)
  14. }
  15. }
  16. class LNOrderRefundViewController: LNViewController {
  17. private let orderId: String
  18. private var curDetail: LNOrderDetailResponse?
  19. private let detailView = LNOrderDetailCardView(type: .small)
  20. private let maxUpload = 6
  21. private let messageInputView = LNCommonTextView()
  22. private let imageUploadView = LNMultiImagesUploadView()
  23. private let submitButton = UIButton()
  24. init(orderId: String) {
  25. self.orderId = orderId
  26. super.init(nibName: nil, bundle: nil)
  27. }
  28. override func viewDidLoad() {
  29. super.viewDidLoad()
  30. setupViews()
  31. updateSubmitButton()
  32. reloadDetail()
  33. }
  34. required init?(coder: NSCoder) {
  35. fatalError("init(coder:) has not been implemented")
  36. }
  37. }
  38. extension LNOrderRefundViewController: LNOrderManagerNotify {
  39. func onOrderInfoChanged(orderId: String) {
  40. guard orderId == self.orderId else { return }
  41. reloadDetail()
  42. }
  43. }
  44. extension LNOrderRefundViewController {
  45. private func reloadDetail() {
  46. LNOrderManager.shared.getOrderDetail(orderId: orderId) { [weak self] detail in
  47. guard let self else { return }
  48. guard let detail else { return }
  49. curDetail = detail
  50. update(detail)
  51. }
  52. }
  53. private func update(_ item: LNOrderDetailResponse) {
  54. detailView.update(item)
  55. }
  56. }
  57. extension LNOrderRefundViewController: UITextViewDelegate {
  58. func textViewDidChange(_ textView: UITextView) {
  59. updateSubmitButton()
  60. }
  61. }
  62. extension LNOrderRefundViewController {
  63. private func updateSubmitButton() {
  64. if !messageInputView.text.isEmpty {
  65. submitButton.backgroundColor = .clear
  66. submitButton.setTitleColor(.text_5, for: .normal)
  67. submitButton.isEnabled = true
  68. } else {
  69. submitButton.backgroundColor = .fill_4
  70. submitButton.setTitleColor(.text_1, for: .normal)
  71. submitButton.isEnabled = false
  72. }
  73. }
  74. }
  75. extension LNOrderRefundViewController {
  76. private func setupViews() {
  77. view.backgroundColor = .primary_1
  78. title = .init(key: "A00284")
  79. let backgroundIc = UIImageView()
  80. backgroundIc.image = .icOrderCancelledBg
  81. view.addSubview(backgroundIc)
  82. backgroundIc.snp.makeConstraints { make in
  83. make.horizontalEdges.equalToSuperview()
  84. make.top.equalToSuperview()
  85. }
  86. submitButton.setTitle(.init(key: "A00179"), for: .normal)
  87. submitButton.titleLabel?.font = .heading_h3
  88. submitButton.layer.cornerRadius = 23.5
  89. submitButton.layer.borderWidth = 1
  90. submitButton.layer.borderColor = UIColor.text_2.cgColor
  91. submitButton.addAction(UIAction(handler: { [weak self] _ in
  92. guard let self else { return }
  93. let reason = messageInputView.text
  94. let attachments = imageUploadView.curFileUrls
  95. LNOrderManager.shared.refundOrder(orderId: orderId, reason: reason, attachments: attachments) { [weak self] success in
  96. guard let self else { return }
  97. guard success else { return }
  98. navigationController?.popViewController(animated: true)
  99. }
  100. }), for: .touchUpInside)
  101. view.addSubview(submitButton)
  102. submitButton.snp.makeConstraints { make in
  103. make.horizontalEdges.equalToSuperview().inset(16)
  104. make.bottom.equalToSuperview().offset(-view.safeBottomInset - 10)
  105. make.height.equalTo(47)
  106. }
  107. let scrollView = UIScrollView()
  108. scrollView.showsVerticalScrollIndicator = false
  109. scrollView.showsHorizontalScrollIndicator = false
  110. view.addSubview(scrollView)
  111. scrollView.snp.makeConstraints { make in
  112. make.horizontalEdges.equalToSuperview()
  113. make.top.equalToSuperview()
  114. make.bottom.equalTo(submitButton.snp.top)
  115. }
  116. let fakeView = UIView()
  117. scrollView.addSubview(fakeView)
  118. fakeView.snp.makeConstraints { make in
  119. make.horizontalEdges.equalToSuperview()
  120. make.top.equalToSuperview()
  121. make.width.equalToSuperview()
  122. make.height.equalTo(0)
  123. }
  124. scrollView.addSubview(detailView)
  125. detailView.snp.makeConstraints { make in
  126. make.horizontalEdges.equalToSuperview().inset(16)
  127. make.top.equalToSuperview().offset(10)
  128. }
  129. let container = UIView()
  130. container.backgroundColor = .fill
  131. container.layer.cornerRadius = 12
  132. scrollView.addSubview(container)
  133. container.snp.makeConstraints { make in
  134. make.horizontalEdges.equalToSuperview().inset(16)
  135. make.top.equalTo(detailView.snp.bottom).offset(16)
  136. make.bottom.equalToSuperview().offset(-16)
  137. }
  138. let textView = buildTextView()
  139. container.addSubview(textView)
  140. textView.snp.makeConstraints { make in
  141. make.horizontalEdges.equalToSuperview()
  142. make.top.equalToSuperview().offset(16)
  143. }
  144. let photoView = buildPhotoView()
  145. container.addSubview(photoView)
  146. photoView.snp.makeConstraints { make in
  147. make.horizontalEdges.equalToSuperview()
  148. make.top.equalTo(textView.snp.bottom).offset(16)
  149. make.bottom.equalToSuperview().offset(-16)
  150. }
  151. view.onTap { [weak self] in
  152. guard let self else { return }
  153. view.endEditing(true)
  154. }
  155. }
  156. private func buildTextView() -> UIView {
  157. let container = UIView()
  158. let titleLabel = UILabel()
  159. titleLabel.text = .init(key: "A00180")
  160. titleLabel.font = .heading_h4
  161. titleLabel.textColor = .text_5
  162. titleLabel.numberOfLines = 0
  163. container.addSubview(titleLabel)
  164. titleLabel.snp.makeConstraints { make in
  165. make.top.equalToSuperview()
  166. make.horizontalEdges.equalToSuperview().inset(16)
  167. }
  168. let descLabel = UILabel()
  169. descLabel.text = .init(key: "A00181")
  170. descLabel.font = .body_s
  171. descLabel.textColor = .text_4
  172. descLabel.numberOfLines = 0
  173. container.addSubview(descLabel)
  174. descLabel.snp.makeConstraints { make in
  175. make.top.equalTo(titleLabel.snp.bottom).offset(2)
  176. make.horizontalEdges.equalToSuperview().inset(16)
  177. }
  178. messageInputView.delegate = self
  179. messageInputView.maxInput = LNOrderManager.orderRefundMaxLength
  180. container.addSubview(messageInputView)
  181. messageInputView.snp.makeConstraints { make in
  182. make.horizontalEdges.equalToSuperview().inset(16)
  183. make.top.equalTo(descLabel.snp.bottom).offset(8)
  184. make.bottom.equalToSuperview()
  185. make.height.equalTo(150)
  186. }
  187. return container
  188. }
  189. private func buildPhotoView() -> UIView {
  190. let container = UIView()
  191. let titleLabel = UILabel()
  192. titleLabel.text = .init(key: "A00177", maxUpload)
  193. titleLabel.font = .heading_h4
  194. titleLabel.textColor = .text_5
  195. container.addSubview(titleLabel)
  196. titleLabel.snp.makeConstraints { make in
  197. make.top.equalToSuperview().offset(16)
  198. make.horizontalEdges.equalToSuperview().inset(16)
  199. }
  200. let descLabel = UILabel()
  201. descLabel.text = .init(key: "A00178")
  202. descLabel.font = .body_s
  203. descLabel.textColor = .text_4
  204. container.addSubview(descLabel)
  205. descLabel.snp.makeConstraints { make in
  206. make.horizontalEdges.equalToSuperview().inset(16)
  207. make.top.equalTo(titleLabel.snp.bottom).offset(2)
  208. }
  209. imageUploadView.maxPhoto = maxUpload
  210. container.addSubview(imageUploadView)
  211. imageUploadView.snp.makeConstraints { make in
  212. make.horizontalEdges.equalToSuperview().inset(16)
  213. make.top.equalTo(descLabel.snp.bottom).offset(16)
  214. make.bottom.equalToSuperview()
  215. make.height.equalTo(0).priority(.low)
  216. }
  217. return container
  218. }
  219. }
  220. #if DEBUG
  221. import SwiftUI
  222. struct LNOrderRefundViewControllerPreview: UIViewControllerRepresentable {
  223. func makeUIViewController(context: Context) -> some UIViewController {
  224. LNOrderRefundViewController(orderId: "")
  225. }
  226. func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { }
  227. }
  228. #Preview(body: {
  229. LNOrderRefundViewControllerPreview()
  230. })
  231. #endif