|
@@ -0,0 +1,485 @@
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+import UIKit
|
|
|
+import PPBadgeViewSwift
|
|
|
+import FWPopupView
|
|
|
+
|
|
|
+class ProductDetailView: BaseView {
|
|
|
+
|
|
|
+ typealias LookAllCommentClosure = () -> Void
|
|
|
+ var lookAllCommentClosure : LookAllCommentClosure?
|
|
|
+
|
|
|
+ typealias AddCartClosure = (ProductDetailSkuModel) -> Void
|
|
|
+ var addCartClosure : AddCartClosure?
|
|
|
+
|
|
|
+ typealias BuyNowClosure = (ProductDetailSkuModel) -> Void
|
|
|
+ var buyNowClosure : BuyNowClosure?
|
|
|
+
|
|
|
+ var productDetailSkuModel : ProductDetailSkuModel?
|
|
|
+
|
|
|
+ var titles = ["","","商品评价","","热销排行","商品参数","商品详情"]
|
|
|
+
|
|
|
+ var index : Int? {
|
|
|
+ didSet {
|
|
|
+ if index == 0 {
|
|
|
+ tableView.scrollToTop()
|
|
|
+ }else {
|
|
|
+ let reloadSection = 2 * index!
|
|
|
+ let rect = tableView.rect(forSection: reloadSection)
|
|
|
+ tableView.setContentOffset(CGPoint(x: 0, y: rect.origin.y - kNavBarTotalHeight), animated: true)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var productDetailModel : ProductDetailModel? {
|
|
|
+ didSet {
|
|
|
+ tableView.ly_startLoading()
|
|
|
+ tableView.reloadData()
|
|
|
+ if productDetailModel != nil {
|
|
|
+
|
|
|
+ if productDetailModel?.commentNumber != 0 && productDetailModel?.commentNumber != nil {
|
|
|
+ titles[2] = "商品评价" + "(" + "\(productDetailModel?.commentNumber ?? 0)" + ")"
|
|
|
+
|
|
|
+ }
|
|
|
+ if productDetailModel?.imgs?.isEmpty ?? true {
|
|
|
+ tableView.tableHeaderView = nil
|
|
|
+ }else {
|
|
|
+ tableView.ly_hideEmpty()
|
|
|
+ tableView.tableHeaderView = productDetailTableViewHeaderView
|
|
|
+ productDetailTableViewHeaderView.productDetailModel = productDetailModel
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var productSearchListModel: ProductSearchListModel? {
|
|
|
+ didSet {
|
|
|
+ tableView.reloadData()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var productCommentListModel :ProductCommentListModel? {
|
|
|
+ didSet {
|
|
|
+ tableView.reloadData()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ override func setupViews() {
|
|
|
+ addSubview(bottomBgView)
|
|
|
+ bottomBgView.addSubview(cartButton)
|
|
|
+ cartButton.addSubview(cartImageView)
|
|
|
+ bottomBgView.addSubview(addCartButton)
|
|
|
+ bottomBgView.addSubview(buyButton)
|
|
|
+ addSubview(tableView)
|
|
|
+ addSubview(topButton)
|
|
|
+ if #available(iOS 11.0, *) {
|
|
|
+ tableView.contentInsetAdjustmentBehavior = .never
|
|
|
+ }
|
|
|
+ let emptyView = EmptyView.shared.diyCustomEmptyViewStyle2(iconStr: "page04", titleStr: "当前暂无数据")
|
|
|
+ emptyView.contentViewY = kScaleValue(value: 182)
|
|
|
+ tableView.ly_emptyView = emptyView
|
|
|
+ }
|
|
|
+
|
|
|
+ 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)
|
|
|
+ }
|
|
|
+ tableView.snp.makeConstraints { (make) in
|
|
|
+ make.top.left.right.equalToSuperview()
|
|
|
+ make.bottom.equalTo(bottomBgView.snp.top)
|
|
|
+ }
|
|
|
+ topButton.snp.makeConstraints { (make) in
|
|
|
+ make.right.equalTo(-10)
|
|
|
+ make.size.equalTo(44)
|
|
|
+ make.bottom.equalTo(-70-kSafeTabBarHeight)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ lazy var tableView: UITableView = {
|
|
|
+ let tableView = UITableView(frame: CGRect.zero, style: UITableView.Style.grouped)
|
|
|
+ tableView.separatorStyle = .none
|
|
|
+ tableView.backgroundColor = kf7f8faColor
|
|
|
+ tableView.dataSource = self
|
|
|
+ tableView.delegate = self
|
|
|
+ tableView.estimatedRowHeight = 0.000001
|
|
|
+ tableView.estimatedSectionFooterHeight = 0.000001
|
|
|
+ tableView.estimatedSectionHeaderHeight = 0.000001
|
|
|
+ return tableView
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var productDetailTableViewHeaderView: ProductDetailTableViewHeaderView = {
|
|
|
+ let productDetailTableViewHeaderView = ProductDetailTableViewHeaderView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 251+kSafeTabBarHeight))
|
|
|
+ return productDetailTableViewHeaderView
|
|
|
+ }()
|
|
|
+
|
|
|
+ private lazy var bottomBgView: UIView = {
|
|
|
+ let bottomBgView = UIView()
|
|
|
+ return bottomBgView
|
|
|
+ }()
|
|
|
+
|
|
|
+ private lazy var cartButton : UIButton = {
|
|
|
+ let cartButton = UIButton()
|
|
|
+ return cartButton
|
|
|
+ }()
|
|
|
+
|
|
|
+ private lazy var cartImageView: UIImageView = {
|
|
|
+ let cartImageView = UIImageView()
|
|
|
+ cartImageView.image = kImage(name: "tabbar_shopping")
|
|
|
+ cartImageView.pp.badgeView.backgroundColor = kfe352bColor
|
|
|
+ cartImageView.pp.moveBadge(x: -2, y: 2)
|
|
|
+ return cartImageView
|
|
|
+ }()
|
|
|
+
|
|
|
+ private lazy var addCartButton : UIButton = {
|
|
|
+ let addCartButton = UIButton(type: UIButton.ButtonType.custom)
|
|
|
+ addCartButton.setTitle("加入购物车", for: UIControl.State.normal)
|
|
|
+ addCartButton.setTitleColor(UIColor.white, for: UIControl.State.normal)
|
|
|
+ addCartButton.backgroundColor = k404040Color
|
|
|
+ addCartButton.titleLabel?.font = kRegularFont16
|
|
|
+ addCartButton.rx.tap.subscribe(onNext: {
|
|
|
+ [weak self] (data) in
|
|
|
+ self?.view.productDetailSkuViewType = ProductDetailSkuViewType.addCart
|
|
|
+ self?.view.productDetailModel = self?.productDetailModel
|
|
|
+ self?.view.show()
|
|
|
+ }).disposed(by: disposeBag)
|
|
|
+ return addCartButton
|
|
|
+ }()
|
|
|
+
|
|
|
+ private lazy var buyButton : UIButton = {
|
|
|
+ let buyButton = UIButton(type: UIButton.ButtonType.custom)
|
|
|
+ buyButton.setTitle("立即购买", for: UIControl.State.normal)
|
|
|
+ buyButton.setTitleColor(UIColor.white, for: UIControl.State.normal)
|
|
|
+ buyButton.backgroundColor = kFFA42FColor
|
|
|
+ buyButton.titleLabel?.font = kRegularFont16
|
|
|
+ buyButton.rx.tap.subscribe(onNext: {
|
|
|
+ [weak self] (data) in
|
|
|
+ self?.view.productDetailSkuViewType = ProductDetailSkuViewType.buyNow
|
|
|
+ self?.view.productDetailModel = self?.productDetailModel
|
|
|
+ self?.view.show()
|
|
|
+ }).disposed(by: disposeBag)
|
|
|
+ return buyButton
|
|
|
+ }()
|
|
|
+
|
|
|
+ private lazy var topButton : UIButton = {
|
|
|
+ let topButton = UIButton(type: UIButton.ButtonType.custom)
|
|
|
+ topButton.setImage(kImage(name: "product_detail_top"), for: UIControl.State.normal)
|
|
|
+ topButton.rx.tap.subscribe(onNext: { [weak self] (data) in
|
|
|
+ self?.tableView.scrollToTop()
|
|
|
+ }).disposed(by: disposeBag)
|
|
|
+ return topButton
|
|
|
+ }()
|
|
|
+
|
|
|
+
|
|
|
+ lazy var view: ProductDetailSkuView = {
|
|
|
+ let view = ProductDetailSkuView(frame: CGRect(x: 0, y: 0, width: kScreenWidth , height: kScreenHeight - 76 - kNavBarTotalHeight))
|
|
|
+ let vProperty1 = FWPopupViewProperty()
|
|
|
+ vProperty1.popupCustomAlignment = .bottomCenter
|
|
|
+ vProperty1.popupAnimationType = .frame
|
|
|
+ vProperty1.maskViewColor = UIColor(white: 0, alpha: 0.5)
|
|
|
+ vProperty1.touchWildToHide = "0"
|
|
|
+ vProperty1.popupViewEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
|
|
|
+ vProperty1.animationDuration = 0.1
|
|
|
+ view.vProperty = vProperty1
|
|
|
+ view.sureClosure = {
|
|
|
+ [weak self] (productDetailSkuViewType,productDetailSkuModel) in
|
|
|
+ self?.productDetailSkuModel = productDetailSkuModel
|
|
|
+ switch productDetailSkuViewType {
|
|
|
+ case .selectSku:
|
|
|
+ self?.tableView.reloadData()
|
|
|
+ view.hide()
|
|
|
+ break
|
|
|
+ case .buyNow:
|
|
|
+ view.hide(popupDidDisappearBlock: { (FWPopupView) in
|
|
|
+ self?.tableView.reloadData()
|
|
|
+ if let buyNowClosure = self?.buyNowClosure {
|
|
|
+ buyNowClosure((self?.productDetailSkuModel)!)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ break
|
|
|
+ case .addCart:
|
|
|
+
|
|
|
+ if let addCartClosure = self?.addCartClosure {
|
|
|
+ addCartClosure((self?.productDetailSkuModel)!)
|
|
|
+ }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return view
|
|
|
+ }()
|
|
|
+
|
|
|
+ var productCartCount : Int = 0 {
|
|
|
+ didSet {
|
|
|
+ if productCartCount == 0 {
|
|
|
+ cartImageView.pp.hiddenBadge()
|
|
|
+ }else {
|
|
|
+ cartImageView.pp.addBadge(number: productCartCount)
|
|
|
+ }
|
|
|
+ self.tableView.reloadData()
|
|
|
+ self.view.hide()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var productCartCountModel : ProductCartCountModel? {
|
|
|
+ didSet {
|
|
|
+ if productCartCountModel != nil {
|
|
|
+ if productCartCountModel?.count == 0 {
|
|
|
+ cartImageView.pp.hiddenBadge()
|
|
|
+ }else {
|
|
|
+ cartImageView.pp.addBadge(number: productCartCountModel?.count ?? 0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+extension ProductDetailView : UITableViewDelegate, UITableViewDataSource {
|
|
|
+ func numberOfSections(in tableView: UITableView) -> Int {
|
|
|
+ if productDetailModel != nil {
|
|
|
+ return 7
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+
|
|
|
+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
|
+ switch section {
|
|
|
+ case 1:
|
|
|
+
|
|
|
+ if !(productDetailModel?.spec?.isEmpty ?? true) && !(productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ return 2
|
|
|
+ }
|
|
|
+
|
|
|
+ if (productDetailModel?.spec?.isEmpty ?? true) && !(productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+
|
|
|
+ if !(productDetailModel?.spec?.isEmpty ?? true) && (productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+
|
|
|
+ case 2:
|
|
|
+ if productCommentListModel != nil {
|
|
|
+ return productCommentListModel?.data?.isEmpty ?? true ? 0 : 1
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+
|
|
|
+ case 5:
|
|
|
+ return productDetailModel?.parameter?.isEmpty ?? true ? 0 : productDetailModel?.parameter?.count ?? 0
|
|
|
+ default:
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
|
+
|
|
|
+
|
|
|
+ switch indexPath.section {
|
|
|
+ case 0:
|
|
|
+ let cell = ProductDetailProductInfoTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ cell.productDetailModel = productDetailModel
|
|
|
+ return cell
|
|
|
+ case 1:
|
|
|
+ if !(productDetailModel?.spec?.isEmpty ?? true) && !(productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ if indexPath.row == 0 {
|
|
|
+ let cell = ProcuctDetailSelectSkuTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ if self.productDetailSkuModel != nil {
|
|
|
+ cell.productDetailSkuModel = self.productDetailSkuModel
|
|
|
+ }
|
|
|
+ return cell
|
|
|
+ }else {
|
|
|
+ let cell = ProductDetailProductLabelTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ cell.productDetailModel = productDetailModel
|
|
|
+ cell.frame = tableView.bounds
|
|
|
+ cell.layoutIfNeeded()
|
|
|
+ cell.reloadData()
|
|
|
+ return cell
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (productDetailModel?.spec?.isEmpty ?? true) && !(productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ let cell = ProductDetailProductLabelTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ cell.productDetailModel = productDetailModel
|
|
|
+ cell.frame = tableView.bounds
|
|
|
+ cell.layoutIfNeeded()
|
|
|
+ cell.reloadData()
|
|
|
+ return cell
|
|
|
+ }
|
|
|
+
|
|
|
+ if !(productDetailModel?.spec?.isEmpty ?? true) && (productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ let cell = ProcuctDetailSelectSkuTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ if self.productDetailSkuModel != nil {
|
|
|
+ cell.productDetailSkuModel = self.productDetailSkuModel
|
|
|
+ }
|
|
|
+ return cell
|
|
|
+ }
|
|
|
+ return UITableViewCell()
|
|
|
+ case 2:
|
|
|
+ let cell = ProductDetailEvaluationTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ cell.productCommentModel = productCommentListModel?.data?[indexPath.row]
|
|
|
+ return cell
|
|
|
+ case 3:
|
|
|
+ let cell = ProductDetailShopTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ cell.productDetailModel = productDetailModel
|
|
|
+ return cell
|
|
|
+ case 4:
|
|
|
+ let cell = ProductDetailHotSellTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ cell.productSearchListModel = productSearchListModel
|
|
|
+ return cell
|
|
|
+ case 5:
|
|
|
+ let cell = ProductDetailParameterTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ cell.productDetailModel = productDetailModel
|
|
|
+ return cell
|
|
|
+ case 6:
|
|
|
+ let cell = ProductDetailDescriptionTableViewCell.cellWith(tableView: tableView, indexPath: indexPath)
|
|
|
+ cell.productDetailModel = productDetailModel
|
|
|
+ return cell
|
|
|
+
|
|
|
+ default:
|
|
|
+
|
|
|
+ return UITableViewCell()
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
|
+ if indexPath.section == 1 {
|
|
|
+ if !(productDetailModel?.spec?.isEmpty ?? true) && !(productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ if indexPath.row == 0 {
|
|
|
+ self.view.productDetailSkuViewType = ProductDetailSkuViewType.selectSku
|
|
|
+ self.view.productDetailModel = self.productDetailModel
|
|
|
+ self.view.show()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if !(productDetailModel?.spec?.isEmpty ?? true) && (productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ self.view.productDetailSkuViewType = ProductDetailSkuViewType.selectSku
|
|
|
+ self.view.productDetailModel = self.productDetailModel
|
|
|
+ self.view.show()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
|
|
+ switch indexPath.section {
|
|
|
+ case 1:
|
|
|
+ if !(productDetailModel?.spec?.isEmpty ?? true) && !(productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ if indexPath.row == 0 {
|
|
|
+ return UITableView.automaticDimension
|
|
|
+ }else {
|
|
|
+ return 65 * kScaleWidth
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (productDetailModel?.spec?.isEmpty ?? true) && !(productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ return 65 * kScaleWidth
|
|
|
+ }
|
|
|
+
|
|
|
+ if !(productDetailModel?.spec?.isEmpty ?? true) && (productDetailModel?.label?.isEmpty ?? true) {
|
|
|
+ return UITableView.automaticDimension
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+ case 4:
|
|
|
+ return 173
|
|
|
+ default:
|
|
|
+ return UITableView.automaticDimension
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
|
|
+ switch section {
|
|
|
+ case 2,4,5,6:
|
|
|
+ return UITableView.automaticDimension
|
|
|
+ default:
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
|
|
+ switch section {
|
|
|
+ case 2,4,5,6:
|
|
|
+ let view = ProductDetailSectionHeader(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 44))
|
|
|
+ view.section = section
|
|
|
+ view.titles = titles
|
|
|
+ view.lookAllCommentClosure = {
|
|
|
+ [weak self] in
|
|
|
+ if let lookAllCommentClosure = self?.lookAllCommentClosure {
|
|
|
+ lookAllCommentClosure()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return view
|
|
|
+ default:
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
|
|
|
+ return 10
|
|
|
+ }
|
|
|
+
|
|
|
+ func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
|
+ var offset = scrollView.contentOffset
|
|
|
+ NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ProductDetailView"), object: offset)
|
|
|
+
|
|
|
+ if (!(scrollView.isTracking || scrollView.isDecelerating)) {
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ offset.y = offset.y + kNavBarTotalHeight
|
|
|
+
|
|
|
+ if offset.y > 251 + kSafeTabBarHeight {
|
|
|
+
|
|
|
+ let indexPath = tableView.indexPathForRow(at: offset)
|
|
|
+ if indexPath != nil {
|
|
|
+ var rect = tableView.rect(forSection: (indexPath?.section)!)
|
|
|
+
|
|
|
+ if rect.size.height + kNavBarTotalHeight - tableView.frame.size.height < 0 {
|
|
|
+
|
|
|
+ rect.size.height = tableView.frame.size.height - kNavBarTotalHeight - rect.size.height
|
|
|
+
|
|
|
+ tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: rect.size.height, right: 0)
|
|
|
+ }
|
|
|
+
|
|
|
+ if indexPath!.section % 2 == 0 {
|
|
|
+ NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ProductDetailViewSection"), object: indexPath!.section)
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|