| | |
| | | 13A830FA2C043A0600BB2F23 /* Lesson_3_AnswerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13A830F92C043A0600BB2F23 /* Lesson_3_AnswerView.xib */; }; |
| | | 13AA25392C00759600F075B3 /* HomeStudyCompleteVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13AA25372C00759600F075B3 /* HomeStudyCompleteVC.swift */; }; |
| | | 13AA253A2C00759600F075B3 /* HomeStudyCompleteVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13AA25382C00759600F075B3 /* HomeStudyCompleteVC.xib */; }; |
| | | 13C23F7B2C186ECB006D4322 /* VoiceHandleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C23F7A2C186ECB006D4322 /* VoiceHandleView.swift */; }; |
| | | 13CD3AC72C0874B3007E1065 /* CommonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CD3AC62C0874B3007E1065 /* CommonModel.swift */; }; |
| | | 13CD3AC92C0886E5007E1065 /* RefreshModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CD3AC82C0886E5007E1065 /* RefreshModel.swift */; }; |
| | | 13CDF4492C0566E400E8D4FD /* HomeListenFight_lesson_4_VC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CDF4482C0566E400E8D4FD /* HomeListenFight_lesson_4_VC.swift */; }; |
| | |
| | | 13A830F92C043A0600BB2F23 /* Lesson_3_AnswerView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Lesson_3_AnswerView.xib; sourceTree = "<group>"; }; |
| | | 13AA25372C00759600F075B3 /* HomeStudyCompleteVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeStudyCompleteVC.swift; sourceTree = "<group>"; }; |
| | | 13AA25382C00759600F075B3 /* HomeStudyCompleteVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeStudyCompleteVC.xib; sourceTree = "<group>"; }; |
| | | 13C23F7A2C186ECB006D4322 /* VoiceHandleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceHandleView.swift; sourceTree = "<group>"; }; |
| | | 13CD3AC62C0874B3007E1065 /* CommonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonModel.swift; sourceTree = "<group>"; }; |
| | | 13CD3AC82C0886E5007E1065 /* RefreshModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshModel.swift; sourceTree = "<group>"; }; |
| | | 13CDF4482C0566E400E8D4FD /* HomeListenFight_lesson_4_VC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeListenFight_lesson_4_VC.swift; sourceTree = "<group>"; }; |
| | |
| | | 1362C75E2BFF4BA900BD7F73 /* StudyHandleView.swift */, |
| | | 1362C7602BFF4BB100BD7F73 /* StudyHandleView.xib */, |
| | | 131C03102C0DA5D500EA4C25 /* CityAddressPickerView.swift */, |
| | | 13C23F7A2C186ECB006D4322 /* VoiceHandleView.swift */, |
| | | ); |
| | | path = UIView; |
| | | sourceTree = "<group>"; |
| | |
| | | 130278412BFD978900DDCE81 /* Config.swift in Sources */, |
| | | 130A2C812C07075B008463B2 /* ListenFight_Game_Pocket_CCell.swift in Sources */, |
| | | 1302784A2BFD979200DDCE81 /* BaseVC.swift in Sources */, |
| | | 13C23F7B2C186ECB006D4322 /* VoiceHandleView.swift in Sources */, |
| | | 13A830F52C041B4400BB2F23 /* ListenFight_lesson_3_CCell.swift in Sources */, |
| | | 137CB4292BFF505800D32862 /* HomeListenFightVC.swift in Sources */, |
| | | 13A04A032C05BFDC00F1F52E /* HomeListenGame_2_VC.swift in Sources */, |
| | |
| | | import AVFAudio |
| | | |
| | | |
| | | protocol VoicePlayerDelegate{ |
| | | func playComplete() |
| | | } |
| | | |
| | | /// 音频播放器 |
| | | class VoicePlayer:NSObject{ |
| | | /// 缓存地址 |
| | | private let voiceCacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("voices") |
| | | private static var _sharedInstance: VoicePlayer? |
| | | private var player:AVAudioPlayer? |
| | | |
| | | var delegate:VoicePlayerDelegate? |
| | | |
| | | //是否正在播放 |
| | | var isPlaying:Bool{return player?.isPlaying ?? false} |
| | |
| | | |
| | | |
| | | /// 单例 |
| | | /// - Returns: <#description#> |
| | | class func share() -> VoicePlayer { |
| | | guard let instance = _sharedInstance else { |
| | | _sharedInstance = VoicePlayer() |
| | |
| | | func playerAt(url:String?){ |
| | | guard let u = url else {return} |
| | | if player?.isPlaying ?? false{ |
| | | VoicePlayer.share().playComplete?() //先通知完成播放 |
| | | player?.stop() |
| | | self.playComplete?() //先通知完成播放 |
| | | } |
| | | |
| | | //文件存在:直接播放缓存路径的语音 |
| | |
| | | extension VoicePlayer:AVAudioPlayerDelegate{ |
| | | func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { |
| | | VoicePlayer.share().playComplete?() |
| | | delegate?.playComplete() |
| | | } |
| | | |
| | | func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: (any Error)?) { |
| | |
| | | class Listen1Model:HandyJSON{ |
| | | var data:Listen1DataModel? |
| | | var subjectList = [Listen1SubModel]() |
| | | var storyList = [Listen1SubModel]() |
| | | |
| | | required init(){} |
| | | } |
| | |
| | | var answerTime = 0 |
| | | var time = 0 |
| | | var count = 0 |
| | | var lookIntegral = 0 |
| | | |
| | | } |
| | | |
| | |
| | | var updateTime: String = "" |
| | | var week: Int = 0 |
| | | } |
| | | |
| | | struct StudyScheduleModel:HandyJSON{ |
| | | var answer: Int = 0 |
| | | var day: Int = 0 |
| | | var id: Int = 0 |
| | | var induction: Int = 0 |
| | | var listen: Int = 0 |
| | | var look: Int = 0 |
| | | var monthStudy: Int = 0 |
| | | var pair: Int = 0 |
| | | var surplus: String = "" |
| | | var todayStudy: Int = 0 |
| | | var totalStudy: Int = 0 |
| | | var userId: Int = 0 |
| | | var week: Int = 0 |
| | | var weekStudy: Int = 0 |
| | | } |
| | |
| | | |
| | | class SimpleImageCCell: UICollectionViewCell { |
| | | |
| | | override func awakeFromNib() { |
| | | @IBOutlet weak var img_cover: UIImageView! |
| | | override func awakeFromNib() { |
| | | super.awakeFromNib() |
| | | |
| | | } |
| | |
| | | <constraint firstAttribute="bottom" secondItem="D8M-NB-xlj" secondAttribute="bottom" constant="5" id="vKt-cE-Srd"/> |
| | | </constraints> |
| | | <size key="customSize" width="869" height="577"/> |
| | | <connections> |
| | | <outlet property="img_cover" destination="D8M-NB-xlj" id="h1w-Ly-yB3"/> |
| | | </connections> |
| | | <point key="canvasLocation" x="439.39024390243901" y="153.81355932203391"/> |
| | | </collectionViewCell> |
| | | </objects> |
| | |
| | | private var randomElement:Listen1SubModel? |
| | | private var page:Int! |
| | | var rootViewModel:HomeListenFightViewModel! |
| | | private var isListen:Bool = false |
| | | private var isAnsterComplete:Bool = false //是否已经回答完成 |
| | | |
| | | private var menuView:StudyHandleView = StudyHandleView.jq_loadNibView() |
| | | private var menuView:VoiceHandleView! |
| | | |
| | | private lazy var collectionView:UICollectionView = { |
| | | let flowLayout = UICollectionViewFlowLayout() |
| | |
| | | navigationItem.titleView = UIView() |
| | | collectionView.reloadData() |
| | | |
| | | menuView.listenType = .lesson1 |
| | | |
| | | // collectionView.isUserInteractionEnabled = false |
| | | //制造随机 |
| | | randomElement = listen1Model.subjectList.randomElement() |
| | | menuView.vioceSoundUrl = randomElement?.correct |
| | | |
| | | VoicePlayer.share().playEnd {[weak self] in |
| | | self?.menuView.reset() |
| | | } |
| | | } |
| | | |
| | | override func viewDidAppear(_ animated: Bool) { |
| | | super.viewDidAppear(animated) |
| | | VoicePlayer.share().delegate = self |
| | | } |
| | | |
| | | override func viewDidDisappear(_ animated: Bool) { |
| | | super.viewDidDisappear(animated) |
| | | VoicePlayer.share().delegate = nil |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | make.bottom.equalToSuperview() |
| | | } |
| | | |
| | | menuView = VoiceHandleView() |
| | | //制造随机 |
| | | randomElement = listen1Model.subjectList.randomElement() |
| | | menuView.playUrl = randomElement?.correct |
| | | menuView.listenType = .lesson1 |
| | | view.addSubview(menuView) |
| | | menuView.snp.makeConstraints { make in |
| | | make.top.equalTo(self.view.safeAreaLayoutGuide.snp.top).offset(24) |
| | | make.centerX.equalToSuperview() |
| | | make.height.equalTo(52) |
| | | make.width.equalTo(199) |
| | | make.width.equalTo(159) |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | if self?.randomElement?.id == self?.listen1Model.subjectList[index.row].id{ |
| | | answer = .success |
| | | self?.rootViewModel.correctNum += 1 |
| | | if self?.isAnsterComplete == false{ |
| | | self?.rootViewModel.correctNum += 1 |
| | | } |
| | | self?.isAnsterComplete = true |
| | | }else{ |
| | | answer = .fail |
| | | self?.rootViewModel.errorNum += 1 |
| | | if self?.isAnsterComplete == false{ |
| | | self?.rootViewModel.errorNum += 1 |
| | | } |
| | | } |
| | | |
| | | switch answer { |
| | |
| | | self.menuView.snp.updateConstraints { make in |
| | | make.top.equalTo(self.view).offset(v.origin.y + UIDevice.jq_safeEdges.top + 101 + 50) |
| | | make.left.equalToSuperview().offset(v.origin.x + 194) |
| | | make.width.equalTo(v.size.width + 50) |
| | | make.width.equalTo(v.size.width - 10) |
| | | make.height.equalTo(40) |
| | | } |
| | | self.view.layoutIfNeeded() |
| | | }completion: { _ in |
| | | self.collectionView.reloadData() |
| | | DispatchQueue.main.asyncAfter(deadline: .now()+2){ |
| | | DispatchQueue.main.asyncAfter(deadline: .now()+1.2){ |
| | | NotificationCenter.default.post(name: NextLession_Noti, object: nil) |
| | | // self.collectionView.isUserInteractionEnabled = true |
| | | self.viewModel.answerType.accept(.none) |
| | |
| | | |
| | | extension HomeListenFight_lesson_1_VC:UICollectionViewDelegate{ |
| | | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { |
| | | if !isListen{ |
| | | alertError(msg: "请先听题");return |
| | | } |
| | | viewModel.selectIndex.accept(indexPath) |
| | | } |
| | | } |
| | |
| | | return min(4,listen1Model.subjectList.count) |
| | | } |
| | | } |
| | | |
| | | extension HomeListenFight_lesson_1_VC:VoicePlayerDelegate{ |
| | | func playComplete() { |
| | | isListen = true |
| | | menuView.resetView() |
| | | } |
| | | } |
| | |
| | | make.edges.equalToSuperview() |
| | | } |
| | | |
| | | addSubview(mask_img) |
| | | mask_img.snp.makeConstraints { make in |
| | | make.edges.equalToSuperview() |
| | | } |
| | | |
| | | addSubview(voice_view) |
| | | voice_view.snp.makeConstraints { make in |
| | | make.edges.equalToSuperview() |
| | | } |
| | | |
| | | addSubview(mask_img) |
| | | mask_img.snp.makeConstraints { make in |
| | | make.edges.equalToSuperview() |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | let img1 = UIImageView(image: UIImage(named: "icon_play_1")) |
| | | let img1 = UIImageView(image: UIImage(named: "icon_play_1")!.withTintColor(UIColor(hexString: "#41A2EB")!)) |
| | | contentVoiceView.addSubview(img1) |
| | | img1.snp.makeConstraints { make in |
| | | make.left.equalTo(23) |
| | |
| | | |
| | | let playBtn = UIButton(type: .custom) |
| | | playBtn.addTarget(self, action: #selector(playAction), for: .touchUpInside) |
| | | playBtn.setImage(UIImage(named: "icon_play"), for: .normal) |
| | | playBtn.setImage(UIImage(named: "icon_play")?.withTintColor(UIColor(hexString: "#41A2EB")!), for: .normal) |
| | | contentVoiceView.addSubview(playBtn) |
| | | playBtn.snp.makeConstraints { make in |
| | | make.right.equalTo(-23) |
| | | make.width.height.equalTo(32) |
| | | make.centerY.equalToSuperview() |
| | | } |
| | | |
| | | |
| | | // let mask_tap = UITapGestureRecognizer(target: self, action: #selector(toFromAction)) |
| | | // mask_img.addGestureRecognizer(mask_tap) |
| | | // mask_img.isUserInteractionEnabled = true |
| | | // |
| | | // let answer_tap = UITapGestureRecognizer(target: self, action: #selector(toBackAction)) |
| | | // answer_img.addGestureRecognizer(answer_tap) |
| | | // answer_img.isUserInteractionEnabled = true |
| | | |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | @IBAction func playAction(_ sender: Any) { |
| | | VoicePlayer.share().playerAt(url: model.correct ?? "") |
| | | VoicePlayer.share().playerAt(url: model.correct) |
| | | playAtClouse?(indexPath) |
| | | } |
| | | } |
| | |
| | | @IBOutlet weak var view_bg1: UIView! |
| | | @IBOutlet weak var view_bg2: UIView! |
| | | @IBOutlet weak var label_title: UILabel! |
| | | @IBOutlet weak var view_state: UIView! |
| | | @IBOutlet weak var label_state: UILabel! |
| | | |
| | | override func awakeFromNib() { |
| | | super.awakeFromNib() |
| | | backgroundColor = .clear |
| | | selectionStyle = .none |
| | | } |
| | | |
| | | func setProgress(progress:Int){ |
| | | |
| | | if progress == 0{ |
| | | view_state.backgroundColor = UIColor(hexString: "#F84D31") |
| | | label_state.text = "未完成" |
| | | }else if progress == 100{ |
| | | view_state.backgroundColor = UIColor(hexString: "#66CFFA") |
| | | label_state.text = "已完成" |
| | | }else{ |
| | | view_state.backgroundColor = UIColor(hexString: "#FF8A66") |
| | | label_state.text = String(format: "%ld%%", progress) |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | </constraints> |
| | | </tableViewCellContentView> |
| | | <connections> |
| | | <outlet property="label_state" destination="VQQ-aH-jOl" id="dMn-PA-um9"/> |
| | | <outlet property="label_title" destination="28J-ZC-IiE" id="kDk-K7-10L"/> |
| | | <outlet property="view_bg1" destination="9XB-yf-tzC" id="u8S-3q-p3Y"/> |
| | | <outlet property="view_bg2" destination="pk7-Y8-Mtb" id="Dyb-wb-cSg"/> |
| | | <outlet property="view_state" destination="KYj-jQ-pUN" id="xiA-D1-4YO"/> |
| | | </connections> |
| | | <point key="canvasLocation" x="282.80487804878049" y="47.033898305084747"/> |
| | | </tableViewCell> |
| | |
| | | // |
| | | |
| | | import UIKit |
| | | import JQTools |
| | | |
| | | class HomeListen_process_TCell: UITableViewCell { |
| | | @IBOutlet weak var label_currentWeek: UILabel! |
| | | @IBOutlet weak var label_completeProgress: UILabel! |
| | | @IBOutlet weak var label_info: UILabel! |
| | | @IBOutlet weak var cons_progress: NSLayoutConstraint! |
| | | |
| | | var studyScheduleModel:StudyScheduleModel?{ |
| | | didSet{ |
| | | if let m = studyScheduleModel{ |
| | | label_currentWeek.text = "当前周目:\(studyScheduleModel?.week.jq_cn ?? "")周目" |
| | | |
| | | label_info.attributedText = AttributedStringbuilder.build().add(string: "学习总时长:", withFont: .systemFont(ofSize: 16), withColor: UIColor(hexString: "#2B3648")!) |
| | | .add(string: "\(m.totalStudy)小时", withFont: .systemFont(ofSize: 16, weight: .medium), withColor: UIColor(hexString: "#2B3648")!) |
| | | .add(string: "|今日学习", withFont: .systemFont(ofSize: 16), withColor: UIColor(hexString: "#2B3648")!) |
| | | .add(string: "\(m.todayStudy)小时", withFont: .systemFont(ofSize: 16, weight: .medium), withColor: UIColor(hexString: "#2B3648")!).mutableAttributedString |
| | | |
| | | cons_progress.constant = ((JQ_ScreenW - 234 * 2 - 44) / 100) * Double(m.day) |
| | | label_completeProgress.text = "已完成:\(m.day)%" |
| | | } |
| | | } |
| | | } |
| | | |
| | | override func awakeFromNib() { |
| | | super.awakeFromNib() |
| | |
| | | <constraint firstItem="RXp-OG-LEf" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="9.5" id="gb6-Z8-JH9"/> |
| | | </constraints> |
| | | </tableViewCellContentView> |
| | | <connections> |
| | | <outlet property="cons_progress" destination="Zzl-QC-ej8" id="5nX-hJ-eUu"/> |
| | | <outlet property="label_completeProgress" destination="tZm-jl-aPX" id="Uqr-wy-HOB"/> |
| | | <outlet property="label_currentWeek" destination="0OR-m9-gOV" id="fZk-hC-CLI"/> |
| | | <outlet property="label_info" destination="4vp-cM-Wt2" id="mql-4J-5Xf"/> |
| | | </connections> |
| | | <point key="canvasLocation" x="168.65853658536585" y="60"/> |
| | | </tableViewCell> |
| | | </objects> |
| | |
| | | import RxRelay |
| | | |
| | | let NextLession_Noti = Notification.Name.init("NextLession_Noti") |
| | | //let Reload_Noti = Notification.Name.init("Reload_Noti") |
| | | |
| | | enum ListenType:Int{ |
| | | case lesson1 = 1 //自主学习-听音选图 |
| | |
| | | private lazy var pageVC:FFPageViewController = { |
| | | let vc = FFPageViewController() |
| | | vc.scrollview.isScrollEnabled = false |
| | | vc.prePages = UInt(viewModel.maxPage.value) / 2 |
| | | vc.maxPages = UInt(viewModel.maxPage.value) + 1 |
| | | return vc |
| | | }() |
| | | |
| | |
| | | |
| | | btn_exit.addTarget(self, action: #selector(quitAction), for: .touchUpInside) |
| | | btn_forward.addTarget(self, action: #selector(beforeAction), for: .touchUpInside) |
| | | btn_next.addTarget(self, action: #selector(nextAction), for: .touchUpInside) |
| | | |
| | | |
| | | if viewModel.listenType.value == .game1 || viewModel.listenType.value == .game2{ |
| | |
| | | if viewModel.listenType.value == .game1{ |
| | | showGameLevel() |
| | | } |
| | | }else if viewModel.listenType.value == .story1 || viewModel.listenType.value == .story2{ |
| | | let count = (data as! Listen1Model).storyList.count |
| | | viewModel.maxPage.accept(count) |
| | | label_pageNum.text = "已完成:\(viewModel.currentPage.value + 1)/\(viewModel.maxPage.value)" |
| | | }else{ |
| | | pageVC.reloadData() |
| | | } |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | private func showGameLevel(){ |
| | | ChooseLevelView.show {[weak self] level in |
| | |
| | | } |
| | | |
| | | override func setRx() { |
| | | |
| | | // NotificationCenter.default.rx.notification(Reload_Noti).take(until: self.rx.deallocated).subscribe(onNext: {[weak self] noti in |
| | | // self?.pageVC.reloadData() |
| | | // }).disposed(by: disposeBag) |
| | | |
| | | |
| | | NotificationCenter.default.rx.notification(NextLession_Noti).take(until: self.rx.deallocated).subscribe(onNext: {[weak self] noti in |
| | | guard let weakSelf = self else { return } |
| | | let nextPage = weakSelf.viewModel.currentPage.value + 1 |
| | | |
| | | if weakSelf.viewModel.listenType.value == .story2{ |
| | | weakSelf.btn_next.isHidden = (nextPage + 1) == weakSelf.viewModel.maxPage.value |
| | | if weakSelf.btn_next.isHidden{ |
| | | weakSelf.btn_exit.setTitle("完成", for: .normal) |
| | | } |
| | | } |
| | | |
| | | //完成 |
| | | if nextPage >= weakSelf.viewModel.maxPage.value{ |
| | |
| | | } |
| | | case .lesson1,.lesson2,.lesson3,.lesson4,.lesson5: |
| | | weakSelf.studyComplete() |
| | | case .story1,.story2:break |
| | | case .story1,.story2: |
| | | if let dict = noti.object as? Dictionary<String,Any>{ |
| | | weakSelf.storyComplete(storyId: dict["storyId"] as! Int, integral: dict["storyIntegral"] as! Int) |
| | | } |
| | | } |
| | | |
| | | return |
| | | } |
| | | |
| | |
| | | |
| | | timer.invalidate() |
| | | |
| | | let vc = HomeStudyCompleteVC(correctNum: viewModel.correctNum, errorNum: viewModel.errorNum, totalCoin: toalIntegral) |
| | | let vc = HomeStudyCompleteVC(correctNum: viewModel.correctNum, errorNum: viewModel.errorNum, totalCoin: toalIntegral, listenType: viewModel.listenType.value) |
| | | vc.title = viewModel.listenType.value.rawTitle |
| | | push(vc: vc) |
| | | } |
| | | |
| | | //游戏类完成 |
| | | private func gamesComplete(gameId:Int,integral:Int){ |
| | | |
| | | var name = "" |
| | |
| | | |
| | | timer.invalidate() |
| | | |
| | | let vc = HomeStudyCompleteVC(correctNum: viewModel.correctNum, errorNum: viewModel.errorNum, totalCoin: integral) |
| | | let vc = HomeStudyCompleteVC(correctNum: viewModel.correctNum, errorNum: viewModel.errorNum, totalCoin: integral, listenType: viewModel.listenType.value) |
| | | vc.title = viewModel.listenType.value.rawTitle |
| | | push(vc: vc) |
| | | } |
| | | |
| | | private func storyComplete(storyId:Int,integral:Int){ |
| | | Services.completeStory(storyId: storyId, integral: integral).subscribe(onNext: {data in |
| | | |
| | | }).disposed(by: disposeBag) |
| | | |
| | | let vc = HomeStudyCompleteVC(correctNum: viewModel.correctNum, errorNum: viewModel.errorNum, totalCoin: integral, listenType: viewModel.listenType.value) |
| | | vc.title = viewModel.listenType.value.rawTitle |
| | | push(vc: vc) |
| | | } |
| | |
| | | } |
| | | |
| | | @objc func quitAction(){ |
| | | CommonAlertView.show(content: "未完成全部答题,确认退出吗?") { |
| | | self.navigationController?.popViewController(animated: true) |
| | | if btn_exit.titleLabel?.text == "完成"{ |
| | | if viewModel.listenType.value == .story2{ |
| | | let v = data as! Listen1Model |
| | | storyComplete(storyId: v.data!.id, integral: v.data!.lookIntegral) |
| | | } |
| | | }else{ |
| | | CommonAlertView.show(content: "未完成全部答题,确认退出吗?") { |
| | | self.navigationController?.popViewController(animated: true) |
| | | } |
| | | } |
| | | } |
| | | |
| | | @objc func nextAction(){ |
| | | // var v = viewModel.currentPage.value |
| | | // v += 1 |
| | | // viewModel.currentPage.accept(v) |
| | | |
| | | if viewModel.listenType.value == .story2{ |
| | | let v = data as! Listen1Model |
| | | var dict = Dictionary<String,Any>() |
| | | dict["storyId"] = v.data?.id ?? 0 |
| | | dict["storyIntegral"] = v.data?.lookIntegral ?? 0 |
| | | NotificationCenter.default.post(name: NextLession_Noti, object: data) |
| | | } |
| | | } |
| | | |
| | |
| | | let beforePage = max(0, viewModel.currentPage.value - 1) |
| | | pageVC.scroll(toPage: beforePage, animation: true) |
| | | viewModel.currentPage.accept(beforePage) |
| | | |
| | | if viewModel.listenType.value == .story2{ |
| | | btn_next.isHidden = false |
| | | } |
| | | |
| | | btn_exit.setTitle("退出", for: .normal) |
| | | } |
| | | } |
| | | |
| | |
| | | if viewModel.listenType.value == .game1 || viewModel.listenType.value == .game2{ |
| | | return 1 |
| | | } |
| | | |
| | | if viewModel.listenType.value == .story1 || viewModel.listenType.value == .story2{ |
| | | return UInt((data as! Listen1Model).storyList.count) |
| | | } |
| | | return UInt(viewModel.maxPage.value) |
| | | } |
| | | |
| | | func pageViewController(_ pageViewController: FFPageViewController, currentPageChanged currentPage: Int) { |
| | | print("---->\(currentPage)") |
| | | |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if viewModel.listenType.value == .story1{ |
| | | let vc = HomeListenStory_1_VC() |
| | | let vc = HomeListenStory_1_VC(page: page, listen1Model: data as! Listen1Model) |
| | | vc.rootViewModel = viewModel |
| | | return vc |
| | | } |
| | | |
| | | if viewModel.listenType.value == .story2{ |
| | | let vc = HomeListenStory_2_VC() |
| | | let vc = HomeListenStory_2_VC(page: page, listen1Model: data as! Listen1Model) |
| | | vc.rootViewModel = viewModel |
| | | return vc |
| | | } |
| | | |
| | |
| | | private var randomElement:Listen1SubModel? |
| | | private var page:Int! |
| | | var rootViewModel:HomeListenFightViewModel! |
| | | private var tempViews = [StudyHandleView]() |
| | | |
| | | private var playedIndex = Set<Int>() //已经播放过的view |
| | | |
| | | private lazy var stackView:UIStackView = { |
| | | let stackView = UIStackView() |
| | |
| | | |
| | | addStackView() |
| | | VoicePlayer.share().playEnd {[weak self] in |
| | | |
| | | //对已经播放过的View,进行刷新 |
| | | for sub in self!.stackView.arrangedSubviews as! [StudyHandleView]{ |
| | | if self!.playedIndex.contains(sub.tag){ |
| | | sub.resetView() |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | private func addStackView(){ |
| | | stackView.removeArrangedSubviews() |
| | | |
| | | var tempViews = [StudyHandleView]() |
| | | for subV in stackView.arrangedSubviews{ |
| | | subV.removeFromSuperview() |
| | | } |
| | | tempViews.removeAll() |
| | | |
| | | for index in 0...2{ |
| | | let handleView = StudyHandleView.jq_loadNibView() |
| | | handleView.listenType = .lesson2 |
| | | handleView.view_choose.alpha = 0 |
| | | handleView.btn_choose.tag = 10 + index |
| | | handleView.tag = 20 + index |
| | | |
| | | let row = viewModel.selectIndex.value!.row |
| | | let model = listen1Model.subjectList[row] |
| | |
| | | handleView.vioceSoundUrl = model.error.components(separatedBy: ",").last |
| | | } |
| | | |
| | | handleView.playAt {[weak self] index in |
| | | self?.playedIndex.insert(index) |
| | | } |
| | | |
| | | handleView.chooseClouse {[weak self] btn in |
| | | guard let weakSelf = self else { return } |
| | | let row = weakSelf.viewModel.selectIndex.value!.row |
| | | |
| | | handleView.view_choose.alpha = 1 |
| | | var lessionType:Fight_lessonType = .none |
| | | |
| | | if handleView.vioceSoundUrl == weakSelf.listen1Model.subjectList[row].correct{ |
| | | lessionType = .success |
| | | VoicePlayer.share().playerEnd() |
| | | }else{ |
| | | lessionType = .fail |
| | | } |
| | |
| | | handleView.btn_state.alpha = 1 |
| | | } |
| | | |
| | | let i = ceil(handleView.x / 300).int |
| | | if let cell = self?.collectionView.dequeueReusableCell(withReuseIdentifier: "_ListenFight_lesson_1_CCell", for: self!.viewModel.selectIndex.value!) as? ListenFight_lesson_1_CCell{ |
| | | self?.viewModel.answerType.accept(.success) |
| | | self?.answerSuccess(cell,index: index) |
| | | self?.answerSuccess(cell,index: i) |
| | | } |
| | | case .fail: |
| | | weakSelf.rootViewModel.errorNum += 1 |
| | |
| | | UIView.animate(withDuration: 0.5) { |
| | | handleView.btn_state.alpha = 1 |
| | | } |
| | | UIView.animate(withDuration: 0.5, delay: 1.2, options: .layoutSubviews) { |
| | | handleView.btn_pay.alpha = 1 |
| | | handleView.btn_voice.alpha = 1 |
| | | handleView.btn_state.alpha = 0 |
| | | } completion: { _ in |
| | | handleView.btn_choose.isSelected = false |
| | | } |
| | | default: |
| | | handleView.btn_state.setImage(nil, for: .normal) |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | handleView.snp.makeConstraints { make in |
| | | make.height.equalTo(52) |
| | | make.width.greaterThanOrEqualTo(159) |
| | | make.width.greaterThanOrEqualTo(221) |
| | | } |
| | | tempViews.append(handleView) |
| | | } |
| | |
| | | //copy试图放在上面进行覆盖 |
| | | let copyHandleView = studyHandleView.copyView() |
| | | copyHandleView.view_choose.isHidden = true |
| | | copyHandleView.vioceSoundUrl = listen1Model.subjectList[self.viewModel.selectIndex.value!.row].correct |
| | | copyHandleView.btn_state.setImage(nil, for: .normal) |
| | | view.addSubview(copyHandleView) |
| | | view.layoutIfNeeded() |
| | |
| | | make.height.equalTo(40) |
| | | } |
| | | self.view.layoutIfNeeded() |
| | | }completion: { _ in |
| | | self.resetStackView() |
| | | |
| | | }completion: { complete in |
| | | if complete{ |
| | | self.resetStackView() |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | VoicePlayer.share().playEnd { [weak self] in |
| | | guard let weakSelf = self else { return } |
| | | if weakSelf.viewModel.selectIndex.value != nil{ |
| | | weakSelf.collectionView.reloadItems(at: [weakSelf.viewModel.selectIndex.value!]) |
| | | weakSelf.viewModel.selectIndex.accept(nil) |
| | | } |
| | | // if weakSelf.viewModel.selectIndex.value != nil{ |
| | | // weakSelf.collectionView.reloadItems(at: [weakSelf.viewModel.selectIndex.value!]) |
| | | // weakSelf.viewModel.selectIndex.accept(nil) |
| | | // } |
| | | weakSelf.collectionView.reloadData() |
| | | } |
| | | } |
| | |
| | | |
| | | var tempImageArray = [String]() |
| | | |
| | | tempImageArray.append(listen1Model.subjectList[2].img ?? "") |
| | | tempImageArray.append(listen1Model.subjectList[4].img ?? "") |
| | | tempImageArray.append(listen1Model.subjectList[5].img ?? "") |
| | | tempImageArray.append(listen1Model.subjectList[2].img) |
| | | tempImageArray.append(listen1Model.subjectList[4].img) |
| | | tempImageArray.append(listen1Model.subjectList[5].img) |
| | | // tempImageArray.shuffle() |
| | | |
| | | view.addSubview(stackView) |
| | |
| | | NotificationCenter.default.post(name: NextLession_Noti, object: nil);return |
| | | } |
| | | |
| | | DispatchQueue.main.asyncAfter(deadline: .now()+1.5) { |
| | | DispatchQueue.main.asyncAfter(deadline: .now()+1.0) { |
| | | self.setAnswerStackView() |
| | | self.viewModel.selectIndex.accept(nil) |
| | | } |
| | |
| | | extension HomeListenGame_2_VC:UICollectionViewDelegate{ |
| | | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { |
| | | |
| | | if listen1Model.subjectList[indexPath.row].isOpen{ |
| | | print("已经展开过了");return |
| | | } |
| | | |
| | | if selectModels.last?.indexPath == indexPath{ |
| | | print("重复点击");return |
| | | } |
| | |
| | | lastM?.model.isOpen = true |
| | | selectModels.removeAll() |
| | | print("相同") |
| | | rootViewModel.correctNum += 1 |
| | | }else{ |
| | | print("不相同") |
| | | rootViewModel.errorNum += 1 |
| | | let firstIndex = firstM!.indexPath |
| | | let secondIndex = lastM!.indexPath |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | let surplusListCount = listen1Model.subjectList.filter({$0.isOpen == false}).count |
| | | if surplusListCount == 0{ |
| | | NotificationCenter.default.post(name: NextLession_Noti, object: ["gameId":listen1Model.data!.id,"gameIntegral":listen1Model.data!.integral]) |
| | | rootViewModel.answerItems[0] = self.listen1Model |
| | | timer?.invalidate() |
| | | } |
| | | print("剩余:\(surplusListCount)") |
| | | |
| | | } |
| | | } |
| | | } |
| | |
| | | let model = listen1Model.subjectList[indexPath.row] |
| | | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "_ListenFight_Game_Pocket_CCell", for: indexPath) as! ListenFight_Game_Pocket_CCell |
| | | cell.setModel(model) |
| | | cell.voice_view.isHidden = !model.correct.isEmpty |
| | | cell.voice_view.isHidden = model.correct.isEmpty |
| | | return cell |
| | | } |
| | | |
| | |
| | | |
| | | private var viewModel = FightAnswerViewModel() |
| | | |
| | | private var listen1Model:Listen1Model! |
| | | private var page:Int! |
| | | var rootViewModel:HomeListenFightViewModel! |
| | | |
| | | private lazy var stackView:UIStackView = { |
| | | let stackView = UIStackView() |
| | | stackView.spacing = 78 |
| | |
| | | collection.register(UINib(nibName: "SimpleImageCCell", bundle: nil), forCellWithReuseIdentifier: "_SimpleImageCCell") |
| | | return collection |
| | | }() |
| | | |
| | | required init(page:Int,listen1Model:Listen1Model){ |
| | | super.init(nibName: nil, bundle: nil) |
| | | self.page = page |
| | | self.listen1Model = listen1Model |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | | |
| | | override func setUI() { |
| | | super.setUI() |
| | |
| | | make.width.greaterThanOrEqualTo(100) |
| | | } |
| | | |
| | | for subV in stackView.arrangedSubviews{ |
| | | subV.removeFromSuperview() |
| | | } |
| | | stackView.removeArrangedSubviews() |
| | | |
| | | var tempHandleViews = [StudyHandleView]() |
| | | for index in 0...2{ |
| | | let handleView = StudyHandleView.jq_loadNibView() |
| | | handleView.listenType = .lesson2 |
| | | |
| | | if index == 0{ |
| | | handleView.vioceSoundUrl = listen1Model.storyList[page].correct |
| | | }else if index == 1{ |
| | | handleView.vioceSoundUrl = listen1Model.storyList[page].error.components(separatedBy: ",").first |
| | | }else{ |
| | | handleView.vioceSoundUrl = listen1Model.storyList[page].error.components(separatedBy: ",").last |
| | | } |
| | | handleView.btn_choose.tag = 10 + index |
| | | handleView.chooseClouse {[weak self] btn in |
| | | guard let weakSelf = self else { return } |
| | | |
| | | var lessionType:Fight_lessonType = .none |
| | | |
| | | lessionType = .success |
| | | if weakSelf.listen1Model.storyList[weakSelf.page].correct == handleView.vioceSoundUrl{ |
| | | lessionType = .success |
| | | }else{ |
| | | lessionType = .fail |
| | | } |
| | | |
| | | switch lessionType { |
| | | case .success: |
| | | // handleView.btn_choose.isEnabled = false |
| | | weakSelf.rootViewModel.correctNum += 1 |
| | | handleView.btn_choose.isSelected = true |
| | | handleView.btn_state.setImage(UIImage(named: "icon_success_small"), for: .normal) |
| | | UIView.animate(withDuration: 0.5) { |
| | | handleView.btn_state.alpha = 1 |
| | | } |
| | | |
| | | // if let cell = self?.collectionView.dequeueReusableCell(withReuseIdentifier: "_SimpleImageCCell", for: self!.viewModel.selectIndex.value!) as? SimpleImageCCell{ |
| | | // self?.viewModel.answerType.accept(.success) |
| | | // } |
| | | DispatchQueue.main.asyncAfter(delay: 1.0) { |
| | | var dict = Dictionary<String,Any>() |
| | | dict["storyIntegral"] = weakSelf.listen1Model.data?.lookIntegral ?? 0 |
| | | dict["storyId"] = weakSelf.listen1Model.data?.id ?? 0 |
| | | NotificationCenter.default.post(name: NextLession_Noti, object: dict) |
| | | VoicePlayer.share().playerEnd() |
| | | return |
| | | } |
| | | |
| | | case .fail: |
| | | weakSelf.rootViewModel.errorNum += 1 |
| | | handleView.btn_state.setImage(UIImage(named: "icon_waring_small"), for: .normal) |
| | | UIView.animate(withDuration: 0.5) { |
| | | handleView.btn_state.alpha = 1 |
| | |
| | | make.height.equalTo(52) |
| | | make.width.greaterThanOrEqualTo(159) |
| | | } |
| | | stackView.addArrangedSubview(handleView) |
| | | tempHandleViews.append(handleView) |
| | | } |
| | | |
| | | tempHandleViews.shuffle() |
| | | stackView.addArrangedSubviews(tempHandleViews) |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | extension HomeListenStory_1_VC:UICollectionViewDataSource{ |
| | | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { |
| | | let m = listen1Model.storyList[page] |
| | | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "_SimpleImageCCell", for: indexPath) as! SimpleImageCCell |
| | | cell.img_cover.sd_setImage(with: URL(string: m.img)) |
| | | cell.jq_cornerRadius = 10 |
| | | return cell |
| | | } |
| | |
| | | class HomeListenStory_2_VC: BaseVC { |
| | | |
| | | private var viewModel = FightAnswerViewModel() |
| | | |
| | | private var listen1Model:Listen1Model! |
| | | private var page:Int! |
| | | var rootViewModel:HomeListenFightViewModel! |
| | | |
| | | |
| | | private lazy var stackView:UIStackView = { |
| | | let stackView = UIStackView() |
| | |
| | | collection.register(UINib(nibName: "SimpleImageCCell", bundle: nil), forCellWithReuseIdentifier: "_SimpleImageCCell") |
| | | return collection |
| | | }() |
| | | |
| | | required init(page:Int,listen1Model:Listen1Model){ |
| | | super.init(nibName: nil, bundle: nil) |
| | | self.page = page |
| | | self.listen1Model = listen1Model |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | | |
| | | |
| | | override func setUI() { |
| | | super.setUI() |
| | |
| | | } |
| | | |
| | | let handleView = StudyHandleView.jq_loadNibView() |
| | | handleView.listenType = .lesson2 |
| | | handleView.listenType = .lesson1 |
| | | DispatchQueue.main.asyncAfter(wallDeadline: .now()+2){ |
| | | handleView.vioceSoundUrl = self.listen1Model.storyList[self.page].correct |
| | | } |
| | | handleView.btn_choose.tag = 10 |
| | | handleView.chooseClouse {[weak self] btn in |
| | | |
| | | guard let weakSelf = self else { return } |
| | | var lessionType:Fight_lessonType = .none |
| | | |
| | | lessionType = .success |
| | | |
| | | switch lessionType { |
| | | case .success: |
| | | handleView.btn_choose.isSelected = true |
| | |
| | | extension HomeListenStory_2_VC:UICollectionViewDataSource{ |
| | | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { |
| | | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "_SimpleImageCCell", for: indexPath) as! SimpleImageCCell |
| | | let m = listen1Model.storyList[page] |
| | | cell.img_cover.sd_setImage(with: URL(string: m.img)) |
| | | cell.jq_cornerRadius = 10 |
| | | return cell |
| | | } |
| | |
| | | private var quarter:Int! |
| | | private var week:Int! |
| | | private var tableView:UITableView! |
| | | private var studyScheduleModel:StudyScheduleModel? |
| | | |
| | | required init(page:Int,quarter:Int,week:Int) { |
| | | super.init(nibName: nil, bundle: nil) |
| | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | navigationItem.titleView = UIView() |
| | | Services.studySchedule(week: week, day: page + 1).subscribe(onNext: {data in |
| | | self.studyScheduleModel = data.data |
| | | self.tableView.reloadData() |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | //听故事 |
| | | if page == 6{ |
| | | if indexPath.row == 0{ |
| | | JQ_currentViewController().jq_push(vc: HomeListenFightVC(listenType: .story1)) |
| | | Services.lookpictureDbu(quarter: quarter, week: week).subscribe(onNext: {result in |
| | | if let data = result.data{ |
| | | let fightVC = HomeListenFightVC(listenType: .story1) |
| | | fightVC.title = ListenType.story1.rawTitle |
| | | fightVC.data = data |
| | | JQ_currentViewController().jq_push(vc: fightVC) |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | if indexPath.row == 1{ |
| | | JQ_currentViewController().jq_push(vc: HomeListenFightVC(listenType: .story2)) |
| | | Services.frameworkMemory(quarter: quarter, week: week).subscribe(onNext: {result in |
| | | if let data = result.data{ |
| | | let fightVC = HomeListenFightVC(listenType: .story2) |
| | | fightVC.title = ListenType.story2.rawTitle |
| | | fightVC.data = data |
| | | JQ_currentViewController().jq_push(vc: fightVC) |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | } |
| | | } |
| | |
| | | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
| | | if indexPath.section == 0 && page <= 4{ |
| | | let cell = tableView.dequeueReusableCell(withIdentifier: "_HomeListen_process_TCell", for: indexPath) as! HomeListen_process_TCell |
| | | cell.studyScheduleModel = studyScheduleModel |
| | | return cell |
| | | }else{ |
| | | let cell = tableView.dequeueReusableCell(withIdentifier: "_HomeListen_item_TCell", for: indexPath) as! HomeListen_item_TCell |
| | |
| | | case 0: |
| | | cell.label_title.text = "自主学习1-听音选图" |
| | | cell.view_bg2.backgroundColor = UIColor(hexString: "#6EC3FF") |
| | | cell.setProgress(progress: studyScheduleModel?.listen ?? 0) |
| | | case 1: |
| | | cell.label_title.text = "自主学习2-看图选音" |
| | | cell.view_bg2.backgroundColor = UIColor(hexString: "#FF9A85") |
| | | cell.setProgress(progress: studyScheduleModel?.look ?? 0) |
| | | case 2: |
| | | cell.label_title.text = "自主学习3-归纳排除" |
| | | cell.view_bg2.backgroundColor = UIColor(hexString: "#28C8C5") |
| | | cell.setProgress(progress: studyScheduleModel?.induction ?? 0) |
| | | case 3: |
| | | cell.label_title.text = "自主学习4-有问有答" |
| | | cell.view_bg2.backgroundColor = UIColor(hexString: "#F8A169") |
| | | cell.setProgress(progress: studyScheduleModel?.answer ?? 0) |
| | | case 4: |
| | | cell.label_title.text = "自主学习5-音图相配" |
| | | cell.view_bg2.backgroundColor = UIColor(hexString: "#92CADB") |
| | | cell.setProgress(progress: studyScheduleModel?.pair ?? 0) |
| | | default:break |
| | | } |
| | | } |
| | |
| | | @IBOutlet weak var label_totalNum: UILabel! |
| | | @IBOutlet weak var label_errorNum: UILabel! |
| | | @IBOutlet weak var label_ratioNum: UILabel! |
| | | @IBOutlet weak var btn_next: UIButton! |
| | | |
| | | private var correctNum:Int = 0 |
| | | private var errorNum:Int = 0 |
| | | private var totalCoin:Int = 0 |
| | | private var listenType:ListenType! |
| | | |
| | | required init(correctNum:Int,errorNum:Int,totalCoin:Int){ |
| | | required init(correctNum:Int,errorNum:Int,totalCoin:Int,listenType:ListenType){ |
| | | super.init(nibName: nil, bundle: nil) |
| | | self.correctNum = correctNum |
| | | self.errorNum = errorNum |
| | | self.totalCoin = totalCoin |
| | | self.listenType = listenType |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | @IBAction func nextAction(_ sender: UIButton) { |
| | | |
| | | } |
| | | } |
| | |
| | | <objects> |
| | | <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="HomeStudyCompleteVC" customModule="DolphinEnglishLearnStudent" customModuleProvider="target"> |
| | | <connections> |
| | | <outlet property="btn_next" destination="gcd-t9-jC7" id="GUH-Wl-YUg"/> |
| | | <outlet property="label_coin" destination="0Rg-U5-bnk" id="Ue5-07-HUP"/> |
| | | <outlet property="label_correctNum" destination="GyL-R8-T1w" id="ljq-bs-33V"/> |
| | | <outlet property="label_errorNum" destination="8Lo-W3-dxd" id="y0q-RX-MkE"/> |
| | |
| | | <real key="value" value="4"/> |
| | | </userDefinedRuntimeAttribute> |
| | | </userDefinedRuntimeAttributes> |
| | | <connections> |
| | | <action selector="nextAction:" destination="-1" eventType="touchUpInside" id="EFz-cI-K4A"/> |
| | | </connections> |
| | | </button> |
| | | </subviews> |
| | | </stackView> |
| | |
| | | } |
| | | |
| | | if let model = result.data?.userStudy{ |
| | | items.append("学习进度:\(model.week)") |
| | | items.append("学习进度:周目\(model.week.jq_cn)") |
| | | items.append("学习总时长:\(model.totalStudy)小时") |
| | | } |
| | | self.label_info.text = items.joined(separator: "|") |
| | |
| | | }else{ |
| | | let attribute = AttributedStringbuilder.build().add(string: "设为默认", withFont: .systemFont(ofSize: 14, weight: .medium), withColor: UIColor(hexStr: "#41A2EB")).underLine(color: UIColor(hexStr: "#41A2EB")).mutableAttributedString |
| | | btn_default.setAttributedTitle(attribute, for: .normal) |
| | | btn_default.backgroundColor = .white |
| | | } |
| | | } |
| | | |
| | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | |
| | | viewModel.configure(tableView) |
| | | viewModel.configure(tableView,needMore: false) |
| | | viewModel.beginRefresh() |
| | | } |
| | | |
| | |
| | | tableView.delegate = self |
| | | tableView.dataSource = self |
| | | tableView.backgroundColor = .clear |
| | | tableView.showsVerticalScrollIndicator = false |
| | | tableView.showsLargeContentViewer = false |
| | | tableView.separatorStyle = .none |
| | | tableView.register(UINib(nibName: "GoodsItemTCell", bundle: nil), forCellReuseIdentifier: "_GoodsItemTCell") |
| | | view.addSubview(tableView) |
| | |
| | | btn_state.alpha = 0 |
| | | view_choose.alpha = 0 |
| | | |
| | | voicePlayer.playEnd {[weak self] in |
| | | self?.reset() |
| | | } |
| | | // voicePlayer.playEnd {[weak self] in |
| | | // guard let weakSelf = self else { return } |
| | | // weakSelf.resetView() |
| | | // } |
| | | } |
| | | |
| | | func chooseClouse(callback:@escaping (UIButton)->Void){ |
| | |
| | | return copyV |
| | | } |
| | | |
| | | func reset(){ |
| | | func resetView(){ |
| | | switch listenType { |
| | | case .lesson1,.lesson5: |
| | | btn_state.setImage(UIImage(named: "icon_play"), for: .normal) |
| | | btn_voice.alpha = 1 |
| | | btn_pay.alpha = 1 |
| | | btn_state.alpha = 0 |
| | | UIView.animate(withDuration: 0.25) { |
| | | self.btn_state.setImage(UIImage(named: "icon_play"), for: .normal) |
| | | self.btn_voice.alpha = 1 |
| | | self.btn_pay.alpha = 1 |
| | | self.btn_state.alpha = 0 |
| | | } |
| | | case .lesson2: |
| | | view_choose.alpha = 1 |
| | | UIView.animate(withDuration: 0.25) { |
| | | self.btn_state.setImage(UIImage(named: "icon_play"), for: .normal) |
| | | self.btn_voice.alpha = 1 |
| | | self.btn_pay.alpha = 1 |
| | | self.btn_state.alpha = 0 |
| | | self.view_choose.alpha = 1 |
| | | } |
| | | default:break |
| | | } |
| | | self.superview?.layoutIfNeeded() |
| | | } |
| | | |
| | | @IBAction func payAction(_ sender: UIButton) { |
| | |
| | | playAtClouse?(self.tag) |
| | | switch listenType { |
| | | case .lesson1,.lesson5: |
| | | btn_state.setImage(UIImage(named: "icon_playing"), for: .normal) |
| | | btn_voice.alpha = 0 |
| | | btn_pay.alpha = 0 |
| | | btn_state.alpha = 1 |
| | | UIView.animate(withDuration: 0.25) { |
| | | self.btn_state.setImage(UIImage(named: "icon_playing"), for: .normal) |
| | | self.btn_voice.alpha = 0 |
| | | self.btn_pay.alpha = 0 |
| | | self.btn_state.alpha = 1 |
| | | } |
| | | break |
| | | case .lesson2: |
| | | view_choose.alpha = 1 |
| | | UIView.animate(withDuration: 0.25) { |
| | | self.btn_state.setImage(UIImage(named: "icon_playing"), for: .normal) |
| | | self.btn_voice.alpha = 0 |
| | | self.btn_pay.alpha = 0 |
| | | self.btn_state.alpha = 1 |
| | | self.view_choose.alpha = 1 |
| | | } |
| | | |
| | | default:break |
| | | } |
| | | } |
| | |
| | | <objects> |
| | | <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> |
| | | <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> |
| | | <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="StudyHandleView" customModule="DolphinEnglishLearnStudent" customModuleProvider="target"> |
| | | <rect key="frame" x="0.0" y="0.0" width="375" height="103"/> |
| | | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
| | | <view autoresizesSubviews="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iN0-l3-epB" customClass="StudyHandleView" customModule="DolphinEnglishLearnStudent" customModuleProvider="target"> |
| | | <rect key="frame" x="0.0" y="0.0" width="360" height="103"/> |
| | | <subviews> |
| | | <stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="eHm-vL-3gG"> |
| | | <rect key="frame" x="0.0" y="0.0" width="375" height="103"/> |
| | | <rect key="frame" x="0.0" y="0.0" width="360" height="103"/> |
| | | <subviews> |
| | | <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0XQ-2a-X00"> |
| | | <rect key="frame" x="0.0" y="0.0" width="313" height="103"/> |
| | | <rect key="frame" x="0.0" y="0.0" width="298" height="103"/> |
| | | <subviews> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eGw-vD-STe"> |
| | | <rect key="frame" x="98.5" y="0.0" width="27" height="103"/> |
| | | <rect key="frame" x="91" y="0.0" width="27" height="103"/> |
| | | <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> |
| | | <state key="normal" image="icon_play_1"/> |
| | | </button> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zhb-53-qPO"> |
| | | <rect key="frame" x="140.5" y="35.5" width="32" height="32"/> |
| | | <rect key="frame" x="133" y="35.5" width="32" height="32"/> |
| | | <constraints> |
| | | <constraint firstAttribute="height" constant="32" id="l56-9N-QqM"/> |
| | | <constraint firstAttribute="width" constant="32" id="yNt-fZ-NqV"/> |
| | |
| | | <state key="normal" image="icon_success_small"/> |
| | | </button> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mz1-vG-vfG"> |
| | | <rect key="frame" x="181.5" y="0.0" width="32" height="103"/> |
| | | <rect key="frame" x="174" y="0.0" width="32" height="103"/> |
| | | <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> |
| | | <state key="normal" image="icon_play"/> |
| | | <connections> |
| | |
| | | <constraint firstItem="eGw-vD-STe" firstAttribute="top" secondItem="0XQ-2a-X00" secondAttribute="top" id="sSv-55-R5E"/> |
| | | <constraint firstItem="zhb-53-qPO" firstAttribute="leading" secondItem="eGw-vD-STe" secondAttribute="trailing" constant="15" id="uxB-Ji-qbq"/> |
| | | <constraint firstItem="zhb-53-qPO" firstAttribute="centerY" secondItem="0XQ-2a-X00" secondAttribute="centerY" id="vt0-xM-xhJ"/> |
| | | <constraint firstAttribute="width" constant="159" id="yYG-aD-bOA"/> |
| | | <constraint firstItem="mz1-vG-vfG" firstAttribute="leading" secondItem="zhb-53-qPO" secondAttribute="trailing" constant="9" id="zfI-8E-Wuj"/> |
| | | </constraints> |
| | | <userDefinedRuntimeAttributes> |
| | |
| | | </userDefinedRuntimeAttributes> |
| | | </view> |
| | | <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xya-RD-K98"> |
| | | <rect key="frame" x="323" y="0.0" width="52" height="103"/> |
| | | <rect key="frame" x="308" y="0.0" width="52" height="103"/> |
| | | <subviews> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="X68-mT-DTX"> |
| | | <rect key="frame" x="0.0" y="0.0" width="52" height="103"/> |
| | |
| | | <constraint firstItem="X68-mT-DTX" firstAttribute="leading" secondItem="xya-RD-K98" secondAttribute="leading" id="TTg-dL-KiZ"/> |
| | | <constraint firstAttribute="trailing" secondItem="X68-mT-DTX" secondAttribute="trailing" id="cc2-ZM-WrM"/> |
| | | <constraint firstAttribute="bottom" secondItem="X68-mT-DTX" secondAttribute="bottom" id="l1j-V9-Z1l"/> |
| | | <constraint firstAttribute="width" constant="52" id="nRM-Df-MFI"/> |
| | | <constraint firstItem="X68-mT-DTX" firstAttribute="top" secondItem="xya-RD-K98" secondAttribute="top" id="rT5-GH-42w"/> |
| | | </constraints> |
| | | </view> |
| | |
| | | </subviews> |
| | | <constraints> |
| | | <constraint firstAttribute="bottom" secondItem="eHm-vL-3gG" secondAttribute="bottom" id="Blb-Nr-aIZ"/> |
| | | <constraint firstAttribute="trailing" secondItem="eHm-vL-3gG" secondAttribute="trailing" id="I3k-vZ-IqT"/> |
| | | <constraint firstItem="eHm-vL-3gG" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="VE4-ti-8X6"/> |
| | | <constraint firstItem="eHm-vL-3gG" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="jOh-WU-Wga"/> |
| | | <constraint firstItem="eHm-vL-3gG" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Bxd-Bu-lDx"/> |
| | | <constraint firstItem="eHm-vL-3gG" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="tYp-rY-CgC"/> |
| | | <constraint firstAttribute="trailing" secondItem="eHm-vL-3gG" secondAttribute="trailing" id="tqt-fU-itS"/> |
| | | </constraints> |
| | | <nil key="simulatedTopBarMetrics"/> |
| | | <nil key="simulatedBottomBarMetrics"/> |
| | | <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> |
| | | <connections> |
| | | <outlet property="btn_choose" destination="X68-mT-DTX" id="xa8-33-1zl"/> |
| | |
| | | <outlet property="btn_voice" destination="eGw-vD-STe" id="vtB-m3-iOY"/> |
| | | <outlet property="view_choose" destination="xya-RD-K98" id="gz4-Jd-l5U"/> |
| | | </connections> |
| | | <point key="canvasLocation" x="94.756097560975604" y="-171.10169491525426"/> |
| | | <point key="canvasLocation" x="89.268292682926827" y="-171.10169491525426"/> |
| | | </view> |
| | | </objects> |
| | | <resources> |
New file |
| | |
| | | // |
| | | // VoiceHandleView.swift |
| | | // DolphinEnglishLearnStudent |
| | | // |
| | | // Created by 无故事王国 on 2024/6/11. |
| | | // |
| | | |
| | | import UIKit |
| | | |
| | | class VoiceHandleView: UIView { |
| | | |
| | | private lazy var img_hint:UIImageView = { |
| | | let img = UIImageView(image: UIImage(named: "icon_play_1")) |
| | | return img |
| | | }() |
| | | |
| | | private lazy var img_hint_playing:UIImageView = { |
| | | let img = UIImageView(image: UIImage(named: "icon_playing")) |
| | | img.isHidden = true |
| | | return img |
| | | }() |
| | | |
| | | private lazy var btn_play:UIButton = { |
| | | let btn = UIButton(type: .custom) |
| | | btn.setImage(UIImage(named: "icon_play"), for: .normal) |
| | | return btn |
| | | }() |
| | | |
| | | var playUrl:String? |
| | | var listenType:ListenType? |
| | | |
| | | override init(frame: CGRect) { |
| | | super.init(frame: frame) |
| | | setUI() |
| | | |
| | | VoicePlayer.share().playEnd { |
| | | self.resetView() |
| | | } |
| | | } |
| | | |
| | | private func setUI(){ |
| | | backgroundColor = UIColor(hexString: "#41A2EB") |
| | | jq_cornerRadius = 8 |
| | | addSubview(img_hint) |
| | | img_hint.snp.makeConstraints { make in |
| | | make.left.equalTo(25) |
| | | make.centerY.equalToSuperview() |
| | | make.width.equalTo(27) |
| | | make.height.equalTo(27) |
| | | } |
| | | |
| | | addSubview(img_hint_playing) |
| | | img_hint_playing.snp.makeConstraints { make in |
| | | make.center.equalToSuperview() |
| | | make.width.equalTo(45) |
| | | make.height.equalTo(31) |
| | | } |
| | | |
| | | addSubview(btn_play) |
| | | btn_play.addTarget(self, action: #selector(playingAction), for: .touchUpInside) |
| | | btn_play.snp.makeConstraints { make in |
| | | make.right.equalTo(-23) |
| | | make.centerY.equalToSuperview() |
| | | make.width.equalTo(32) |
| | | make.height.equalTo(32) |
| | | } |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | | |
| | | func resetView(){ |
| | | img_hint.isHidden = false |
| | | btn_play.isHidden = false |
| | | img_hint_playing.isHidden = true |
| | | } |
| | | |
| | | @objc func playingAction(){ |
| | | if let url = playUrl{ |
| | | VoicePlayer.share().playerAt(url: url) |
| | | img_hint.isHidden = true |
| | | btn_play.isHidden = true |
| | | img_hint_playing.isHidden = false |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | params.append(key: "week", value: week) |
| | | return NetworkRequest.request(params: params, method: .get, progress: true) |
| | | } |
| | | |
| | | class func frameworkMemory(quarter:Int,week:Int)->Observable<BaseResponse<Listen1Model>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/study/base/study/frameworkMemory") |
| | | params.append(key: "quarter", value: quarter) |
| | | params.append(key: "week", value: week) |
| | | return NetworkRequest.request(params: params, method: .get, progress: true) |
| | | } |
| | | |
| | | class func lookpictureDbu(quarter:Int,week:Int)->Observable<BaseResponse<Listen1Model>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/study/base/study/lookPictureDbu") |
| | | params.append(key: "quarter", value: quarter) |
| | | params.append(key: "week", value: week) |
| | | return NetworkRequest.request(params: params, method: .get, progress: true) |
| | | } |
| | | |
| | | class func completeStory(storyId:Int,integral:Int)->Observable<BaseResponse<SimpleModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/study/base/study/completeStory") |
| | | params.append(key: "storyId", value: storyId) |
| | | params.append(key: "integral", value: integral) |
| | | return NetworkRequest.request(params: params, method: .get, progress: true) |
| | | } |
| | | |
| | | class func studySchedule(week:Int,day:Int)->Observable<BaseResponse<StudyScheduleModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | params.interface(url: "/study/base/study/studySchedule") |
| | | params.append(key: "week", value: week) |
| | | params.append(key: "day", value: day) |
| | | return NetworkRequest.request(params: params, method: .get, progress: true) |
| | | } |
| | | } |
| | | |
| | | // MARK: -- 登录部分 |