| | |
| | | 1385E00B2C6C57A900AADB1F /* HomeItemDetailVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1385E0092C6C57A900AADB1F /* HomeItemDetailVC.xib */; }; |
| | | 1388840E2C92B5E80043AAB4 /* CommonBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1388840D2C92B5E80043AAB4 /* CommonBannerView.swift */; }; |
| | | 13897D892C7DB9D7006209E0 /* EqualCellSpaceFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13897D882C7DB9D7006209E0 /* EqualCellSpaceFlowLayout.swift */; }; |
| | | 138995402C943AA700BC7F78 /* static-level-3.png in Resources */ = {isa = PBXBuildFile; fileRef = 138995362C943AA500BC7F78 /* static-level-3.png */; }; |
| | | 138995412C943AA700BC7F78 /* static-level-5.png in Resources */ = {isa = PBXBuildFile; fileRef = 138995372C943AA500BC7F78 /* static-level-5.png */; }; |
| | | 138995422C943AA700BC7F78 /* static-level-9.png in Resources */ = {isa = PBXBuildFile; fileRef = 138995382C943AA500BC7F78 /* static-level-9.png */; }; |
| | | 138995432C943AA700BC7F78 /* static-level-2.png in Resources */ = {isa = PBXBuildFile; fileRef = 138995392C943AA600BC7F78 /* static-level-2.png */; }; |
| | | 138995442C943AA700BC7F78 /* static-level-8.png in Resources */ = {isa = PBXBuildFile; fileRef = 1389953A2C943AA600BC7F78 /* static-level-8.png */; }; |
| | | 138995452C943AA700BC7F78 /* static-level-6.png in Resources */ = {isa = PBXBuildFile; fileRef = 1389953B2C943AA600BC7F78 /* static-level-6.png */; }; |
| | | 138995462C943AA700BC7F78 /* static-level-7.png in Resources */ = {isa = PBXBuildFile; fileRef = 1389953C2C943AA600BC7F78 /* static-level-7.png */; }; |
| | | 138995472C943AA700BC7F78 /* static-level-4.png in Resources */ = {isa = PBXBuildFile; fileRef = 1389953D2C943AA700BC7F78 /* static-level-4.png */; }; |
| | | 138995482C943AA700BC7F78 /* static-level-10.png in Resources */ = {isa = PBXBuildFile; fileRef = 1389953E2C943AA700BC7F78 /* static-level-10.png */; }; |
| | | 138995492C943AA700BC7F78 /* static-level-1.png in Resources */ = {isa = PBXBuildFile; fileRef = 1389953F2C943AA700BC7F78 /* static-level-1.png */; }; |
| | | 138F0C322C7594BB0072A16C /* TreatyVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 138F0C312C7594BB0072A16C /* TreatyVC.swift */; }; |
| | | 138F0C352C7597CA0072A16C /* HelpCenterVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 138F0C332C7597CA0072A16C /* HelpCenterVC.swift */; }; |
| | | 138F0C362C7597CA0072A16C /* HelpCenterVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 138F0C342C7597CA0072A16C /* HelpCenterVC.xib */; }; |
| | |
| | | 1385E0092C6C57A900AADB1F /* HomeItemDetailVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeItemDetailVC.xib; sourceTree = "<group>"; }; |
| | | 1388840D2C92B5E80043AAB4 /* CommonBannerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommonBannerView.swift; sourceTree = "<group>"; }; |
| | | 13897D882C7DB9D7006209E0 /* EqualCellSpaceFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EqualCellSpaceFlowLayout.swift; sourceTree = "<group>"; }; |
| | | 138995362C943AA500BC7F78 /* static-level-3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-3.png"; sourceTree = "<group>"; }; |
| | | 138995372C943AA500BC7F78 /* static-level-5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-5.png"; sourceTree = "<group>"; }; |
| | | 138995382C943AA500BC7F78 /* static-level-9.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-9.png"; sourceTree = "<group>"; }; |
| | | 138995392C943AA600BC7F78 /* static-level-2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-2.png"; sourceTree = "<group>"; }; |
| | | 1389953A2C943AA600BC7F78 /* static-level-8.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-8.png"; sourceTree = "<group>"; }; |
| | | 1389953B2C943AA600BC7F78 /* static-level-6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-6.png"; sourceTree = "<group>"; }; |
| | | 1389953C2C943AA600BC7F78 /* static-level-7.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-7.png"; sourceTree = "<group>"; }; |
| | | 1389953D2C943AA700BC7F78 /* static-level-4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-4.png"; sourceTree = "<group>"; }; |
| | | 1389953E2C943AA700BC7F78 /* static-level-10.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-10.png"; sourceTree = "<group>"; }; |
| | | 1389953F2C943AA700BC7F78 /* static-level-1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "static-level-1.png"; sourceTree = "<group>"; }; |
| | | 138F0C312C7594BB0072A16C /* TreatyVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreatyVC.swift; sourceTree = "<group>"; }; |
| | | 138F0C332C7597CA0072A16C /* HelpCenterVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpCenterVC.swift; sourceTree = "<group>"; }; |
| | | 138F0C342C7597CA0072A16C /* HelpCenterVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HelpCenterVC.xib; sourceTree = "<group>"; }; |
| | |
| | | 137ECADB2C78578A00C338BE /* Pngs */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | 138995352C943A4300BC7F78 /* droop */, |
| | | 13C9DDD02C8EE8EB0008946B /* apngb-animated-level-6.png */, |
| | | 13C9DDCF2C8EE8EB0008946B /* apngb-animated-level-7.png */, |
| | | 13C9DDD12C8EE8EB0008946B /* apngb-animated-level-8.png */, |
| | |
| | | 135B1D212C8868170089A9BE /* Models.swift */, |
| | | ); |
| | | path = Network; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | 138995352C943A4300BC7F78 /* droop */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | 1389953F2C943AA700BC7F78 /* static-level-1.png */, |
| | | 138995392C943AA600BC7F78 /* static-level-2.png */, |
| | | 138995362C943AA500BC7F78 /* static-level-3.png */, |
| | | 1389953D2C943AA700BC7F78 /* static-level-4.png */, |
| | | 138995372C943AA500BC7F78 /* static-level-5.png */, |
| | | 1389953B2C943AA600BC7F78 /* static-level-6.png */, |
| | | 1389953C2C943AA600BC7F78 /* static-level-7.png */, |
| | | 1389953A2C943AA600BC7F78 /* static-level-8.png */, |
| | | 138995382C943AA500BC7F78 /* static-level-9.png */, |
| | | 1389953E2C943AA700BC7F78 /* static-level-10.png */, |
| | | ); |
| | | path = droop; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | 139228AD2C6B8339006F3CB6 /* View */ = { |
| | |
| | | 13A37A012C75C1DE0038D5C8 /* LevelVC.xib in Resources */, |
| | | 1324A6452C805B4000AA5098 /* FlyFlowerSong.otf in Resources */, |
| | | 130C07092C76D51900ADB098 /* SpendingDetailHeaderVC.xib in Resources */, |
| | | 138995412C943AA700BC7F78 /* static-level-5.png in Resources */, |
| | | 1327C6832C81D107005DA44B /* PlanGuide_3_VC.xib in Resources */, |
| | | 138FE0DF2C757B2A00A964E8 /* BindPhone_1_VC.xib in Resources */, |
| | | 138995402C943AA700BC7F78 /* static-level-3.png in Resources */, |
| | | 13FB6D842C6EEFE900A0685D /* MenuListTCell.xib in Resources */, |
| | | 13B06A082C78A0D300477FA9 /* apngb-animated-level-1.png in Resources */, |
| | | 138F0C362C7597CA0072A16C /* HelpCenterVC.xib in Resources */, |
| | | 131CE0FB2C91299400D1234A /* TreeTeskListView.xib in Resources */, |
| | | 138995432C943AA700BC7F78 /* static-level-2.png in Resources */, |
| | | 134803D72C76E3E000F4FDDA /* WatchHistoryVC.xib in Resources */, |
| | | 1377768E2C6AFD25004FF994 /* LoginVC.xib in Resources */, |
| | | 134CC7E02C73283700EAEFB7 /* PavilionSearchVC.xib in Resources */, |
| | |
| | | 13FB6D8C2C6EFB5400A0685D /* CourseDetailHeaderView.xib in Resources */, |
| | | 1324A64D2C80706700AA5098 /* PlanGuide_1_VC.xib in Resources */, |
| | | 13985D9F2C69B2440046B6DC /* Assets.xcassets in Resources */, |
| | | 138995472C943AA700BC7F78 /* static-level-4.png in Resources */, |
| | | 13FCCE272C75E8C400AC7E02 /* BankInfoTCell.xib in Resources */, |
| | | 138995442C943AA700BC7F78 /* static-level-8.png in Resources */, |
| | | 13EFCDC22C6DD27A00B51AE6 /* PaymentOrderVC.xib in Resources */, |
| | | 13A379FC2C75B7280038D5C8 /* BindAccountVC.xib in Resources */, |
| | | 13F24E412C758DF100D2BA90 /* LogoutAccountVC.xib in Resources */, |
| | |
| | | 137175CC2C6C412A00B38EF1 /* BackgroundVoiceVC.xib in Resources */, |
| | | 130602882C91790B0019ECDE /* TreeTeskExchangeSuccessView.xib in Resources */, |
| | | 13ED09482C916FD30018BB10 /* TreeTeskEnergyTCell.xib in Resources */, |
| | | 138995492C943AA700BC7F78 /* static-level-1.png in Resources */, |
| | | 13BF65EB2C804BE100E20F0E /* apngb-animated-flow.png in Resources */, |
| | | 13FAD54E2C901D6300566998 /* SearchContentVC.xib in Resources */, |
| | | 137776932C6AFE69004FF994 /* SearchVC.xib in Resources */, |
| | |
| | | 13985DBF2C69DDF90046B6DC /* HomeTopMenuView.xib in Resources */, |
| | | 13C5838E2C86A4F90071BCBE /* apngb-animated-level-5.png in Resources */, |
| | | 1385E00B2C6C57A900AADB1F /* HomeItemDetailVC.xib in Resources */, |
| | | 138995422C943AA700BC7F78 /* static-level-9.png in Resources */, |
| | | 13B021DB2C75DD0600414769 /* BankWithdrawVC.xib in Resources */, |
| | | 1338A6DE2C76DD5E006CDD15 /* SpendingDetailInfoVC.xib in Resources */, |
| | | 137ECAD72C783C7700C338BE /* TreeTeskVC.xib in Resources */, |
| | |
| | | 13EA70052C75FA16005DF280 /* WalletRechargeVC.xib in Resources */, |
| | | 13A0A8AE2C74757200DF08B6 /* MessageTCell.xib in Resources */, |
| | | 1324A6482C80632500AA5098 /* SourceHanSerifCN-Semibold.otf in Resources */, |
| | | 138995462C943AA700BC7F78 /* static-level-7.png in Resources */, |
| | | 138995452C943AA700BC7F78 /* static-level-6.png in Resources */, |
| | | 130913EA2C6DE33200418201 /* PaymentOrderResultVC.xib in Resources */, |
| | | 139F1F622C81AE920055CE8F /* PlanGuidePromptView.xib in Resources */, |
| | | 130ED7ED2C6AF05C00D0736E /* Home_Style_4_Inner_CCell.xib in Resources */, |
| | |
| | | 13E0FBFB2C6C8BE3009997AE /* CountdownChooseListView.xib in Resources */, |
| | | 13A0A89F2C746A8700DF08B6 /* CommonAlertSheetView.xib in Resources */, |
| | | 13E4ECEF2C80778A0095AD04 /* PlanGuide_2_VC.xib in Resources */, |
| | | 138995482C943AA700BC7F78 /* static-level-10.png in Resources */, |
| | | 13F24E462C75901600D2BA90 /* CommonAlertView.xib in Resources */, |
| | | 130B765A2C6C4963006371AF /* HomeRelaxVoiceCCell.xib in Resources */, |
| | | 130C07122C76DA0500ADB098 /* SpendingDetailContentTCell.xib in Resources */, |
| | |
| | | case offline = 2 //线下课程 |
| | | } |
| | | |
| | | enum ConditionType:Int,HandyJSONEnum{ |
| | | enum ConditionType:Int,HandyJSONEnum,Codable{ |
| | | case yes = 1 |
| | | case no = 2 |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | enum TreeLevel:Int,HandyJSONEnum,Codable{ |
| | | case level_1 = 1 |
| | | case level_2 = 2 |
| | | case level_3 = 3 |
| | | case level_4 = 4 |
| | | case level_5 = 5 |
| | | case level_6 = 6 |
| | | case level_7 = 7 |
| | | case level_8 = 8 |
| | | case level_9 = 9 |
| | | case level_10 = 10 |
| | | |
| | | var aniResource:String{ |
| | | switch self { |
| | | case .level_1:return "apngb-animated-level-1" |
| | | case .level_2:return "apngb-animated-level-2" |
| | | case .level_3:return "apngb-animated-level-3" |
| | | case .level_4:return "apngb-animated-level-4" |
| | | case .level_5:return "apngb-animated-level-5" |
| | | case .level_6:return "apngb-animated-level-6" |
| | | case .level_7:return "apngb-animated-level-7" |
| | | case .level_8:return "apngb-animated-level-8" |
| | | case .level_9:return "apngb-animated-level-9" |
| | | case .level_10:return "apngb-animated-level-10" |
| | | } |
| | | } |
| | | |
| | | var staticDroopResource:String{ |
| | | switch self { |
| | | case .level_1:return "static-level-1" |
| | | case .level_2:return "static-level-2" |
| | | case .level_3:return "static-level-3" |
| | | case .level_4:return "static-level-4" |
| | | case .level_5:return "static-level-5" |
| | | case .level_6:return "static-level-6" |
| | | case .level_7:return "static-level-7" |
| | | case .level_8:return "static-level-8" |
| | | case .level_9:return "static-level-9" |
| | | case .level_10:return "static-level-10" |
| | | } |
| | | } |
| | | |
| | | var title:String{ |
| | | switch self { |
| | | case .level_1:return "第一" |
| | | case .level_2:return "第二" |
| | | case .level_3:return "第三" |
| | | case .level_4:return "第四" |
| | | case .level_5:return "第五" |
| | | case .level_6:return "第六" |
| | | case .level_7:return "第七" |
| | | case .level_8:return "第八" |
| | | case .level_9:return "第九" |
| | | case .level_10:return "第十" |
| | | } |
| | | } |
| | | } |
| | |
| | | webView.scrollView.backgroundColor = .clear |
| | | webView.isOpaque = false |
| | | |
| | | self.webView.scrollView.rx.observe(CGSize.self, "contentSize").map { (size) -> CGFloat? in |
| | | if let size = size{ |
| | | return size.height |
| | | } |
| | | return nil |
| | | }.subscribe(onNext: { [unowned self](height) in |
| | | if let height = height{ |
| | | self.cons_webHei.constant = height |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | |
| | | } |
| | | |
| | | func setContent(title:String,content:String){ |
| | | label_title.text = title |
| | | webView.loadHTMLString(content.jq_wrapHtml(), baseURL: nil) |
| | | } |
| | | } |
| | |
| | | <autoresizingMask key="autoresizingMask"/> |
| | | <subviews> |
| | | <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="课程介绍" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Lg9-70-w3n"> |
| | | <rect key="frame" x="21.666666666666668" y="35" width="61.333333333333329" height="14"/> |
| | | <rect key="frame" x="21.666666666666668" y="35" width="61.333333333333329" height="20"/> |
| | | <constraints> |
| | | <constraint firstAttribute="height" constant="14" id="WNQ-mw-uOi"/> |
| | | <constraint firstAttribute="height" constant="20" id="8dQ-Gi-hJh"/> |
| | | </constraints> |
| | | <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> |
| | | <color key="textColor" red="0.15686274509803921" green="0.15686274509803921" blue="0.15686274509803921" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| | | <nil key="highlightedColor"/> |
| | | </label> |
| | | <wkWebView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WYV-JQ-E3S"> |
| | | <rect key="frame" x="0.0" y="68.666666666666671" width="501" height="100.00000000000001"/> |
| | | <rect key="frame" x="0.0" y="74.666666666666671" width="501" height="100.00000000000001"/> |
| | | <constraints> |
| | | <constraint firstAttribute="height" constant="100" id="hfa-qQ-TpS"/> |
| | | </constraints> |
| | |
| | | @IBOutlet weak var tableView: UITableView! |
| | | @IBOutlet weak var cons_tableHei: NSLayoutConstraint! |
| | | |
| | | private var items = [CourseItemModel]() |
| | | private var model:CourseModel? |
| | | |
| | | override func awakeFromNib() { |
| | | super.awakeFromNib() |
| | |
| | | cons_tableHei.constant = 0 |
| | | } |
| | | |
| | | func setItems(_ items:[CourseItemModel]){ |
| | | self.items = items |
| | | cons_tableHei.constant = 70.5 * Double(items.count) |
| | | func setItems(_ model:CourseModel){ |
| | | self.model = model |
| | | cons_tableHei.constant = 70.5 * Double(model.list.count) |
| | | self.tableView.reloadData() |
| | | } |
| | | } |
| | |
| | | extension CourseDetail_2_TCell:UITableViewDelegate & UITableViewDataSource{ |
| | | |
| | | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { |
| | | let vc = CourseDetialVideoVC(items: items, selectIndex: indexPath) |
| | | JQ_currentViewController().jq_push(vc: vc) |
| | | |
| | | guard let m = model else {return} |
| | | if m.chargeType == .free || (m.chargeType == .vipFree && UserViewModel.getAvatarInfo().isVip == .yes) || (m.chargeType == .payment && m.isBuy == .yes){ |
| | | let vc = CourseDetialVideoVC(items: model!.list, selectIndex: indexPath) |
| | | JQ_currentNavigationController().pushViewController(vc) |
| | | }else{ |
| | | let vc = PaymentOrderVC(courseId: m.id) |
| | | JQ_currentNavigationController().pushViewController(vc) |
| | | } |
| | | } |
| | | |
| | | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
| | | return items.count |
| | | return model?.list.count ?? 0 |
| | | } |
| | | |
| | | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
| | | let model = items[indexPath.row] |
| | | let model = model!.list[indexPath.row] |
| | | let cell = tableView.dequeueReusableCell(withIdentifier: "_CourseDetail_2_Inner_TCell", for: indexPath) as! CourseDetail_2_Inner_TCell |
| | | cell.setModel(model, index: indexPath) |
| | | cell.backgroundColor = .clear |
| | |
| | | case style2 //无视频 |
| | | } |
| | | |
| | | let CourseRefresh_Noti = Notification.Name.init("CourseRefresh_Noti") |
| | | |
| | | class CourseDetialVC: BaseVC { |
| | | |
| | | private var tableView:UITableView? |
| | | private let studyBtn = QMUIButton(type: .custom) |
| | | private var headerView = CourseDetailHeaderView.jq_loadNibView() |
| | | private var barStyle:UIStatusBarStyle = .lightContent |
| | | private var scrollShowCell = false |
| | |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | title = "课程详情" |
| | | |
| | | Services.getCourseDetail(courseId: courseId).subscribe(onNext: {data in |
| | | if let m = data.data{ |
| | | self.courseDetailModel = m |
| | | self.headerView.setCourseModel(m) |
| | | self.section1TCell.setItems(m.list) |
| | | self.section2TCell.setItems(m.list2) |
| | | |
| | | if m.detailUrl.jq_isVideo{ |
| | | self.style = .style1 |
| | | self.pageMenu.setItems(["简介","章节","相关推荐"], selectedItemIndex: 0) |
| | | }else{ |
| | | self.style = .style2 |
| | | self.pageMenu.setItems(["简介"], selectedItemIndex: 0) |
| | | } |
| | | self.tableView?.reloadData() |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | getData() |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | setFootView() |
| | | } |
| | | |
| | | private func getData(){ |
| | | Services.getCourseDetail(courseId: courseId).subscribe(onNext: {data in |
| | | if let m = data.data{ |
| | | self.courseDetailModel = m |
| | | self.headerView.setCourseModel(m) |
| | | self.section1TCell.setItems(m) |
| | | self.section2TCell.setItems(m.list2) |
| | | |
| | | if m.isBuy != .yes{ |
| | | let attribute = AttributedStringbuilder.build().add(string: " 疗愈币", withFont: .systemFont(ofSize: 12,weight: .bold), withColor: UIColor(hexString: "#F6F6F6")!).add(string: "\(m.generalPrice.jq_formatFloat)", withFont: .systemFont(ofSize: 21.71, weight: .bold), withColor: UIColor(hexString: "#F6F6F6")!).add(string: " 立即购买 ", withFont: .systemFont(ofSize: 16, weight: .bold), withColor: UIColor(hexString: "#F6F6F6")!).mutableAttributedString |
| | | self.studyBtn.setAttributedTitle(attribute, for: .normal) |
| | | } |
| | | |
| | | if m.detailUrl.jq_isVideo{ |
| | | self.style = .style1 |
| | | self.pageMenu.setItems(["简介","章节","相关推荐"], selectedItemIndex: 0) |
| | | }else{ |
| | | self.style = .style2 |
| | | self.pageMenu.setItems(["简介"], selectedItemIndex: 0) |
| | | } |
| | | self.tableView?.reloadData() |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | private func setFootView(){ |
| | | let footView = UIView() |
| | | footView.backgroundColor = .white |
| | |
| | | make.top.equalTo(26.5) |
| | | } |
| | | |
| | | let studyBtn = QMUIButton(type: .custom) |
| | | studyBtn.setTitleColor(UIColor.white, for: .normal) |
| | | studyBtn.setTitle(" 立即学习 ", for: .normal) |
| | | studyBtn.addTarget(self, action: #selector(handleAction(_:)), for: .touchUpInside) |
| | |
| | | } |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | |
| | | NotificationCenter.default.rx.notification(CourseRefresh_Noti).take(until: self.rx.deallocated).subscribe(onNext: {data in |
| | | self.getData() |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | @objc func handleAction(_ btn:QMUIButton){ |
| | | if let items = courseDetailModel?.list{ |
| | | let vc = CourseDetialVideoVC(items: items, selectIndex: IndexPath(row: 0, section: 0)) |
| | | |
| | | if let m = courseDetailModel{ |
| | | if m.chargeType == .free || (m.chargeType == .vipFree && UserViewModel.getAvatarInfo().isVip == .yes) || (m.chargeType == .payment && m.isBuy == .yes){ |
| | | let vc = CourseDetialVideoVC(items: m.list, selectIndex: IndexPath(row: 0, section: 0)) |
| | | push(vc: vc);return |
| | | } |
| | | let vc = PaymentOrderVC(courseId: m.id) |
| | | push(vc: vc) |
| | | } |
| | | } |
| | |
| | | @objc func sendGift(_ btn:QMUIButton){ |
| | | if let price = courseDetailModel?.generalPrice{ |
| | | CourseSendGiftView.show(price:price) { |
| | | let vc = PaymentOrderVC() |
| | | let vc = PaymentOrderVC(courseId: self.courseDetailModel!.id,giftToOther: true) |
| | | self.push(vc: vc) |
| | | } |
| | | } |
| | |
| | | let model = viewModel.dataSource.value!.list[indexPath.row] |
| | | let vc = CourseDetialVC(courseId: model.id) |
| | | JQ_currentViewController().jq_push(vc: vc) |
| | | |
| | | // let isVip = UserViewModel.getAvatarInfo().isVip == .yes |
| | | // if model.isBuy == .yes || model.chargeType == .free || (model.chargeType == .vipFree && isVip){ |
| | | // |
| | | // return |
| | | // }else{ |
| | | // let vc = CourseDetialVC(courseId: model.id) |
| | | // JQ_currentViewController().jq_push(vc: vc) |
| | | // } |
| | | } |
| | | |
| | | |
| | |
| | | class CourseVCTeacherSpecialVC: BaseVC { |
| | | private var tableView:UITableView? |
| | | private var headerView:VideoView! |
| | | private var model:TutorInfoModel? |
| | | |
| | | private var cell0:CourseDetail_1_TCell? |
| | | private var cell1:CourseDetail_3_TCell? |
| | | |
| | | override func viewDidDisappear(_ animated: Bool) { |
| | | super.viewDidDisappear(animated) |
| | | headerView.pauseVideo() |
| | | } |
| | | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | |
| | | cell0 = (tableView!.dequeueReusableCell(withIdentifier: "_CourseDetail_1_TCell") as! CourseDetail_1_TCell) |
| | | cell1 = (tableView!.dequeueReusableCell(withIdentifier: "_CourseDetail_3_TCell") as! CourseDetail_3_TCell) |
| | | |
| | | cell0!.backgroundColor = UIColor(hexString: "#f6f6f6") |
| | | cell1!.backgroundColor = UIColor(hexString: "#f6f6f6") |
| | | |
| | | Services.tutorInfo().subscribe(onNext: { data in |
| | | if let m = data.data{ |
| | | self.model = m |
| | | self.cell0!.setContent(title: "导师简介", content: m.tutorIntroduction) |
| | | self.cell1!.setItems(m.list) |
| | | self.tableView?.reloadData() |
| | | self.headerView.updateVideoUrl(m.videoUrl,autoPlay: false,placeHoderImageUrl: m.coverUrl) |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | } |
| | | |
| | | DispatchQueue.main.async { |
| | | self.headerView = VideoView(url: "http://vfx.mtime.cn/Video/2021/07/10/mp4/210710094507540173.mp4") |
| | | self.headerView = VideoView(url: nil) |
| | | self.tableView!.tableHeaderView = self.headerView |
| | | self.headerView.frame = CGRect(x: 0, y: 0, width: JQ_ScreenW, height: JQ_ScreenW * 0.56) |
| | | } |
| | | } |
| | | |
| | | override func setRx() { |
| | | self.cell0?.webView.scrollView.rx.observe(CGSize.self, "contentSize").map { (size) -> CGFloat? in |
| | | if let size = size{ |
| | | return size.height |
| | | } |
| | | return nil |
| | | }.subscribe(onNext: { [unowned self](height) in |
| | | if let height = height{ |
| | | if height > self.cell0?.cons_webHei.constant ?? 0{ |
| | | self.cell0?.cons_webHei.constant = height |
| | | self.tableView?.reloadData() |
| | | } |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | override var shouldAutorotate: Bool{ |
| | |
| | | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
| | | |
| | | if indexPath.row == 0{ |
| | | let cell = tableView.dequeueReusableCell(withIdentifier: "_CourseDetail_1_TCell") as! CourseDetail_1_TCell |
| | | cell.backgroundColor = UIColor(hexString: "#f6f6f6") |
| | | cell.setContent(title: "导师简介", content: "") |
| | | return cell |
| | | return cell0! |
| | | } |
| | | |
| | | if indexPath.row == 1{ |
| | | let cell = tableView.dequeueReusableCell(withIdentifier: "_CourseDetail_3_TCell") as! CourseDetail_3_TCell |
| | | cell.backgroundColor = UIColor(hexString: "#f6f6f6") |
| | | return cell |
| | | return cell1! |
| | | } |
| | | |
| | | var cell = tableView.dequeueReusableCell(withIdentifier: "cell") |
| | |
| | | } |
| | | |
| | | if m.chargeType == .payment && m.paidStatus == .no{ |
| | | let vc = PaymentOrderVC() |
| | | let vc = PaymentOrderVC(courseId: m.id) |
| | | JQ_currentViewController().jq_push(vc: vc) |
| | | return |
| | | } |
| | |
| | | class PaymentOrderResultVC: BaseVC { |
| | | |
| | | var collectionView:UICollectionView! |
| | | private let topView = PaymentOrderResultTopView.jq_loadNibView() |
| | | // private let shadowView = UIView() |
| | | private let topView = PaymentOrderResultTopView.jq_loadNibView() |
| | | private var courseId:Int! |
| | | private var price:Double! |
| | | private var models = [CourseModel]() |
| | | |
| | | init(courseId:Int,price:Double) { |
| | | super.init(nibName: nil, bundle: nil) |
| | | self.courseId = courseId |
| | | self.price = price |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | title = "支付结果" |
| | | |
| | | NotificationCenter.default.post(name: CourseRefresh_Noti, object: nil) |
| | | |
| | | yy_popBlock = { [weak self] () in |
| | | var toVC:UIViewController? |
| | | for v in self?.navigationController?.viewControllers ?? []{ |
| | | if v is CourseDetialVC{ |
| | | toVC = v;break |
| | | } |
| | | } |
| | | if toVC != nil{ |
| | | self?.navigationController?.popToViewController(toVC!, animated: true) |
| | | }else{ |
| | | self?.navigationController?.popToRootViewController(animated: true) |
| | | } |
| | | } |
| | | |
| | | topView.setPrice(price) |
| | | |
| | | Services.paymentSuccess(courseId: courseId).subscribe(onNext: {data in |
| | | self.models = data.data ?? [] |
| | | self.collectionView.reloadData() |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | extension PaymentOrderResultVC:UIScrollViewDelegate{ |
| | | func scrollViewDidScroll(_ scrollView: UIScrollView) { |
| | | let v = (scrollView.contentOffset.y) + 298 |
| | | topView.y = -v |
| | | navigationController?.navigationBar.standardAppearance.backgroundColor = .white |
| | | } |
| | | } |
| | | |
| | | extension PaymentOrderResultVC:UICollectionViewDelegate & UICollectionViewDataSource{ |
| | | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { |
| | | return 50 |
| | | return models.count |
| | | } |
| | | |
| | | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { |
| | | // let vc = HomeItemDetailVC() |
| | | // push(vc: vc) |
| | | |
| | | let model = models[indexPath.row] |
| | | let vc = CourseDetialVC(courseId: model.id) |
| | | push(vc: vc) |
| | | } |
| | | |
| | | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { |
| | |
| | | import UIKit |
| | | import QMUIKit |
| | | |
| | | let Refreh_PaymentWallet_Noti = Notification.Name.init("Refreh_PaymentWallet_Noti") |
| | | |
| | | class PaymentOrderVC: BaseVC { |
| | | |
| | | @IBOutlet weak var image_cover: UIImageView! |
| | | @IBOutlet weak var label_price: UILabel! |
| | | @IBOutlet weak var label_teacher: UILabel! |
| | | @IBOutlet weak var label_paymentCount: UILabel! |
| | | @IBOutlet weak var label_courseName: UILabel! |
| | | @IBOutlet weak var label_orderPrice: UILabel! |
| | | @IBOutlet weak var label_currentAccount: UILabel! |
| | | @IBOutlet weak var label_totalPrice: UILabel! |
| | | @IBOutlet weak var view_searchUserInput: UIView! |
| | | @IBOutlet weak var view_searchUserResult: UIView! |
| | | |
| | | @IBOutlet weak var image_avatar: UIImageView! |
| | | @IBOutlet weak var label_userName: UILabel! |
| | | @IBOutlet weak var label_userPhone: UILabel! |
| | | @IBOutlet weak var label_searchInfo: UILabel! |
| | | @IBOutlet weak var btn_invate: UIButton! |
| | | @IBOutlet weak var btn_isRead: UIButton! |
| | | |
| | | @IBOutlet weak var tf_phone: QMUITextField! |
| | | @IBOutlet weak var label_walletBalance: UILabel! |
| | | @IBOutlet weak var btn_isreadAgreement: UIButton! |
| | | private var courseId:Int! |
| | | private var giftUserId:Int? |
| | | private var giftToOther:Bool! |
| | | private var courseModel:CourseModel? |
| | | private var balance:Double = 0 |
| | | |
| | | init(courseId:Int,giftToOther:Bool = false) { |
| | | super.init(nibName: nil, bundle: nil) |
| | | self.courseId = courseId |
| | | self.giftToOther = giftToOther |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | title = "确认订单" |
| | | view_searchUserResult.isHidden = true |
| | | view_searchUserInput.isHidden = !giftToOther |
| | | |
| | | getBalance() |
| | | |
| | | Services.getCourseDetail(courseId: courseId).subscribe(onNext: {data in |
| | | if let m = data.data{ |
| | | self.courseModel = m |
| | | self.image_cover.sd_setImage(with: URL(string: m.coverUrl)) |
| | | self.label_courseName.text = m.courseTitle |
| | | self.label_price.text = "愈疗币\(m.generalPrice.jq_formatFloat)" |
| | | self.label_teacher.text = "导师\(m.tutor)" |
| | | self.label_paymentCount.text = "x\(m.count)" |
| | | self.label_orderPrice.text = "愈疗币\(m.generalPrice.jq_formatFloat)" |
| | | self.label_totalPrice.text = "愈疗币\(m.generalPrice.jq_formatFloat)" |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | override func setUI() { |
| | | super.setUI() |
| | | |
| | | } |
| | | |
| | | override func setRx() { |
| | | NotificationCenter.default.rx.notification(Refreh_PaymentWallet_Noti).take(until: self.rx.deallocated).subscribe(onNext: {_ in |
| | | self.getBalance() |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | private func getBalance(){ |
| | | Services.getUserBalance().subscribe(onNext: {data in |
| | | self.balance = data.data ?? 0 |
| | | self.label_walletBalance.text = String(format: "当前可用 %@疗愈币", data.data?.jq_formatFloat ?? "0") |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | @IBAction func invateRegisterAction(_ sender: UIButton) { |
| | |
| | | } |
| | | |
| | | @IBAction func searchUserAction(_ sender: UIButton) { |
| | | guard !tf_phone.text!.isEmpty else { |
| | | alertError(msg: tf_phone.placeholder ?? "请输入好友手机号");return |
| | | } |
| | | |
| | | guard tf_phone.text!.jq_isPhone else { |
| | | alertError(msg: "请输入正确的手机号");return |
| | | } |
| | | |
| | | Services.searchUserByPhone(tf_phone.text!).subscribe(onNext: { data in |
| | | self.view_searchUserResult.isHidden = false |
| | | if let m = data.data,m.id != 0{ |
| | | self.giftUserId = m.userId |
| | | self.image_avatar.sd_setImage(with: URL(string: m.avatar)) |
| | | self.label_userName.text = m.nickname |
| | | self.label_userPhone.text = m.cellPhone |
| | | self.label_searchInfo.isHidden = true |
| | | self.btn_invate.isHidden = true |
| | | }else{ |
| | | self.image_avatar.isHidden = true |
| | | self.label_userName.isHidden = true |
| | | self.label_userPhone.isHidden = true |
| | | self.label_searchInfo.isHidden = false |
| | | self.btn_invate.isHidden = false |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | @IBAction func webAgreementAction(_ sender: UIButton) { |
| | | |
| | | let vc = WebVC(type: .course) |
| | | push(vc: vc) |
| | | } |
| | | |
| | | @IBAction func completeAction(_ sender: UIButton) { |
| | | let vc = PaymentOrderResultVC() |
| | | |
| | | guard let m = courseModel else {return} |
| | | |
| | | guard balance > m.generalPrice else{ |
| | | CommonAlertView.show(title: "提示", content: "当前余额不足,请先充值", cancelStr: "暂不充值", completeStr: "去充值", isSingle: false) { state in |
| | | if state{ |
| | | |
| | | } |
| | | } |
| | | return |
| | | } |
| | | |
| | | guard btn_isRead.isSelected else { |
| | | alertError(msg: "请先阅读并同意《课程/疗愈音频购买协议》");return |
| | | } |
| | | |
| | | if giftToOther { |
| | | guard giftUserId != nil else { |
| | | alertError(msg: "请输入您要赠送人的手机号");return |
| | | } |
| | | } |
| | | |
| | | let vc = PaymentOrderResultVC(courseId: courseId, price: m.generalPrice) |
| | | push(vc: vc) |
| | | } |
| | | } |
| | |
| | | <objects> |
| | | <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="PaymentOrderVC" customModule="XQMuse" customModuleProvider="target"> |
| | | <connections> |
| | | <outlet property="btn_invate" destination="3oo-WM-iPM" id="gMF-RC-xpe"/> |
| | | <outlet property="btn_isRead" destination="9jh-cC-nHB" id="a2J-f4-hup"/> |
| | | <outlet property="btn_isreadAgreement" destination="9jh-cC-nHB" id="kmT-qh-HGA"/> |
| | | <outlet property="image_avatar" destination="TT7-tl-th0" id="5bW-5j-b49"/> |
| | | <outlet property="image_cover" destination="LBY-Q2-RQA" id="ygZ-SN-xO1"/> |
| | | <outlet property="label_courseName" destination="GMw-pK-u8J" id="bFk-Vl-gDP"/> |
| | | <outlet property="label_currentAccount" destination="W3z-Hl-09j" id="Lrx-D9-x8Y"/> |
| | | <outlet property="label_orderPrice" destination="s0D-hY-lov" id="Y0T-c6-a7g"/> |
| | | <outlet property="label_paymentCount" destination="hW7-II-bKY" id="6Oe-Qv-0S4"/> |
| | | <outlet property="label_price" destination="iyN-A8-Fyo" id="2M1-II-1hx"/> |
| | | <outlet property="label_searchInfo" destination="jVb-Rt-nvY" id="Vty-h8-0vY"/> |
| | | <outlet property="label_teacher" destination="y7d-Qe-XsO" id="I7L-lZ-geq"/> |
| | | <outlet property="label_totalPrice" destination="M0e-rH-WtI" id="BHo-Bg-EhQ"/> |
| | | <outlet property="label_userName" destination="hrJ-kN-vso" id="HlX-AF-pbk"/> |
| | | <outlet property="label_userPhone" destination="ZF1-aZ-gRo" id="Htl-Of-nO6"/> |
| | | <outlet property="label_walletBalance" destination="W3z-Hl-09j" id="CNw-KV-Uyh"/> |
| | | <outlet property="tf_phone" destination="W3K-U0-zHA" id="IkD-kf-fwY"/> |
| | | <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> |
| | | <outlet property="view_searchUserInput" destination="4AR-Ov-N15" id="PUF-Q2-O32"/> |
| | | <outlet property="view_searchUserResult" destination="nDP-lX-aFn" id="dT4-gg-Lzj"/> |
| | | </connections> |
| | | </placeholder> |
| | | <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> |
| | |
| | | |
| | | class PaymentOrderResultTopView: UIView,JQNibView{ |
| | | |
| | | |
| | | @IBOutlet weak var label_price: UILabel! |
| | | @IBOutlet weak var btn_lookCourse: UIButton! |
| | | |
| | |
| | | super.awakeFromNib() |
| | | } |
| | | |
| | | func setPrice(_ price:Double){ |
| | | label_price.text = "\(price.jq_formatFloat)" |
| | | } |
| | | |
| | | @IBAction func backRootAction(_ sender: UIButton) { |
| | | JQ_currentNavigationController().popToRootViewController(animated: true) |
| | | } |
| | |
| | | <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> |
| | | <nil key="highlightedColor"/> |
| | | </label> |
| | | <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2980.00" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hDa-VO-Vzk"> |
| | | <rect key="frame" x="160.66666666666666" y="165" width="124.99999999999997" height="37"/> |
| | | <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hDa-VO-Vzk"> |
| | | <rect key="frame" x="213" y="165" width="20.333333333333343" height="37"/> |
| | | <constraints> |
| | | <constraint firstAttribute="height" constant="37" id="9iu-Ck-Y6k"/> |
| | | </constraints> |
| | |
| | | |
| | | Services.loginBy(phone: viewModel.loginPhone.value, content: viewModel.loginContent.value, type: viewModel.loginType.value).subscribe(onNext: { data in |
| | | if let model = data.data{ |
| | | UserViewModel.saveUserInfo(model) |
| | | sceneDelegate?.loginSuccess() |
| | | |
| | | UserViewModel.saveLoginInfo(model) |
| | | |
| | | Services.getUserInfo().subscribe(onNext: {data in |
| | | if let model = data.data{ |
| | | UserViewModel.saveAvatarInfo(model) |
| | | } |
| | | }).disposed(by: self.disposeBag) |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | |
| | | |
| | | Services.register(cellPhone: viewModel.phone.value, captcha: viewModel.code.value, password: viewModel.pwd.value).subscribe(onNext: {data in |
| | | if let model = data.data{ |
| | | UserViewModel.saveUserInfo(model) |
| | | sceneDelegate?.loginSuccess() |
| | | |
| | | UserViewModel.saveLoginInfo(model) |
| | | Services.getUserInfo().subscribe(onNext: {data in |
| | | if let model = data.data{ |
| | | UserViewModel.saveAvatarInfo(model) |
| | | } |
| | | }).disposed(by: self.disposeBag) |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | |
| | | var headers = [String]() |
| | | var id: Int = 0 |
| | | var iosPrice: Int = 0 |
| | | var isBuy: Int = 0 |
| | | var isVip: Int = 0 |
| | | var isBuy: ConditionType = .no |
| | | var isVip: ConditionType = .no |
| | | var latitude: Int = 0 |
| | | var listingStatus: Int = 0 |
| | | var longitude: Int = 0 |
| | |
| | | } |
| | | |
| | | |
| | | struct UserInfoModel:HandyJSON,Identifiable,Codable{ |
| | | |
| | | static let idKey = \UserInfoModel.id |
| | | |
| | | var appleId: String = "" |
| | | var avatar: String = "" |
| | | var balance: Int = 0 |
| | | var birthday: String = "" |
| | | var cellPhone: String = "" |
| | | var company: String = "" |
| | | var createBy: String = "" |
| | | var createTime: String = "" |
| | | var delFlag: Int = 0 |
| | | var education: String = "" |
| | | var email: String = "" |
| | | var freezingOperator: String = "" |
| | | var freezingReason: String = "" |
| | | var gender: Int = 0 |
| | | var hometown: String = "" |
| | | var id: Int = 0 |
| | | var income: Int = 0 |
| | | var industry: String = "" |
| | | var inviteUserId: Int = 0 |
| | | var isFirst: Int = 0 |
| | | var levelSettingId: Int = 0 |
| | | var location: String = "" |
| | | var logoutTime: String = "" |
| | | var nickname: String = "" |
| | | var occupation: String = "" |
| | | var registerTime: String = "" |
| | | var sanskritFlag: Int = 0 |
| | | var signature: String = "" |
| | | var signTime: String = "" |
| | | var tagId: String = "" |
| | | var totalEnergyValue: Int = 0 |
| | | var updateBy: String = "" |
| | | var updateTime: String = "" |
| | | var userId: Int = 0 |
| | | var userStatus: Int = 0 |
| | | var vipExpireTime: String = "" |
| | | var isVip:ConditionType = .no |
| | | var wxOpenId: String = "" |
| | | } |
| | | |
| | | struct TutorInfoModel:HandyJSON{ |
| | | var id = 0 |
| | | var tutorIntroduction = "" |
| | | var coverUrl = "" |
| | | var videoUrl = "" |
| | | var list = [CourseModel]() |
| | | } |
| | | |
| | | |
| | | struct TreeInfoModel:HandyJSON,Identifiable,Codable{ |
| | | |
| | | static let idKey = \TreeInfoModel.id |
| | | |
| | | var appUserId: Int = 0 |
| | | var createBy: String = "" |
| | | var createTime: String = "" |
| | | var currentEnergyValue: Int = 0 |
| | | var delFlag: Int = 0 |
| | | var growthValue: Int = 0 |
| | | var id: Int = 0 |
| | | var isSign: ConditionType = .no |
| | | var nextLevel: Int = 0 |
| | | var sowAgain: ConditionType = .no |
| | | var taskOne: ConditionType = .no |
| | | var taskTwo: ConditionType = .no |
| | | var treeLevelType: TreeLevel = .level_1 |
| | | var updateBy: String = "" |
| | | var updateTime: String = "" |
| | | var status:ConditionType = .no //是否枯萎 |
| | | } |
| | | |
| | | struct WateringModel:HandyJSON{ |
| | | var growthValue = 0 |
| | | var nextLevel = 0 |
| | | var isNext = false |
| | | var status = 0 //是否枯萎 1是2否(暂时不用) |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | extension Double: HandyJSON{ |
| | | |
| | | } |
| | | |
| | | class ParamsAppender: NSObject { |
| | | var url: URL |
| | | var params:Dictionary = [String: Any]() |
| | |
| | | return NetworkRequest.request(params: params, method: .post, progress: false) |
| | | } |
| | | |
| | | /// 课程详情 |
| | | class func getCourseDetail(courseId:Int)->Observable<BaseResponse<CourseModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/course/client/course/course/getPayCourseInfoById") |
| | | .append(key: "id", value: courseId) |
| | | .append(key: "apipost_id", value: "2d2eb9d23993bd") |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | |
| | | class func tutorInfo()->Observable<BaseResponse<TutorInfoModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/course/client/course/tutor-special-column/getCoursePageList") |
| | | .append(key: "apipost_id", value: "2d2eb9d23993c2") |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | ///用户相关 |
| | | extension Services{ |
| | | class func searchUserByPhone(_ phone:String)->Observable<BaseResponse<UserInfoModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/user/client/app-user/getUserByPhone") |
| | | .append(key: "phone", value: phone) |
| | | .append(key: "apipost_id", value: "2e763463799135") |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | |
| | | /// 获取用户信息 |
| | | class func getUserInfo()->Observable<BaseResponse<UserInfoModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/user/client/app-user/getCurrentUser") |
| | | .append(key: "apipost_id", value: "2e763463799132") |
| | | return NetworkRequest.request(params: params, method: .post, progress: false) |
| | | } |
| | | |
| | | /// 支付成功 |
| | | class func paymentSuccess(courseId:Int)->Observable<BaseResponse<[CourseModel]>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/course/client/course/course/successOrder") |
| | | .append(key: "courseId", value: courseId) |
| | | .append(key: "apipost_id", value: "2d2eb9d23993c0") |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | |
| | | class func getUserBalance()->Observable<BaseResponse<Double>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/user/client/app-user/getUserBalance") |
| | | .append(key: "apipost_id", value: "2e763463799134") |
| | | return NetworkRequest.request(params: params, method: .post, progress: false) |
| | | } |
| | | } |
| | | |
| | | |
| | | /// 树苗 |
| | | extension Services{ |
| | | class func treeInfo()->Observable<BaseResponse<TreeInfoModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/user/client/app-user-tree/getUserTree") |
| | | .append(key: "apipost_id", value: "2e76346379912c") |
| | | return NetworkRequest.request(params: params, method: .post, progress: false) |
| | | } |
| | | |
| | | //浇水 |
| | | class func watering()->Observable<BaseResponse<WateringModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/user/client/app-user-tree/watering") |
| | | .append(key: "apipost_id", value: "2e763463799130") |
| | | return NetworkRequest.request(params: params, method: .post, progress: false) |
| | | } |
| | | } |
| | | |
| | | extension Services{ |
| | | /// 获取协议 |
| | | class func agreementBy(_ type:AgreementType)->Observable<BaseResponse<HtmlModel>>{ |
| | |
| | | } |
| | | |
| | | class UserViewModel{ |
| | | private static let userInfo = UserDefaultsStore<LoginUserInfoModel>(uniqueIdentifier: "UserInfoModel")! |
| | | private static let userLoginInfo = UserDefaultsStore<LoginUserInfoModel>(uniqueIdentifier: "userLoginInfo")! |
| | | private static let userAvatarInfo = UserDefaultsStore<UserInfoModel>(uniqueIdentifier: "userAvatarInfo")! |
| | | |
| | | static func getToken()->String?{ |
| | | return UserDefaults.standard.object(forKey: "_userToken") as? String |
| | |
| | | UserDefaults.standard.synchronize() |
| | | } |
| | | |
| | | static func saveUserInfo(_ model:LoginUserInfoModel){ |
| | | static func saveLoginInfo(_ model:LoginUserInfoModel){ |
| | | do{ |
| | | try UserViewModel.userInfo.save(model) |
| | | try UserViewModel.userLoginInfo.save(model) |
| | | }catch{ |
| | | |
| | | } |
| | | } |
| | | |
| | | static func getUserInfo()->LoginUserInfoModel?{ |
| | | return UserViewModel.userInfo.allObjects().first |
| | | static func getLoginInfo()->LoginUserInfoModel?{ |
| | | return UserViewModel.userLoginInfo.allObjects().first |
| | | } |
| | | |
| | | static func clearUserInfo(){ |
| | | UserViewModel.userInfo.deleteAll() |
| | | static func clearLoginInfo(){ |
| | | UserViewModel.userLoginInfo.deleteAll() |
| | | } |
| | | |
| | | |
| | | static func saveAvatarInfo(_ model:UserInfoModel){ |
| | | do{ |
| | | try UserViewModel.userAvatarInfo.save(model) |
| | | }catch{ |
| | | |
| | | } |
| | | } |
| | | |
| | | static func getAvatarInfo()->UserInfoModel{ |
| | | let userModel = UserViewModel.userAvatarInfo.allObjects().first |
| | | return userModel == nil ? UserInfoModel():userModel! |
| | | } |
| | | |
| | | static func clearAvatarInfo(){ |
| | | UserViewModel.userAvatarInfo.deleteAll() |
| | | } |
| | | } |
| | |
| | | |
| | | private var url:String? |
| | | private var disposeBag = DisposeBag() |
| | | private var placeHoderImageUrl:String? |
| | | |
| | | private lazy var player: CLPlayer = { |
| | | private(set) lazy var player: CLPlayer = { |
| | | let p = CLPlayer(frame: .zero) { config in |
| | | config.topBarHiddenStyle = .always |
| | | config.isHiddenMorePanel = true |
| | |
| | | return p |
| | | }() |
| | | |
| | | required init(url:String) { |
| | | required init(url:String? = nil,autoPlay:Bool = false,placeHoderImageUrl:String? = nil) { |
| | | super.init(frame: .zero) |
| | | self.url = url |
| | | addSubview(player) |
| | | player.delegate = self |
| | | player.snp.makeConstraints { make in |
| | | make.edges.equalToSuperview() |
| | | } |
| | | self.placeHoderImageUrl = placeHoderImageUrl |
| | | if placeHoderImageUrl != nil{ |
| | | addPlaceHoderView(placeHoderImage: placeHoderImageUrl!) |
| | | } |
| | | |
| | | if let Url = URL(string: url){ |
| | | self.url = url |
| | | player.url = Url |
| | | addSubview(player) |
| | | player.delegate = self |
| | | player.snp.makeConstraints { make in |
| | | make.edges.equalToSuperview() |
| | | if autoPlay{ |
| | | player.play() |
| | | } |
| | | player.play() |
| | | } |
| | | } |
| | | |
| | | |
| | | func updateVideoUrl(_ url:String){ |
| | | func updateVideoUrl(_ url:String,autoPlay:Bool = false,placeHoderImageUrl:String? = nil){ |
| | | |
| | | self.placeHoderImageUrl = placeHoderImageUrl |
| | | if placeHoderImageUrl != nil{ |
| | | addPlaceHoderView(placeHoderImage: placeHoderImageUrl!) |
| | | } |
| | | |
| | | if let Url = URL(string: url){ |
| | | player.url = Url |
| | | player.play() |
| | | if autoPlay{ |
| | | player.play() |
| | | } |
| | | } |
| | | } |
| | | |
| | | private func addPlaceHoderView(placeHoderImage:String){ |
| | | let placeV = UIView() |
| | | placeV.backgroundColor = .black |
| | | placeV.frame = player.frame |
| | | |
| | | let imageView = UIImageView() |
| | | imageView.sd_setImage(with: URL(string: placeHoderImage)) |
| | | imageView.contentMode = .scaleAspectFill |
| | | placeV.addSubview(imageView) |
| | | imageView.frame = player.frame |
| | | |
| | | let btn_placeholder = UIButton(type: .custom) |
| | | btn_placeholder.setImage(UIImage(named: "icon_play"), for: .normal) |
| | | btn_placeholder.addTarget(self, action: #selector(continueVideo), for: .touchUpInside) |
| | | placeV.addSubview(btn_placeholder) |
| | | btn_placeholder.snp.makeConstraints { make in |
| | | make.center.equalToSuperview() |
| | | } |
| | | |
| | | player.placeholder = placeV |
| | | } |
| | | |
| | | func pauseVideo(){ |
| | | player.pause() |
| | | } |
| | | |
| | | @objc func continueVideo(){ |
| | | player.play() |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | |
| | | import AVKit |
| | | import JQTools |
| | | import APNGKit |
| | | |
| | | enum TreeLevel:Int{ |
| | | case level_1 = 1 |
| | | case level_2 = 2 |
| | | case level_3 = 3 |
| | | case level_4 = 4 |
| | | case level_5 = 5 |
| | | case level_6 = 6 |
| | | case level_7 = 7 |
| | | case level_8 = 8 |
| | | case level_9 = 9 |
| | | case level_10 = 10 |
| | | |
| | | var aniResource:String{ |
| | | switch self { |
| | | case .level_1:return "apngb-animated-level-1" |
| | | case .level_2:return "apngb-animated-level-2" |
| | | case .level_3:return "apngb-animated-level-3" |
| | | case .level_4:return "apngb-animated-level-4" |
| | | case .level_5:return "apngb-animated-level-5" |
| | | case .level_6:return "apngb-animated-level-6" |
| | | case .level_7:return "apngb-animated-level-7" |
| | | case .level_8:return "apngb-animated-level-8" |
| | | case .level_9:return "apngb-animated-level-9" |
| | | case .level_10:return "apngb-animated-level-10" |
| | | } |
| | | } |
| | | } |
| | | import UserDefaultsStore |
| | | |
| | | class TreeTeskVC: BaseVC { |
| | | |
| | | private let cacheTreeInfoModel = UserDefaultsStore<TreeInfoModel>(uniqueIdentifier: "cacheTreeInfoModel")! |
| | | |
| | | @IBOutlet weak var view_energy: UIView! |
| | | @IBOutlet weak var icon_energy: UILabel! |
| | |
| | | @IBOutlet weak var view_progress: UIView! |
| | | @IBOutlet weak var cons_progressHei: NSLayoutConstraint! |
| | | @IBOutlet weak var label_progress: UILabel! |
| | | |
| | | private var tempEnergy:Int = 0 |
| | | |
| | | private lazy var player:AVPlayer = { |
| | | let bgPath = Bundle.main.url(forResource: "bg", withExtension: "mov") |
| | |
| | | private var aPNGSunImageView:APNGImageView? |
| | | private var aPNGActionImageView:APNGImageView? |
| | | |
| | | private var treeLevel:TreeLevel = .level_1{ |
| | | didSet{ |
| | | updateAni() |
| | | } |
| | | } |
| | | |
| | | private var treeInfoModel:TreeInfoModel? |
| | | |
| | | override func viewDidDisappear(_ animated: Bool) { |
| | | super.viewDidDisappear(animated) |
| | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | title = "树苗打卡站" |
| | | treeLevel = .level_1 |
| | | btn_seedingAgain.isHidden = true |
| | | |
| | | if settingModel!.userFirstOpenTreeTask{ |
| | | DispatchQueue.main.asyncAfter(delay: 2.0) { |
| | |
| | | } |
| | | } |
| | | |
| | | let h = (JQ_ScreenW - 90) * 0.7729 |
| | | TreeTeskFirstRuleView.show(title: "升级", content:"恭喜!你的树苗已升级为XX阶段!",textAlignment: .center,height: h,textTopOffset: 57) |
| | | |
| | | DispatchQueue.main.asyncAfter(deadline: .now()+2.0) { |
| | | self.setProgress(current: 900, total: 1800) |
| | | } |
| | | |
| | | getTreeData() |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | make.bottom.equalToSuperview().offset((JQ_ScreenW * 0.655 - 50)) |
| | | make.height.equalTo(JQ_ScreenW * 0.655) |
| | | } |
| | | } |
| | | |
| | | private func getTreeData(){ |
| | | |
| | | //缓存的树苗信息 |
| | | if let cacheModel = cacheTreeInfoModel.allObjects().first{ |
| | | treeInfoModel = cacheModel |
| | | updateTreeInfo() |
| | | } |
| | | |
| | | Services.treeInfo().subscribe(onNext: {data in |
| | | if let m = data.data{ |
| | | try? self.cacheTreeInfoModel.save(m) |
| | | |
| | | //检查hash,进行同步 |
| | | if m.toJSON()?.jq_hash() != self.treeInfoModel?.toJSON()?.jq_hash(){ |
| | | self.treeInfoModel = m |
| | | self.updateTreeInfo() |
| | | } |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | private func updateTreeInfo(){ |
| | | btn_seedingAgain.isHidden = treeInfoModel!.sowAgain == .no |
| | | |
| | | // if treeLevel.rawValue != treeInfoModel?.treeLevelType.rawValue{ |
| | | // treeLevel = treeInfoModel!.treeLevelType |
| | | // } |
| | | |
| | | icon_energy.text = String(format: "当前能量值:%ld", treeInfoModel!.currentEnergyValue) |
| | | setProgress(current: treeInfoModel!.growthValue, total: treeInfoModel!.nextLevel) |
| | | } |
| | | |
| | | override func setRx() { |
| | |
| | | |
| | | //能量明细 |
| | | @IBAction func energyDetailAction(_ sender: TapBtn) { |
| | | |
| | | let vc = TreeTeskDetailVC() |
| | | push(vc: vc) |
| | | } |
| | |
| | | } |
| | | |
| | | @IBAction func wateringAction(_ sender: UIButton) { |
| | | sender.isUserInteractionEnabled = false |
| | | |
| | | if treeInfoModel == nil {return} |
| | | |
| | | // guard m.currentEnergyValue != 0 else{ |
| | | // alert(msg: "已经没有能量值了,快去做任务吧");return |
| | | // } |
| | | |
| | | Services.watering().subscribe(onNext: {data in |
| | | if let m = data.data{ |
| | | if m.isNext{ |
| | | var type = self.treeInfoModel?.treeLevelType ?? .level_1 |
| | | self.treeInfoModel!.treeLevelType = TreeLevel(rawValue: type.rawValue + 1) ?? .level_1 |
| | | |
| | | let h = (JQ_ScreenW - 90) * 0.7729 |
| | | TreeTeskFirstRuleView.show(title: "升级", content:"恭喜!你的树苗已升级为\(self.treeInfoModel!.treeLevelType.title)阶段!",textAlignment: .center,height: h,textTopOffset: 57) |
| | | |
| | | self.updateAni() |
| | | } |
| | | self.treeInfoModel?.currentEnergyValue = 0 |
| | | self.treeInfoModel?.growthValue = m.growthValue |
| | | self.treeInfoModel?.nextLevel = m.nextLevel |
| | | self.updateTreeInfo() |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | |
| | | if let waterApngImage = try? APNGImage(fileURL: Bundle.main.url(forResource: "apngb-animated-flow", withExtension:"png")!){ |
| | | waterApngImage.numberOfPlays = 2 |
| | | aPNGActionImageView = APNGImageView(image: waterApngImage) |
| | |
| | | |
| | | aPNGActionImageView!.onOnePlayDone.delegate(on: self) {[unowned self] a,b in |
| | | if b == 2{ |
| | | sender.isUserInteractionEnabled = true |
| | | UIView.animate(withDuration: 0.5) { |
| | | self.aPNGActionImageView!.alpha = 0 |
| | | }completion: { _ in |
| | |
| | | } |
| | | |
| | | @objc func jumpAction(){ |
| | | treeLevel = TreeLevel(rawValue: treeLevel.rawValue + 1) ?? TreeLevel.level_1 |
| | | // treeLevel = TreeLevel(rawValue: treeLevel.rawValue + 1) ?? TreeLevel.level_1 |
| | | } |
| | | |
| | | @objc func ruleAction(){ |
| | |
| | | } |
| | | |
| | | private func updateAni(){ |
| | | let treeLevel = treeInfoModel?.treeLevelType ?? .level_1 |
| | | |
| | | guard let url = Bundle.main.url(forResource: treeLevel.aniResource, withExtension: "png") else {return} |
| | | if let treeApngImage = try? APNGImage(fileURL: url){ |
| | | guard let animateUrl = Bundle.main.url(forResource: treeLevel.aniResource, withExtension: "png") else {return} |
| | | guard let staticDroopUrl = Bundle.main.url(forResource: treeLevel.staticDroopResource, withExtension: "png") else {return} |
| | | |
| | | if let treeApngImage = try? APNGImage(fileURL: animateUrl){ |
| | | |
| | | if treeLevel == .level_1{ |
| | | treeApngImage.numberOfPlays = 1 |
| | |
| | | view.addSubview(aPNGTreeImageView!) |
| | | } |
| | | |
| | | // aPNGTreeImageView!.backgroundColor = .red.withAlphaComponent(0.1) |
| | | let scale:Double = 0.55 |
| | | let scale:Double = 0.55 //放大倍数 |
| | | |
| | | aPNGTreeImageView!.snp.remakeConstraints { make in |
| | | make.centerX.equalToSuperview().offset(-10) |
| | |
| | | self.aPNGTreeImageView?.alpha = 1 |
| | | }completion: { _ in |
| | | self.aPNGTreeImageView!.startAnimating() |
| | | |
| | | if self.treeInfoModel?.status == .yes{ |
| | | self.aPNGTreeImageView?.stopAnimating() |
| | | self.aPNGTreeImageView?.image = nil |
| | | self.aPNGTreeImageView?.staticImage = UIImage(contentsOfFile: staticDroopUrl.droppedScheme()!.absoluteString) |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | func needLogin(){ |
| | | UserViewModel.clearToken() |
| | | UserViewModel.clearLoginInfo() |
| | | UserViewModel.clearAvatarInfo() |
| | | |
| | | let loginNav = LoginNav(rootViewController: LoginVC()) |
| | | loginNav.modalPresentationStyle = .fullScreen |
| | | JQ_currentViewController().present(loginNav, animated: true) |