PQStuckPointMusicContentController.swift 18 KB

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