PQStuckPointMusicContentController.swift 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. //
  2. // PQStuckPointMusicContentController.swift
  3. // PQSpeed
  4. //
  5. // Created by SanW on 2021/4/28.
  6. // Copyright © 2021 BytesFlow. All rights reserved.
  7. //
  8. import UIKit
  9. class PQStuckPointMusicContentController: PQBaseViewController {
  10. var itemList: [Any] = Array<Any>.init() // 所有分类数据
  11. // 当前选择的位置
  12. var lastIndexPath: IndexPath?
  13. let lineSpacing: CGFloat = 12
  14. let leftMargin: CGFloat = 16
  15. // cell高度
  16. var cellHight: CGFloat = cDefaultMargin * 5
  17. // 顶部距离
  18. var topHight: CGFloat = cDefaultMargin * 6
  19. /// 二级标签信息
  20. var tagsInfo: ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))?
  21. // 点击的回调
  22. var didSelectedHandle: ((_ isTagsClick: Bool, _ contentType: stuckPointMusicContentType, _ indexPath: IndexPath, _ itemData: Any) -> Void)?
  23. // 按钮点击的回调
  24. var btnClickHandle: ((_ sender: UIButton, _ bgmData: Any?) -> Void)?
  25. // 滑动的回调
  26. var scroDidScroHandle: (() -> Void)?
  27. // 刷新的回调
  28. var refreshHandle: ((_ isRefresh: Bool, _ contentType: stuckPointMusicContentType) -> Void)?
  29. // 卡点音乐页面类型
  30. var contentType: stuckPointMusicContentType = .catagery {
  31. didSet {
  32. if contentType == .page || contentType == .serach {
  33. collectionView.addRefreshView(type: .REFRESH_TYPE_FOOTER) { [weak self] isRefresh in
  34. if self?.refreshHandle != nil {
  35. self?.refreshHandle!(isRefresh, self?.contentType ?? .catagery)
  36. }
  37. }
  38. } else {
  39. lastIndexPath = IndexPath(item: 0, section: 0)
  40. }
  41. }
  42. }
  43. lazy var collectionView: UICollectionView = {
  44. let flowLayout = UICollectionViewFlowLayout()
  45. flowLayout.sectionInset = UIEdgeInsets.zero
  46. flowLayout.minimumLineSpacing = 0
  47. flowLayout.minimumInteritemSpacing = 0
  48. flowLayout.scrollDirection = .vertical
  49. let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height), collectionViewLayout: flowLayout)
  50. collectionView.showsVerticalScrollIndicator = false
  51. collectionView.showsHorizontalScrollIndicator = false
  52. collectionView.delegate = self
  53. collectionView.dataSource = self
  54. collectionView.backgroundColor = UIColor.clear
  55. collectionView.register(PQStuckPointMusicContentCell.self, forCellWithReuseIdentifier: String(describing: PQStuckPointMusicContentCell.self))
  56. collectionView.register(PQStuckPointMusicTagsCell.self, forCellWithReuseIdentifier: String(describing: PQStuckPointMusicTagsCell.self))
  57. collectionView.register(PQStuckPointSearchEmptyCell.self, forCellWithReuseIdentifier: String(describing: PQStuckPointSearchEmptyCell.self))
  58. if #available(iOS 11.0, *) {
  59. collectionView.contentInsetAdjustmentBehavior = .never
  60. } else {
  61. automaticallyAdjustsScrollViewInsets = false
  62. }
  63. // 延迟scrollView上子视图的响应,所以当直接拖动UISlider时,如果此时touch时间在150ms以内,UIScrollView会认为是拖动自己,从而拦截了event,导致UISlider接收不到滑动的event
  64. collectionView.delaysContentTouches = false
  65. return collectionView
  66. }()
  67. lazy var emptyRemindView: PQEmptyRemindView = {
  68. let emptyRemindView = PQEmptyRemindView(frame: collectionView.bounds)
  69. emptyRemindView.remindLab.font = UIFont.systemFont(ofSize: 16)
  70. emptyRemindView.remindLab.textColor = UIColor.hexColor(hexadecimal: "#575757")
  71. emptyRemindView.isHidden = true
  72. emptyRemindView.emptyData = emptyData
  73. emptyRemindView.fullRefreshBloc = { [weak self] _, _ in
  74. if self?.refreshHandle != nil {
  75. self?.refreshHandle!(true, self?.contentType ?? .catagery)
  76. }
  77. }
  78. collectionView.addSubview(emptyRemindView)
  79. return emptyRemindView
  80. }()
  81. var emptyData: PQEmptyModel? = {
  82. let emptyData = PQEmptyModel()
  83. emptyData.title = "暂无音乐"
  84. return emptyData
  85. }()
  86. override func viewDidLoad() {
  87. super.viewDidLoad()
  88. hiddenNavigation()
  89. view.addSubview(collectionView)
  90. }
  91. /// 更新frame
  92. /// - Parameter newFrame: <#newFrame description#>
  93. /// - Returns: <#description#>
  94. func updateViewFrame(newFrame: CGRect) {
  95. view.frame = newFrame
  96. collectionView.frame = CGRect(origin: CGPoint.zero, size: newFrame.size)
  97. emptyRemindView.frame = collectionView.bounds
  98. collectionView.reloadData()
  99. }
  100. /// 配置数据
  101. /// - Parameter musicListData: <#musicListData description#>
  102. /// - Returns: <#description#>
  103. func configMusicListData(isResetData: Bool = false, isRefresh: Bool = true, musicListData: [Any]) {
  104. if isRefresh {
  105. if contentType == .catagery {
  106. lastIndexPath = IndexPath(item: 0, section: 0)
  107. } else {
  108. lastIndexPath = nil
  109. }
  110. itemList.removeAll()
  111. if tagsInfo != nil {
  112. itemList = musicListData
  113. itemList.insert(tagsInfo!, at: 0)
  114. } else {
  115. itemList = musicListData
  116. }
  117. } else {
  118. itemList = itemList + musicListData
  119. }
  120. if musicListData.count < 20 || itemList.first is PQEmptyModel {
  121. collectionView.mj_footer?.endRefreshingWithNoMoreData()
  122. } else {
  123. collectionView.mj_footer?.endRefreshing()
  124. }
  125. collectionView.reloadData()
  126. // 展示空页面
  127. if isResetData {
  128. emptyRemindView.isHidden = true
  129. } else {
  130. showEmptyView()
  131. }
  132. }
  133. /// 展示空页面
  134. func showEmptyView() {
  135. if contentType != .catagery {
  136. emptyRemindView.isHidden = contentType == .serach ? itemList.count > 0 : itemList.count > 1
  137. if !emptyRemindView.isHidden, itemList.count > 0, ((itemList.first as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)))?.0.count ?? 0) > 0 {
  138. let maxH = (((itemList.first as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)))?.1.1 ?? 0) + 35)
  139. emptyRemindView.frame = CGRect(x: 0, y: maxH, width: collectionView.frame.width, height: collectionView.frame.height - maxH)
  140. } else {
  141. emptyRemindView.frame = collectionView.bounds
  142. }
  143. emptyRemindView.emptyData = emptyData
  144. }
  145. }
  146. /// 更新当前播放视频
  147. /// - Returns: <#description#>
  148. func updateCurrentPlayMusic(isPlaying: Bool, isClearCurrentMusic: Bool) {
  149. if lastIndexPath != nil, itemList.count > (lastIndexPath?.item ?? 0) {
  150. (itemList[lastIndexPath?.item ?? 0] as? PQVoiceModel)?.isPlaying = isPlaying
  151. collectionView.reloadData()
  152. }
  153. if isClearCurrentMusic {
  154. if lastIndexPath != nil, itemList.count > (lastIndexPath?.item ?? 0) {
  155. (itemList[lastIndexPath?.item ?? 0] as? PQVoiceModel)?.isSelected = false
  156. (itemList[lastIndexPath?.item ?? 0] as? PQVoiceModel)?.isPlaying = false
  157. }
  158. lastIndexPath = nil
  159. collectionView.reloadData()
  160. }
  161. }
  162. }
  163. // MARK: - 卡点音乐相关代理
  164. /// 卡点音乐相关代理
  165. extension PQStuckPointMusicContentController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate {
  166. func collectionView(_: UICollectionView, numberOfItemsInSection _: Int) -> Int {
  167. return itemList.count
  168. }
  169. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  170. let itemData: Any = itemList[indexPath.item]
  171. if itemData is ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)) {
  172. let cell = PQStuckPointMusicTagsCell.stuckPointMusicTagsCell(collectionView: collectionView, indexPath: indexPath)
  173. cell.itemData = itemData as! ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))
  174. cell.tagsDidSelectedHandle = { [weak self] indexPath, tagsData in
  175. if self?.didSelectedHandle != nil {
  176. self?.didSelectedHandle!(true, self?.contentType ?? .catagery, indexPath, tagsData ?? PQStuckPointMusicTagsModel())
  177. }
  178. if tagsData != nil {
  179. // 点击上报:选择音乐分类下的 TAG
  180. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_chooseMusicCategoryTag, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: ["categoryName": tagsData?.tagName ?? "", "categoryId": tagsData?.tagId ?? ""], remindmsg: "卡点视频数据上报-(点击上报:选择音乐分类下的 TAG)")
  181. }
  182. }
  183. return cell
  184. } else if itemData is PQEmptyModel {
  185. let cell = PQStuckPointSearchEmptyCell.stuckPointSearchEmptyCell(collectionView: collectionView, indexPath: indexPath)
  186. cell.bgmData = itemData as? PQEmptyModel
  187. return cell
  188. } else {
  189. let cell = PQStuckPointMusicContentCell.stuckPointMusicContentCell(collectionView: collectionView, indexPath: indexPath)
  190. cell.contentType = contentType
  191. cell.bgmData = itemList[indexPath.item]
  192. cell.btnClickHandle = { [weak self] sender, bgmData in
  193. if self?.btnClickHandle != nil {
  194. self?.btnClickHandle!(sender, bgmData)
  195. }
  196. if bgmData is PQVoiceModel {
  197. if self?.contentType == .page {
  198. // 卡点视频音乐选择音乐素材
  199. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_chooseMusic, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: ["musicName": (bgmData as? PQVoiceModel)?.musicName ?? "", "musicId": (bgmData as? PQVoiceModel)?.musicId ?? ""], remindmsg: "卡点视频数据上报-(点击上报:选择音乐素材)")
  200. } else if self?.contentType == .serach {
  201. // 点击上报:选择音乐素材
  202. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_chooseSearchMusic, pageSource: .sp_stuck_searchSyncedUpMusic, extParams: ["musicName": (bgmData as? PQVoiceModel)?.musicName ?? "", "musicId": (bgmData as? PQVoiceModel)?.musicId ?? "", "isHotMusic": self?.itemList.first is PQEmptyModel], remindmsg: "卡点视频数据上报-(点击上报:选择音乐素材)")
  203. }
  204. }
  205. }
  206. return cell
  207. }
  208. }
  209. func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  210. let itemData: Any = itemList[indexPath.item]
  211. if itemData is ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)) {
  212. let height: CGFloat = ((itemData as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)))?.0.count ?? 0) > 0 ? (((itemData as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)))?.1.1 ?? 0) + 35) : 0
  213. return CGSize(width: collectionView.frame.width, height: height)
  214. } else if itemData is PQEmptyModel {
  215. return CGSize(width: collectionView.frame.width, height: 290)
  216. } else {
  217. return CGSize(width: collectionView.frame.width, height: cellHight)
  218. }
  219. }
  220. func collectionView(_: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  221. if !isNetConnected() {
  222. cShowHUB(superView: nil, msg: "请有网时再试")
  223. return
  224. }
  225. if !(itemList[indexPath.item] is PQEmptyModel) {
  226. if lastIndexPath != indexPath {
  227. if contentType == .catagery {
  228. (itemList[lastIndexPath?.item ?? 0] as? PQStuckPointMusicTagsModel)?.isSelected = false
  229. (itemList[indexPath.item] as? PQStuckPointMusicTagsModel)?.isSelected = true
  230. } else {
  231. (itemList[lastIndexPath?.item ?? 0] as? PQVoiceModel)?.isSelected = false
  232. (itemList[lastIndexPath?.item ?? 0] as? PQVoiceModel)?.isPlaying = false
  233. (itemList[indexPath.item] as? PQVoiceModel)?.isSelected = true
  234. (itemList[indexPath.item] as? PQVoiceModel)?.isPlaying = true
  235. }
  236. lastIndexPath = indexPath
  237. collectionView.reloadData()
  238. } else if contentType != .catagery {
  239. (itemList[indexPath.item] as? PQVoiceModel)?.isPlaying = !((itemList[indexPath.item] as? PQVoiceModel)?.isPlaying ?? false)
  240. (itemList[indexPath.item] as? PQVoiceModel)?.isSelected = true
  241. collectionView.reloadData()
  242. }
  243. }
  244. if contentType == .catagery {
  245. collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
  246. }
  247. if didSelectedHandle != nil {
  248. didSelectedHandle!(false, contentType, indexPath, itemList[indexPath.item])
  249. }
  250. if itemList[indexPath.item] is PQVoiceModel {
  251. if contentType == .page {
  252. // 卡点视频音乐素材试听
  253. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_auditionMusic, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: ["musicName": (itemList[indexPath.item] as? PQVoiceModel)?.musicName ?? "", "musicId": (itemList[indexPath.item] as? PQVoiceModel)?.musicId ?? ""], remindmsg: "卡点视频数据上报-(点击上报:音乐素材试听)")
  254. } else if contentType == .serach {
  255. // 点击上报:试听音乐素材
  256. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_auditionSearchMusic, pageSource: .sp_stuck_searchSyncedUpMusic, extParams: ["musicName": (itemList[indexPath.item] as? PQVoiceModel)?.musicName ?? "", "musicId": (itemList[indexPath.item] as? PQVoiceModel)?.musicId ?? "", "isHotMusic": itemList.first is PQEmptyModel], remindmsg: "卡点视频数据上报-(点击上报:试听音乐素材)")
  257. }
  258. } else if contentType == .catagery && (itemList[indexPath.item] is PQStuckPointMusicTagsModel) {
  259. // 点击上报:选择音乐分类
  260. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_chooseMusicCategory, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: ["categoryName": (itemList[indexPath.item] as? PQStuckPointMusicTagsModel)?.tagName ?? "", "categoryId": (itemList[indexPath.item] as? PQStuckPointMusicTagsModel)?.tagId ?? ""], remindmsg: "卡点视频数据上报-(点击上报:选择音乐分类)")
  261. }
  262. }
  263. func scrollViewDidScroll(_: UIScrollView) {
  264. if scroDidScroHandle != nil {
  265. scroDidScroHandle!()
  266. }
  267. }
  268. func collectionView(_: UICollectionView, willDisplay _: UICollectionViewCell, forItemAt indexPath: IndexPath) {
  269. let itemData: Any = itemList[indexPath.item]
  270. if itemData is PQVoiceModel {
  271. if contentType == .page {
  272. // 卡点视频音乐音乐素材曝光
  273. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonView, objectType: .ot_view_syncedUpMusic, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: ["musicName": (itemData as? PQVoiceModel)?.musicName ?? "", "musicId": (itemData as? PQVoiceModel)?.musicId ?? ""], remindmsg: "卡点视频数据上报-(曝光上报:音乐素材曝光)")
  274. } else if contentType == .serach {
  275. // 曝光上报:搜索结果音乐素材曝光
  276. PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonView, objectType: .ot_view_searchMusic, pageSource: .sp_stuck_searchSyncedUpMusic, extParams: ["musicName": (itemData as? PQVoiceModel)?.musicName ?? "", "musicId": (itemData as? PQVoiceModel)?.musicId ?? "", "isHotMusic": itemList.first is PQEmptyModel], remindmsg: "卡点视频数据上报-(曝光上报:搜索结果音乐素材曝光)")
  277. }
  278. }
  279. }
  280. }