| | |
| | | <rect key="frame" x="0.0" y="498.33333333333326" width="393" height="353.66666666666674"/> |
| | | <subviews> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="60u-g2-ZcS"> |
| | | <rect key="frame" x="357.66666666666669" y="18.000000000000057" width="21.333333333333314" height="22"/> |
| | | <rect key="frame" x="359" y="18.000000000000057" width="20" height="22"/> |
| | | <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> |
| | | <state key="normal" image="btn_close"/> |
| | | <connections> |
| | |
| | | </label> |
| | | <wkWebView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EJM-vb-bxZ"> |
| | | <rect key="frame" x="0.0" y="56.333333333333314" width="393" height="297.33333333333331"/> |
| | | <color key="backgroundColor" red="0.36078431370000003" green="0.38823529410000002" blue="0.4039215686" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| | | <wkWebViewConfiguration key="configuration"> |
| | | <audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/> |
| | | <wkPreferences key="preferences"/> |
| | |
| | | </view> |
| | | </objects> |
| | | <resources> |
| | | <image name="btn_close" width="21.333333969116211" height="21.333333969116211"/> |
| | | <image name="btn_close" width="20" height="20"/> |
| | | <systemColor name="systemBackgroundColor"> |
| | | <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> |
| | | </systemColor> |
| | |
| | | } |
| | | |
| | | |
| | | enum StudentAppointType:Int,HandyJSONEnum{ |
| | | case pedding = 1 |
| | | case begining = 2 |
| | | case complete = 3 |
| | | case cancel = 4 |
| | | |
| | | var strTitle:String{ |
| | | switch self{ |
| | | case .pedding:return "待上课" |
| | | case .begining:return "已开始" |
| | | case .complete:return "已完成" |
| | | case .cancel:return "已取消" |
| | | } |
| | | } |
| | | } |
| | | |
| | | enum StudentAppointDateType:Int,HandyJSONEnum{ |
| | | case all = 0 |
| | | case week = 1 |
| | | case month = 2 |
| | | case year = 3 |
| | | } |
| | | |
| | | enum MedalType:Int,HandyJSONEnum{ |
| | | case club = 1 |
| | | case sport = 2 |
| | | case communtiy = 3 |
| | | case deepPlayer = 4 |
| | | |
| | | |
| | | var image:UIImage{ |
| | | switch self { |
| | | case .club:return UIImage(named: "icon_coupon_1")! |
| | | case .sport:return UIImage(named: "icon_coupon_2")! |
| | | case .communtiy:return UIImage(named: "icon_coupon_3")! |
| | | case .deepPlayer:return UIImage(named: "icon_coupon_4")! |
| | | } |
| | | } |
| | | |
| | | var title_en:String{ |
| | | switch self { |
| | | case .club:return "COURSE" |
| | | case .sport:return "EVENTS" |
| | | case .communtiy:return "ON_LINE" |
| | | case .deepPlayer:return "APPOINTMENT" |
| | | } |
| | | } |
| | | |
| | | var title:String{ |
| | | switch self { |
| | | case .club:return "俱乐部之星" |
| | | case .sport:return "运动大人" |
| | | case .communtiy:return "社区之王" |
| | | case .deepPlayer:return "深度玩家" |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | |
| | | |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_1"), t1: "COURSE", t2: "俱乐部之星")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_2"), t1: "EVENTS", t2: "运动大人")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_3"), t1: "ON_LINE", t2: "社区之王")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_4"), t1: "APPOINTMENT", t2: "深度玩家")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_5"), t1: "EVENTS", t2: "月度冠军")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_6"), t1: "MORE", t2: "更多"))*/ |
| | | } |
| | | |
| | | |
| | |
| | | var deductedNums: Int = 0 |
| | | var exerciseVideoList = [StartClouseVideoListModel]() |
| | | var height: Int = 0 |
| | | var imgs: String? |
| | | var imgs: String = "" |
| | | ///是否有学员信息 (1. 有学员信息 2.没有学员信息) |
| | | var isThere: Int = 2 |
| | | var remainingNums: Int = 0 |
| | | var stuAge: Int = 0 |
| | | var stuId: Int = 0 |
| | | var stuImg: String? |
| | | var stuName: String? |
| | | var stuImg: String = "" |
| | | var stuName: String = "" |
| | | var stuSex: GenderType = .man |
| | | var totalNums: Int = 0 |
| | | var weight: Int = 0 |
| | |
| | | |
| | | } |
| | | |
| | | class StudentAppointModel:HandyJSON { |
| | | var courseHours: Int = 0 |
| | | var coursePackageId: Int = 0 |
| | | var coursePackageName: String = "" |
| | | var courseStuRecordId: Int = 0 |
| | | var status:StudentAppointType = .complete |
| | | var storeNameAddr: String = "" |
| | | var timeFrame: String = "" |
| | | |
| | | required init() {} |
| | | } |
| | | |
| | | |
| | | struct ExerciseVideoModel:HandyJSON { |
| | | var coursePackageId: Int = 0 |
| | | var coverImage: String = "" |
| | | var integral:Int = 0 |
| | | var packageName: String = "" |
| | | var studyStatus: Int = 0 |
| | | var synopsis: String = "" |
| | | var videoId: Int = 0 |
| | | var videoName: String = "" |
| | | } |
| | | |
| | | struct ExerciseVideoDetailModel:HandyJSON { |
| | | var coursePackageId: Int = 0 |
| | | var detailedDiagram: String = "" |
| | | var integral: Int = 0 |
| | | var packageName: String = "" |
| | | var studyStatus: Int = 0 |
| | | var synopsis: String = "" |
| | | var videoId: Int = 0 |
| | | var videoName: String = "" |
| | | var videoURL: String = "" |
| | | } |
| | | |
| | | struct StudentMedalModel:HandyJSON { |
| | | var medalName = "" |
| | | var medalType:MedalType = .club |
| | | } |
| | | |
| | | |
| | |
| | | .interface(url: "/account/api/useBenefit/userDetails") |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | |
| | | /// 勋章 |
| | | static func studMedalList(studentId:Int)->Observable<BaseResponse<[StudentMedalModel]>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | .interface(url: "/account/api/startCource/stuGoog") |
| | | .append(key: "stuId", value: studentId) |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | } |
| | | |
| | | // MARK: -- 福利相关 |
| | |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | |
| | | // static func |
| | | |
| | | /// 学员预约课程列表 |
| | | static func studentAppointList(stuId:Int,status:StudentAppointType?,search:String,timeType:StudentAppointDateType)->Observable<BaseResponse<[StudentAppointModel]>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | .interface(url: "/account/api/startCource/stuAppointList") |
| | | .append(key: "status", value: status?.rawValue) |
| | | .append(key: "timeType", value: timeType.rawValue) |
| | | .append(key: "search", value: search) |
| | | .append(key: "stuId", value: stuId) |
| | | return NetworkRequest.request(params: params, method: .post, progress: false) |
| | | } |
| | | |
| | | /// 课后练习-获取布置课程列表 |
| | | static func queryArrangeCourseList()->Observable<BaseResponse<[CityProfileModel]>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | .interface(url: "/course/api/course/queryArrangeCourseList") |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | |
| | | /// 课后练习-课后视频列表 |
| | | static func exerciseCourseList(courseTypeId:Int?,search:String)->Observable<BaseResponse<[ExerciseVideoModel]>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | .interface(url: "/course/api/startCource/afterSourceList") |
| | | .append(key: "courseTypeId", value: courseTypeId) |
| | | .append(key: "search", value: search) |
| | | return NetworkRequest.request(params: params, method: .post, progress: false) |
| | | } |
| | | |
| | | /// 课后练习-课后视频详情 |
| | | static func exerciseCourseDetail(coursePackageId:Int,videoId:Int)->Observable<BaseResponse<ExerciseVideoDetailModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | .interface(url: "/course/api/startCource/afterSourceDetail") |
| | | .append(key: "coursePackageId", value: coursePackageId) |
| | | .append(key: "videoId", value: videoId) |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | |
| | | |
| | | /// 取消预约 |
| | | static func cancelCourse(courseStuRecordId:Int)->Observable<BaseResponse<SimpleModel>>{ |
| | | let params = ParamsAppender.build(url: All_Url) |
| | | .interface(url: "/account/api/startCource/cancelCourse") |
| | | .append(key: "courseStuRecordId", value: courseStuRecordId) |
| | | return NetworkRequest.request(params: params, method: .post, progress: true) |
| | | } |
| | | |
| | | } |
| | | |
| | | // MARK: -- 探索玩湃 |
| | |
| | | |
| | | import UIKit |
| | | import JQTools |
| | | import RxSwift |
| | | |
| | | class CourseBooking_1_TCell: UITableViewCell { |
| | | |
| | | var indexPath:IndexPath! |
| | | |
| | | var studentAppointModel:StudentAppointModel!{ |
| | | didSet{ |
| | | label_title.text = studentAppointModel.coursePackageName |
| | | label_courseNum.text = "\(studentAppointModel.courseHours)课时" |
| | | label_address.text = studentAppointModel.storeNameAddr |
| | | label_datetime.text = studentAppointModel.timeFrame |
| | | label_status.text = studentAppointModel.status.strTitle |
| | | |
| | | btn_exercise.isHidden = studentAppointModel.status != .complete |
| | | btn_cancel.isHidden = studentAppointModel.status != .pedding |
| | | |
| | | switch studentAppointModel.status{ |
| | | case .pedding:label_status.textColor = UIColor(hexStr: "#FD7402") |
| | | default:label_status.textColor = UIColor(hexStr: "#3D3E45") |
| | | } |
| | | } |
| | | } |
| | | |
| | | @IBOutlet weak var label_title: UILabel! |
| | | @IBOutlet weak var label_courseNum: UILabel! |
| | | @IBOutlet weak var label_address: UILabel! |
| | | @IBOutlet weak var label_datetime: UILabel! |
| | | @IBOutlet weak var btn_exercise: UIButton! |
| | | @IBOutlet weak var label_status: UILabel! |
| | | @IBOutlet weak var btn_cancel: UIButton! |
| | | |
| | | private var disposeBag = DisposeBag() |
| | | |
| | | override func awakeFromNib() { |
| | | super.awakeFromNib() |
| | | selectionStyle = .none |
| | | } |
| | | |
| | | |
| | | @IBAction func exerciseAction(_ sender: UIButton) { |
| | | let vc = CourseExerciseSubListVC() |
| | | JQ_currentViewController().jq_push(vc: vc) |
| | | } |
| | | |
| | | @IBAction func cancelAction(_ sender: UIButton) { |
| | | CommonAlertView.show(title: "取消预约", content: "是否取消当前预约?") {[weak self] status in |
| | | guard let weakSelf = self else { return } |
| | | if status{ |
| | | Services.cancelCourse(courseStuRecordId: weakSelf.studentAppointModel.courseStuRecordId).subscribe(onNext: { data in |
| | | NotificationCenter.default.post(name: CourseBooking_Noti, object: weakSelf.indexPath) |
| | | }).disposed(by: weakSelf.disposeBag) |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | <subviews> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Lsb-45-cHD"> |
| | | <rect key="frame" x="0.0" y="0.0" width="65" height="31"/> |
| | | <color key="backgroundColor" red="0.0" green="0.28235294117647058" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| | | <color key="backgroundColor" red="0.1764705882352941" green="0.47843137254901957" blue="0.89411764705882346" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| | | <constraints> |
| | | <constraint firstAttribute="height" constant="31" id="1Yg-zk-B6F"/> |
| | | <constraint firstAttribute="width" constant="65" id="xk7-VO-G4n"/> |
| | |
| | | <real key="value" value="4"/> |
| | | </userDefinedRuntimeAttribute> |
| | | </userDefinedRuntimeAttributes> |
| | | <connections> |
| | | <action selector="cancelAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="cyx-B3-6JO"/> |
| | | </connections> |
| | | </button> |
| | | </subviews> |
| | | </stackView> |
| | |
| | | </tableViewCellContentView> |
| | | <viewLayoutGuide key="safeArea" id="njF-e1-oar"/> |
| | | <connections> |
| | | <outlet property="btn_cancel" destination="7q7-IT-nb7" id="M9q-V4-ucL"/> |
| | | <outlet property="btn_exercise" destination="Lsb-45-cHD" id="Mwu-mB-auF"/> |
| | | <outlet property="label_address" destination="ktg-rh-qFI" id="gv3-e7-O9G"/> |
| | | <outlet property="label_courseNum" destination="5sN-Qk-YoW" id="1n8-pe-TiT"/> |
| | | <outlet property="label_datetime" destination="Ezt-vJ-DRh" id="eSv-rM-t8Y"/> |
| | | <outlet property="label_status" destination="99b-Wb-RuW" id="VWI-IV-HY9"/> |
| | | <outlet property="label_title" destination="LvX-FX-4Fb" id="bgZ-DE-fLm"/> |
| | | </connections> |
| | | <point key="canvasLocation" x="157.25190839694656" y="52.464788732394368"/> |
| | | </tableViewCell> |
| | |
| | | |
| | | class CourseExerciseTCell: UITableViewCell { |
| | | |
| | | var exerciseVideoModel:ExerciseVideoModel!{ |
| | | didSet{ |
| | | img_cover.sd_setImage(with: URL(string: exerciseVideoModel.coverImage)) |
| | | label_title.text = exerciseVideoModel.packageName |
| | | label_course.text = "布置课程:\(exerciseVideoModel.videoName)" |
| | | label_info.text = exerciseVideoModel.synopsis |
| | | label_obtainCoin.text = "\(exerciseVideoModel.integral)积分" |
| | | if exerciseVideoModel.studyStatus == 1{ |
| | | label_status.text = "未学习" |
| | | label_status.textColor = Def_ThemeColor |
| | | view_status.backgroundColor = UIColor(hexStr: "#FD9331").withAlphaComponent(0.29) |
| | | }else{ |
| | | label_status.text = "已学习" |
| | | label_status.textColor = .white |
| | | view_status.backgroundColor = UIColor(hexStr: "#ACACAC") |
| | | } |
| | | } |
| | | } |
| | | |
| | | @IBOutlet weak var img_cover: UIImageView! |
| | | @IBOutlet weak var label_title: UILabel! |
| | | @IBOutlet weak var label_course: UILabel! |
| | | @IBOutlet weak var label_info: UILabel! |
| | | @IBOutlet weak var label_obtainCoin: UILabel! |
| | | @IBOutlet weak var label_status: UILabel! |
| | | @IBOutlet weak var view_status: UIView! |
| | | |
| | | override func awakeFromNib() { |
| | | super.awakeFromNib() |
| | | selectionStyle = .none |
| | | } |
| | | |
| | | @IBAction func detailAction(_ sender: UIButton) { |
| | | let vc = CourseVideoDetailVC(id: 0) |
| | | let vc = CourseVideoDetailVC(model: exerciseVideoModel) |
| | | vc.title = "课后练习" |
| | | JQ_currentViewController().jq_push(vc: vc) |
| | | } |
| | |
| | | </constraints> |
| | | </tableViewCellContentView> |
| | | <viewLayoutGuide key="safeArea" id="njF-e1-oar"/> |
| | | <connections> |
| | | <outlet property="img_cover" destination="D8i-5m-KbW" id="rWa-Ps-JLF"/> |
| | | <outlet property="label_course" destination="w8Y-sZ-oiu" id="KCN-01-PrT"/> |
| | | <outlet property="label_info" destination="ucP-Ze-NXw" id="zNz-AB-41x"/> |
| | | <outlet property="label_obtainCoin" destination="2KD-0O-4Io" id="hGR-nR-hYs"/> |
| | | <outlet property="label_status" destination="MN0-XR-aVY" id="poj-2e-5Dq"/> |
| | | <outlet property="label_title" destination="gzO-xf-hET" id="QQg-Mk-Zk4"/> |
| | | <outlet property="view_status" destination="16o-eh-HEi" id="0o5-Jq-Fn6"/> |
| | | </connections> |
| | | <point key="canvasLocation" x="-61.832061068702288" y="34.507042253521128"/> |
| | | </tableViewCell> |
| | | </objects> |
| | |
| | | return v |
| | | }() |
| | | |
| | | var startClouseHomeModel:StartClouseHomeModel! |
| | | |
| | | |
| | | private lazy var label_student:UILabel = { |
| | | let label = UILabel() |
| | |
| | | return label |
| | | }() |
| | | |
| | | init(student:StartClouseHomeModel) { |
| | | super.init(nibName: nil, bundle: nil) |
| | | self.startClouseHomeModel = student |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | title = "预约课程" |
| | |
| | | pageViewController.delegate = self |
| | | edgesForExtendedLayout = .top |
| | | funcView.btn_datetime.addTarget(self, action: #selector(datetimeAction), for: .touchUpInside) |
| | | funcView.btn_search.addTarget(self, action: #selector(searchAction), for: .touchUpInside) |
| | | funcView.tf_search.delegate = self |
| | | |
| | | label_student.text = "当前学员:\(startClouseHomeModel.stuName)" |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | } |
| | | |
| | | @objc func datetimeAction(){ |
| | | JQ_MenuView().show(self, tapView: funcView.btn_datetime, items: ["全部","最近一周","最近一月","最近一年"],tableHei: 150) { index, str in |
| | | |
| | | JQ_MenuView().show(self, tapView: funcView.btn_datetime, items: ["全部","最近一周","最近一月","最近一年"],tableHei: 150) {[weak self] index, str in |
| | | let vc = self?.pageViewController.currentController as! CourseBookingSubListVC |
| | | vc.viewModel.timeType.accept(StudentAppointDateType(rawValue: index)!) |
| | | vc.viewModel.beginRefresh() |
| | | } |
| | | } |
| | | |
| | | @objc func searchAction(){ |
| | | funcView.tf_search.resignFirstResponder() |
| | | let vc = pageViewController.currentController as! CourseBookingSubListVC |
| | | vc.viewModel.search.accept(funcView.tf_search.text!) |
| | | vc.viewModel.beginRefresh() |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | func pageViewController(_ pageViewConteoller: FFPageViewController, controllerForPage page: Int) -> UIViewController { |
| | | let vc = CourseBookingSubListVC() |
| | | var vc:CourseBookingSubListVC! |
| | | switch page{ |
| | | case 1:vc = CourseBookingSubListVC(status: .pedding, studentId: startClouseHomeModel.stuId) |
| | | case 2:vc = CourseBookingSubListVC(status: .complete, studentId: startClouseHomeModel.stuId) |
| | | case 3:vc = CourseBookingSubListVC(status: .cancel, studentId: startClouseHomeModel.stuId) |
| | | default:vc = CourseBookingSubListVC(status: nil, studentId: startClouseHomeModel.stuId) |
| | | } |
| | | return vc |
| | | } |
| | | } |
| | | |
| | | extension CourseBookingListVC:QMUITextFieldDelegate{ |
| | | func textFieldShouldReturn(_ textField: UITextField) -> Bool { |
| | | textField.resignFirstResponder() |
| | | let vc = pageViewController.currentController as! CourseBookingSubListVC |
| | | vc.viewModel.search.accept(textField.text!) |
| | | vc.viewModel.beginRefresh() |
| | | return true |
| | | } |
| | | } |
| | |
| | | |
| | | import UIKit |
| | | import JQTools |
| | | import RxSwift |
| | | import RxRelay |
| | | |
| | | class CourseBookingViewModel:RefreshModel<StudentAppointModel>{ |
| | | |
| | | let status = BehaviorRelay<StudentAppointType?>(value: nil) |
| | | let search = BehaviorRelay<String>(value: "") |
| | | let studentId = BehaviorRelay<Int>(value: 0) |
| | | let timeType = BehaviorRelay<StudentAppointDateType>(value: .all) |
| | | |
| | | override func api() -> (Observable<BaseResponse<[StudentAppointModel]>>)? { |
| | | Services.studentAppointList(stuId: studentId.value, status: status.value,search: search.value,timeType: timeType.value) |
| | | } |
| | | } |
| | | |
| | | let CourseBooking_Noti = Notification.Name("CourseBooking_Noti") |
| | | |
| | | class CourseBookingSubListVC: BaseVC { |
| | | |
| | | lazy private var tableView:UITableView = { |
| | | let table = UITableView(frame: .zero, style: .plain) |
| | | let viewModel = CourseBookingViewModel() |
| | | |
| | | lazy private var tableView:BaseTableView = { |
| | | let table = BaseTableView(frame: .zero, style: .plain) |
| | | table.separatorStyle = .none |
| | | table.delegate = self |
| | | table.dataSource = self |
| | |
| | | return table |
| | | }() |
| | | |
| | | |
| | | required init(status:StudentAppointType?,studentId:Int) { |
| | | super.init(nibName: nil, bundle: nil) |
| | | viewModel.status.accept(status) |
| | | viewModel.studentId.accept(studentId) |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | | fatalError("init(coder:) has not been implemented") |
| | | } |
| | | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | view.backgroundColor = .white |
| | | viewModel.configure(tableView) |
| | | viewModel.beginRefresh() |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | tableView.snp.makeConstraints { make in |
| | | make.edges.equalToSuperview() |
| | | } |
| | | tableView.jq_setEmptyView() |
| | | } |
| | | |
| | | override func setRx() { |
| | | NotificationCenter.default.rx.notification(CourseBooking_Noti).take(until: self.rx.deallocated).subscribe(onNext: {[weak self] noti in |
| | | guard let weakSelf = self else { return } |
| | | if let obj = noti.object as? IndexPath{ |
| | | let model = weakSelf.viewModel.dataSource.value[obj.row] |
| | | model.status = .cancel |
| | | weakSelf.tableView.beginUpdates() |
| | | weakSelf.tableView.reloadRows(at: [obj], with: .automatic) |
| | | weakSelf.tableView.endUpdates() |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | extension CourseBookingSubListVC:UITableViewDataSource{ |
| | | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
| | | return 5 |
| | | return viewModel.dataSource.value.count |
| | | } |
| | | |
| | | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
| | | let cell = tableView.dequeueReusableCell(withIdentifier: "_CourseBooking_1_TCell") as! CourseBooking_1_TCell |
| | | cell.indexPath = indexPath |
| | | cell.studentAppointModel = viewModel.dataSource.value[indexPath.row] |
| | | return cell |
| | | } |
| | | } |
| | |
| | | |
| | | import UIKit |
| | | import QMUIKit |
| | | import RxSwift |
| | | import RxRelay |
| | | |
| | | class CourseExerciseViewModel:RefreshModel<ExerciseVideoModel>{ |
| | | let courseTypeId = BehaviorRelay<Int?>(value: nil) |
| | | let search = BehaviorRelay<String>(value: "") |
| | | override func api() -> (Observable<BaseResponse<[ExerciseVideoModel]>>)? { |
| | | return Services.exerciseCourseList(courseTypeId: courseTypeId.value, search: search.value) |
| | | } |
| | | } |
| | | |
| | | class CourseExerciseSubListVC: BaseVC { |
| | | |
| | | @IBOutlet weak var view_topView: UIView! |
| | | @IBOutlet weak var btn_assign: QMUIButton! |
| | | @IBOutlet weak var tableView: UITableView! |
| | | @IBOutlet weak var tableView: BaseTableView! |
| | | @IBOutlet weak var tf_search: QMUITextField! |
| | | private var types = [CityProfileModel]() |
| | | private var selectType:NormalSimpleModel? |
| | | let viewModel = CourseExerciseViewModel() |
| | | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | title = "课后练习" |
| | | getType() |
| | | viewModel.beginRefresh() |
| | | } |
| | | |
| | | private func getType(){ |
| | | Services.queryArrangeCourseList().subscribe(onNext: { data in |
| | | if let models = data.data{ |
| | | self.types = models |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | override func setUI() { |
| | | btn_assign.imagePosition = .right |
| | | btn_assign.spacingBetweenImageAndTitle = 5 |
| | | tf_search.delegate = self |
| | | |
| | | tableView.register(UINib(nibName: "CourseExerciseTCell", bundle: nil), forCellReuseIdentifier: "_CourseExerciseTCell") |
| | | tableView.delegate = self |
| | | tableView.dataSource = self |
| | | tableView.separatorStyle = .none |
| | | viewModel.configure(tableView) |
| | | tableView.jq_setEmptyView() |
| | | } |
| | | |
| | | |
| | | @IBAction func searchAction(_ sender: UIButton) { |
| | | tf_search.resignFirstResponder() |
| | | viewModel.search.accept(tf_search.text!) |
| | | viewModel.beginRefresh() |
| | | } |
| | | |
| | | @IBAction func assignAction(_ sender: QMUIButton) { |
| | | guard !sender.isSelected else {return} |
| | | sender.isSelected = true |
| | | let items = Array<NormalSimpleModel>() |
| | | CourseSubTypeView.show(inView: self.view, afterView: view_topView, items: items) { m in |
| | | sender.isSelected = false |
| | | guard types.count != 0 else {return} |
| | | |
| | | sender.isSelected = true |
| | | var items = Array<NormalSimpleModel>() |
| | | items.append(NormalSimpleModel(id: 0, name: "全部课程")) |
| | | for type in types { |
| | | items.append(NormalSimpleModel(id: type.id, name: type.name)) |
| | | } |
| | | |
| | | CourseSubTypeView.show(inView: self.view, afterView: view_topView, items: items, selectModel: selectType) {[weak self] m in |
| | | sender.isSelected = false |
| | | self?.selectType = m |
| | | if m.id == 0{ |
| | | sender.setTitle("布置课程", for: .normal) |
| | | self?.viewModel.courseTypeId.accept(nil) |
| | | }else{ |
| | | sender.setTitle(m.name, for: .normal) |
| | | self?.viewModel.courseTypeId.accept(m.id) |
| | | } |
| | | self?.viewModel.beginRefresh() |
| | | } closeClouse: { |
| | | sender.isSelected = false |
| | | } |
| | |
| | | |
| | | extension CourseExerciseSubListVC:UITableViewDataSource{ |
| | | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
| | | let model = viewModel.dataSource.value[indexPath.row] |
| | | let cell = tableView.dequeueReusableCell(withIdentifier: "_CourseExerciseTCell") as! CourseExerciseTCell |
| | | cell.exerciseVideoModel = model |
| | | return cell |
| | | } |
| | | |
| | | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
| | | return 5 |
| | | return viewModel.dataSource.value.count |
| | | } |
| | | } |
| | | |
| | | extension CourseExerciseSubListVC:QMUITextFieldDelegate{ |
| | | func textFieldShouldReturn(_ textField: UITextField) -> Bool { |
| | | textField.resignFirstResponder() |
| | | viewModel.search.accept(textField.text!) |
| | | viewModel.beginRefresh() |
| | | return true |
| | | } |
| | | } |
| | |
| | | <connections> |
| | | <outlet property="btn_assign" destination="jwk-F4-OqE" id="4PD-bc-l1K"/> |
| | | <outlet property="tableView" destination="oVl-x5-GNE" id="tkE-dh-5vr"/> |
| | | <outlet property="tf_search" destination="qIm-p1-qCB" id="xsQ-5v-dGL"/> |
| | | <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> |
| | | <outlet property="view_topView" destination="2Qr-aS-IbC" id="brL-sJ-q9k"/> |
| | | </connections> |
| | |
| | | <state key="normal" title="搜索"> |
| | | <color key="titleColor" name="FE6E0D"/> |
| | | </state> |
| | | <connections> |
| | | <action selector="searchAction:" destination="-1" eventType="touchUpInside" id="8fa-7d-ilb"/> |
| | | </connections> |
| | | </button> |
| | | <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="NDx-vs-KqL"> |
| | | <rect key="frame" x="14" y="47" width="86" height="40"/> |
| | |
| | | </userDefinedRuntimeAttribute> |
| | | </userDefinedRuntimeAttributes> |
| | | </view> |
| | | <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="oVl-x5-GNE"> |
| | | <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="oVl-x5-GNE" customClass="BaseTableView" customModule="WanPai" customModuleProvider="target"> |
| | | <rect key="frame" x="0.0" y="156" width="393" height="652"/> |
| | | <color key="backgroundColor" systemColor="systemBackgroundColor"/> |
| | | </tableView> |
| | |
| | | |
| | | class CourseInfoVC: BaseVC { |
| | | |
| | | private struct MentalInfo { |
| | | var img:UIImage! |
| | | var t1:String! |
| | | var t2:String! |
| | | } |
| | | // private struct MentalInfo { |
| | | // var img:UIImage! |
| | | // var t1:String! |
| | | // var t2:String! |
| | | // } |
| | | |
| | | @IBOutlet weak var scrollView: CourseInfoScrollView! |
| | | @IBOutlet weak var view_container: UIView! |
| | |
| | | var startClouseHomeModel:StartClouseHomeModel? |
| | | private var currentDate = Date() |
| | | |
| | | private var mentals = [MentalInfo]() |
| | | private var mentals = [StudentMedalModel]() |
| | | |
| | | private var pageMenu:SPPageMenu = { |
| | | let pageMenu = SPPageMenu(frame: .zero, trackerStyle: .line) |
| | |
| | | super.viewDidLoad() |
| | | |
| | | if let m = startClouseHomeModel{ |
| | | |
| | | img_header.sd_setImage(with: URL(string: m.stuImg)) |
| | | label_stu_name.text = m.stuName |
| | | img_gender.image = m.stuSex == .man ? UIImage(named: "icon_man") : UIImage(named: "icon_woman") |
| | |
| | | cons_menuHeight.constant = 25 |
| | | pageMenu.setItems(m.courseList.map({$0.courseName}), selectedItemIndex: 0) |
| | | } |
| | | |
| | | |
| | | Services.studMedalList(studentId: m.stuId).subscribe(onNext: {[weak self] data in |
| | | guard let weakSelf = self else { return } |
| | | if let models = data.data{ |
| | | weakSelf.mentals = models |
| | | weakSelf.mentalCollectionView.reloadData() |
| | | let he = ceil(Double(models.count) / 3) * 91 + floor(Double(models.count) / 3) * 35 |
| | | weakSelf.cons_mentalViewHei.constant = he |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | } |
| | | |
| | |
| | | exerciseCollectionView.register(UINib(nibName: "StudentVideoCCell", bundle: nil), forCellWithReuseIdentifier: "_StudentVideoCCell") |
| | | |
| | | |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_1"), t1: "COURSE", t2: "俱乐部之星")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_2"), t1: "EVENTS", t2: "运动大人")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_3"), t1: "ON_LINE", t2: "社区之王")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_4"), t1: "APPOINTMENT", t2: "深度玩家")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_5"), t1: "EVENTS", t2: "月度冠军")) |
| | | mentals.append(MentalInfo(img: UIImage(named: "icon_coupon_6"), t1: "MORE", t2: "更多")) |
| | | |
| | | cons_mentalViewHei.constant = ceil(Double(mentals.count) / 3) * 91 + floor(Double(mentals.count) / 3) * 30 |
| | | |
| | | navigationItem.leftBarButtonItem = UIBarButtonItem(customView: leftBtn) |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | @IBAction func bookingRecordAction(_ sender: UIButton) { |
| | | let vc = CourseBookingListVC() |
| | | guard startClouseHomeModel != nil else {return} |
| | | let vc = CourseBookingListVC(student: startClouseHomeModel!) |
| | | push(vc: vc) |
| | | } |
| | | |
| | |
| | | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { |
| | | if collectionView.tag == 1000{ |
| | | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "_StudentMedalCCell", for: indexPath) as! StudentMedalCCell |
| | | cell.img.image = mentals[indexPath.row].img |
| | | cell.t1.text = mentals[indexPath.row].t1 |
| | | cell.t2.text = mentals[indexPath.row].t2 |
| | | cell.img.image = mentals[indexPath.row].medalType.image |
| | | cell.t1.text = mentals[indexPath.row].medalType.title_en |
| | | cell.t2.text = mentals[indexPath.row].medalType.title |
| | | return cell |
| | | } else{ |
| | | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "_StudentVideoCCell", for: indexPath) as! StudentVideoCCell |
| | |
| | | class CourseVideoDetailVC: BaseVC { |
| | | @IBOutlet weak var view_videoContainer: UIView! |
| | | |
| | | private var id:Int! |
| | | private var id:Int? |
| | | private var model:ExerciseVideoModel? |
| | | |
| | | @IBOutlet weak var label_name: UILabel! |
| | | @IBOutlet weak var label_introduce: UILabel! |
| | |
| | | }() |
| | | |
| | | |
| | | required init(id:Int) { |
| | | init(id:Int) { |
| | | super.init(nibName: nil, bundle: nil) |
| | | self.id = id |
| | | } |
| | | |
| | | init(model:ExerciseVideoModel){ |
| | | super.init(nibName: nil, bundle: nil) |
| | | self.model = model |
| | | } |
| | | |
| | | required init?(coder: NSCoder) { |
| | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | |
| | | Services.benefitsVideoDetail(id: id).subscribe(onNext: { [weak self] data in |
| | | if let model = data.data{ |
| | | self?.playerVC.player = AVPlayer(url: URL(string: model.courseVideo)!) |
| | | self?.playerVC.player?.play() |
| | | if let id { |
| | | Services.benefitsVideoDetail(id: id).subscribe(onNext: { [weak self] data in |
| | | if let model = data.data{ |
| | | self?.playerVC.player = AVPlayer(url: URL(string: model.courseVideo)!) |
| | | self?.playerVC.player?.play() |
| | | |
| | | self?.label_name.text = model.name |
| | | self?.label_coin.text = "\(model.integral)积分" |
| | | self?.label_introduce.text = model.introduce |
| | | if model.study == 1{ |
| | | self?.label_studyState.text = "已学习" |
| | | self?.label_studyState.backgroundColor = UIColor(hexStr: "#318C10").withAlphaComponent(0.29) |
| | | self?.label_studyState.textColor = UIColor(hexStr: "#318C10") |
| | | }else{ |
| | | self?.label_studyState.text = "未学习" |
| | | self?.label_studyState.backgroundColor = UIColor(hexStr: "#FD9331").withAlphaComponent(0.29) |
| | | self?.label_studyState.textColor = Def_ThemeColor |
| | | } |
| | | self?.label_name.text = model.name |
| | | self?.label_coin.text = "\(model.integral)积分" |
| | | self?.label_introduce.text = model.introduce |
| | | if model.study == 1{ |
| | | self?.label_studyState.text = "已学习" |
| | | self?.label_studyState.backgroundColor = UIColor(hexStr: "#318C10").withAlphaComponent(0.29) |
| | | self?.label_studyState.textColor = UIColor(hexStr: "#318C10") |
| | | }else{ |
| | | self?.label_studyState.text = "未学习" |
| | | self?.label_studyState.backgroundColor = UIColor(hexStr: "#FD9331").withAlphaComponent(0.29) |
| | | self?.label_studyState.textColor = Def_ThemeColor |
| | | } |
| | | |
| | | SDWebImageDownloader.shared.downloadImage(with: URL(string: model.introductionDrawing)) { image, data, error, state in |
| | | if let img = image{ |
| | | self?.img_introduceCover.image = img |
| | | let radio = img.size.width / img.size.height |
| | | self?.cons_imgHei.constant = JQ_ScreenW * radio |
| | | SDWebImageDownloader.shared.downloadImage(with: URL(string: model.introductionDrawing)) { image, data, error, state in |
| | | if let img = image{ |
| | | self?.img_introduceCover.image = img |
| | | let radio = img.size.width / img.size.height |
| | | self?.cons_imgHei.constant = JQ_ScreenW * radio |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | |
| | | if let model{ |
| | | Services.exerciseCourseDetail(coursePackageId: model.coursePackageId, videoId: model.videoId).subscribe(onNext: {[weak self] data in |
| | | if let model = data.data{ |
| | | self?.playerVC.player = AVPlayer(url: URL(string: model.videoURL)!) |
| | | self?.playerVC.player?.play() |
| | | |
| | | self?.label_name.text = model.packageName |
| | | self?.label_coin.text = "\(model.integral)积分" |
| | | self?.label_introduce.text = model.synopsis |
| | | if model.studyStatus == 1{ |
| | | self?.label_studyState.text = "已学习" |
| | | self?.label_studyState.backgroundColor = UIColor(hexStr: "#318C10").withAlphaComponent(0.29) |
| | | self?.label_studyState.textColor = UIColor(hexStr: "#318C10") |
| | | }else{ |
| | | self?.label_studyState.text = "未学习" |
| | | self?.label_studyState.backgroundColor = UIColor(hexStr: "#FD9331").withAlphaComponent(0.29) |
| | | self?.label_studyState.textColor = Def_ThemeColor |
| | | } |
| | | |
| | | SDWebImageDownloader.shared.downloadImage(with: URL(string: model.detailedDiagram)) { image, data, error, state in |
| | | if let img = image{ |
| | | self?.img_introduceCover.image = img |
| | | let radio = img.size.width / img.size.height |
| | | self?.cons_imgHei.constant = JQ_ScreenW * radio |
| | | } |
| | | } |
| | | } |
| | | }).disposed(by: disposeBag) |
| | | } |
| | | } |
| | | |
| | | override func setUI() { |
| | |
| | | |
| | | override func viewDidLoad() { |
| | | super.viewDidLoad() |
| | | title = "学员徽章" |
| | | title = "学员勋章" |
| | | |
| | | items.append(MentalInfo(icon: UIImage(named: "icon_coupon_1"), l1: "COURSE", l2: "俱乐部之星", level: 0, info: "再上课打卡10次可升级LV2", btnName: "去预约")) |
| | | items.append(MentalInfo(icon: UIImage(named: "icon_coupon_2"), l1: "EVENTS", l2: "运动大人", level: 0, info: "再参与赛事10次可升级LV2", btnName: "去报名")) |
| | |
| | | class CourseBookingFuncView: UIView,JQNibView{ |
| | | |
| | | @IBOutlet weak var btn_datetime: QMUIButton! |
| | | |
| | | @IBOutlet weak var tf_search: QMUITextField! |
| | | @IBOutlet weak var btn_search: UIButton! |
| | | |
| | | override func awakeFromNib() { |
| | | super.awakeFromNib() |
| | | btn_datetime.spacingBetweenImageAndTitle = 5 |
| | | btn_datetime.imagePosition = .right |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> |
| | | <connections> |
| | | <outlet property="btn_datetime" destination="m0Y-Ci-yzA" id="Tii-Oe-DgZ"/> |
| | | <outlet property="btn_search" destination="yjj-rT-1Pw" id="iaU-27-llh"/> |
| | | <outlet property="tf_search" destination="Mrw-tc-NDG" id="UqT-JY-MSD"/> |
| | | </connections> |
| | | <point key="canvasLocation" x="61.832061068702288" y="-206.33802816901411"/> |
| | | </view> |
| | |
| | | @IBOutlet weak var cons_webHeight: NSLayoutConstraint! |
| | | |
| | | private let bannerView = CommonBannerView() |
| | | private var recordsDetailModel:RecordsDetailModel? |
| | | |
| | | required init(id:Int,goodsType:ExchangeType) { |
| | | super.init(nibName: nil, bundle: nil) |
| | |
| | | |
| | | Services.exchangeRecordDetail(id: id, goodType: goodsType).subscribe(onNext: { [weak self] data in |
| | | if let model = data.data{ |
| | | self?.recordsDetailModel = model |
| | | self?.label_title.text = model.goodName |
| | | self?.label_duetime.text = String(format: "%@-%@", model.startTime,model.endTime) |
| | | self?.label_course.text = "\(model.classHours)课时" |
| | |
| | | override func setUI() { |
| | | view_banner.addSubview(bannerView) |
| | | bannerView.frame = CGRect(x: 0, y: 0, width: JQ_ScreenW, height: JQ_ScreenW * 0.56) |
| | | // view_course.isHidden = true |
| | | // view_verifiStore.isHidden = true |
| | | // view_verifitime.isHidden = true |
| | | // view_ordertime.isHidden = true |
| | | // view_duetime.isHidden = true |
| | | // view_assignStore.isHidden = true |
| | | } |
| | | |
| | | |
| | | @IBAction func showStoreDetailAction(_ sender: Any) { |
| | | AgreentView.show(type: .other,content:recordsDetailModel?.belongs ?? "") |
| | | } |
| | | |
| | | override func setRx() { |
| | |
| | | <state key="normal" title="查看详情"> |
| | | <color key="titleColor" red="0.0" green="0.28235294119999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| | | </state> |
| | | <connections> |
| | | <action selector="showStoreDetailAction:" destination="-1" eventType="touchUpInside" id="YLP-Yq-4Rl"/> |
| | | </connections> |
| | | </button> |
| | | </subviews> |
| | | <color key="backgroundColor" systemColor="systemBackgroundColor"/> |