南鑫林 6 jaren geleden
bovenliggende
commit
22f2299822

+ 18 - 0
RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj

@@ -41,6 +41,8 @@
 		A70B2C732289019200B2449F /* ProductDetailSkuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A70B2C722289019200B2449F /* ProductDetailSkuView.swift */; };
 		A70B2C75228920BA00B2449F /* ProductDetailSkuSectionHeaerCollectionReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A70B2C74228920BA00B2449F /* ProductDetailSkuSectionHeaerCollectionReusableView.swift */; };
 		A70EBBC022561179000AD74F /* Extension+UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A70EBBBF22561179000AD74F /* Extension+UITableView.swift */; };
+		A7146349228EFCE20066099B /* ORSKUDataFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = A7146347228EFCE20066099B /* ORSKUDataFilter.m */; };
+		A714634E228F020A0066099B /* ORSKUDataFilterSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = A714634D228F020A0066099B /* ORSKUDataFilterSwift.swift */; };
 		A71738A622897892000AEA6A /* SwiftMoyaServiceShopApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71738A522897892000AEA6A /* SwiftMoyaServiceShopApi.swift */; };
 		A71738A822897E96000AEA6A /* SwiftMoyaNetWorkServiceShop.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71738A722897E96000AEA6A /* SwiftMoyaNetWorkServiceShop.swift */; };
 		A71738AB22898660000AEA6A /* ShopModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71738AA22898660000AEA6A /* ShopModel.swift */; };
@@ -413,6 +415,9 @@
 		A70B2C722289019200B2449F /* ProductDetailSkuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailSkuView.swift; sourceTree = "<group>"; };
 		A70B2C74228920BA00B2449F /* ProductDetailSkuSectionHeaerCollectionReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailSkuSectionHeaerCollectionReusableView.swift; sourceTree = "<group>"; };
 		A70EBBBF22561179000AD74F /* Extension+UITableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+UITableView.swift"; sourceTree = "<group>"; };
+		A7146347228EFCE20066099B /* ORSKUDataFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSKUDataFilter.m; sourceTree = "<group>"; };
+		A7146348228EFCE20066099B /* ORSKUDataFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSKUDataFilter.h; sourceTree = "<group>"; };
+		A714634D228F020A0066099B /* ORSKUDataFilterSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORSKUDataFilterSwift.swift; sourceTree = "<group>"; };
 		A71738A522897892000AEA6A /* SwiftMoyaServiceShopApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMoyaServiceShopApi.swift; sourceTree = "<group>"; };
 		A71738A722897E96000AEA6A /* SwiftMoyaNetWorkServiceShop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMoyaNetWorkServiceShop.swift; sourceTree = "<group>"; };
 		A71738AA22898660000AEA6A /* ShopModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShopModel.swift; sourceTree = "<group>"; };
@@ -1057,6 +1062,16 @@
 			path = ProductDetailSkuView;
 			sourceTree = "<group>";
 		};
+		A7146346228EFCE20066099B /* SKUDataFilter */ = {
+			isa = PBXGroup;
+			children = (
+				A7146348228EFCE20066099B /* ORSKUDataFilter.h */,
+				A7146347228EFCE20066099B /* ORSKUDataFilter.m */,
+				A714634D228F020A0066099B /* ORSKUDataFilterSwift.swift */,
+			);
+			path = SKUDataFilter;
+			sourceTree = "<group>";
+		};
 		A71738A42289787C000AEA6A /* SwiftMoyaServiceShop */ = {
 			isa = PBXGroup;
 			children = (
@@ -2110,6 +2125,7 @@
 		A77F2CBC2232022A001BD3F6 /* Tools */ = {
 			isa = PBXGroup;
 			children = (
+				A7146346228EFCE20066099B /* SKUDataFilter */,
 				A7274C51228EE635000E3A07 /* SwiftScan */,
 				A7274C4E228EE5EF000E3A07 /* PhotoAndCameraManager */,
 				A70B2C232286C03800B2449F /* NXLPageControl */,
@@ -3464,6 +3480,7 @@
 				A7CC752F2271A1F2003C4F38 /* SetPasswordView.swift in Sources */,
 				A7A98E09227EB8DD005306E9 /* CategoryView.swift in Sources */,
 				A7CC75362271AC14003C4F38 /* AddressManagerView.swift in Sources */,
+				A7146349228EFCE20066099B /* ORSKUDataFilter.m in Sources */,
 				BDF8629C228E4125000DEF84 /* OrderCommentController.swift in Sources */,
 				A7B4E75A228289BB0012914A /* ProductFloorCenterHeaderCollectionReusableView.swift in Sources */,
 				A71901752275F71F00104A50 /* BaiduToCityModel.swift in Sources */,
@@ -3565,6 +3582,7 @@
 				A7284440224DFACD00F82F30 /* InfoModel.swift in Sources */,
 				A72A72B522321DE000B21995 /* Extension+UITextView.swift in Sources */,
 				BDF47D822282B3D100941AB9 /* ShoppingCartHotSaleTableViewCell.swift in Sources */,
+				A714634E228F020A0066099B /* ORSKUDataFilterSwift.swift in Sources */,
 				BD20F1CB2283C12000677D8E /* ShoppingCartListNoneItemCell.swift in Sources */,
 				A7B4E756228281620012914A /* ShoppingMallSlidingLeftRightBgCollectionViewCell.swift in Sources */,
 				A757C92E22744ACE00226355 /* AddressManagerListModel.swift in Sources */,

+ 2 - 0
RainbowPlanet/RainbowPlanet/Macro/RainbowPlanet-Bridging-Header.h

@@ -21,6 +21,8 @@
 //空白页面占位图
 #import <LYEmptyView/LYEmptyViewHeader.h>
 
+#import "ORSKUDataFilter.h"
+
 #import "FMDB.h"
 
 //友盟

+ 29 - 28
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ProductAllComment/View/ProductAllCommentView.swift

@@ -23,11 +23,11 @@ class ProductAllCommentView: BaseView {
 
     
     override func setupViews() {
-        addSubview(bottomBgView)
-        bottomBgView.addSubview(cartButton)
-        cartButton.addSubview(cartImageView)
-        bottomBgView.addSubview(addCartButton)
-        bottomBgView.addSubview(buyButton)
+//        addSubview(bottomBgView)
+//        bottomBgView.addSubview(cartButton)
+//        cartButton.addSubview(cartImageView)
+//        bottomBgView.addSubview(addCartButton)
+//        bottomBgView.addSubview(buyButton)
         addSubview(tableView)
         let emptyView =  EmptyView.shared.diyCustomEmptyViewStyle2(iconStr: "page04", titleStr: "当前暂无数据")
         emptyView.contentViewY = kScaleValue(value: 182)
@@ -35,31 +35,32 @@ class ProductAllCommentView: BaseView {
     }
     
     override func setupLayouts() {
-        bottomBgView.snp.makeConstraints { (make) in
-            make.left.bottom.right.equalToSuperview()
-            make.height.equalTo(50 + kSafeTabBarHeight)
-        }
-        cartButton.snp.makeConstraints { (make) in
-            make.top.left.equalToSuperview()
-            make.width.equalTo(71 * kScaleWidth)
-            make.bottom.equalTo(-kSafeTabBarHeight)
-        }
-        cartImageView.snp.makeConstraints { (make) in
-            make.center.equalToSuperview()
-        }
-        addCartButton.snp.makeConstraints { (make) in
-            make.left.equalTo(cartButton.snp.right)
-            make.top.bottom.equalTo(cartButton)
-            make.width.equalTo(152 * kScaleWidth)
-        }
-        buyButton.snp.makeConstraints { (make) in
-            make.left.equalTo(addCartButton.snp.right)
-            make.top.bottom.equalTo(cartButton)
-            make.width.equalTo(152 * kScaleWidth)
-        }
+//        bottomBgView.snp.makeConstraints { (make) in
+//            make.left.bottom.right.equalToSuperview()
+//            make.height.equalTo(50 + kSafeTabBarHeight)
+//        }
+//        cartButton.snp.makeConstraints { (make) in
+//            make.top.left.equalToSuperview()
+//            make.width.equalTo(71 * kScaleWidth)
+//            make.bottom.equalTo(-kSafeTabBarHeight)
+//        }
+//        cartImageView.snp.makeConstraints { (make) in
+//            make.center.equalToSuperview()
+//        }
+//        addCartButton.snp.makeConstraints { (make) in
+//            make.left.equalTo(cartButton.snp.right)
+//            make.top.bottom.equalTo(cartButton)
+//            make.width.equalTo(152 * kScaleWidth)
+//        }
+//        buyButton.snp.makeConstraints { (make) in
+//            make.left.equalTo(addCartButton.snp.right)
+//            make.top.bottom.equalTo(cartButton)
+//            make.width.equalTo(152 * kScaleWidth)
+//        }
         tableView.snp.makeConstraints { (make) in
             make.top.left.right.equalToSuperview()
-            make.bottom.equalTo(bottomBgView.snp.top)
+//            make.bottom.equalTo(bottomBgView.snp.top)
+            make.bottom.equalTo(0)
         }
     }
     

+ 25 - 27
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ProductDetail/View/Cell/ProductDetailProductSku/ProductDetailProductSkuLabelCollectionViewCell.swift

@@ -56,48 +56,46 @@ class ProductDetailProductSkuLabelCollectionViewCell: UICollectionViewCell {
         return titleLabel
     }()
     
-//    var skuModelMainkey : String? {
-//        didSet {
-//            
-//        }
-//    }
     
     var productDetailSpecValueModel: ProductDetailSpecValueModel? {
         didSet {
             titleLabel.text = productDetailSpecValueModel?.value
-            if productDetailSkuModels?.isEmpty ?? true {
+        }
+    }
+    
+    var filter: ORSKUDataFilter? {
+        didSet {
+            if (filter?.availableIndexPathsSet.contains(indexPath!))! {
                 self.backgroundColor = kf5f5f5Color
                 self.layer.cornerRadius = 4
                 self.layer.masksToBounds = true
                 self.layer.borderColor = kf5f5f5Color.cgColor
                 self.layer.borderWidth = 1
-                titleLabel.textColor = k666666Color
-                
+                titleLabel.textColor = k333333Color
             }else {
-                for productDetailSkuModel in productDetailSkuModels! {
-                    if  (productDetailSkuModel.key ?? "").contains("\(productDetailSpecValueModel?.id ?? 0)"){
-                        self.backgroundColor = kf5f5f5Color
-                        self.layer.cornerRadius = 4
-                        self.layer.masksToBounds = true
-                        self.layer.borderColor = kf5f5f5Color.cgColor
-                        self.layer.borderWidth = 1
-                        titleLabel.textColor = k333333Color
-                    }else {
-                        self.backgroundColor = kf5f5f5Color
-                        self.layer.cornerRadius = 4
-                        self.layer.masksToBounds = true
-                        self.layer.borderColor = kf5f5f5Color.cgColor
-                        self.layer.borderWidth = 1
-                        titleLabel.textColor = k999999Color
-                    }
-                }
+
+                self.backgroundColor = kf5f5f5Color
+                self.layer.cornerRadius = 4
+                self.layer.masksToBounds = true
+                self.layer.borderColor = kf5f5f5Color.cgColor
+                self.layer.borderWidth = 1
+                titleLabel.textColor = k999999Color
+            }
+            
+            if (filter?.selectedIndexPaths.contains(indexPath!))! {
+                self.backgroundColor =  kffffffColor
+                self.layer.cornerRadius = 4
+                self.layer.masksToBounds = true
+                self.layer.borderColor = kFFA42FColor.cgColor
+                self.layer.borderWidth = 1
+                titleLabel.textColor = kFFA42FColor
             }
         }
     }
     
-    var productDetailSkuModels : [ProductDetailSkuModel]? {
+    var text : String? {
         didSet {
-            
+            titleLabel.text = text
         }
     }
 }

+ 98 - 94
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ProductDetail/View/ProductDetailSkuView/ProductDetailSkuView.swift

@@ -12,14 +12,42 @@ import RxSwift
 import RxCocoa
 
 class ProductDetailSkuView: FWPopupView {
-    
-    let disposeBag = DisposeBag()
+    var dataSource = [
+        [
+            "name": "重量",
+            "value": ["3","5"],
+            "i": 6,
+        ],
+        [
+            "name": "大小",
+            "value": ["6", "7", "8"],
+            "i": 7,
+        ],
+    ]
+
+    var skuData = [
+    [
+    "contition": "3_6",
+    "price": "1120",
+    "store": "167"
+    ],
+    [
+    "contition": "3_7",
+    "price": "1200",
+    "store": "289"
+    ],
+    [
+    "contition": "5_8",
+    "price": "889",
+    "store": "300"
+    ]
+    ]
+
     
     
+    let disposeBag = DisposeBag()
     override init(frame: CGRect) {
         super.init(frame: frame)
-        setupViews()
-        setupLayouts()
     }
     
     required init?(coder aDecoder: NSCoder) {
@@ -28,7 +56,6 @@ class ProductDetailSkuView: FWPopupView {
     
     private func setupViews() {
        
-        
         addSubview(topBgView)
         topBgView.addSubview(productImageView)
         topBgView.addSubview(priceLabel)
@@ -255,19 +282,6 @@ class ProductDetailSkuView: FWPopupView {
         plusButton.contentHorizontalAlignment = .center
         plusButton.rx.tap.subscribe(onNext: {
              [weak self](data) in
-            
-            if self?.productDetailModel?.limitNumber ?? 0 > 0 {
-                
-                if self?.productCount ?? 1 <= self?.productDetailModel?.limitNumber ?? 0 && self?.productCount ?? 1 < self?.productDetailSkuModel?.stock ?? 0 {
-                    self?.productCount += 1
-                    self?.numberLabel.text = "\(self?.productCount ?? 0)"
-                }else {
-                    SwiftProgressHUD.shared().showText("该数量已超库存数量",view: self!)
-                }
-            }else {
-                self?.productCount += 1
-                self?.numberLabel.text = "\(self?.productCount ?? 0)"
-            }
         }).disposed(by: disposeBag)
         return plusButton
     }()
@@ -281,12 +295,6 @@ class ProductDetailSkuView: FWPopupView {
         reduceButton.contentHorizontalAlignment = .center
         reduceButton.rx.tap.subscribe(onNext: {
             [weak self] (data) in
-            if self?.productCount ?? 1 <= 1 {
-                SwiftProgressHUD.shared().showText("该数量已是最低数量",view: self!)
-            }else {
-                self?.productCount -= 1
-                self?.numberLabel.text = "\(self?.productCount ?? 0)"
-            }
         }).disposed(by: disposeBag)
         return reduceButton
     }()
@@ -319,6 +327,8 @@ class ProductDetailSkuView: FWPopupView {
         sureButton.backgroundColor = kFFA42FColor
         sureButton.setTitle("确  认", for: UIControl.State.normal)
         sureButton.setTitleColor(UIColor.white, for: UIControl.State.normal)
+        sureButton.setTitleColor(k666666Color, for: UIControl.State.disabled)
+
         sureButton.titleLabel?.font = kRegularFont16
         return sureButton
     }()
@@ -332,45 +342,33 @@ class ProductDetailSkuView: FWPopupView {
     
     var productDetailModel : ProductDetailModel? {
         didSet {
+            filter = ORSKUDataFilter.init(dataSource: self)
+            setupViews()
+            setupLayouts()
+            filter!.needDefaultValue = true
+            self.collectionView.reloadData()
+            actionComplete()
             productImageView.kf.setImage(with: kURLImage(name: productDetailModel?.img ?? "pic_preload")
                 , placeholder: kImage(name: "pic_preload"))
-            if !(productDetailModel?.sku?.isEmpty ?? true) {
-                for skuModel in (productDetailModel?.sku)! {
-                    if skuModel.isMain == 1 {
-                        priceLabel.text = "¥\(skuModel.price ?? 0)"
-                        stockLabel.text = "库存\(skuModel.stock ?? 0)件"
-                        if productDetailModel?.limitNumber ?? 0 > 0 {
-                            limitLabel.text = "(每人限购\(productDetailModel?.limitNumber ?? 0)件)"
-                            limitLabel.isHidden = false
-                        }else {
-                            limitLabel.isHidden = true
-                        }
-                        if !(productDetailModel?.spec?.isEmpty ?? true) {
-                            skuIdArray = Array<String>.init(repeating: "", count: productDetailModel?.spec?.count ?? 0)
-                            skuIdArray = skuModelMainkey.components(separatedBy: "_")
-                        }
-                        skuModelMainkey = skuModel.key ?? ""
-                        productDetailSkuModel = skuModel
-                    }
-                }
-            }
         }
     }
     
-//    func observableString() {
-//        Observable.combineLatest(Observable.just(productCount),Observable.just(productCount)) {
-//             [weak self] (textValue,textValue1) -> Bool in
-//            let textValue = textValue as Int
-//            if textValue > self?.productDetailSkuModel?.stock ?? 0  {
-//                    return false
-//                }else {
-//                    return true
-//                }
-//            }.subscribe(onNext: {
-//                [weak self] isEmpty in
-//                self?.sureButton.isEnabled = isEmpty
-//            }).disposed(by: self.disposeBag)
-//    }
+    func actionComplete() {
+         let  productDetailSkuModel = filter?.currentResult as? ProductDetailSkuModel
+        if productDetailSkuModel != nil {
+            priceLabel.text = "¥\(productDetailSkuModel!.price ?? 0)"
+            stockLabel.text = "库存\(productDetailSkuModel!.stock ?? 0)件"
+            sureButton.isEnabled = true
+        }else {
+            sureButton.isEnabled = false
+        }
+       
+    }
+    
+    var selectedIndexPaths = Array<Any>()
+    
+    var filter : ORSKUDataFilter?
+    
     
     static func productDetailSkuView(productDetailModel : ProductDetailModel) {
         let view = ProductDetailSkuView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: kScreenHeight - 76 - kNavBarTotalHeight))
@@ -402,49 +400,18 @@ extension ProductDetailSkuView: UICollectionViewDelegateFlowLayout,UICollectionV
     
     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
         let cell = ProductDetailProductSkuLabelCollectionViewCell.cellWith(collectionView: collectionView, indexPath: indexPath)
-//        cell.skuModelMainkey = skuModelMainkey
-        cell.productDetailSkuModels = productDetailModel?.sku
         cell.productDetailSpecValueModel = (productDetailModel?.spec?[indexPath.section].value?[indexPath.row])!
+        cell.filter = filter
 
         return cell
         
     }
     
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        let cell = collectionView.cellForItem(at: indexPath) as! ProductDetailProductSkuLabelCollectionViewCell
-        
-//        var tempSkuIdArray = skuIdArray
-//        var tempSkuModelMainkey = skuModelMainkey
-//        tempSkuIdArray![indexPath.section] = "\(cell.productDetailSpecValueModel?.id ?? 0)"
-//        tempSkuModelMainkey = (tempSkuIdArray?.joined(separator: "_"))!
-//
-//        for skuModel in (productDetailModel?.sku)! {
-//            if skuModel.key == skuModelMainkey {
-//                skuIdArray?.removeAll()
-//                skuIdArray = tempSkuIdArray
-//                skuModelMainkey = tempSkuModelMainkey
-//                productDetailSkuModel = skuModel
-//                priceLabel.text = "¥\(skuModel.price ?? 0)"
-//                stockLabel.text = "库存\(skuModel.stock ?? 0)件"
-//
-////                if self.productCount > skuModel.stock ?? 0 {
-////                    if skuModel.stock == 0 {
-////                        numberLabel.text = "1"
-////                    }else {
-////                        numberLabel.text = "\(skuModel.stock ?? 0)"
-////                    }
-////                }else{
-////                    if skuModel.stock == 0 {
-////                        numberLabel.text = "1"
-////                    }else {
-////                        numberLabel.text = "\(self.productCount)"
-////                    }
-////                }
-//                collectionView.reloadSections([indexPath.section])
-//            }else {
-//                SwiftProgressHUD.shared().showText("暂时没有该规格的商品",view: self)
-//            }
-//        }
+        filter!.didSelectedProperty(with: indexPath)
+        collectionView.reloadData()
+        actionComplete()
+
     }
     
     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
@@ -466,3 +433,40 @@ extension ProductDetailSkuView: UICollectionViewDelegateFlowLayout,UICollectionV
     }
     
 }
+
+extension ProductDetailSkuView: ORSKUDataFilterDataSource {
+    
+    
+    func numberOfSectionsForProperties(in filter: ORSKUDataFilter!) -> Int {
+        return  (self.productDetailModel?.spec?.count)!
+    }
+    
+    func filter(_ filter: ORSKUDataFilter!, propertiesInSection section: Int) -> [Any]! {
+        return self.productDetailModel?.spec?[section].value!
+    }
+    
+    func numberOfConditions(in filter: ORSKUDataFilter!) -> Int {
+        return (self.productDetailModel?.sku!.count)!
+    }
+    func filter(_ filter: ORSKUDataFilter!, conditionForRow row: Int) -> [Any]! {
+        let key = self.productDetailModel?.sku?[row].key
+        let keys = key?.components(separatedBy: "_")
+        var deystrs = Array<ProductDetailSpecValueModel>()
+       
+        for key in keys! {
+            for specs in self.productDetailModel!.spec! {
+                for spec in specs.value! {
+                    if spec.id == Int(key) {
+                        deystrs.append(spec)
+                    }
+                }
+            }
+        }
+        return deystrs
+    }
+    
+    func filter(_ filter: ORSKUDataFilter!, resultOfConditionForRow row: Int) -> Any! {
+        return self.productDetailModel?.sku?[row]
+    }
+}
+

+ 2 - 2
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ProductDetail/View/ProductDetailView.swift

@@ -54,13 +54,13 @@ class ProductDetailView: BaseView {
     
     var productSearchListModel: ProductSearchListModel? {
         didSet {
-            tableView.reloadSections([4], with: UITableView.RowAnimation.none)
+            tableView.reloadData()
         }
     }
     
     var productCommentListModel :ProductCommentListModel? {
         didSet {
-            tableView.reloadSections([2], with: UITableView.RowAnimation.none)
+            tableView.reloadData()
         }
     }
     

+ 2 - 2
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ProductDetail/ViewController/ProductDetailViewController.swift

@@ -22,9 +22,9 @@ class ProductDetailViewController: BaseViewController {
 
     override func viewDidLoad() {
         super.viewDidLoad()
+        setupData()
         setupViews()
         setupLayouts()
-        setupData()
     }
     
     override func setupViews() {
@@ -50,7 +50,7 @@ class ProductDetailViewController: BaseViewController {
             [weak self] (page) in
             self?.productDetailApi()
             self?.productListApi()
-//            self?.productCommentListApi()
+            self?.productCommentListApi()
         }
         
         observe = NotificationCenter.default.addObserver(forName: NSNotification.Name("ProductDetailView"), object: nil, queue: OperationQueue.main) {[weak self] (notification) in

+ 130 - 0
RainbowPlanet/RainbowPlanet/Tools/SKUDataFilter/ORSKUDataFilter.h

@@ -0,0 +1,130 @@
+//
+//  ORSKUDataFilter.h
+//  SKUFilterfilter
+//
+//  Created by OrangesAL on 2017/12/3.
+//  Copyright © 2017年 OrangesAL. All rights reserved.
+//
+
+/* Tips:
+ *
+ *  ----------------- warning -----------------
+ *  使用注意
+ 1、虽然SKUDataFilter不关心具体的值,但是条件式本质是由属性组成,故代理方法filter:propertiesInSection:和方法filter:conditionForRow:数据类型应该保持一致
+ 2、因为SKUDataFilter关心的是属性的坐标,那么在代理方法传值的时候,代理方法filter:propertiesInSection:和方法filter:conditionForRow:各自的数据顺序要保持一致 并且两个方法的数据也要对应
+ 
+ 实际项目中,这两种情况发生的概率都非常小,因为 第一数据统一返回统一解析,格式99%都是一样。第二数据是从服务器返回,服务器的数据要进行筛选和过滤,顺序也不能弄错,一旦错误,首先服务器就会出问题
+ *
+ *
+ *
+ *  ----------------- indexPath -----------------
+ *
+ *  indexPath记录属性的位置坐标
+ *  表示为 第section 种属性类下面的 第item个 属性 (从0计数)
+ *
+ *  例:
+ *
+ *  颜色: r g
+ *  尺寸: s m l
+ *
+ *  属性m 表示为 secton : 1, item : 1
+ *
+ *  ----------------- conditionIndexs -----------------
+ *
+ *  条件式(符合条件的属性组合-在商品中表示有库存,可售等)
+ *  conditionIndex 是本filter对属性管理的关键
+ *
+ *  condition (r,s)
+ *  使用 conditionIndex 用属性下标表示则为 (0,0)
+ *
+ *  conditionIndex 通过它本身的值(即为属性的Item)和下标(即为属性的section) 可以查询任何一个属性的indexPath
+ 
+ *  ----------------- links -----------------
+ *
+ *  github: https://github.com/SunriseOYR/SKUDataFilter
+ *  bigo: https://www.jianshu.com/p/295737e2ac77
+ */
+
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@class ORSKUDataFilter;
+@class ORSKUProperty;
+
+@protocol ORSKUDataFilterDataSource <NSObject>
+
+@required
+
+//属性种类个数
+- (NSInteger)numberOfSectionsForPropertiesInFilter:(ORSKUDataFilter *)filter;
+
+/*
+ * 每个种类所有的的属性值
+ * 这里不关心具体的值,可以是属性ID, 属性名,字典、model
+ */
+- (NSArray *)filter:(ORSKUDataFilter *)filter propertiesInSection:(NSInteger)section;
+
+//满足条件 的 个数
+- (NSInteger)numberOfConditionsInFilter:(ORSKUDataFilter *)filter;
+
+/*
+ * 对应的条件式
+ * 这里条件式的属性值,需要和propertiesInSection里面的数据类型保持一致
+ */
+- (NSArray *)filter:(ORSKUDataFilter *)filter conditionForRow:(NSInteger)row;
+
+//条件式 对应的 结果数据(库存、价格等)
+- (id)filter:(ORSKUDataFilter *)filter resultOfConditionForRow:(NSInteger)row;
+
+@end
+
+@interface ORSKUDataFilter : NSObject
+
+@property (nonatomic, assign) id<ORSKUDataFilterDataSource> dataSource;
+
+//当前 选中的属性indexPath
+@property (nonatomic, strong, readonly) NSArray <NSIndexPath *> *selectedIndexPaths;
+//当前 可选的属性indexPath
+@property (nonatomic, strong, readonly) NSSet <NSIndexPath *> *availableIndexPathsSet;
+//当前 结果
+@property (nonatomic, strong, readonly) id  currentResult;
+
+@property (nonatomic, assign) BOOL needDefaultValue;
+
+//init
+- (instancetype)initWithDataSource:(id<ORSKUDataFilterDataSource>)dataSource;
+
+- (instancetype)init UNAVAILABLE_ATTRIBUTE;
++ (instancetype)new UNAVAILABLE_ATTRIBUTE;
+
+
+//选中 属性的时候 调用
+- (void)didSelectedPropertyWithIndexPath:(NSIndexPath *)indexPath;
+
+//重新加载数据
+- (void)reloadData;
+
+
+@end
+
+
+@interface ORSKUCondition :NSObject
+
+@property (nonatomic, strong) NSArray<ORSKUProperty *> *properties;
+
+@property (nonatomic, strong, readonly) NSArray<NSNumber *> *conditionIndexs;
+
+@property (nonatomic, strong) id result;
+
+@end
+
+@interface ORSKUProperty :NSObject
+
+@property (nonatomic, copy, readonly) NSIndexPath * indexPath;
+@property (nonatomic, copy, readonly) id value;
+
+- (instancetype)initWithValue:(id)value indexPath:(NSIndexPath *)indexPath;
+
+@end
+

+ 376 - 0
RainbowPlanet/RainbowPlanet/Tools/SKUDataFilter/ORSKUDataFilter.m

@@ -0,0 +1,376 @@
+//
+//  ORSKUDataFilter.m
+//  SKUFilterfilter
+//
+//  Created by OrangesAL on 2017/12/3.
+//  Copyright © 2017年 OrangesAL. All rights reserved.
+//
+
+#import "ORSKUDataFilter.h"
+
+@interface ORSKUDataFilter() {
+    ORSKUCondition *_defaultSku;
+}
+
+@property (nonatomic, strong) NSSet <ORSKUCondition *> *conditions;
+
+@property (nonatomic, strong) NSMutableArray <NSIndexPath *> *selectedIndexPaths;
+
+@property (nonatomic, strong) NSMutableSet <NSIndexPath *> *availableIndexPathsSet;
+
+//全可用的
+@property (nonatomic, strong) NSSet <NSIndexPath *> *allAvailableIndexPaths;
+
+@property (nonatomic, strong) id  currentResult;
+
+@end
+
+@implementation ORSKUDataFilter
+
+- (instancetype)initWithDataSource:(id<ORSKUDataFilterDataSource>)dataSource
+{
+    self = [super init];
+    if (self) {
+        _dataSource = dataSource;
+        _selectedIndexPaths = [NSMutableArray array];
+        [self initPropertiesSkuListData];
+    }
+    return self;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        _selectedIndexPaths = [NSMutableArray array];
+    }
+    return self;
+}
+
+- (void)reloadData {
+    [_selectedIndexPaths removeAllObjects];
+    _defaultSku = nil;
+    [self initPropertiesSkuListData];
+    [self updateCurrentResult];
+}
+
+#pragma mark -- public method
+//选中某个属性
+- (void)didSelectedPropertyWithIndexPath:(NSIndexPath *)indexPath {
+    
+    if (![_availableIndexPathsSet containsObject:indexPath]) {
+        //不可选
+        return;
+    }
+    
+    if (indexPath.section > [_dataSource numberOfSectionsForPropertiesInFilter:self] || indexPath.item >= [[_dataSource filter:self propertiesInSection:indexPath.section] count]) {
+        //越界
+        NSLog(@"indexPath is out of range");
+        return;
+    }
+    
+    if ([_selectedIndexPaths containsObject:indexPath]) {
+        //已被选
+        [_selectedIndexPaths removeObject:indexPath];
+        
+        [self updateAvailableIndexPaths];
+        [self updateCurrentResult];
+        return;
+    }
+    
+    __block NSIndexPath *lastIndexPath = nil;
+    
+    [_selectedIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        if (indexPath.section == obj.section) {
+            lastIndexPath = obj;
+        }
+    }];
+    
+    if (!lastIndexPath) {
+        //添加新属性
+        [_selectedIndexPaths addObject:indexPath];
+        [_availableIndexPathsSet intersectSet:[self availableIndexPathsFromSelctedIndexPath:indexPath sectedIndexPaths:_selectedIndexPaths]];
+        [self updateCurrentResult];
+        return;
+    }
+    
+    if (lastIndexPath.item != indexPath.item) {
+        //切换属性
+        [_selectedIndexPaths addObject:indexPath];
+        [_selectedIndexPaths removeObject:lastIndexPath];
+        [self updateAvailableIndexPaths];
+        [self updateCurrentResult];
+    }
+    
+}
+
+
+#pragma mark -- private method
+
+//获取初始数据
+- (void)initPropertiesSkuListData {
+    
+    NSMutableSet *modelSet = [NSMutableSet set];
+
+    for (int i = 0; i < [_dataSource numberOfConditionsInFilter:self]; i ++) {
+        
+        ORSKUCondition *model = [ORSKUCondition new];
+        NSArray * conditions = [_dataSource filter:self conditionForRow:i];
+        
+        if (![self checkConformToSkuConditions:conditions]) {
+            NSLog(@"第 %d 个 condition 不完整 \n %@", i, conditions);
+            continue;
+        }
+        
+        model.properties = [self propertiesWithConditionRawData:conditions];
+        model.result = [_dataSource filter:self resultOfConditionForRow:i];
+        
+        if (self.selectedIndexPaths.count == 0 && _needDefaultValue && !_defaultSku) {
+            _defaultSku = model;
+        }
+        
+        [modelSet addObject:model];
+    }
+    _conditions = [modelSet copy];
+    
+    [self getAllAvailableIndexPaths];
+    
+    if (_defaultSku) {
+        [_defaultSku.properties enumerateObjectsUsingBlock:^(ORSKUProperty * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+            [self didSelectedPropertyWithIndexPath:obj.indexPath];
+        }];
+    }
+}
+
+//检查数据是否正确
+- (BOOL)checkConformToSkuConditions:(NSArray *)conditions {
+    if (conditions.count != [_dataSource numberOfSectionsForPropertiesInFilter:self]) {
+        return NO;
+    }
+    
+    __block BOOL  flag = YES;
+    [conditions enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        NSArray *properties = [self.dataSource filter:self propertiesInSection:idx];
+        if (![properties containsObject:obj]) {
+            flag = NO;
+            *stop = YES;
+        }
+    }];
+    return flag;
+}
+
+//获取属性
+- (NSArray<ORSKUProperty *> *)propertiesWithConditionRawData:(NSArray *)data {
+    
+    NSMutableArray *array = [NSMutableArray array];
+    [data enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        [array addObject:[self propertyOfValue:obj inSection:idx]];
+    }];
+    
+    return array;
+}
+
+- (ORSKUProperty *)propertyOfValue:(id)value inSection:(NSInteger)section {
+    
+    NSArray *properties = [_dataSource filter:self propertiesInSection:section];
+    
+    NSString *str = [NSString stringWithFormat:@"Properties for %ld dosen‘t exist %@", (long)section, value];
+    NSAssert([properties containsObject:value], str);
+    
+    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[properties indexOfObject:value] inSection:section];
+    
+    return [[ORSKUProperty alloc] initWithValue:value indexPath:indexPath];
+}
+
+//获取条件式 对应 的数据
+- (id)skuResultWithConditionIndexs:(NSArray<NSNumber *> *)conditionIndexs {
+    
+    __block id result = nil;
+    
+    [_conditions enumerateObjectsUsingBlock:^(ORSKUCondition * _Nonnull obj, BOOL * _Nonnull stop) {
+        
+        if ([obj.conditionIndexs isEqual:conditionIndexs]) {
+            result = obj.result;
+            *stop = YES;
+        }
+    }];
+    
+    return result;
+}
+
+//获取初始可选的所有IndexPath
+- (NSMutableSet<NSIndexPath *> *)getAllAvailableIndexPaths {
+
+    NSMutableSet *set = [NSMutableSet set];
+    [_conditions enumerateObjectsUsingBlock:^(ORSKUCondition * _Nonnull obj, BOOL * _Nonnull stop) {
+        [obj.conditionIndexs enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj1, NSUInteger idx1, BOOL * _Nonnull stop1) {
+            [set addObject:[NSIndexPath indexPathForItem:obj1.integerValue inSection:idx1]];
+        }];
+    }];
+    
+    _availableIndexPathsSet = set;
+    
+    _allAvailableIndexPaths = [set copy];
+    
+    return set;
+}
+
+//选中某个属性时 根据已选中的系列属性 获取可选的IndexPath
+- (NSMutableSet<NSIndexPath *> *)availableIndexPathsFromSelctedIndexPath:(NSIndexPath *)selectedIndexPath sectedIndexPaths:(NSArray<NSIndexPath *> *)indexPaths{
+    
+    NSMutableSet *set = [NSMutableSet set];
+    [_conditions enumerateObjectsUsingBlock:^(ORSKUCondition * _Nonnull obj, BOOL * _Nonnull stop) {
+        if ([obj.conditionIndexs objectAtIndex:selectedIndexPath.section].integerValue == selectedIndexPath.item) {
+            
+            [obj.properties enumerateObjectsUsingBlock:^(ORSKUProperty * _Nonnull property, NSUInteger idx2, BOOL * _Nonnull stop1) {
+                                
+                //从condition中添加种类不同的属性时,需要根据已选中的属性过滤
+                //过滤方式为 condition要么包含已选中 要么和已选中属性是同级
+                if (property.indexPath.section != selectedIndexPath.section) {
+                    
+                    __block BOOL flag = YES;
+                    
+                    [indexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj1, NSUInteger idx, BOOL * _Nonnull stop) {
+                        
+                        flag = (([obj.conditionIndexs[obj1.section] integerValue] == obj1.row) || (obj1.section == property.indexPath.section)) && flag;
+                    }];
+                    
+                    if (flag) {
+                        [set addObject:property.indexPath];
+                    }
+                    
+                }else {
+                    [set addObject:property.indexPath];
+                }
+            }];
+        }
+    }];
+    
+    //合并本行数据
+    [_allAvailableIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, BOOL * _Nonnull stop) {
+        if (obj.section == selectedIndexPath.section) {
+            [set addObject:obj];
+        }
+    }];
+    
+    return set;
+}
+
+//当前可用的
+- (void)updateAvailableIndexPaths {
+    
+    if (_selectedIndexPaths.count == 0) {
+        
+        _availableIndexPathsSet = [_allAvailableIndexPaths mutableCopy];
+        return ;
+    }
+    
+    __block NSMutableSet *set = [NSMutableSet set];
+    
+    NSMutableArray *seleted = [NSMutableArray array];
+    
+    [_selectedIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        
+        [seleted addObject:obj];
+        
+        NSMutableSet *tempSet = nil;
+        
+        tempSet = [self availableIndexPathsFromSelctedIndexPath:obj sectedIndexPaths:seleted];
+        
+        if (set.count == 0) {
+            set = [tempSet mutableCopy];
+        }else {
+            [set intersectSet:tempSet];
+        }
+        
+    }];
+    
+    _availableIndexPathsSet = set;
+
+    
+}
+
+// 当前结果
+- (void)updateCurrentResult {
+    
+    if (_selectedIndexPaths.count != [_dataSource numberOfSectionsForPropertiesInFilter:self]) {
+        _currentResult = nil;
+        return;
+    }
+    NSMutableArray *conditions = [NSMutableArray array];
+    
+    for (int i = 0; i < [_dataSource numberOfSectionsForPropertiesInFilter:self]; i ++) {
+        [_selectedIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+            if (obj.section == i) {
+                [conditions addObject:@(obj.row)];
+            }
+        }];
+        
+    }
+    _currentResult = [self skuResultWithConditionIndexs:[conditions copy]];
+}
+
+- (BOOL)isAvailableWithPropertyIndexPath:(NSIndexPath *)indexPath {
+    
+    __block BOOL isAvailable = NO;
+    
+    [_conditions enumerateObjectsUsingBlock:^(ORSKUCondition * _Nonnull obj, BOOL * _Nonnull stop) {
+        if ([obj.conditionIndexs objectAtIndex:indexPath.section].integerValue == indexPath.row) {
+            isAvailable = YES;
+            *stop = YES;
+        }
+    }];;
+    
+    return isAvailable;
+}
+
+
+#pragma mark -- setter
+- (void)setDataSource:(id<ORSKUDataFilterDataSource>)dataSource {
+    _dataSource = dataSource;
+    [self reloadData];
+}
+
+- (void)setNeedDefaultValue:(BOOL)needDefaultValue {
+    
+    _needDefaultValue = needDefaultValue;
+    
+    if (_selectedIndexPaths.count > 0 || !needDefaultValue) {
+        return;
+    }
+    
+    [self reloadData];
+}
+
+@end
+
+@implementation ORSKUCondition
+
+- (void)setProperties:(NSArray<ORSKUProperty *> *)properties {
+    
+    _properties = properties;
+    NSMutableArray *array = [NSMutableArray array];
+    [properties enumerateObjectsUsingBlock:^(ORSKUProperty * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        [array addObject:@(obj.indexPath.item)];
+    }];
+    _conditionIndexs = [array copy];
+}
+
+@end
+
+@implementation ORSKUProperty
+
+- (instancetype)initWithValue:(id)value indexPath:(NSIndexPath *)indexPath
+{
+    self = [super init];
+    if (self) {
+        _value = value;
+        _indexPath = indexPath;
+    }
+    return self;
+}
+
+@end
+
+
+

+ 13 - 0
RainbowPlanet/RainbowPlanet/Tools/SKUDataFilter/ORSKUDataFilterSwift.swift

@@ -0,0 +1,13 @@
+//
+//  ORSKUDataFilterSwift.swift
+//  RainbowPlanet
+//
+//  Created by 南鑫林 on 2019/5/17.
+//  Copyright © 2019 RainbowPlanet. All rights reserved.
+//
+
+import UIKit
+
+class ORSKUDataFilterSwift: NSObject {
+
+}