杨锴
2024-10-25 098286ed0313b1d3f1141113b371f8b17b8b26b5
fix API
2 文件已重命名
5个文件已删除
28个文件已修改
1个文件已添加
1331 ■■■■■ 已修改文件
XQMuse/Assets.xcassets/Btns/btn_share_1.imageset/Contents.json 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Config/HoverHeaderFlowLayout.swift 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Config/InPurchaseManager.swift 305 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Config/Layouts/EqualCellSpaceFlowLayout.swift 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Config/Layouts/TestLeftRightCollectionViewFlowLayout.swift 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Config/StoreKit/StoreKitTestCertificate.cer 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Config/XQMuseStoreKit.storekit 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Course/VC/CourseDetialVC.swift 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Course/VC/CourseDetialVideoVC.swift 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Home/HomeVC.swift 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Home/VC/HomeItemDetailVC.swift 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Login/LoginVC.swift 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Login/VC/ForgotPasswordChangeVC.swift 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Login/VC/ForgotPasswordInputCodeVC.swift 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Login/VC/UpdatePhoneVC.swift 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Login/VC/UpdatePhoneVC.xib 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Me/MeVC.swift 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Me/MeVC.xib 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Me/VC/BindAccountVC.swift 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Me/VC/SettingVC.swift 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Me/VC/SettingVC.xib 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Me/VC/VIPCenterVC.swift 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Me/VC/WatchHistoryDetailVC.swift 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Network/Models.swift 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Network/Services.swift 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Other/View/CountdownChooseListView.swift 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/Other/View/VideoView.swift 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/PayMusicView/PayMusicVC.swift 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/TreeGroup/TCell/TreeTeskEnergyTCell.xib 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/TreeGroup/TreeTeskVC.swift 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/TreeGroup/VC/TreeTeskEnergyExchangeVC.swift 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/TreeGroup/View/TreeTeskExchangeSuccessView.swift 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/TreeGroup/View/TreeTeskExchangeSuccessView.xib 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Root/TreeGroup/View/TreeTeskListView.swift 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/SceneDelegate.swift 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuseStoreKit.storekit 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
XQMuse/Assets.xcassets/Btns/btn_share_1.imageset/Contents.json
File was deleted
XQMuse/Config/HoverHeaderFlowLayout.swift
File was deleted
XQMuse/Config/InPurchaseManager.swift
File was deleted
XQMuse/Config/Layouts/EqualCellSpaceFlowLayout.swift
New file
@@ -0,0 +1,136 @@
//
//  EqualCellSpaceFlowLayout.swift
//  XQMuse
//
//  Created by 无故事王国 on 2024/8/27.
//
import UIKit
enum AlignType : NSInteger {
                case left = 0
                case center = 1
                case right = 2
}
class EqualCellSpaceFlowLayout: UICollectionViewFlowLayout {
                //两个Cell之间的距离
                private var horizontalSpace : CGFloat{
                                didSet{
                                                self.minimumInteritemSpacing = horizontalSpace
                                }
                }
                //cell对齐方式
                private var alignType : AlignType = AlignType.center
                //在居中对齐的时候需要知道这行所有cell的宽度总和
                var cellWidthInLine : CGFloat = 0.0
                override init() {
                                horizontalSpace = 5.0
                                super.init()
                                scrollDirection = UICollectionView.ScrollDirection.vertical
                                minimumLineSpacing = 5
                                sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
                }
                convenience init(_ cellType:AlignType){
                                self.init()
                                self.alignType = cellType
                }
                convenience init(_ cellType: AlignType, _ horizontalSpace: CGFloat){
                                self.init()
                                self.alignType = cellType
                                self.horizontalSpace = horizontalSpace
                }
                required init?(coder aDecoder: NSCoder) {
                                horizontalSpace = 5.0
                                super.init(coder: aDecoder)
                                scrollDirection = UICollectionView.ScrollDirection.vertical
                                minimumLineSpacing = 5
                                sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
                }
                override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
                                let layoutAttributes_super : [UICollectionViewLayoutAttributes] = super.layoutAttributesForElements(in: rect) ?? [UICollectionViewLayoutAttributes]()
                                let layoutAttributes:[UICollectionViewLayoutAttributes] = NSArray(array: layoutAttributes_super, copyItems:true)as! [UICollectionViewLayoutAttributes]
                                var layoutAttributes_t : [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
                                for index in 0..<layoutAttributes.count{
                                                print("index in 0..<layoutAttributes.count ==============")
                                                let currentAttr = layoutAttributes[index]
                                                let previousAttr = index == 0 ? nil : layoutAttributes[index-1]
                                                let nextAttr = index + 1 == layoutAttributes.count ?
                                                nil : layoutAttributes[index+1]
                                                layoutAttributes_t.append(currentAttr)
                                                cellWidthInLine += currentAttr.frame.size.width
                                                let previousY :CGFloat = previousAttr == nil ? 0 : previousAttr!.frame.maxY
                                                let currentY :CGFloat = currentAttr.frame.maxY
                                                let nextY:CGFloat = nextAttr == nil ? 0 : nextAttr!.frame.maxY
                                                if currentY != previousY && currentY != nextY{
                                                                if currentAttr.representedElementKind == UICollectionView.elementKindSectionHeader{
                                                                                layoutAttributes_t.removeAll()
                                                                                cellWidthInLine = 0.0
                                                                                print("currentAttr.representedElementKind == UICollectionView.elementKindSectionHeader =========== Header")
                                                                }else if currentAttr.representedElementKind == UICollectionView.elementKindSectionFooter{
                                                                                layoutAttributes_t.removeAll()
                                                                                cellWidthInLine = 0.0
                                                                                print("currentAttr.representedElementKind == UICollectionView.elementKindSectionFooter ============ Footer")
                                                                }else{
                                                                                self.setCellFrame(with: layoutAttributes_t)
                                                                                layoutAttributes_t.removeAll()
                                                                                cellWidthInLine = 0.0
                                                                                print("currentY != previousY && currentY != nextY ============== Item")
                                                                }
                                                } else if currentY != nextY { //这里currentY == previousY 说明和上一个项目在同一行,currentY != nextY说明下一个项目要换行了,这种情况直接计算本行的对齐方式
                                                                self.setCellFrame(with: layoutAttributes_t)
                                                                layoutAttributes_t.removeAll()
                                                                cellWidthInLine = 0.0
                                                                print("currentY != nextY ======== Else")
                                                }
                                }
                                return layoutAttributes
                }
                /// 调整Cell的Frame
                ///
                /// - Parameter layoutAttributes: layoutAttribute 数组
                func setCellFrame(with layoutAttributes : [UICollectionViewLayoutAttributes]){
                                var nowWidth : CGFloat = 0.0
                                switch alignType {
                                                case AlignType.left:
                                                                nowWidth = self.sectionInset.left
                                                                for attributes in layoutAttributes {
                                                                                var nowFrame = attributes.frame
                                                                                nowFrame.origin.x = nowWidth
                                                                                attributes.frame = nowFrame
                                                                                nowWidth += nowFrame.size.width + self.horizontalSpace
                                                                }
                                                                break;
                                                case AlignType.center:
                                                                nowWidth = (self.collectionView!.frame.size.width - cellWidthInLine - (CGFloat(layoutAttributes.count - 1) * horizontalSpace)) / 2
                                                                for attributes in layoutAttributes{
                                                                                var nowFrame = attributes.frame
                                                                                nowFrame.origin.x = nowWidth
                                                                                attributes.frame = nowFrame
                                                                                nowWidth += nowFrame.size.width + self.horizontalSpace
                                                                }
                                                                break;
                                                case AlignType.right:
                                                                nowWidth = self.collectionView!.frame.size.width - self.sectionInset.right
                                                                for var index in 0 ..< layoutAttributes.count{
                                                                                index = layoutAttributes.count - 1 - index
                                                                                let attributes = layoutAttributes[index]
                                                                                var nowFrame = attributes.frame
                                                                                nowFrame.origin.x = nowWidth - nowFrame.size.width
                                                                                attributes.frame = nowFrame
                                                                                nowWidth = nowWidth - nowFrame.size.width - horizontalSpace
                                                                }
                                                                break;
                                }
                }
}
XQMuse/Config/Layouts/TestLeftRightCollectionViewFlowLayout.swift
XQMuse/Config/StoreKit/StoreKitTestCertificate.cer
Binary files differ
XQMuse/Config/XQMuseStoreKit.storekit
File was deleted
XQMuse/Root/Course/VC/CourseDetialVC.swift
@@ -21,6 +21,7 @@
                private var tableView:UITableView?
    private var collect_bitem:UIBarButtonItem!
    private var share_bitem:UIBarButtonItem!
                private let studyBtn = QMUIButton(type: .custom)
                private var headerView = CourseDetailHeaderView.jq_loadNibView()
                private var barStyle:UIStatusBarStyle = .lightContent
@@ -121,7 +122,7 @@
        collect_bitem = UIBarButtonItem(image: UIImage(named: "btn_collect"), style: .plain, target: self, action: #selector(collectionAction))
        collect_bitem.tintColor = .white
        let share_bitem = UIBarButtonItem(image: UIImage(named: "btn_share"), style: .plain, target: self, action: #selector(shareAction))
        share_bitem = UIBarButtonItem(image: UIImage(named: "btn_share"), style: .plain, target: self, action: #selector(shareAction))
        share_bitem.tintColor = .white
        share_bitem.imageInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 15)
        navigationItem.rightBarButtonItems = [share_bitem,collect_bitem]
@@ -349,10 +350,21 @@
                                if v > 0{
                                                (navigationItem.leftBarButtonItem?.customView as? UIButton)?.setImage(UIImage(named: "btn_back")?.withTintColor(.black.withAlphaComponent(v)), for: .normal)
            (navigationItem.rightBarButtonItem?.customView as? UIButton)?.setImage(UIImage(named: "btn_back")?.withTintColor(.black.withAlphaComponent(v)), for: .normal)
            collect_bitem.tintColor = .black
            share_bitem.tintColor = .black
                                                self.navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:Def_NavFontColor.withAlphaComponent(v),.font:Def_NavFont]
                                                barStyle = .darkContent
                                }else{
            collect_bitem.tintColor = .white
            share_bitem.tintColor = .white
                                                (navigationItem.leftBarButtonItem?.customView as? UIButton)?.setImage(UIImage(named: "btn_back")?.withTintColor(.white), for: .normal)
                                                self.navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor.white,.font:Def_NavFont]
                                }
XQMuse/Root/Course/VC/CourseDetialVideoVC.swift
@@ -15,6 +15,8 @@
                private var videoView:VideoView?
                private var items = [CourseItemModel]()
                private var selectIndex:IndexPath!
    private var secondLook:Int = 0
    private var isOver:Bool = false
                override func viewWillAppear(_ animated: Bool) {
                                super.viewWillAppear(animated)
@@ -31,11 +33,22 @@
                                fatalError("init(coder:) has not been implemented")
                }
                
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        let item = items[selectIndex.row]
        guard secondLook > 0 else {return}
        Services.watchClouse(chapterId: item.id, isOver: isOver, minuteLook: 0, secondLook: secondLook).subscribe(onNext: { _ in
        }).disposed(by: disposeBag)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
                                title = "课程详情"
                                videoView = VideoView(url: items[selectIndex.row].videoUrl)
        videoView = VideoView(url: items[selectIndex.row].videoUrl,delegate: self)
        videoView?.player.play()
                                view_bg_video.addSubview(videoView!)
                                videoView!.snp.makeConstraints { make in
@@ -104,3 +117,16 @@
                                tableView.reloadData()
                }
}
extension CourseDetialVideoVC:CLPlayerDelegate{
    func player(_ player: CLPlayer, playProgressChanged value: CGFloat) {
        secondLook = player.currentDuration.int
        print("视频播放进度:\(player.currentDuration.int)")
    }
    func didPlayToEnd(in player: CLPlayer) {
        isOver = true
        print("视频播放进度:【完成】")
    }
}
XQMuse/Root/Home/HomeVC.swift
@@ -142,6 +142,10 @@
                                NotificationCenter.default.rx.notification(PlantGuideQuit_Noti).take(until: self.rx.deallocated).subscribe(onNext: {data in
                                                self.getData()
                                }).disposed(by: disposeBag)
        NotificationCenter.default.rx.notification(LoginSuccess_Noti).take(until: self.rx.deallocated).subscribe(onNext: {data in
            self.getData()
        }).disposed(by: disposeBag)
                }
                private func getData(){
@@ -210,6 +214,7 @@
                @objc func jumpMoreAction(_ sender:UIButton){
                                switch sender.tag {
                                                case 201:
                guard sceneDelegate!.checkisLoginState() else {return}
                                                                //跳转计划引导
                                                                let nav    = BaseNav(rootViewController: PlanGuideVC())
                                                                nav.modalPresentationStyle = .fullScreen
XQMuse/Root/Home/VC/HomeItemDetailVC.swift
@@ -29,6 +29,7 @@
                private var collect_bitem:UIBarButtonItem!
                private var audioPlayer:AudioPlayer = AudioPlayer.getSharedInstance()
                private var id:Int!
    private var timeLook:Int = 0 //观看时间记录
                private var settingViewModel = UserDefaultSettingViewModel.getSetting()
                private var model:MeditationModel?{
                                didSet{
@@ -84,6 +85,16 @@
        super.viewWillAppear(animated)
        (navigationItem.leftBarButtonItem?.customView as? UIButton)?.setImage(UIImage(named: "btn_back")?.withTintColor(.white), for: .normal)
        navigationController?.navigationBar.scrollEdgeAppearance?.backgroundColor = .clear
    }
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        if let m = model,timeLook > 0{
            Services.watchMuse(id: m.id, timeLook: timeLook).subscribe(onNext: {_ in
            }).disposed(by: disposeBag)
        }
    }
                override func setUI() {
@@ -244,8 +255,7 @@
                                                                PayMusicVC.show(model: model!)
                                                                if btn_play.isHidden == false {btn_play.isHidden = true}
                                                                hiddenHUD()
                                                case .paurse:
                                                                btn_play.isHidden = false
                                                case .paurse:btn_play.isHidden = false
                                                case .end:break
                                                case .next:break
                                }
@@ -256,6 +266,8 @@
                                guard !totalInterval.isNaN else {return}
                                guard !currentInterval.isNaN else {return}
        timeLook += 1
                                let v = currentInterval / totalInterval * 100
                                print("music:当前时间:\(currentInterval) ---- \(totalInterval) -- \(v)%")
                                self.slider_voice.value = Float(v)
XQMuse/Root/Login/LoginVC.swift
@@ -12,6 +12,8 @@
import AuthenticationServices
let LoginSuccess_Noti = Notification.Name.init("LoginSuccess_Noti")
class LoginViewModel{
                var loginType = BehaviorRelay<LoginType>(value:.pwd)
                var loginPhone = BehaviorRelay<String>(value:"")
@@ -275,7 +277,8 @@
        if let credential = authorization.credential as? ASAuthorizationAppleIDCredential{
            Services.loginByApple(appleId: credential.user).subscribe(onNext: {data in
                if var m = data.data,m.bindStatus == 2{
                if var m = data.data{
                    if m.bindStatus == 2{
                    sceneDelegate?.loginSuccess()
                    m.loginByAppleToken = String(data: credential.identityToken!, encoding: .utf8)
                    m.appleId = credential.user
@@ -290,22 +293,11 @@
                        }
                    }).disposed(by: self.disposeBag)
                }else{
                    let vc = UpdatePhoneVC(credential: credential)
                        let vc = UpdatePhoneVC(credential: credential,firstAccessToken: m.accessToken)
                    self.jq_push(vc: vc)
                }
                }
            }).disposed(by: disposeBag)
//            print(credential.user)
//            print(credential.state)
//            print(credential.email)
//            print(credential.fullName?.familyName)
//            print(credential.fullName?.givenName)
//            print(credential.fullName?.middleName)
//            print(String(data: credential.identityToken!, encoding: .utf8))
        }
    }
XQMuse/Root/Login/VC/ForgotPasswordChangeVC.swift
@@ -65,7 +65,7 @@
                                guard tf_input.text!.jq_isComplexPassword else {alertError(msg: "密码至少8个字符,不能全是字母或数字");return}
                                Services.updatePwd(cellPhone: phone, password: tf_input.text!, secretCode: secretCode).subscribe(onNext: {data in
                                                if let model = data.data{
            if data.code == 200{
                                                                Popup_1_View.show(state: .success, title: "修改成功", subtitle: "您的密码已修改成功,快去登录账户吧") {
                                                                                self.navigationController?.popToRootViewController(animated: true)
                                                                }
XQMuse/Root/Login/VC/ForgotPasswordInputCodeVC.swift
@@ -103,13 +103,13 @@
                                times = 60
                                btn_retry.isEnabled = false
                                btn_retry.alpha = 0.5
                                timer = Timer(timeInterval: 1.0, repeats: true) {[unowned self] t in
                                                self.times -= 1
                                                self.label_retryCode.text = "\(self.times)s后可重新发送验证码"
                                                if self.times == 0{
                                                                self.label_retryCode.text = ""
                                                                self.btn_retry.isEnabled = true
                                                                self.btn_retry.alpha = 1.0
                                timer = Timer(timeInterval: 1.0, repeats: true) {[weak self] t in
                                                self?.times -= 1
                                                self?.label_retryCode.text = "\(self?.times ?? 0)s后可重新发送验证码"
                                                if self?.times == 0{
                                                                self?.label_retryCode.text = ""
                                                                self?.btn_retry.isEnabled = true
                                                                self?.btn_retry.alpha = 1.0
                                                                t.invalidate()
                                                }
                                }
XQMuse/Root/Login/VC/UpdatePhoneVC.swift
@@ -12,24 +12,30 @@
class UpdatePhoneVC: BaseVC {
    private var credential:ASAuthorizationAppleIDCredential?
    private var firstAccessToken:String? //后端问题,要把上次的token带过来
    @IBOutlet weak var tf_phone: QMUITextField!
    @IBOutlet weak var tf_code: QMUITextField!
    @IBOutlet weak var btn_code: UIButton!
    @IBOutlet weak var btn_isRead: UIButton!
    
    init(credential:ASAuthorizationAppleIDCredential? = nil) {
    init(credential:ASAuthorizationAppleIDCredential? = nil,firstAccessToken:String?) {
        super.init(nibName: nil, bundle: nil)
        self.credential = credential
        self.firstAccessToken = firstAccessToken
    }
    
    @MainActor required init?(coder: NSCoder) {
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
                                title = "验证手机号"
    }
                                
    @IBAction func isReadAction(_ sender: UIButton) {
        btn_isRead.isSelected = !btn_isRead.isSelected
    }
    @IBAction func getCodeAction(_ sender: UIButton) {
@@ -51,8 +57,33 @@
        }).disposed(by: disposeBag)
    }
    @IBAction func userRegisterTreatyAction(_ sender: UIButton) {
        let vc = LoginTreatyVC()
        vc.topIndex = 0
        vc.clickHandle {[unowned self] state in
            self.btn_isRead.isSelected = state
        }
        vc.modalPresentationStyle = .custom
        present(vc, animated: true)
    }
    @IBAction func userPrivateTreatyAction(_ sender: UIButton) {
        let vc = LoginTreatyVC()
        vc.topIndex = 1
        vc.clickHandle {[unowned self] state in
            self.btn_isRead.isSelected = state
        }
        vc.modalPresentationStyle = .custom
        present(vc, animated: true)
    }
    @IBAction func loginAction(_ sender: UIButton) {
        view.endEditing(true)
        guard btn_isRead.isSelected else {
            alertError(msg: "请先阅读并同意《用户注册协议》《用户隐私协议》");return
        }
        guard tf_phone.text!.jq_isPhone else {
            alertError(msg: "请输入正确的手机号");return
        }
@@ -69,6 +100,7 @@
        Services.confirmByApple(cellPhone: tf_phone.text!, captcha: tf_code.text!, loginType: .apple, wxOrAppleId: credentialUser,name: formatName, mail: credential!.email).subscribe(onNext: {data in
            if var model = data.data{
                model.loginByAppleToken = String(data: self.credential!.identityToken!, encoding: .utf8)
                model.accessToken = self.firstAccessToken ?? ""
                model.appleId = self.credential!.user
                sceneDelegate?.loginSuccess()
                NotificationCenter.default.post(name: LoginDismiss_Noti, object: nil, userInfo: nil)
@@ -83,4 +115,7 @@
        }).disposed(by: disposeBag)
    }
    
}
XQMuse/Root/Login/VC/UpdatePhoneVC.xib
@@ -142,6 +142,9 @@
                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                    <state key="normal" title="Button" image="btn_choose"/>
                    <state key="selected" image="btn_choose_s"/>
                    <connections>
                        <action selector="isReadAction:" destination="-1" eventType="touchUpInside" id="Qpg-Tx-ank"/>
                    </connections>
                </button>
                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="我已阅读并同意" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="38g-LO-yZD">
                    <rect key="frame" x="57.000000000000007" y="350" width="83.666666666666686" height="14.333333333333314"/>
@@ -156,6 +159,9 @@
                    <state key="normal" title="《用户隐私协议》">
                        <color key="titleColor" red="0.58823529409999997" green="0.67843137249999996" blue="0.50588235290000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                    </state>
                    <connections>
                        <action selector="userPrivateTreatyAction:" destination="-1" eventType="touchUpInside" id="BiC-Bb-hbQ"/>
                    </connections>
                </button>
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ztb-yJ-wp8">
                    <rect key="frame" x="145.66666666666666" y="343.66666666666669" width="84" height="27"/>
@@ -164,6 +170,9 @@
                    <state key="normal" title="《用户注册协议》">
                        <color key="titleColor" red="0.58823529409999997" green="0.67843137249999996" blue="0.50588235290000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                    </state>
                    <connections>
                        <action selector="userRegisterTreatyAction:" destination="-1" eventType="touchUpInside" id="iLB-7u-HH0"/>
                    </connections>
                </button>
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zN9-OK-XPQ">
                    <rect key="frame" x="31" y="423" width="331" height="40"/>
XQMuse/Root/Me/MeVC.swift
@@ -78,20 +78,29 @@
                                                self.queryNotice()
                                }).disposed(by: disposeBag)
        NotificationCenter.default.rx.notification(LoginSuccess_Noti).take(until: self.rx.deallocated).subscribe(onNext: {data in
            self.getData()
            self.queryNotice()
        }).disposed(by: disposeBag)
                }
                private func getData(){
                                Services.getUserDetail().subscribe(onNext: {data in
                                Services.getUserInfo().subscribe(onNext: {[weak self] data in
                                                if let model = data.data{
                                                                UserViewModel.saveAvatarInfo(model)
                self?.setUserUI(model: model)
                                                }
                                }).disposed(by: self.disposeBag)
        },onError: {[weak self]error in
            let model = UserViewModel.getAvatarInfo()
            if model.id > 0{
                self?.setUserUI(model: model)
            }
        }).disposed(by: disposeBag)
                }
                                Services.getUserInfo().subscribe(onNext: {data in
                                                if let model = data.data{
    private func setUserUI(model:UserInfoModel){
                                                                self.image_userAvatar.sd_setImage(with: URL(string: model.avatar))
                                                                self.label_userName.text = model.nickname
                                                                self.label_phone.text = model.cellPhone.jq_blotOutPhone()
@@ -106,8 +115,6 @@
                                                                self.label_today.attributedText = AttributedStringbuilder.build().add(string: "\(timeTurple.hour)", withFont: .systemFont(ofSize: 23), withColor: UIColor(hexString: "#152715")!).add(string: "时", withFont: .systemFont(ofSize: 12), withColor: UIColor(hexString: "#152715")!).add(string: "\(timeTurple.minute)", withFont: .systemFont(ofSize: 23), withColor: UIColor(hexString: "#152715")!).add(string: "分", withFont: .systemFont(ofSize: 12), withColor: UIColor(hexString: "#152715")!).mutableAttributedString
                                                                if model.isVip == .yes{
                                                                                self.image_vipBg.image = UIImage(named: "bg_vip")
                                                                                self.label_vipInfo.text = "你已是高级会员"
@@ -118,8 +125,6 @@
                                                                                self.label_expirtTime.text = "你还未开通会员服务"
                                                                }
                                                }
                                }).disposed(by: disposeBag)
                }
                @objc func rankAction(){
                                let vc = WebVC()
@@ -128,17 +133,20 @@
                }
                @IBAction func vipCenterAction(_ sender: Any) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                 let vc = VIPCenterVC()
                                push(vc: vc)
                }
                
                @IBAction func userProfileAction(_ sender: UIButton) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let profileVC = UserProfileVC()
                                jq_push(vc: profileVC)
                }
                @IBAction func studyLevelAction(_ sender: TapBtn) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = LevelVC()
                                push(vc: vc)
                }
@@ -155,6 +163,7 @@
                
                //学习记录
                @IBAction func studyAction(_ sender: UIButton) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = StudyListVC()
                                push(vc: vc)
                }
@@ -162,24 +171,28 @@
                //我的账户
                @IBAction func myAccountAction(_ sender: QMUIButton) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                 let vc = WalletVC()
                                push(vc: vc)
                }
                //观看历史
                @IBAction func watchHistoryAction(_ sender: QMUIButton) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = WatchHistoryVC(type: .history)
                                push(vc: vc)
                }
                //我的收藏
                @IBAction func myColletAction(_ sender: QMUIButton) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = WatchHistoryVC(type: .collect)
                                push(vc: vc)
                }
                /// 我的已购
                @IBAction func paymentCourseAction(_ sender: QMUIButton) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = WatchHistoryVC(type: .payment)
                                push(vc: vc)
                }
XQMuse/Root/Me/MeVC.xib
@@ -62,14 +62,14 @@
                                        </userDefinedRuntimeAttribute>
                                    </userDefinedRuntimeAttributes>
                                </imageView>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="--" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xiq-PE-zPH">
                                    <rect key="frame" x="86" y="17.666666666666671" width="15.333333333333329" height="20.333333333333329"/>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="请先登录" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xiq-PE-zPH">
                                    <rect key="frame" x="86" y="17.666666666666671" width="67.666666666666686" height="20.333333333333329"/>
                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                    <color key="textColor" red="0.082352941176470587" green="0.15294117647058825" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <nil key="highlightedColor"/>
                                </label>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="--" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xL7-Qf-iI2">
                                    <rect key="frame" x="86" y="48.333333333333336" width="13" height="17.000000000000007"/>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xL7-Qf-iI2">
                                    <rect key="frame" x="86" y="48.333333333333336" width="0.0" height="0.0"/>
                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                    <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <nil key="highlightedColor"/>
XQMuse/Root/Me/VC/BindAccountVC.swift
@@ -19,12 +19,14 @@
    }
                @IBAction func bindPhoneAction(_ sender: Any) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = BindPhone_1_VC()
                                push(vc: vc)
                }
                @IBAction func updatePwdAction(_ sender: TapBtn) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = ForgotPasswordVC()
                                push(vc: vc)
                }
XQMuse/Root/Me/VC/SettingVC.swift
@@ -10,10 +10,17 @@
class SettingVC: BaseVC {
    @IBOutlet weak var btn_exchange: UIButton!
    @IBOutlet weak var btn_logout: UIButton!
    @IBOutlet weak var btn_dispel: TapBtn!
    override func viewDidLoad() {
        super.viewDidLoad()
                                title = "设置"
                                
        btn_exchange.isHidden = UserViewModel.getLoginInfo()?.accessToken.isEmpty ?? true
        btn_logout.isHidden = UserViewModel.getLoginInfo()?.accessToken.isEmpty ?? true
        btn_dispel.isHidden = UserViewModel.getLoginInfo()?.accessToken.isEmpty ?? true
    }
                override func setUI() {
@@ -22,6 +29,7 @@
                }
                @IBAction func bindPhoneAction(_ sender: TapBtn) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = BindAccountVC()
                                push(vc: vc)
                }
XQMuse/Root/Me/VC/SettingVC.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_12" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -11,6 +11,9 @@
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SettingVC" customModule="XQMuse" customModuleProvider="target">
            <connections>
                <outlet property="btn_dispel" destination="ta8-pP-aEf" id="cYz-J5-XFi"/>
                <outlet property="btn_exchange" destination="yK9-0E-44J" id="Dlg-Zq-IOs"/>
                <outlet property="btn_logout" destination="7uR-yB-LEb" id="scc-Tc-lfH"/>
                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
            </connections>
        </placeholder>
@@ -26,7 +29,7 @@
                            <rect key="frame" x="0.0" y="0.0" width="382" height="48"/>
                            <subviews>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="账号绑定" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NDO-GB-voX">
                                    <rect key="frame" x="11.666666666666668" y="15" width="61.333333333333329" height="18"/>
                                    <rect key="frame" x="11.666666666666668" y="15" width="59.666666666666657" height="18"/>
                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
                                    <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <nil key="highlightedColor"/>
@@ -61,7 +64,7 @@
                            <rect key="frame" x="0.0" y="48" width="382" height="48"/>
                            <subviews>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="清理缓存" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jnR-cP-A56">
                                    <rect key="frame" x="11.666666666666668" y="15" width="61.333333333333329" height="18"/>
                                    <rect key="frame" x="11.666666666666668" y="15" width="59.666666666666657" height="18"/>
                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
                                    <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <nil key="highlightedColor"/>
@@ -96,7 +99,7 @@
                            <rect key="frame" x="0.0" y="96" width="382" height="48"/>
                            <subviews>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="关于心泉" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="B6x-dn-wFm">
                                    <rect key="frame" x="11.666666666666668" y="15" width="61.333333333333329" height="18"/>
                                    <rect key="frame" x="11.666666666666668" y="15" width="59.666666666666657" height="18"/>
                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
                                    <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <nil key="highlightedColor"/>
@@ -131,7 +134,7 @@
                            <rect key="frame" x="0.0" y="144" width="382" height="48"/>
                            <subviews>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="注销账号" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tVJ-zS-iAQ">
                                    <rect key="frame" x="11.666666666666668" y="15" width="61.333333333333329" height="18"/>
                                    <rect key="frame" x="11.666666666666668" y="15" width="59.666666666666657" height="18"/>
                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
                                    <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <nil key="highlightedColor"/>
@@ -166,7 +169,7 @@
                            <rect key="frame" x="0.0" y="192" width="382" height="48"/>
                            <subviews>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="协议政策" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bcv-yx-5hJ">
                                    <rect key="frame" x="11.666666666666668" y="15" width="61.333333333333329" height="18"/>
                                    <rect key="frame" x="11.666666666666668" y="15" width="59.666666666666657" height="18"/>
                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
                                    <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <nil key="highlightedColor"/>
XQMuse/Root/Me/VC/VIPCenterVC.swift
@@ -47,6 +47,7 @@
            alert(msg: "请先阅读并同意《会员用户协议》");return
        }
        guard products.count != 0 else {return}
        let product = products[selectIndex]
XQMuse/Root/Me/VC/WatchHistoryDetailVC.swift
@@ -10,16 +10,16 @@
import RxRelay
import RxSwift
class WatchHistoryViewModel:RefreshInnerModel<CourseModel>{
class WatchHistoryViewModel:RefreshModel<CourseModel>{
                let state = BehaviorRelay<Int>(value: 1)
                var type = BehaviorRelay<WatchType>(value: .collect)
                override func api() -> (Observable<BaseResponse<BaseResponseList<CourseModel>>>)? {
    override func api() -> (Observable<BaseResponse<[CourseModel]>>)? {
                                switch type.value {
                                                case .history:Services.lookHistory(page: page, pageSize: 20, state: state.value)
                                                case .collect:Services.myCollect(page: page, pageSize: 20, state: state.value)
                                                case .payment:Services.myOrderCourse(page: page, pageSize: 20, state: state.value)
            case .history:return Services.lookHistory(page: page, pageSize: 20, state: state.value)
            case .collect:return Services.myCollect(page: page, pageSize: 20, state: state.value)
            case .payment:return Services.myOrderCourse(page: page, pageSize: 20, state: state.value)
                                }
                }
}
@@ -66,12 +66,12 @@
extension WatchHistoryDetailVC:UICollectionViewDelegate & UICollectionViewDataSource{
                func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
                                return viewModel.dataSource.value?.list.count ?? 0
        return viewModel.dataSource.value.count
                }
                func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
                                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "_HomeRelaxBannerCCell", for: indexPath) as! HomeRelaxBannerCCell
                                let m = viewModel.dataSource.value!.list[indexPath.row]
                                let m = viewModel.dataSource.value[indexPath.row]
                                cell.setCourseModel(m)
                                return cell
                }
@@ -82,12 +82,12 @@
                func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
                                let m = viewModel.dataSource.value!.list[indexPath.row]
                                let m = viewModel.dataSource.value[indexPath.row]
                                if viewModel.state.value == 1{
                                                let vc = HomeItemDetailVC(id: m.id)
            let vc = HomeItemDetailVC(id: m.businessId)
                                                JQ_currentViewController().jq_push(vc: vc)
                                }else{
                                                let vc = CourseDetialVC(courseId: m.id)
                                                let vc = CourseDetialVC(courseId: m.businessId)
                                                JQ_currentViewController().jq_push(vc: vc)
                                }
                }
XQMuse/Root/Network/Models.swift
@@ -176,6 +176,7 @@
                var generalPrice: Double = 0
                var headers = [String]()
                var id: Int = 0
    var businessId:Int = 0 // 课程/音频id 收藏用
                var iosPrice: Int = 0
                var isBuy: ConditionType = .no
                var isVip: ConditionType = .no
@@ -280,7 +281,7 @@
                var appUserId: Int = 0
                var createBy: String = ""
                var createTime: String = ""
                var currentEnergyValue: Int = 0
                var energyValue: Int = 0
                var delFlag: Int = 0
                var growthValue: Int = 0
                var id: Int = 0
XQMuse/Root/Network/Services.swift
@@ -56,13 +56,13 @@
    class func loginByWechat(headImgUrl:String,nickname:String,sex:Int,wxOpenId:String)->Observable<BaseResponse<LoginUserInfoModel>>{
        let params = ParamsAppender.build(url: All_Url)
        params.interface(url: "/auth/app/appleLogin")
        params.interface(url: "/auth/app/wxLogin")
            .append(key: "headImgUrl", value: headImgUrl)
            .append(key: "nickname", value: nickname)
            .append(key: "sex", value: sex)
            .append(key: "wxOpenId", value: wxOpenId)
            .append(key: "apipost_id", value: "246d7806b0e26c")
        return NetworkRequest.request(params: params, method: .post, progress: true)
        return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding(), progress: true)
    }
    /// Apple登录 【验证】
@@ -76,7 +76,7 @@
            .append(key: "name", value: name)
            .append(key: "mail", value: mail)
            .append(key: "apipost_id", value: "246d7806b0e26a")
        return NetworkRequest.request(params: params, method: .post,encoding: (JSONEncoding.self as! ParameterEncoding), progress: true)
        return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding(), progress: true)
    }
                /// 发送验证码
@@ -108,7 +108,7 @@
                                                .append(key: "cellPhone", value: cellPhone)
                                                .append(key: "captcha", value: captcha)
                                                .append(key: "apipost_id", value: "246d7806b0e26b")
                                return NetworkRequest.request(params: params, method: .post, progress: true)
        return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding(), progress: true)
                }
                class func updatePwd(cellPhone:String,password:String,secretCode:String)->Observable<BaseResponse<SimpleModel>>{
@@ -118,7 +118,7 @@
                                                .append(key: "password", value: password.jq_md5String().uppercased())
                                                .append(key: "secret", value: secretCode)
                                                .append(key: "apipost_id", value: "246d780670e266")
                                return NetworkRequest.request(params: params, method: .post, progress: true)
        return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding(), progress: true)
                }
}
@@ -235,10 +235,30 @@
                                                .append(key: "apipost_id", value: "25c3e3d0b0e160")
                                return NetworkRequest.request(params: params, method: .post, progress: false)
                }
    class func watchMuse(id:Int,timeLook:Int)->Observable<BaseResponse<SimpleModel>>{
        let params = ParamsAppender.build(url: All_Url)
        params.interface(url: "/user/user/app-user-viewing-history/saveViewingHistory")
            .append(key: "id", value: id)
            .append(key: "timeLook", value: timeLook)
        return NetworkRequest.request(params: params, method: .post, progress: false)
    }
}
/// 课程
extension Services{
    class func watchClouse(chapterId:Int,isOver:Bool,minuteLook:Int,secondLook:Int)->Observable<BaseResponse<SimpleModel>>{
        let params = ParamsAppender.build(url: All_Url)
        params.interface(url: "/user/user/app-user-viewing-history/saveCourseStudyHistory")
            .append(key: "id", value: chapterId)
            .append(key: "isOver", value: isOver)
            .append(key: "isOver", value: isOver)
            .append(key: "minuteLook", value: minuteLook)
            .append(key: "secondLook", value: secondLook)
        return NetworkRequest.request(params: params, method: .post, progress: false)
    }
                //课程分类
                class func getCourseCategory()->Observable<BaseResponse<[CategoryModel]>>{
                                let params = ParamsAppender.build(url: All_Url)
@@ -289,7 +309,7 @@
                                let params = ParamsAppender.build(url: All_Url)
                                params.interface(url: "/course/client/course/course/studyPage")
                                                .append(key: "apipost_id", value: "2d2eb9d23993be")
                                return NetworkRequest.request(params: params, method: .post, progress: true)
                                return NetworkRequest.request(params: params, method: .get, progress: true)
                }
}
@@ -399,7 +419,7 @@
                /// 冥想等级
                class func userHeadingLevel()->Observable<BaseResponse<HeadingLevelModel>>{
                                let params = ParamsAppender.build(url: All_Url)
                                params.interface(url: "/client/app-user/healingLevel")
                                params.interface(url: "/user/client/app-user/healingLevel")
                                                .append(key: "apipost_id", value: "34d924b4b991f0")
                                return NetworkRequest.request(params: params, method: .post, progress: true)
                }
@@ -430,7 +450,7 @@
                //添加银行卡
                class func addBank(_ model:AddBankInfoVC.AddBankRequestModel)->Observable<BaseResponse<SimpleModel>>{
                                let params = ParamsAppender.build(url: All_Url)
                                params.interface(url: "/user/client/app-user-withdraw/withdraw")
                                params.interface(url: "/user/client/app-user-withdraw/addBank")
                                                .append(key: "apipost_id", value: "361bdf11f992d1")
                                                .append(dic: model.toRequest())
                                return NetworkRequest.request(params: params, method: .post, progress: true)
@@ -462,7 +482,7 @@
                /// 观看历史
                /// - Parameters:
                ///   - state: 1冥想 2课程
                class func lookHistory(page:Int,pageSize:Int = 20,state:Int)->Observable<BaseResponse<BaseResponseList<CourseModel>>>{
                class func lookHistory(page:Int,pageSize:Int = 20,state:Int)->Observable<BaseResponse<[CourseModel]>>{
                                let params = ParamsAppender.build(url: All_Url)
                                params.interface(url: "/user/user/app-user-viewing-history/lookHistory")
                                                .append(key: "apipost_id", value: "361bdf123992fb")
@@ -475,7 +495,7 @@
                /// 我的收藏
                /// - Parameters:
                ///   - state: 1冥想 2课程
                class func myCollect(page:Int,pageSize:Int = 20,state:Int)->Observable<BaseResponse<BaseResponseList<CourseModel>>>{
                class func myCollect(page:Int,pageSize:Int = 20,state:Int)->Observable<BaseResponse<[CourseModel]>>{
                                let params = ParamsAppender.build(url: All_Url)
                                params.interface(url: "/course/client/course/course/myCollect")
                                                .append(key: "apipost_id", value: "365e099bb9988b")
@@ -488,7 +508,7 @@
                /// 我的购买
                /// - Parameters:
                ///   - state: 1冥想 2课程
                class func myOrderCourse(page:Int,pageSize:Int = 20,state:Int)->Observable<BaseResponse<BaseResponseList<CourseModel>>>{
                class func myOrderCourse(page:Int,pageSize:Int = 20,state:Int)->Observable<BaseResponse<[CourseModel]>>{
                                let params = ParamsAppender.build(url: All_Url)
                                params.interface(url: "/order/client/order/order/myOrderCourse")
                                                .append(key: "apipost_id", value: "365f4fc1b99030")
@@ -572,7 +592,7 @@
                }
                /// 兑换礼物
                class func exchangeGift(prizeId:Int)->Observable<BaseResponse<SimpleModel>>{
    class func exchangeGift(prizeId:Int)->Observable<BaseResponse<String>>{
                                let params = ParamsAppender.build(url: All_Url)
                                params.interface(url: "/user/client/app-user-tree/exchange")
                                                .append(key: "apipost_id", value: "2e76346339912a")
@@ -607,7 +627,7 @@
                                let params = ParamsAppender.build(url: All_Url)
                                                .interface(url: "/system/system/common-question/getQrCode")
                                                .append(key: "apipost_id", value: "2fcbf1daf99704")
                                return NetworkRequest.request(params: params, method: .get, progress: false)
        return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding(), progress: false)
                }
                /// 问题列表
@@ -617,7 +637,7 @@
                                                .append(key: "apipost_id", value: "36618045f991c4")
                                                .append(key: "pageCurr", value: page)
                                                .append(key: "pageSize", value: pageSize)
                                return NetworkRequest.request(params: params, method: .post, progress: false)
                                return NetworkRequest.request(params: params, method: .get, progress: false)
                }
    class func addQuestion(content:String,meditationId:Int)->Observable<BaseResponse<SimpleModel>>{
XQMuse/Root/Other/View/CountdownChooseListView.swift
@@ -11,6 +11,11 @@
class CountdownChooseListView: UIView,JQNibView{
    enum CountDownStatus {
        case close
        case choose(Int)
    }
                @IBOutlet weak var btn_cancel: UIButton!
                @IBOutlet weak var stackView: UIStackView!
                @IBOutlet weak var view_content: UIView!
@@ -18,6 +23,8 @@
                @IBOutlet weak var tf_input: UITextField!
                private var disposeBag = DisposeBag()
                private var clouse:((Int)->Void)?
    private var status:CountDownStatus = .close
                var numberMinutes = 1
                override func awakeFromNib() {
@@ -98,7 +105,11 @@
                @IBAction func cancelAction(_ sender: UIButton) {
                                endEditing(true)
                                clouse?(numberMinutes)
        if case .choose(let v) = status {
            clouse?(v)
        }
                                cons_bottom.constant = -JQ_ScreenH
                                UIView.animate(withDuration: 0.4) {
                                                self.alpha = 0
@@ -142,12 +153,16 @@
                                                                                                label.textColor = UIColor(hexString: "#8AAE65")
                                                                                                switch label.text {
                                                                                                                case "关闭倒计时":numberMinutes = -1;break
                                                                                                                case "自定义","分钟":numberMinutes = self.tf_input.text!.int ?? 1;break
                                                                                                                case "关闭倒计时":
                                numberMinutes = -1
                                status = .close
                                                                                                                case "自定义","分钟":
                                numberMinutes = self.tf_input.text!.int ?? 1
                                status = .choose(numberMinutes)
                                                                                                                default:
                                                                                                                                numberMinutes = label.text?.jq_filterNum().int ?? 0
                                                                                                                                self.tf_input.text = numberMinutes.string
                                status = .choose(numberMinutes)
                                                                                                }
                                                                                }
XQMuse/Root/Other/View/VideoView.swift
@@ -32,10 +32,10 @@
                                return p
                }()
                required    init(url:String? = nil,autoPlay:Bool = false,placeHoderImageUrl:String? = nil) {
    required    init(url:String? = nil,autoPlay:Bool = false,placeHoderImageUrl:String? = nil,delegate:CLPlayerDelegate? = nil) {
                                super.init(frame: .zero)
                                addSubview(player)
                                player.delegate = self
                                player.delegate = delegate
                                player.snp.makeConstraints { make in
                                                make.edges.equalToSuperview()
                                }
@@ -102,8 +102,4 @@
                required init?(coder: NSCoder) {
                                fatalError("init(coder:) has not been implemented")
                }
}
extension VideoView:CLPlayerDelegate{
}
XQMuse/Root/PayMusicView/PayMusicVC.swift
@@ -29,7 +29,7 @@
                private var label_name:UILabel!
                private var btn_handle:UIButton!
                private var btn_handleClose:UIButton!
                private var audioPlayer:AudioPlayer!
                private(set) var audioPlayer:AudioPlayer!
                private var isAniLoop:Bool = false
                private var meditationModel:MeditationModel?{
                                didSet{
@@ -120,6 +120,16 @@
                                                                                make.bottom.equalToSuperview().offset(-(tabBarHeight))
                                                                }
                                                                vc.startRunloopAni()
                                                }
                                }
                }
    static func hidden(){
        if let tabBarVC = JQ_currentViewController().navigationController?.tabBarController as? BaseTabBarVC{
            if let vc = tabBarVC.children.filter({$0 is PayMusicVC}).first{
                AudioPlayer.destroy()
                vc.view.removeFromSuperview()
                vc.removeFromParent()
                                                }
                                }
                }
@@ -222,8 +232,12 @@
                                self.playIndex = firstPlayIndex
                                self.meditationModel = model
                                let urls = model.backgroundUrl.components(separatedBy: ",").map { str in
                                                return URL(string: str)!
        let urls = model.meditationMusicList.map { url in
            return URL(string: url)!
        }
        if urls.count == 0{
            alertError(msg: "数据获取失败");return
                                }
                                let masterUrl = URL(string: model.tutorAudioUrl)
@@ -255,11 +269,13 @@
                                                if loadTime >= totalTime{
                                                                if weakSelf.playIndex <= urls.count - 1{
                                                                if weakSelf.playIndex < urls.count - 1{
                                                                                weakSelf.next()
                                                                                weakSelf.delegate?.playState(.next)
                                                                }else{
                                                                                weakSelf.delegate?.playState(.end)
                    PayMusicVC.hidden()
                    MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
                                                                }
                                                }
@@ -330,7 +346,10 @@
                }
                func next(){
        if UserDefaultSettingViewModel.getSetting()?.playModel == .line{
                                playIndex += 1
        }
                                let index = min((urls.count - 1), playIndex)
                                bgmPlayer?.replaceCurrentItem(with: AVPlayerItem(url: urls[index]))
                                bgmPlayer?.play()
@@ -417,6 +436,12 @@
                                                if newTimes <= 0{
                                                                weakSelf.times.accept(nil)
                                                                weakSelf.stopTimer()
                weakSelf.bgmPlayer?.pause()
                weakSelf.masterPlayer?.pause()
                weakSelf.scenePlayer?.pause()
                MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
                AudioPlayer.destroy()
                PayMusicVC.hidden()
                                                }else{
                                                                weakSelf.times.accept(newTimes)
                                                }
XQMuse/Root/TreeGroup/TCell/TreeTeskEnergyTCell.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_12" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
@@ -22,7 +22,7 @@
                        <subviews>
                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="e5F-Yd-WS5">
                                <rect key="frame" x="11" y="43.666666666666657" width="50" height="50"/>
                                <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.40000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="50" id="Iyf-X2-uW5"/>
                                    <constraint firstAttribute="height" constant="50" id="kwz-cW-a3N"/>
@@ -47,7 +47,7 @@
                                <nil key="highlightedColor"/>
                            </label>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="所需能量值:0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zFc-Mw-j6J">
                                <rect key="frame" x="71" y="86" width="68" height="12"/>
                                <rect key="frame" x="71" y="86" width="66.666666666666686" height="12"/>
                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="10"/>
                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
                                <nil key="highlightedColor"/>
XQMuse/Root/TreeGroup/TreeTeskVC.swift
@@ -158,12 +158,12 @@
                                                                self.taskListView.setTreeInfoModel(m)
                                                                //检查hash,进行同步
                                                                if m.toJSON()?.jq_hash() != self.treeInfoModel?.toJSON()?.jq_hash(){
//                                                                if m.toJSON()?.jq_hash() != self.treeInfoModel?.toJSON()?.jq_hash(){
                                                                                self.treeInfoModel = m
                                                                                self.updateTreeInfo()
                                                                }
                    self.updateAni(false)
                                                                try? self.cacheTreeInfoModel.save(m)
//                                                                }
                                                }
                                }).disposed(by: disposeBag)
                }
@@ -174,8 +174,7 @@
//                                if treeLevel.rawValue != treeInfoModel?.treeLevelType.rawValue{
//                                                treeLevel = treeInfoModel!.treeLevelType
//                                }
                                icon_energy.text = String(format: "当前能量值:%ld", treeInfoModel!.currentEnergyValue)
                                icon_energy.text = String(format: "当前能量值:%ld", treeInfoModel!.energyValue)
                                setProgress(current: treeInfoModel!.growthValue, total: treeInfoModel!.nextLevel)
                }
@@ -223,6 +222,10 @@
                                                                                }
                                                }
                                }
        taskListView.signSuccess {[weak self] in
            self?.getTreeData()
        }
                }
                // 0 - 100
@@ -244,22 +247,26 @@
                //能量明细
                @IBAction func energyDetailAction(_ sender: TapBtn) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = TreeTeskDetailVC()
                                push(vc: vc)
                }
                //兑换
                @IBAction func exchangeAction(_ sender: TapBtn) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                let vc = TreeTeskEnergyExchangeVC()
                                push(vc: vc)
                }
                @IBAction func wateringAction(_ sender: UIButton) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                sender.isUserInteractionEnabled = false
                                if treeInfoModel == nil {return}
                                guard treeInfoModel!.currentEnergyValue != 0 else{
                                guard treeInfoModel!.energyValue != 0 else{
                                                alert(msg: "已经没有能量值了,快去做任务吧");return
                                }
@@ -279,9 +286,12 @@
                        weakSelf.voicePlayer.play()
                    }
                    weakSelf.updateAni()
                    weakSelf.getTreeData()
                    return
                                                                }
                weakSelf.treeInfoModel?.currentEnergyValue = 0
                weakSelf.treeInfoModel?.growthValue = m.growthValue
                weakSelf.treeInfoModel?.energyValue = 0
                weakSelf.treeInfoModel?.nextLevel = m.nextLevel
                weakSelf.updateTreeInfo()
                                                }
@@ -326,7 +336,7 @@
                                push(vc: vc)
                }
                private func updateAni(){
    private func updateAni(_ needAni:Bool = true){
                                let treeLevel = treeInfoModel?.treeLevelType ?? .level_1
                                guard let animateUrl = Bundle.main.url(forResource: treeLevel.aniResource, withExtension: "png") else {return}
@@ -361,7 +371,8 @@
                                                                make.height.equalTo(731 * scale)
                                                }
                                                UIView.animate(withDuration: 0.6) {
            let duration = needAni ? 0.6:0
                                                UIView.animate(withDuration: duration) {
                                                                self.aPNGTreeImageView?.alpha = 0
                                                }completion: { state in
XQMuse/Root/TreeGroup/VC/TreeTeskEnergyExchangeVC.swift
@@ -105,7 +105,8 @@
                                CommonAlertView.show(title: "提示", attribute: attribute, isSingle: false, cancelStr: "再想想", completeStr: "确认") { state in
                                                if state{
                                                                Services.exchangeGift(prizeId: m.id).subscribe(onNext: {data in
                                                                                TreeTeskExchangeSuccessView.show()
                    TreeTeskExchangeSuccessView.show(code: data.data ?? "",customerImage: self.image_qrCode.image ?? UIImage())
                    self.viewModel.beginRefresh()
                                                                }).disposed(by: self.disposeBag)
                                                }
                                }
XQMuse/Root/TreeGroup/View/TreeTeskExchangeSuccessView.swift
@@ -11,6 +11,7 @@
class TreeTeskExchangeSuccessView: UIView,JQNibView{
                @IBOutlet weak var view_container: UIView!
    @IBOutlet weak var image_qrCode: UIImageView!
    @IBOutlet weak var label_code: UILabel!
    
                override func awakeFromNib() {
                                super.awakeFromNib()
@@ -23,9 +24,11 @@
        image_qrCode.addGestureRecognizer(longPress)
                }
                static func show(){
    static func show(code:String,customerImage:UIImage){
                                let view = TreeTeskExchangeSuccessView.jq_loadNibView()
                                sceneDelegate?.window?.addSubview(view)
        view.label_code.text = "领取验证码:\(code)"
        view.image_qrCode.image = customerImage
                                view.frame = sceneDelegate?.window?.frame ?? .zero
                                UIView.animate(withDuration: 0.5, delay: 0.1, usingSpringWithDamping: 0.5, initialSpringVelocity: 1.0, options: .curveEaseIn) {
XQMuse/Root/TreeGroup/View/TreeTeskExchangeSuccessView.xib
@@ -123,6 +123,7 @@
            </constraints>
            <connections>
                <outlet property="image_qrCode" destination="GQk-cT-1IF" id="U2k-zg-3wi"/>
                <outlet property="label_code" destination="psN-sL-6pq" id="IdT-sk-KdH"/>
                <outlet property="view_container" destination="4ru-7s-yUN" id="C6v-VX-yVc"/>
            </connections>
            <point key="canvasLocation" x="65" y="21"/>
XQMuse/Root/TreeGroup/View/TreeTeskListView.swift
@@ -22,6 +22,7 @@
                @IBOutlet weak var tap_sign: TapBtn!
                
                private var clouse:((TreeTeskListSwipe)->Void)?
    private var signClouse:(()->Void)?
                private var disposeBag = DisposeBag()
                private var treeInfoModel:TreeInfoModel?
@@ -68,6 +69,10 @@
                                self.clouse = clouse
                }
    func signSuccess(signClouse:@escaping ()->Void){
        self.signClouse = signClouse
    }
                func setTreeInfoModel(_ model:TreeInfoModel){
                                self.treeInfoModel = model
@@ -87,12 +92,16 @@
                }
                @IBAction func signAction(_ sender: TapBtn) {
        guard sceneDelegate!.checkisLoginState() else {return}
                                tap_sign.isUserInteractionEnabled = false
                                label_sign.text = "已签到"
                                view_sign.backgroundColor = .gray.withAlphaComponent(0.1)
                                label_sign.textColor = .white
                                view_sign_cricle.jq_borderColor = .gray.withAlphaComponent(0.9)
        Services.treeTaskSign().subscribe(onNext: {[weak self] _ in
            guard let weakSelf = self else { return }
            weakSelf.signClouse?()
            weakSelf.tap_sign.isUserInteractionEnabled = false
            weakSelf.label_sign.text = "已签到"
            weakSelf.view_sign.backgroundColor = .gray.withAlphaComponent(0.1)
            weakSelf.label_sign.textColor = .white
            weakSelf.view_sign_cricle.jq_borderColor = .gray.withAlphaComponent(0.9)
                                let imageView = UIImageView(image: UIImage(named: "icon_signSuccess"))
                                imageView.transform = .init(scaleX: 0.1, y: 0.1)
@@ -117,6 +126,9 @@
                                                                imageView.removeFromSuperview()
                                                }
                                }
        }).disposed(by: disposeBag)
                }
                @IBAction func toMuse(_ sender: TapBtn) {
XQMuse/SceneDelegate.swift
@@ -67,8 +67,17 @@
                                JQ_currentViewController().present(loginNav, animated: true)
                }
                
                func loginSuccess(){
    //判断是否需要登录
    func checkisLoginState()->Bool{
        if UserViewModel.getLoginInfo()?.accessToken.isEmpty ?? true{
            sceneDelegate?.needLogin()
            return false
        }
        return true
    }
                                
                func loginSuccess(){
        NotificationCenter.default.post(name: LoginSuccess_Noti, object: nil)
                }
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
XQMuseStoreKit.storekit
File was deleted