ShoppingCartView.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. //
  2. // ShoppingCartView.swift
  3. // RainbowPlanet
  4. //
  5. // Created by Christopher on 2019/5/8.
  6. // Copyright © 2019 RainbowPlanet. All rights reserved.
  7. // 购物车--首页View
  8. import UIKit
  9. class ShoppingCartView: BaseView {
  10. typealias ProductDidSelectRowAt = (ProductModel) -> Void
  11. var productDidSelectRowAt : ProductDidSelectRowAt?
  12. // 购物车列表ModelArr
  13. var cartListModelArr : Array<CartProductListModel>? {
  14. didSet {
  15. self.judgeAllSelectedStatus()
  16. self.refreshAccountView()
  17. self.updateAccountViewCondition()
  18. tableView.reloadData()
  19. }
  20. }
  21. // 热销ModelArr
  22. var hotSaleModelArr : Array<ProductSearchModel>? {
  23. didSet {
  24. // 预计算热销Cell行高
  25. let count = self.hotSaleModelArr?.count ?? 0
  26. let rows = count / 2 + count % 2
  27. let cSpace = 10 * (rows - 1) + 30
  28. let collectionH: CGFloat = (170 * kScaleWidth + 80) * CGFloat(rows) + CGFloat(cSpace)
  29. self.hotSaleHeight = collectionH + 39
  30. tableView.reloadData()
  31. }
  32. }
  33. // 热销Cell行高
  34. private var hotSaleHeight: CGFloat = 0
  35. // 已选商品总价
  36. private var totalPrice: Int = 0
  37. // 已选商品件数
  38. private var totalNum: Int = 0
  39. // 已选商品ModelArr
  40. private var selModelArr: Array<CartProductListModel> = []
  41. // 订单支付--次级block
  42. typealias OrderPayTransBlock = (_ selMdlArr: Array<CartProductListModel>, _ totalPrice: Int) -> Void
  43. var orderPayTransBlock : OrderPayTransBlock?
  44. // 刷新列表(数据)--次级block
  45. typealias RefreshTransBlock = () -> Void
  46. var refreshTransBlock : RefreshTransBlock?
  47. // 点击店铺跳转--次级block
  48. typealias ShopClickedTransBlock = (_ shopId: Int) -> Void
  49. var shopClickedTransBlock : ShopClickedTransBlock?
  50. override func setupViews() {
  51. self.backgroundColor = kf7f8faColor
  52. addSubview(accountView)
  53. addSubview(tableView)
  54. let emptyView = EmptyView.shared.diyCustomEmptyViewStyle2(iconStr: "page04", titleStr: "当前暂无数据")
  55. emptyView.contentViewY = kScaleValue(value: 182)
  56. tableView.ly_emptyView = emptyView
  57. tableView.ly_startLoading()
  58. self.updateAccountViewCondition()
  59. }
  60. override func setupLayouts() {
  61. accountView.snp.makeConstraints { (make) in
  62. make.left.right.bottom.equalToSuperview()
  63. make.height.equalTo(48)
  64. }
  65. tableView.snp.makeConstraints { (make) in
  66. make.top.left.right.equalToSuperview()
  67. make.bottom.equalTo(accountView.snp_top).offset(0)
  68. }
  69. }
  70. // 处理购物车结算是否显示
  71. func updateAccountViewCondition() {
  72. if cartListModelArr?.isEmpty ?? true {
  73. accountView.isHidden = true
  74. accountView.snp.remakeConstraints { (make) in
  75. make.left.right.bottom.equalToSuperview()
  76. make.height.equalTo(0)
  77. }
  78. tableView.snp.remakeConstraints { (make) in
  79. make.edges.equalToSuperview()
  80. }
  81. } else {
  82. accountView.isHidden = false
  83. accountView.snp.remakeConstraints { (make) in
  84. make.left.right.bottom.equalToSuperview()
  85. make.height.equalTo(48)
  86. }
  87. tableView.snp.remakeConstraints { (make) in
  88. make.top.left.right.equalToSuperview()
  89. make.bottom.equalTo(accountView.snp_top).offset(0)
  90. }
  91. }
  92. }
  93. lazy var accountView: ShoppingCartAccountView = {
  94. let accountView = ShoppingCartAccountView()
  95. accountView.allSelectBlock = { [weak self]
  96. (isAllSelected) in
  97. self?.productCartAllSelApi(isSel: isAllSelected)
  98. }
  99. accountView.orderPayBlock = {
  100. [weak self] in
  101. if let orderPayTransBlock = self?.orderPayTransBlock {
  102. orderPayTransBlock(self!.selModelArr, self!.totalPrice)
  103. }
  104. }
  105. return accountView
  106. }()
  107. lazy var tableView: UITableView = {
  108. let tableView = UITableView(frame: CGRect.zero, style: UITableView.Style.grouped)
  109. tableView.separatorStyle = .none
  110. tableView.backgroundColor = kf7f8faColor
  111. tableView.dataSource = self
  112. tableView.delegate = self
  113. tableView.estimatedRowHeight = self.hotSaleHeight
  114. tableView.estimatedSectionFooterHeight = 0.000001
  115. tableView.estimatedSectionHeaderHeight = 0.000001
  116. return tableView
  117. }()
  118. }
  119. // MARK: - tableView dataSource && delegate
  120. extension ShoppingCartView : UITableViewDelegate, UITableViewDataSource {
  121. func numberOfSections(in tableView: UITableView) -> Int {
  122. // 购物车列表 + 超值热卖
  123. return cartListModelArr?.isEmpty ?? true ? 2 : cartListModelArr!.count + 1
  124. }
  125. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  126. if cartListModelArr?.isEmpty ?? true {
  127. return 1
  128. } else {
  129. if section < cartListModelArr!.count {
  130. return cartListModelArr![section].productList?.isEmpty ?? true ? 0 : cartListModelArr![section].productList!.count
  131. } else {
  132. return 1
  133. }
  134. }
  135. }
  136. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  137. if cartListModelArr?.isEmpty ?? true {
  138. switch indexPath.section {
  139. case 0:
  140. // 购物车列表为空
  141. let cell = ShoppingCartListNoneItemCell.cellWith(tableView: tableView, indexPath: indexPath)
  142. return cell
  143. case 1:
  144. // 超值热卖
  145. let hotSaleCell = ShoppingCartHotSaleTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
  146. hotSaleCell.hotSaleModelArr = hotSaleModelArr
  147. hotSaleCell.layoutIfNeeded()
  148. hotSaleCell.reloadData()
  149. hotSaleCell.refreshBlock = {
  150. [weak self] in
  151. if let refreshTransBlock = self?.refreshTransBlock {
  152. refreshTransBlock()
  153. }
  154. }
  155. return hotSaleCell
  156. default:
  157. return UITableViewCell()
  158. }
  159. } else {
  160. if indexPath.section < cartListModelArr!.count {
  161. // 购物车列表Item
  162. let cell = ShoppingCartListTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
  163. cell.productMdl = cartListModelArr![indexPath.section].productList![indexPath.row]
  164. cell.productSelBlock = { [weak self]
  165. (isProductSel) in
  166. let productMdl: ProductModel = (self?.cartListModelArr![indexPath.section].productList![indexPath.row])!
  167. self?.productCartIsSelApi(pro_id: productMdl.id!, isSel: isProductSel, indexPath: indexPath)
  168. }
  169. cell.changeProductBlock = { [weak self]
  170. (productId, type) in
  171. // 最少只能减到1件商品
  172. let curAmount = self?.cartListModelArr![indexPath.section].productList![indexPath.row].amount
  173. if type == 2 && curAmount == 1 {
  174. AlertSheetView.alert(title: "确认删除商品", cancelTitle: "取消", sureTitle: "确认", cancelBlock: { (popupView, index, string) in
  175. }, confirmBlock: {
  176. [weak self] (popupView, index, string) in
  177. // 删除商品
  178. let productId = self?.cartListModelArr![indexPath.section].productList?[indexPath.row].id
  179. SwiftMoyaNetWorkServiceProduct.shared().productCartDeleteApi(id: productId ?? 0) { [weak self] (data) -> (Void) in
  180. self?.cartListModelArr![indexPath.section].productList?.remove(at: indexPath.row)
  181. tableView.deleteRows(at: [indexPath], with: .none)
  182. // 删除后商店为空,刷新table
  183. if self?.cartListModelArr![indexPath.section].productList?.isEmpty ?? true {
  184. self?.cartListModelArr?.remove(at: indexPath.section)
  185. tableView.reloadData()
  186. }
  187. }
  188. })
  189. return
  190. }
  191. // 更改数量Api
  192. SwiftMoyaNetWorkServiceProduct.shared().productCartAmountApi(id: productId, type: type, completion: { [weak self] (amountData) -> (Void) in
  193. // 1.更新数据源
  194. let cartAmountMdl = amountData as? CartAmountModel
  195. let amount = cartAmountMdl?.amount
  196. self?.cartListModelArr![indexPath.section].productList![indexPath.row].amount = amount
  197. // 2.刷新cell及合计View
  198. self?.refreshAccountView()
  199. UIView.performWithoutAnimation {
  200. tableView.reloadData()
  201. }
  202. })
  203. }
  204. return cell
  205. } else {
  206. // 超值热卖
  207. let hotSaleCell = ShoppingCartHotSaleTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
  208. hotSaleCell.frame = tableView.bounds
  209. hotSaleCell.hotSaleModelArr = hotSaleModelArr
  210. hotSaleCell.layoutIfNeeded()
  211. hotSaleCell.reloadData()
  212. hotSaleCell.refreshBlock = {
  213. [weak self] in
  214. if let refreshTransBlock = self?.refreshTransBlock {
  215. refreshTransBlock()
  216. }
  217. }
  218. return hotSaleCell
  219. }
  220. }
  221. }
  222. func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  223. if cartListModelArr?.isEmpty ?? true {
  224. switch indexPath.section {
  225. case 0:
  226. // 购物车列表为空
  227. return 302
  228. case 1:
  229. // 超值热卖
  230. return self.hotSaleHeight
  231. default:
  232. return UITableView.automaticDimension
  233. }
  234. } else {
  235. if indexPath.section < cartListModelArr!.count {
  236. // 购物车列表Item
  237. return 148
  238. } else {
  239. // 超值热卖
  240. return self.hotSaleHeight
  241. }
  242. }
  243. }
  244. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  245. if !(cartListModelArr?.isEmpty ?? true) {
  246. //跳转商品详情
  247. if indexPath.section < cartListModelArr!.count {
  248. let productMdl = (cartListModelArr?[indexPath.section].productList?[indexPath.row])!
  249. if let productDidSelectRowAt = productDidSelectRowAt {
  250. productDidSelectRowAt(productMdl)
  251. }
  252. }
  253. }
  254. }
  255. func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
  256. if cartListModelArr?.count ?? 0 > 0 && section < cartListModelArr!.count {
  257. return 58
  258. } else {
  259. return 10
  260. }
  261. }
  262. func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
  263. if cartListModelArr?.count ?? 0 > 0 && section < cartListModelArr!.count {
  264. let headerView = ShoppingCartListTableViewHeader(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 58))
  265. headerView.shopName = cartListModelArr![section].shopName
  266. headerView.isSectionSelected = self.judgeSectionSelectedStatus(section)
  267. headerView.secSelectBlock = { [weak self]
  268. (isSectionSel) in
  269. let proListMdl: CartProductListModel = (self?.cartListModelArr![section])!
  270. self?.productCartIsSelApi(shop_id: proListMdl.shopId!, isSel: isSectionSel, section: section)
  271. // self?.shopSelectedAction(isSectionSel, section: section)
  272. // self?.judgeAllSelectedStatus()
  273. // self?.refreshAccountView()
  274. }
  275. headerView.shopClickedBlock = {
  276. [weak self] in
  277. if let shopClickedTransBlock = self?.shopClickedTransBlock {
  278. shopClickedTransBlock(self!.cartListModelArr![section].shopId ?? 0)
  279. }
  280. }
  281. return headerView
  282. } else {
  283. return nil
  284. }
  285. }
  286. func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
  287. return 0.000001
  288. }
  289. func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
  290. return nil
  291. }
  292. func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
  293. // 非商品Item拦截滑动删除
  294. if cartListModelArr?.isEmpty ?? true {
  295. return false
  296. }
  297. if indexPath.section == cartListModelArr!.count {
  298. return false
  299. }
  300. return true
  301. }
  302. func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
  303. if editingStyle == .delete {
  304. // 删除商品
  305. let productId = cartListModelArr![indexPath.section].productList?[indexPath.row].id
  306. SwiftMoyaNetWorkServiceProduct.shared().productCartDeleteApi(id: productId ?? 0) { [weak self] (data) -> (Void) in
  307. self?.cartListModelArr![indexPath.section].productList?.remove(at: indexPath.row)
  308. tableView.deleteRows(at: [indexPath], with: .none)
  309. // 删除后商店为空,刷新table
  310. if self?.cartListModelArr![indexPath.section].productList?.isEmpty ?? true {
  311. self?.cartListModelArr?.remove(at: indexPath.section)
  312. tableView.reloadData()
  313. }
  314. }
  315. }
  316. }
  317. func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
  318. return "删除"
  319. }
  320. }
  321. // MARK: - 购物车逻辑处理
  322. extension ShoppingCartView {
  323. // 全选点击事件
  324. func allSelectedAction(_ isSelected: Int) {
  325. for cartProListMdl in cartListModelArr ?? [] {
  326. for productMdl in cartProListMdl.productList! {
  327. // 已售罄/下架商品不改变选中状态
  328. if productMdl.upStatus != 0 && productMdl.stock != 0 {
  329. productMdl.isSelect = isSelected
  330. }
  331. }
  332. }
  333. tableView.reloadData()
  334. }
  335. // 店铺(全选)点击事件
  336. func shopSelectedAction(_ isSelected: Int, section: Int) {
  337. let cartProListMdl: CartProductListModel = cartListModelArr![section]
  338. for productMdl in cartProListMdl.productList! {
  339. // 已售罄/下架商品不改变选中状态
  340. if productMdl.upStatus != 0 && productMdl.stock != 0 {
  341. productMdl.isSelect = isSelected
  342. }
  343. }
  344. self.tableView.reloadSections([section], with: UITableView.RowAnimation.none)
  345. self.judgeAllSelectedStatus()
  346. }
  347. // 校验Section内商品是否全选
  348. func judgeSectionSelectedStatus(_ section: Int) -> Int {
  349. let cartProListMdl: CartProductListModel = cartListModelArr![section]
  350. for productMdl in cartProListMdl.productList! {
  351. if productMdl.isSelect == 0 {
  352. return 0
  353. }
  354. }
  355. return 1
  356. }
  357. // 校验购物车内商品是否全选
  358. func judgeAllSelectedStatus() -> Void {
  359. let secCount: Int = cartListModelArr?.isEmpty ?? true ? 0 : cartListModelArr!.count
  360. for sec in 0..<secCount {
  361. let secStatus: Int = self.judgeSectionSelectedStatus(sec)
  362. if secStatus == 0 {
  363. self.accountView.isAllSelected = 0
  364. return
  365. }
  366. }
  367. self.accountView.isAllSelected = 1
  368. }
  369. // 计算结算数据,刷新结算View
  370. func refreshAccountView() {
  371. totalPrice = 0
  372. totalNum = 0
  373. selModelArr = []
  374. // 深拷贝数组
  375. for listModel in cartListModelArr! {
  376. let copyListMdl: CartProductListModel = listModel.copy() as! CartProductListModel
  377. selModelArr.append(copyListMdl)
  378. }
  379. for (secIdx, cartProListMdl) in (cartListModelArr?.enumerated())! {
  380. var subTag: Int = 0
  381. for (rowIdx, productMdl) in cartProListMdl.productList!.enumerated() {
  382. if productMdl.isSelect == 1 {
  383. totalPrice += productMdl.skuPrice! * productMdl.amount!
  384. totalNum += 1
  385. } else {
  386. if !cartListModelArr![secIdx].productList!.isEmpty {
  387. selModelArr[secIdx].productList!.remove(at: rowIdx-subTag)
  388. subTag += 1
  389. }
  390. }
  391. }
  392. }
  393. self.accountView.tPrice = totalPrice
  394. self.accountView.tNumber = totalNum
  395. }
  396. // 选中单个商品
  397. func productCartIsSelApi(pro_id:Int = 0, isSel:Int, indexPath:IndexPath) {
  398. SwiftMoyaNetWorkServiceProduct.shared().productCartIsSelApi(id: pro_id, shop_id: 0, isSelect: isSel) { (data) -> (Void) in
  399. self.cartListModelArr![indexPath.section].productList![indexPath.row].isSelect = isSel
  400. self.tableView.reloadSections([indexPath.section], with: UITableView.RowAnimation.none)
  401. self.judgeAllSelectedStatus()
  402. self.refreshAccountView()
  403. }
  404. }
  405. // 选中section内商品
  406. func productCartIsSelApi(shop_id:Int = 0, isSel:Int, section:Int) {
  407. SwiftMoyaNetWorkServiceProduct.shared().productCartIsSelApi(id: 0, shop_id: shop_id, isSelect: isSel) { (data) -> (Void) in
  408. self.shopSelectedAction(isSel, section: section)
  409. self.judgeAllSelectedStatus()
  410. self.refreshAccountView()
  411. }
  412. }
  413. // 全选商品
  414. func productCartAllSelApi(isSel:Int) {
  415. SwiftMoyaNetWorkServiceProduct.shared().productCartAllSelApi(isSelect: isSel) { (data) -> (Void) in
  416. self.allSelectedAction(isSel)
  417. self.refreshAccountView()
  418. }
  419. }
  420. }