younger_times
2023-07-26 3e3bfd1ad307ec2ea42f66e298ccb24cec26955f
新增
19个文件已修改
600 ■■■■ 已修改文件
WanPai/Common/View/AgreentView.xib 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Config/Enums.swift 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Model/CommonModels.swift 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Network/Services.swift 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/TCell/CourseBooking_1_TCell.swift 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/TCell/CourseBooking_1_TCell.xib 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/TCell/CourseExerciseTCell.swift 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/TCell/CourseExerciseTCell.xib 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseBookingListVC.swift 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseBookingSubListVC.swift 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseExerciseSubListVC.swift 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseExerciseSubListVC.xib 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseInfoVC.swift 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseVideoDetailVC.swift 88 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/StudentMentalListVC.swift 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/View/CourseBookingFuncView.swift 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/View/CourseBookingFuncView.xib 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/WelfareExchangeRecordDetailVC.swift 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/WelfareExchangeRecordDetailVC.xib 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Common/View/AgreentView.xib
@@ -19,7 +19,7 @@
                    <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>
@@ -34,7 +34,6 @@
                        </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"/>
@@ -72,7 +71,7 @@
        </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>
WanPai/Config/Enums.swift
@@ -315,3 +315,73 @@
}
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: "更多"))*/
}
WanPai/Model/CommonModels.swift
@@ -291,14 +291,14 @@
    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
@@ -514,4 +514,45 @@
}
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
}
WanPai/Network/Services.swift
@@ -106,6 +106,14 @@
            .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: -- 福利相关
@@ -326,7 +334,52 @@
        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: -- 探索玩湃
WanPai/Root/Course/TCell/CourseBooking_1_TCell.swift
@@ -7,17 +7,59 @@
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)
            }
        }
    }
}
WanPai/Root/Course/TCell/CourseBooking_1_TCell.xib
@@ -119,7 +119,7 @@
                        <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"/>
@@ -153,6 +153,9 @@
                                        <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>
@@ -183,7 +186,13 @@
            </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>
WanPai/Root/Course/TCell/CourseExerciseTCell.swift
@@ -10,13 +10,40 @@
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)
    }
WanPai/Root/Course/TCell/CourseExerciseTCell.xib
@@ -156,6 +156,15 @@
                </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>
WanPai/Root/Course/VC/CourseBookingListVC.swift
@@ -55,6 +55,8 @@
        return v
    }()
    var startClouseHomeModel:StartClouseHomeModel!
    private lazy var label_student:UILabel = {
        let label = UILabel()
@@ -64,6 +66,15 @@
        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 = "预约课程"
@@ -72,6 +83,10 @@
        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() {
@@ -112,9 +127,18 @@
    }
    @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()
    }
}
@@ -136,7 +160,23 @@
    }
    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
    }
}
WanPai/Root/Course/VC/CourseBookingSubListVC.swift
@@ -7,11 +7,29 @@
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
@@ -19,9 +37,22 @@
        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() {
@@ -29,6 +60,20 @@
        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)
    }
}
@@ -36,11 +81,13 @@
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
    }
}
WanPai/Root/Course/VC/CourseExerciseSubListVC.swift
@@ -7,35 +7,84 @@
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
        }
@@ -48,11 +97,22 @@
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
    }
}
WanPai/Root/Course/VC/CourseExerciseSubListVC.xib
@@ -14,6 +14,7 @@
            <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>
@@ -66,6 +67,9 @@
                            <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"/>
@@ -113,7 +117,7 @@
                        </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>
WanPai/Root/Course/VC/CourseInfoVC.swift
@@ -13,11 +13,11 @@
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!
@@ -41,7 +41,7 @@
    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)
@@ -96,6 +96,7 @@
        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")
@@ -112,6 +113,17 @@
                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)
        }
    }
@@ -157,15 +169,6 @@
        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)
    }
@@ -207,7 +210,8 @@
    }
    @IBAction func bookingRecordAction(_ sender: UIButton) {
        let vc = CourseBookingListVC()
        guard startClouseHomeModel != nil else {return}
        let vc = CourseBookingListVC(student: startClouseHomeModel!)
        push(vc: vc)
    }
@@ -270,9 +274,9 @@
    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
WanPai/Root/Course/VC/CourseVideoDetailVC.swift
@@ -13,7 +13,8 @@
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!
@@ -31,9 +32,14 @@
    }()
   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) {
@@ -43,33 +49,65 @@
    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() {
WanPai/Root/Course/VC/StudentMentalListVC.swift
@@ -31,7 +31,7 @@
    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: "去报名"))
WanPai/Root/Course/View/CourseBookingFuncView.swift
@@ -12,11 +12,14 @@
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
    }
}
WanPai/Root/Course/View/CourseBookingFuncView.xib
@@ -112,6 +112,8 @@
            <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>
WanPai/Root/Welfare/VC/WelfareExchangeRecordDetailVC.swift
@@ -34,6 +34,7 @@
    @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)
@@ -51,6 +52,7 @@
        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)课时"
@@ -98,12 +100,11 @@
    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() {
WanPai/Root/Welfare/VC/WelfareExchangeRecordDetailVC.xib
@@ -339,6 +339,9 @@
                                                            <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"/>