Parcourir la source

VIP课程组详情进入教室

Steven il y a 9 mois
Parent
commit
ae45978a6f
14 fichiers modifiés avec 699 ajouts et 107 suppressions
  1. 21 4
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/AccompanyCourse/Controller/AccompanyCourseGroupViewController.m
  2. 6 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Controller/VIPCourseGroupViewController.h
  3. 177 75
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Controller/VIPCourseGroupViewController.m
  4. 21 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Controller/VipCouseDetailViewController.m
  5. 1 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Model/GroupCourseListModel.h
  6. 8 4
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Model/GroupCourseListModel.m
  7. 4 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseGroupBodyView.h
  8. 278 2
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseGroupBodyView.m
  9. 1 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseListCell.h
  10. 44 3
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseListCell.m
  11. 18 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseListCell.xib
  12. 21 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/View/CourseGroupView/GroupCourseSortView.h
  13. 67 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/View/CourseGroupView/GroupCourseSortView.m
  14. 32 15
      KulexiuForTeacher/KulexiuForTeacher/Module/Course/View/CourseGroupView/GroupCourseSortView.xib

+ 21 - 4
KulexiuForTeacher/KulexiuForTeacher/Module/Course/AccompanyCourse/Controller/AccompanyCourseGroupViewController.m

@@ -6,7 +6,6 @@
 //
 
 #import "AccompanyCourseGroupViewController.h"
-#import <RecordCheckManager.h>
 #import "CourseGroupNavView.h"
 #import "JXCategoryView.h"
 #import "JXPagerListRefreshView.h"
@@ -31,6 +30,10 @@
 
 @property (nonatomic, strong) CourseGroupDetailModel *detailModel;
 
+@property (nonatomic, assign) NSInteger enterStartTime;  // 开课前可进入时间配置(分钟)
+
+@property (nonatomic, assign) NSInteger quitEndTime;    // 结束后退出时间配置(分钟)
+
 @end
 
 @implementation AccompanyCourseGroupViewController
@@ -78,6 +81,10 @@
         if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
             NSDictionary *parm = [dic ks_dictionaryValueForKey:@"data"];
             self.detailModel = [[CourseGroupDetailModel alloc] initWithDictionary:parm];
+            // 配置信息
+            NSDictionary *config = [[dic ks_dictionaryValueForKey:@"data"] ks_dictionaryValueForKey:@"sysConfig"];
+            self.enterStartTime = [config ks_integerValueForKey:@"practiceStartTime"];
+            self.quitEndTime = [config ks_integerValueForKey:@"practiceEndTime"];
         }
         else {
             [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
@@ -89,6 +96,7 @@
 }
 
 - (void)refreshHeadView {
+    [self refreshListPage];
     self.topViewHeight = [ProgramCourseInfoView getViewHeightWithPlanString:self.detailModel.coursePlan];
     [self.infoView configWithSource:self.detailModel];
     [self.pagerView reloadData];
@@ -124,17 +132,22 @@
 - (void)viewWillAppear:(BOOL)animated {
     [super viewWillAppear:animated];
     self.navigationController.interactivePopGestureRecognizer.enabled = YES;
+    // 刷新课程详情
+    [self requestCourseInfo];
+    
     if (self.isFirstLoad == NO) {
         [self refreshListPage];
     }
     self.isFirstLoad = NO;
-    [self requestCourseInfo];
+    
 }
 
 - (void)refreshListPage {
     id value = self.listViewArray[0];
-    if ([value isKindOfClass:[KSJXBodyView class]]) {
-        KSJXBodyView *listView = (KSJXBodyView *)value;
+    if ([value isKindOfClass:[ProgramCourseGroupBodyView class]]) {
+        ProgramCourseGroupBodyView *listView = (ProgramCourseGroupBodyView *)value;
+        listView.enterStartTime = self.enterStartTime;
+        listView.quitEndTime = self.quitEndTime;
         [listView beginFirstRefresh];
     }
 }
@@ -172,6 +185,10 @@
     listView.selectIndex = index;
     listView.courseGroupId = self.courseGroupId;
     listView.isVipCourse = NO;
+    if (self.enterStartTime) {
+        listView.enterStartTime = self.enterStartTime;
+        listView.quitEndTime = self.quitEndTime;
+    }
     [self.listViewArray replaceObjectAtIndex:index withObject:listView];
     self.listViewArray[index] = listView;
     [listView beginFirstRefresh];

+ 6 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Controller/VIPCourseGroupViewController.h

@@ -6,7 +6,8 @@
 //
 
 #import "KSBaseViewController.h"
-
+#import "JXCategoryView.h"
+#import "JXPagerView.h"
 NS_ASSUME_NONNULL_BEGIN
 
 // VIP定制课--课程组
@@ -14,6 +15,10 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, strong) NSString *courseGroupId; // 课程组ID
 
+@property (nonatomic, strong) JXPagerView *pagerView;
+@property (nonatomic, strong, readonly) JXCategoryTitleView *categoryView;
+@property (nonatomic, strong) NSArray <NSString *> *titles;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 177 - 75
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Controller/VIPCourseGroupViewController.m

@@ -6,28 +6,33 @@
 //
 
 #import "VIPCourseGroupViewController.h"
-#import <RecordCheckManager.h>
-#import "KSPremissionAlert.h"
-#import "OnlineClassManager.h"
-#import "HomeworkDetailModel.h"
 #import "CourseGroupNavView.h"
+#import "JXCategoryView.h"
+#import "JXPagerListRefreshView.h"
+#import "ProgramCourseInfoView.h"
+#import "ProgramCourseGroupBodyView.h"
+#import "CourseGroupDetailModel.h"
+#import "CourseGroupPlanAlertView.h"
 
-@interface VIPCourseGroupViewController ()
+@interface VIPCourseGroupViewController ()<JXPagerViewDelegate,JXCategoryViewDelegate>
+
+@property (nonatomic, strong) NSMutableArray *listViewArray;
 
 @property (nonatomic, strong) CourseGroupNavView *navView;
 
-@property (nonatomic, strong) NSString *courseId;
+@property (nonatomic, assign) NSInteger headHeight;
 
-@property (nonatomic, strong) NSString *studentId;
+@property (nonatomic, assign) NSInteger topViewHeight;
 
-@property (nonatomic, assign) NSInteger joinRoomBeforeTime; // 上课开始时间
+@property (nonatomic, strong) ProgramCourseInfoView *infoView;
 
-@property (nonatomic, assign) NSInteger quitRomeEndTime;    // 下课截止时间
+@property (nonatomic, assign) BOOL isFirstLoad;
 
-@property (nonatomic, strong) HomeworkDetailModel *homeworkModel;
+@property (nonatomic, strong) CourseGroupDetailModel *detailModel;
 
-@property (nonatomic, strong) OnlineClassManager *classManager;
+@property (nonatomic, assign) NSInteger enterStartTime;  // 开课前可进入时间配置(分钟)
 
+@property (nonatomic, assign) NSInteger quitEndTime;    // 结束后退出时间配置(分钟)
 
 @end
 
@@ -38,8 +43,19 @@
     // Do any additional setup after loading the view.
     self.ks_prefersNavigationBarHidden = YES;
     [self configUI];
+    self.isFirstLoad = YES;
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(forceScroll) name:@"UITextViewScroll" object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enableScroll) name:@"UITextViewEndScroll" object:nil];
+}
+
+
+- (void)forceScroll {
+    self.pagerView.mainTableView.scrollEnabled = NO;
 }
 
+- (void)enableScroll {
+    self.pagerView.mainTableView.scrollEnabled = YES;
+}
 
 - (void)configUI {
     [self.scrollView removeFromSuperview];
@@ -55,97 +71,183 @@
         make.left.right.top.mas_equalTo(self.view);
         make.height.mas_equalTo(navHeight);
     }];
+    self.headHeight = CGFLOAT_MIN;
+    self.titles = @[@""];
+    [self configCategoryView:navHeight];
 }
 
-- (void)tryJoinRoom {
+- (void)requestCourseInfo {
     
-    NSDateFormatter *dateFormatter = [NSObject getDateformatter];
-    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
-    NSDate *beginDate = [dateFormatter dateFromString:self.homeworkModel.startTime];
-    NSDate *endDate = [dateFormatter dateFromString:self.homeworkModel.endTime];
-    NSDate *currentDate = [NSDate date];
-    NSTimeInterval beginTimeInterval = [beginDate timeIntervalSinceDate:currentDate];
-    NSTimeInterval endTimeInterval = [currentDate timeIntervalSinceDate:endDate];
-    if (beginTimeInterval <= self.joinRoomBeforeTime * 60 && endTimeInterval < 0) {
-        [self joinClassRoom];
-    }
-    else if (endTimeInterval > 0) {
-        [LOADING_MANAGER MBShowAUTOHidingInWindow:@"该课程已结束"];
-    }
-    else {
-        NSString *tipsString = [NSString stringWithFormat:@"课程还未开始,请在上课前%zd分钟进入", self.joinRoomBeforeTime];
-        [LOADING_MANAGER MBShowAUTOHidingInWindow:tipsString];
-    }
-}
-
-// 加入房间
-- (void)joinClassRoom {
-    
-    // 加入房间前判断摄像头和麦克风逻辑
-    [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
-        [self afterCheckCameraCheckMic:type];
-    }];
-}
-
-- (void)afterCheckCameraCheckMic:(PREMISSIONTYPE)cameraType {
-    [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
-        if (type == PREMISSIONTYPE_YES && cameraType == PREMISSIONTYPE_YES) {
-            // 判断是否进行课前检测
-            [self.classManager joinRoomWithId:self.courseId subjectName:self.homeworkModel.subjectName classEndTime:self.homeworkModel.endTime inViewController:self];
+    [KSNetworkingManager getCourseGroupDetailRequest:KS_POST courseGroupId:self.courseGroupId success:^(NSDictionary * _Nonnull dic) {
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            NSDictionary *parm = [dic ks_dictionaryValueForKey:@"data"];
+            self.detailModel = [[CourseGroupDetailModel alloc] initWithDictionary:parm];
+            
+            // 配置信息
+            NSDictionary *config = [[dic ks_dictionaryValueForKey:@"data"] ks_dictionaryValueForKey:@"sysConfig"];
+            self.enterStartTime = [config ks_integerValueForKey:@"vipStartTime"];
+            self.quitEndTime = [config ks_integerValueForKey:@"vipEndTime"];
         }
         else {
-            NSString *content = @"";
-            CHECKDEVICETYPE checkType = CHECKDEVICETYPE_BOTH;
-            if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_NO) {
-                content = @"请开启相机和麦克风访问权限";
-                checkType = CHECKDEVICETYPE_BOTH;
-            }
-            else if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_YES) {
-                content =  @"请开启相机访问权限";
-                checkType = CHECKDEVICETYPE_CAMREA;
-            }
-            else if (cameraType == PREMISSIONTYPE_YES && type == PREMISSIONTYPE_NO) {
-                content = @"请开启麦克风访问权限";
-                checkType = CHECKDEVICETYPE_MIC;
-            }
-            [self showAlertWithMessage:content type:checkType];
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
         }
+        [self refreshHeadView];
+    } faliure:^(NSError * _Nonnull error) {
+        [self refreshHeadView];
     }];
-    
 }
 
-- (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {
-    [KSPremissionAlert shareInstanceDisplayImage:deviceType message:message showInView:self.view cancel:^{
-        
-    } confirm:^{
-        [self openSettingView];
-    }];
+- (void)refreshHeadView {
+    [self refreshListPage];
+    self.topViewHeight = [ProgramCourseInfoView getViewHeightWithPlanString:self.detailModel.coursePlan];
+    [self.infoView configWithSource:self.detailModel];
+    [self.pagerView reloadData];
+}
+
+- (void)configCategoryView:(NSInteger)topHeight {
     
+    _categoryView = [[JXCategoryTitleView alloc] initWithFrame:CGRectMake(0, topHeight, KPortraitWidth, self.headHeight)];
+    self.categoryView.titles = self.titles;
+    self.categoryView.delegate = self;
+    self.categoryView.titleFont = [UIFont systemFontOfSize:16.0f];
+    self.categoryView.titleSelectedFont = [UIFont systemFontOfSize:16.0f weight:UIFontWeightSemibold];
+    self.categoryView.titleSelectedColor = HexRGB(0x333333);
+    self.categoryView.titleColor = HexRGB(0x666666);
+    self.categoryView.titleColorGradientEnabled = YES;
+    
+    _pagerView = [self preferredPagingView];
+    self.pagerView.frame = CGRectMake(0, topHeight, KPortraitWidth, KPortraitHeight - topHeight);
+    self.pagerView.backgroundColor = [UIColor clearColor];
+    self.pagerView.mainTableView.backgroundColor = [UIColor clearColor];
+    self.pagerView.listContainerView.backgroundColor = [UIColor clearColor];
+//    self.pagerView.mainTableView.gestureDelegate = self;
+    self.categoryView.listContainer = (id<JXCategoryViewListContainer>)self.pagerView.listContainerView;
+    self.pagerView.listContainerView.listCellBackgroundColor = [UIColor clearColor];
+    [self.view addSubview:self.pagerView];
 }
 
-- (void)openSettingView {
-    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
+- (void)viewDidAppear:(BOOL)animated {
+    [super viewDidAppear:animated];
+    self.navigationController.interactivePopGestureRecognizer.enabled = (self.categoryView.selectedIndex == 0);
 }
 
-#pragma mark ----- lazying
-- (OnlineClassManager *)classManager {
-    if (!_classManager) {
-        _classManager = [[OnlineClassManager alloc] init];
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
+    // 刷新课程详情
+    [self requestCourseInfo];
+    if (self.isFirstLoad == NO) {
+        [self refreshListPage];
+    }
+    self.isFirstLoad = NO;
+}
+
+- (void)refreshListPage {
+    id value = self.listViewArray[0];
+    if ([value isKindOfClass:[ProgramCourseGroupBodyView class]]) {
+        ProgramCourseGroupBodyView *listView = (ProgramCourseGroupBodyView *)value;
+        listView.enterStartTime = self.enterStartTime;
+        listView.quitEndTime = self.quitEndTime;
+        [listView beginFirstRefresh];
     }
-    return _classManager;
 }
 
+- (JXPagerView *)preferredPagingView {
+    return [[JXPagerListRefreshView alloc] initWithDelegate:self];
+}
+
+#pragma mark - JXPagerViewDelegate
+
+- (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView {
+    return self.infoView;
+}
+
+- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView {
+    return self.topViewHeight;
+}
+
+- (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
+    return self.headHeight;
+}
+
+- (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
+    return self.categoryView;
+}
+
+- (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView {
+    //和categoryView的item数量一致
+    return self.titles.count;
+}
+
+- (id<JXPagerViewListViewDelegate>)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index {
+    ProgramCourseGroupBodyView *listView = [[ProgramCourseGroupBodyView alloc] init];
+    listView.naviController = self.navigationController;
+    listView.selectIndex = index;
+    listView.courseGroupId = self.courseGroupId;
+    listView.isVipCourse = YES;
+    [self.listViewArray replaceObjectAtIndex:index withObject:listView];
+    self.listViewArray[index] = listView;
+    [listView beginFirstRefresh];
+    return listView;
+}
+
+- (void)dealloc {
+   [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark ----- lazying
+
 - (CourseGroupNavView *)navView {
     if (!_navView) {
         _navView = [CourseGroupNavView sharedInstance];
         MJWeakSelf;
-        [_navView configWithNavTitle:@"VIP定制课详情" callback:^{
+        [_navView configWithNavTitle:@"VIP定制课设置" callback:^{
             [weakSelf backAction];
         }];
     }
     return _navView;
 }
+- (NSMutableArray *)listViewArray {
+    if (!_listViewArray) {
+        _listViewArray = [NSMutableArray arrayWithArray:@[@""]];
+    }
+    return _listViewArray;
+}
+- (ProgramCourseInfoView *)infoView {
+    if (!_infoView) {
+        _infoView  =[ProgramCourseInfoView sharedInstance];
+        MJWeakSelf;
+        [_infoView programActionCallback:^{
+            [weakSelf showModifyPlanView];
+        }];
+    }
+    return _infoView;
+}
+
+- (void)showModifyPlanView {
+    CourseGroupPlanAlertView *alert = [CourseGroupPlanAlertView sharedInstance];
+    MJWeakSelf;
+    [alert configWithDesc:self.detailModel.coursePlan callback:^(NSString * _Nullable planString) {
+        [weakSelf submitAction:planString];
+    }];
+    [alert showInView:self.view];
+}
 
+- (void)submitAction:(NSString *)planString {
+    [LOADING_MANAGER showHUD];
+    [KSNetworkingManager updateCoursePlanRequset:KS_POST courseGroupId:self.courseGroupId coursePlan:planString success:^(NSDictionary * _Nonnull dic) {
+        [LOADING_MANAGER removeHUD];
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            [self requestCourseInfo];
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+        
+    } faliure:^(NSError * _Nonnull error) {
+        [LOADING_MANAGER removeHUD];
+    }];
+}
 /*
 #pragma mark - Navigation
 

+ 21 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Controller/VipCouseDetailViewController.m

@@ -22,6 +22,7 @@
 #import <RecordCheckManager.h>
 #import "KSPremissionAlert.h"
 #import "OnlineClassManager.h"
+#import "AccompanyDetailBottomView.h"
 
 @interface VipCouseDetailViewController ()<UITableViewDelegate,UITableViewDataSource,WMPlayerDelegate>
 {
@@ -40,6 +41,8 @@
 
 @property (nonatomic, strong) EvaluateDetailModel *evaluateModel;
 
+@property (nonatomic, strong) AccompanyDetailBottomView *bottomView;
+
 @property (nonatomic, strong) AccompanyAlertView *alertView;
 
 @property (nonatomic, strong) NSMutableArray *fileArray;
@@ -142,14 +145,20 @@
     if ([self.homeworkModel.courseStatus isEqualToString:@"COMPLETE"]) {
         statusLabel.text = @"已结束";
         statusLabel.textColor = HexRGB(0x999999);
+        [self.bottomView.sureButton setTitle:@"已结束" forState:UIControlStateNormal];
+        [self.bottomView.sureButton setBackgroundColor:HexRGB(0xd5d5d5)];
     }
     else if ([self.homeworkModel.courseStatus isEqualToString:@"ING"]) {
         statusLabel.text = @"进行中";
         statusLabel.textColor = THEMECOLOR;
+        [self.bottomView.sureButton setTitle:@"进入教室" forState:UIControlStateNormal];
+        [self.bottomView.sureButton setBackgroundColor:THEMECOLOR];
     }
     else {
         statusLabel.text = @"未开始";
         statusLabel.textColor = HexRGB(0xff802c);
+        [self.bottomView.sureButton setTitle:@"进入教室" forState:UIControlStateNormal];
+        [self.bottomView.sureButton setBackgroundColor:THEMECOLOR];
     }
 }
 
@@ -421,6 +430,8 @@
         [_tableView registerNib:[UINib nibWithNibName:@"AccompanyHomeworkCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"AccompanyHomeworkCell"];
         [_tableView registerNib:[UINib nibWithNibName:@"AccompanyRemarkCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"AccompanyRemarkCell"];
         _tableView.estimatedRowHeight = 136.0f;
+        self.bottomView.frame = CGRectMake(0, 0, kScreenWidth, 70);
+        _tableView.tableFooterView = self.bottomView;
     }
     return _tableView;
 }
@@ -436,6 +447,16 @@
     return _navView;
 }
 
+- (AccompanyDetailBottomView *)bottomView {
+    if (!_bottomView) {
+        _bottomView = [AccompanyDetailBottomView shareInstance];
+        MJWeakSelf;
+        [_bottomView joinroomCallback:^{
+            [weakSelf tryJoinRoom];
+        }];
+    }
+    return _bottomView;
+}
 
 - (void)tryJoinRoom {
     

+ 1 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Model/GroupCourseListModel.h

@@ -20,6 +20,7 @@
 @property (nonatomic, strong) NSString *startTime;
 @property (nonatomic, strong) NSString *courseGroupName;
 @property (nonatomic, assign) BOOL attendanceStatus;
+@property (nonatomic, strong) NSString *subjectName;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
 - (instancetype)initWithDictionary:(NSDictionary *)dict;

+ 8 - 4
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/Model/GroupCourseListModel.m

@@ -17,7 +17,7 @@ NSString *const kGroupCourseListModelCourseGoupId = @"courseGoupId";
 NSString *const kGroupCourseListModelStartTime = @"startTime";
 NSString *const kGroupCourseListModelCourseGroupName = @"courseGroupName";
 NSString *const kGroupCourseListModelAttendanceStatus = @"attendanceStatus";
-
+NSString *const kGroupCourseListModelSubjectName = @"subjectName";
 
 @interface GroupCourseListModel ()
 
@@ -36,7 +36,7 @@ NSString *const kGroupCourseListModelAttendanceStatus = @"attendanceStatus";
 @synthesize startTime = _startTime;
 @synthesize courseGroupName = _courseGroupName;
 @synthesize attendanceStatus = _attendanceStatus;
-
+@synthesize subjectName = _subjectName;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
 {
@@ -73,7 +73,7 @@ NSString *const kGroupCourseListModelAttendanceStatus = @"attendanceStatus";
             self.attendanceStatus = [[self objectOrNilForKey:kGroupCourseListModelAttendanceStatus fromDictionary:dict] boolValue];
 
     }
-    
+    self.subjectName = [self objectOrNilForKey:kGroupCourseListModelSubjectName fromDictionary:dict];
     return self;
     
 }
@@ -100,7 +100,8 @@ NSString *const kGroupCourseListModelAttendanceStatus = @"attendanceStatus";
     [mutableDict setValue:self.startTime forKey:kGroupCourseListModelStartTime];
     [mutableDict setValue:self.courseGroupName forKey:kGroupCourseListModelCourseGroupName];
     [mutableDict setValue:[NSNumber numberWithBool:self.attendanceStatus] forKey:kGroupCourseListModelAttendanceStatus];
-
+    [mutableDict setValue:self.subjectName forKey:kGroupCourseListModelSubjectName];
+    
     return [NSDictionary dictionaryWithDictionary:mutableDict];
 }
 
@@ -136,6 +137,7 @@ NSString *const kGroupCourseListModelAttendanceStatus = @"attendanceStatus";
     self.startTime = [aDecoder decodeObjectForKey:kGroupCourseListModelStartTime];
     self.courseGroupName = [aDecoder decodeObjectForKey:kGroupCourseListModelCourseGroupName];
     self.attendanceStatus = [aDecoder decodeBoolForKey:kGroupCourseListModelAttendanceStatus];
+    self.subjectName = [aDecoder decodeObjectForKey:kGroupCourseListModelSubjectName];
     return self;
 }
 
@@ -151,6 +153,7 @@ NSString *const kGroupCourseListModelAttendanceStatus = @"attendanceStatus";
     [aCoder encodeObject:_startTime forKey:kGroupCourseListModelStartTime];
     [aCoder encodeObject:_courseGroupName forKey:kGroupCourseListModelCourseGroupName];
     [aCoder encodeBool:_attendanceStatus forKey:kGroupCourseListModelAttendanceStatus];
+    [aCoder encodeObject:_subjectName forKey:kGroupCourseListModelSubjectName];
 }
 
 - (id)copyWithZone:(NSZone *)zone
@@ -168,6 +171,7 @@ NSString *const kGroupCourseListModelAttendanceStatus = @"attendanceStatus";
         copy.startTime = [self.startTime copyWithZone:zone];
         copy.courseGroupName = [self.courseGroupName copyWithZone:zone];
         copy.attendanceStatus = self.attendanceStatus;
+        copy.subjectName = [self.subjectName copyWithZone:zone];
     }
     
     return copy;

+ 4 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseGroupBodyView.h

@@ -15,6 +15,10 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, assign) BOOL isVipCourse;
 
+@property (nonatomic, assign) NSInteger enterStartTime;  // 开课前可进入时间配置(分钟)
+
+@property (nonatomic, assign) NSInteger quitEndTime;    // 结束后退出时间配置(分钟)
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 278 - 2
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseGroupBodyView.m

@@ -13,9 +13,16 @@
 #import "AccompanyDetailViewController.h"
 #import "VipCouseDetailViewController.h"
 #import "GroupCourseListModel.h"
+#import "OnlineClassManager.h"
+#import "KSPremissionAlert.h"
+#import "RecordCheckManager.h"
+#import <KSChoosePicker.h>
+#import <KSFullDatePicker.h>
 
 @interface ProgramCourseGroupBodyView ()<UITableViewDelegate,UITableViewDataSource>
 
+@property (nonatomic, strong) NSDateFormatter *dateFormatter;
+
 @property (nonatomic, strong) NSMutableArray *dataArray;
 
 @property (nonatomic, strong) StateView *promptView;
@@ -31,6 +38,20 @@
 
 @property (nonatomic, strong) NSString *courseStatus;
 
+@property (nonatomic, strong) OnlineClassManager *classManager;
+
+@property (nonatomic, assign) NSInteger secondChooseIndex;
+
+@property (nonatomic, assign) NSInteger thirdChooseIndex;
+
+@property (nonatomic, strong) NSMutableArray *statusArray;
+
+@property (nonatomic, strong) NSMutableArray *attendenceStatusArray;
+
+@property (nonatomic, assign) NSInteger joinRoomBeforeTime; // 上课开始时间
+
+@property (nonatomic, assign) NSInteger quitRomeEndTime;    // 下课截止时间
+
 @end
 
 @implementation ProgramCourseGroupBodyView
@@ -53,6 +74,7 @@
         UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, iPhoneXSafeBottomMargin)];
         bottomView.backgroundColor = [UIColor clearColor];
         self.tableView.tableFooterView = bottomView;
+        [self configDefault];
         
         MJWeakSelf;
         self.tableView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
@@ -65,6 +87,12 @@
     return self;
 }
 
+- (void)configDefault {
+    [self.dateFormatter setDateFormat:@"yyyy-MM"];
+    NSDate *currentDate = [NSDate date];
+    self.classDate = [self.dateFormatter stringFromDate:currentDate];
+}
+
 - (void)forceScroll {
     self.tableView.scrollEnabled = NO;
 }
@@ -94,6 +122,21 @@
     });
 }
 
+- (void)requestRoomConfig {
+    [KSNetworkingManager selectRoomConfigRequest:KS_GET success:^(NSDictionary * _Nonnull dic) {
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            NSDictionary *result = [dic ks_dictionaryValueForKey:@"data"];
+            self.joinRoomBeforeTime = [result ks_integerValueForKey:@"practiceStartTime"];
+            self.quitRomeEndTime = [result ks_integerValueForKey:@"practiceEndTime"];
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        
+    }];
+}
+
 - (void)requestData {
     [KSNetworkingManager courseScheduleListRequest:KS_POST courseGroupId:self.courseGroupId classMonth:self.classDate attendanceStatus:self.attendanceStatus courseStatus:self.courseStatus success:^(NSDictionary * _Nonnull dic) {
         [self endRefresh];
@@ -129,6 +172,7 @@
         [self beginRefreshImmediately];
     }
 }
+
 - (void)selectCellAtIndexPath:(NSIndexPath *)indexPath {
     
     if (self.lastSelectedIndexPath == indexPath) {
@@ -153,6 +197,9 @@
             make.left.right.top.mas_equalTo(self);
             make.height.mas_equalTo(sortViewHeight);
         }];
+        [self.dateFormatter setDateFormat:@"yyyy年MM月"];
+        NSDate *currentDate = [NSDate date];
+        [self.sortView.firstLabel setText:[self.dateFormatter stringFromDate:currentDate]];
     }
 
     [self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
@@ -174,7 +221,7 @@
     GroupCourseListModel *model = self.dataArray[indexPath.row];
     ProgramCourseListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ProgramCourseListCell"];
     MJWeakSelf;
-    [cell configWithSource:model callback:^(GroupCourseListModel * _Nonnull model) {
+    [cell configWithSource:model beforeTime:self.enterStartTime callback:^(GroupCourseListModel * _Nonnull model) {
         [weakSelf enterClassRoom:model];
     }];
     return cell;
@@ -182,6 +229,25 @@
 
 - (void)enterClassRoom:(GroupCourseListModel *)model {
     
+    NSDateFormatter *dateFormatter = [NSObject getDateformatter];
+    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *beginDate = [dateFormatter dateFromString:model.startTime];
+    NSDate *endDate = [dateFormatter dateFromString:model.endTime];
+    NSDate *currentDate = [NSDate date];
+    NSTimeInterval beginTimeInterval = [beginDate timeIntervalSinceDate:currentDate];
+    NSTimeInterval endTimeInterval = [currentDate timeIntervalSinceDate:endDate];
+    if (beginTimeInterval <= self.joinRoomBeforeTime * 60 && endTimeInterval < 0) {
+        [self joinClassRoom:model];
+    }
+    else if (endTimeInterval > 0) {
+        [LOADING_MANAGER MBShowAUTOHidingInWindow:@"该课程已结束"];
+    }
+    else {
+        NSString *tipsString = [NSString stringWithFormat:@"课程还未开始,请在上课前%zd分钟进入", self.joinRoomBeforeTime];
+        [LOADING_MANAGER MBShowAUTOHidingInWindow:tipsString];
+    }
+    
+    [self joinClassRoom:model];
 }
 
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
@@ -208,11 +274,77 @@
 - (GroupCourseSortView *)sortView {
     if (!_sortView) {
         _sortView = [GroupCourseSortView sharedInstance];
-        
+        MJWeakSelf;
+        [_sortView sortAction:^(SORT_TYPE type) {
+            [weakSelf sortWithType:type];
+        }];
     }
     return _sortView;
 }
 
+- (NSMutableArray *)statusArray {
+    if (!_statusArray) {
+        _statusArray = [NSMutableArray arrayWithObject:@[]];
+    }
+    return _statusArray;
+}
+
+- (OnlineClassManager *)classManager {
+    if (!_classManager) {
+        _classManager = [[OnlineClassManager alloc] init];
+    }
+    return _classManager;
+}
+
+
+// 加入房间
+- (void)joinClassRoom:(GroupCourseListModel *)model {
+    
+    // 加入房间前判断摄像头和麦克风逻辑
+    [RecordCheckManager checkCameraPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        [self afterCheckCameraCheckMic:type source:model];
+    }];
+}
+
+- (void)afterCheckCameraCheckMic:(PREMISSIONTYPE)cameraType source:(GroupCourseListModel *)model {
+    [RecordCheckManager checkMicPermissionAvaiableCallback:^(PREMISSIONTYPE type) {
+        if (type == PREMISSIONTYPE_YES && cameraType == PREMISSIONTYPE_YES) {
+            // 判断是否进行课前检测
+            [self.classManager joinRoomWithId:model.courseId subjectName:model.subjectName classEndTime:model.endTime inViewController:(KSBaseViewController *)self.naviController.visibleViewController];
+        }
+        else {
+            NSString *content = @"";
+            CHECKDEVICETYPE checkType = CHECKDEVICETYPE_BOTH;
+            if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_NO) {
+                content = @"请开启相机和麦克风访问权限";
+                checkType = CHECKDEVICETYPE_BOTH;
+            }
+            else if (cameraType == PREMISSIONTYPE_NO && type == PREMISSIONTYPE_YES) {
+                content =  @"请开启相机访问权限";
+                checkType = CHECKDEVICETYPE_CAMREA;
+            }
+            else if (cameraType == PREMISSIONTYPE_YES && type == PREMISSIONTYPE_NO) {
+                content = @"请开启麦克风访问权限";
+                checkType = CHECKDEVICETYPE_MIC;
+            }
+            [self showAlertWithMessage:content type:checkType];
+        }
+    }];
+    
+}
+
+- (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {
+    [KSPremissionAlert shareInstanceDisplayImage:deviceType message:message showInView:[NSObject getKeyWindow] cancel:^{
+        
+    } confirm:^{
+        [self openSettingView];
+    }];
+    
+}
+
+- (void)openSettingView {
+    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
+}
 /**
  设置没有数据时的显示
  
@@ -277,6 +409,150 @@
 - (void)dealloc {
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
+
+
+- (NSDateFormatter *)dateFormatter {
+    if (!_dateFormatter) {
+        _dateFormatter = [NSObject getDateformatter];
+    }
+    return _dateFormatter;
+}
+- (void)sortWithType:(SORT_TYPE)type {
+    
+    if (type == SORT_TYPE_TIME) { // time
+        [self showPickerView];
+    }
+    else if (type == SORT_TYPE_STATUS) { // 状态
+        MJWeakSelf;
+        KSChoosePicker *picker = [[KSChoosePicker alloc] initWithTitle:@"课程状态" sourceData:@[@"全部",@"未开始",@"进行中",@"已结束"]  lastChooseIndex:self.secondChooseIndex sureButtonColor:THEMECOLOR chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
+            weakSelf.secondChooseIndex = chooseIndex;
+            if (chooseIndex == 0) {
+                [weakSelf.sortView.secondLabel setText:@"全部状态"];
+                weakSelf.courseStatus = nil;
+            }
+            else {
+                [weakSelf.sortView.secondLabel setText:returnValue];
+                [weakSelf evaluateStatusWithIndex:chooseIndex isCourseStatus:YES];
+            }
+            self.sortView.secondArrowUp = NO;
+            [weakSelf refreshAndRequestData];
+        } cancel:^{
+            self.sortView.secondArrowUp = NO;
+        }];
+        [picker showPicker];
+    }
+    else if (type == SORT_TYPE_ATTENDENCE) {
+        
+        MJWeakSelf;
+        KSChoosePicker *picker = [[KSChoosePicker alloc] initWithTitle:@"考勤" sourceData:@[@"全部",@"到课",@"旷课"]  lastChooseIndex:self.secondChooseIndex sureButtonColor:THEMECOLOR chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
+            weakSelf.thirdChooseIndex = chooseIndex;
+            if (chooseIndex == 0) {
+                [weakSelf.sortView.thirdLabel setText:@"全部考勤"];
+                weakSelf.attendanceStatus = nil;
+            }
+            else {
+                [weakSelf.sortView.thirdLabel setText:returnValue];
+                [weakSelf evaluateStatusWithIndex:chooseIndex isCourseStatus:NO];
+            }
+            self.sortView.thirdArrowUp = NO;
+            [weakSelf refreshAndRequestData];
+        } cancel:^{
+            self.sortView.thirdArrowUp = NO;
+        }];
+        [picker showPicker];
+    }
+    else {
+        [self hiddenPopView];
+    }
+}
+
+- (void)evaluateStatusWithIndex:(NSInteger)chooseIndex isCourseStatus:(BOOL)isCourseStatus {
+    if (isCourseStatus) {
+        switch (chooseIndex) {
+            case 0:
+            {
+                self.courseStatus = nil;
+                [self.sortView.secondLabel setText:@"全部状态"];
+            }
+                break;
+            case 1:
+            {
+                self.courseStatus = @"NOT_START";
+            }
+                break;
+            case 2:
+            {
+                self.courseStatus = @"ING";
+            }
+                break;
+            case 3:
+            {
+                self.courseStatus = @"COMPLETE";
+            }
+                break;
+                
+            default:
+                break;
+        }
+    }
+    else {
+        switch (chooseIndex) {
+            case 0:
+            {
+                self.attendanceStatus = nil;
+                [self.sortView.thirdLabel setText:@"全部考勤"];
+            }
+                break;
+            case 1:
+            {
+                self.attendanceStatus = @"1";
+            }
+                break;
+            case 2:
+            {
+                self.attendanceStatus = @"0";
+            }
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+- (void)showPickerView {
+    KSFullDatePicker *picker = [[KSFullDatePicker alloc] initWithTitle:@"" date:[NSDate date] pickMode:KSDATEPICKER_MODE_YEAR_MONTH sureButtonColor:THEMECOLOR selectDateBlock:^(NSString *date) {
+
+        self.classDate = date;
+        NSString *displayTime = [self getTimeDisplay:date];
+        [self.sortView.firstLabel setText:displayTime];
+        [self resetPickerStatus];
+        // 请求数据
+        [self refreshAndRequestData];
+    } cancleBlock:^{
+        [self resetPickerStatus];
+    }];
+    [picker show];
+}
+
+- (void)hiddenPopView {
+    self.sortView.firstArrowUp = NO;
+    self.sortView.secondArrowUp = NO;
+    self.sortView.thirdArrowUp = NO;
+}
+
+
+- (NSString *)getTimeDisplay:(NSString *)chooseMonth {
+    [self.dateFormatter setDateFormat:@"yyyy-MM"];
+    NSDate *chooseDate = [self.dateFormatter dateFromString:chooseMonth];
+    [self.dateFormatter setDateFormat:@"yyyy年MM月"];
+    NSString *displayTime = [self.dateFormatter stringFromDate:chooseDate];
+    return displayTime;
+}
+
+- (void)resetPickerStatus {
+    self.sortView.firstArrowUp = NO;
+}
+
 /*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.

+ 1 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseListCell.h

@@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface ProgramCourseListCell : UITableViewCell
 
-- (void)configWithSource:(GroupCourseListModel *)model callback:(GroupListModelCallback)callback;
+- (void)configWithSource:(GroupCourseListModel *)model beforeTime:(NSInteger)beforeTime callback:(GroupListModelCallback)callback;
 
 @end
 

+ 44 - 3
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseListCell.m

@@ -9,6 +9,8 @@
 
 @interface ProgramCourseListCell ()
 
+@property (weak, nonatomic) IBOutlet UIButton *enterButton;
+
 @property (weak, nonatomic) IBOutlet UILabel *timeLabel;
 
 @property (weak, nonatomic) IBOutlet UILabel *statusLabel;
@@ -28,6 +30,8 @@
 
 @property (nonatomic, copy) GroupListModelCallback callback;
 
+@property (nonatomic, assign) NSInteger beforeTime;
+
 @end
 
 @implementation ProgramCourseListCell
@@ -38,7 +42,7 @@
     self.selectionStyle = UITableViewCellSelectionStyleNone;
 }
 
-- (void)configWithSource:(GroupCourseListModel *)model callback:(GroupListModelCallback)callback {
+- (void)configWithSource:(GroupCourseListModel *)model beforeTime:(NSInteger)beforeTime callback:(GroupListModelCallback)callback {
     if (callback) {
         self.callback = callback;
     }
@@ -56,6 +60,7 @@
     CourseStudentVos *studentInfo = [model.courseStudentVos lastObject];
     [self.avatar sd_setImageWithURL:[NSURL URLWithString:[studentInfo.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:STUDENT_AVATAR]];
     self.nameLabel.text = [NSString returnNoNullStringWithString:studentInfo.userName];
+    self.subjectLabel.text = [NSString returnNoNullStringWithString:model.subjectName];
     [self evaluateWithSource:model];
 }
 
@@ -64,24 +69,60 @@
     if ([model.status isEqualToString:@"ING"]) {
         self.statusLabel.text = @"进行中";
         self.statusLabel.textColor = THEMECOLOR;
-        self.arriveStatus.hidden = NO;
-        self.arriveStatusWidth.constant = 36.0f;
+        self.arriveStatus.hidden = YES;
+        self.arriveStatusWidth.constant = 0.0f;
+        self.enterButton.hidden = NO;
+        self.enterButton.userInteractionEnabled = YES;
     }
     else if ([model.status isEqualToString:@"NOT_START"]) {
         self.statusLabel.text = @"未开始";
         self.statusLabel.textColor = HexRGB(0xFF802C);
         self.arriveStatus.hidden = YES;
         self.arriveStatusWidth.constant = 0.0f;
+        
+        // 判断按钮显示调课还是进入教室
+        NSDate *currentDate = [NSDate date];
+        NSDate *beginDate = [self getCourseBeginDate:model.startTime];
+        NSTimeInterval beginTimeInterval = [beginDate timeIntervalSinceDate:currentDate];
+        BOOL canChange = NO;
+        if (beginTimeInterval > self.beforeTime * 60) {
+            canChange = YES;
+        }
+        if (canChange) {
+            self.enterButton.hidden = YES;
+            self.enterButton.userInteractionEnabled = NO;
+        }
+        else {
+            self.enterButton.hidden = NO;
+            self.enterButton.userInteractionEnabled = YES;
+        }
     }
     else if ([model.status isEqualToString:@"COMPLETE"]) {
         self.statusLabel.text = @"已结束";
         self.statusLabel.textColor = HexRGB(0x999999);
         self.arriveStatus.hidden = NO;
         self.arriveStatusWidth.constant = 36.0f;
+        self.enterButton.hidden = YES;
+        self.enterButton.userInteractionEnabled = NO;
     }
     [self.arriveStatus setImage:[UIImage imageNamed:imageName]];
 }
 
+
+
+- (IBAction)enterClassRoom:(id)sender {
+    if (self.callback) {
+        self.callback(self.sourceModel);
+    }
+}
+
+- (NSDate *)getCourseBeginDate:(NSString *)beginTime {
+    NSDateFormatter *dateFormatter = [NSObject getDateformatter];
+    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+    NSDate *beginDate = [dateFormatter dateFromString:beginTime];
+    return beginDate;
+}
+
 - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
     [super setSelected:selected animated:animated];
 

+ 18 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Course/VIPCourse/View/ProgramCourseListCell.xib

@@ -120,10 +120,25 @@
                                     <constraint firstAttribute="width" constant="36" id="gMd-pw-6Q3"/>
                                 </constraints>
                             </imageView>
+                            <button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Dqu-Jf-1D9">
+                                <rect key="frame" x="215" y="12" width="62" height="22"/>
+                                <color key="backgroundColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="62" id="QYf-fZ-JiH"/>
+                                    <constraint firstAttribute="height" constant="22" id="ajo-2K-RFf"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
+                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                                <state key="normal" title="开始上课"/>
+                                <connections>
+                                    <action selector="enterClassRoom:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="fN5-pz-tM3"/>
+                                </connections>
+                            </button>
                         </subviews>
                         <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                         <constraints>
                             <constraint firstItem="n5o-cB-ZAV" firstAttribute="leading" secondItem="fC0-s3-zGf" secondAttribute="trailing" constant="10" id="7Hn-gP-Gfh"/>
+                            <constraint firstItem="Dqu-Jf-1D9" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="IZA-Ec-v3k" secondAttribute="trailing" constant="5" id="9SA-Em-VRf"/>
                             <constraint firstAttribute="trailing" secondItem="cms-Uu-AjN" secondAttribute="trailing" constant="10" id="9bT-Vd-f8p"/>
                             <constraint firstAttribute="bottom" secondItem="fC0-s3-zGf" secondAttribute="bottom" constant="12" id="Ah1-VO-xwc"/>
                             <constraint firstItem="qS2-Zu-yal" firstAttribute="leading" secondItem="2NK-NE-SfV" secondAttribute="trailing" constant="2" id="Cct-nq-47C"/>
@@ -131,11 +146,12 @@
                             <constraint firstAttribute="trailing" secondItem="qS2-Zu-yal" secondAttribute="trailing" constant="12" id="EVJ-Qc-kNM"/>
                             <constraint firstItem="VwE-ev-4NJ" firstAttribute="leading" secondItem="n5o-cB-ZAV" secondAttribute="leading" id="Ehn-EO-ici"/>
                             <constraint firstItem="fC0-s3-zGf" firstAttribute="top" secondItem="cms-Uu-AjN" secondAttribute="bottom" constant="12" id="F67-Fp-zCL"/>
-                            <constraint firstItem="2NK-NE-SfV" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="IZA-Ec-v3k" secondAttribute="trailing" constant="10" id="FeT-Zz-TRG"/>
+                            <constraint firstItem="Dqu-Jf-1D9" firstAttribute="top" secondItem="DbI-ca-fVq" secondAttribute="top" constant="12" id="FVr-bj-Ma1"/>
                             <constraint firstItem="cms-Uu-AjN" firstAttribute="top" secondItem="zF6-bQ-6kl" secondAttribute="bottom" constant="15" id="Guj-pG-kNB"/>
                             <constraint firstItem="nM7-0u-1Vp" firstAttribute="leading" secondItem="n5o-cB-ZAV" secondAttribute="trailing" constant="5" id="Quj-Mk-SRG"/>
                             <constraint firstItem="IN8-fl-KKM" firstAttribute="leading" secondItem="VwE-ev-4NJ" secondAttribute="trailing" constant="5" id="S5x-NE-bKj"/>
                             <constraint firstItem="fC0-s3-zGf" firstAttribute="leading" secondItem="DbI-ca-fVq" secondAttribute="leading" constant="12" id="Uo9-fx-EKh"/>
+                            <constraint firstAttribute="trailing" secondItem="Dqu-Jf-1D9" secondAttribute="trailing" constant="15" id="Uu6-A8-Gya"/>
                             <constraint firstItem="VwE-ev-4NJ" firstAttribute="top" secondItem="n5o-cB-ZAV" secondAttribute="bottom" constant="4" id="VY7-N5-kOX"/>
                             <constraint firstItem="IN8-fl-KKM" firstAttribute="centerY" secondItem="VwE-ev-4NJ" secondAttribute="centerY" id="Xfo-bh-3Dl"/>
                             <constraint firstItem="n5o-cB-ZAV" firstAttribute="top" secondItem="fC0-s3-zGf" secondAttribute="top" constant="-1" id="Zf7-e6-HR1"/>
@@ -170,6 +186,7 @@
                 <outlet property="arriveStatusWidth" destination="gMd-pw-6Q3" id="BSA-9V-x7b"/>
                 <outlet property="avatar" destination="fC0-s3-zGf" id="eQU-zt-sOx"/>
                 <outlet property="courseGroupName" destination="n5o-cB-ZAV" id="02s-Db-N24"/>
+                <outlet property="enterButton" destination="Dqu-Jf-1D9" id="FZy-Cb-KFs"/>
                 <outlet property="nameLabel" destination="VwE-ev-4NJ" id="MOV-h8-dpI"/>
                 <outlet property="statusLabel" destination="2NK-NE-SfV" id="uu3-nS-teP"/>
                 <outlet property="subjectLabel" destination="Uk4-i9-HBZ" id="xbf-8n-kcl"/>

+ 21 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Course/View/CourseGroupView/GroupCourseSortView.h

@@ -7,14 +7,35 @@
 
 #import <UIKit/UIKit.h>
 
+typedef NS_ENUM(NSInteger, SORT_TYPE) {
+    SORT_TYPE_TIME = 1,   // 课程时间
+    SORT_TYPE_STATUS = 2, // 课程状态
+    SORT_TYPE_ATTENDENCE = 3,  // 考勤筛选
+    SORT_TYPE_HIDDEN = 4, // 隐藏
+};
+
+typedef void(^SortActionBlock)(SORT_TYPE type);
+
 NS_ASSUME_NONNULL_BEGIN
 
 @interface GroupCourseSortView : UIView
 
+@property (weak, nonatomic) IBOutlet UILabel *firstLabel;
+@property (weak, nonatomic) IBOutlet UILabel *secondLabel;
+@property (weak, nonatomic) IBOutlet UILabel *thirdLabel;
+
+@property (nonatomic, assign) BOOL firstArrowUp;
+
+@property (nonatomic, assign) BOOL secondArrowUp;
+
+@property (nonatomic, assign) BOOL thirdArrowUp;
+
 + (instancetype)sharedInstance;
 
 + (CGFloat)getViewHeight;
 
+- (void)sortAction:(SortActionBlock)block;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 67 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Course/View/CourseGroupView/GroupCourseSortView.m

@@ -9,18 +9,84 @@
 
 @interface GroupCourseSortView ()
 
+@property (nonatomic, copy) SortActionBlock block;
+
+@property (weak, nonatomic) IBOutlet UIImageView *firstArrow;
+@property (weak, nonatomic) IBOutlet UIImageView *secondArrow;
+@property (weak, nonatomic) IBOutlet UIImageView *thirdArrow;
 
 
 @end
 
 @implementation GroupCourseSortView
-
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.firstArrowUp = NO;
+    self.secondArrowUp = NO;
+    self.thirdArrowUp = NO;
+}
 
 + (instancetype)sharedInstance {
     GroupCourseSortView *view = [[[NSBundle mainBundle] loadNibNamed:@"GroupCourseSortView" owner:nil options:nil] firstObject];
     return view;
 }
 
+- (void)sortAction:(SortActionBlock)block {
+    if (block) {
+        self.block = block;
+    }
+}
+
+- (IBAction)buttonClickAction:(UIButton *)sender {
+    NSInteger index = sender.tag - 1000;
+    BOOL isHidden;
+    if (index == 1) {
+        self.firstArrowUp = !self.firstArrowUp;
+        self.secondArrowUp = NO;
+        self.thirdArrowUp = NO;
+        isHidden = !self.firstArrowUp;
+    }
+    else if (index == 2) {
+        self.secondArrowUp = !self.secondArrowUp;
+        self.firstArrowUp = NO;
+        self.thirdArrowUp = NO;
+        isHidden = !self.secondArrowUp;
+    }
+    else {
+        self.thirdArrowUp = !self.thirdArrowUp;
+        self.firstArrowUp = NO;
+        self.secondArrowUp = NO;
+        isHidden = !self.thirdArrowUp;
+    }
+    
+    if (self.block) {
+        if (isHidden) {
+            index = 4;
+        }
+        self.block(index);
+    }
+}
+
+- (void)setFirstArrowUp:(BOOL)firstArrowUp {
+    _firstArrowUp = firstArrowUp;
+    NSString *imageName = firstArrowUp ? @"sort_up_blue" : @"sort_down_grey";
+    [_firstArrow setImage:[UIImage imageNamed:imageName]];
+}
+
+- (void)setSecondArrowUp:(BOOL)secondArrowUp {
+    _secondArrowUp = secondArrowUp;
+    NSString *imageName = secondArrowUp ? @"sort_up_blue" : @"sort_down_grey";
+    [_secondArrow setImage:[UIImage imageNamed:imageName]];
+
+
+}
+
+- (void)setThirdArrowUp:(BOOL)thirdArrowUp {
+    _thirdArrowUp = thirdArrowUp;
+    NSString *imageName = thirdArrowUp ? @"sort_up_blue" : @"sort_down_grey";
+    [_thirdArrow setImage:[UIImage imageNamed:imageName]];
+}
+
 + (CGFloat)getViewHeight {
     return 50.0f;
 }

+ 32 - 15
KulexiuForTeacher/KulexiuForTeacher/Module/Course/View/CourseGroupView/GroupCourseSortView.xib

@@ -14,30 +14,33 @@
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nUQ-28-ciH">
-                    <rect key="frame" x="0.0" y="0.0" width="385" height="55"/>
+                    <rect key="frame" x="14" y="0.0" width="357" height="55"/>
                     <subviews>
                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3ud-K6-gBw">
-                            <rect key="frame" x="0.0" y="0.0" width="121.66666666666667" height="55"/>
+                            <rect key="frame" x="0.0" y="0.0" width="112.33333333333333" height="55"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="XXXX年XX月" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cfT-LB-SNv">
-                                    <rect key="frame" x="12" y="19" width="90" height="17"/>
+                                    <rect key="frame" x="7.3333333333333286" y="19" width="89.999999999999986" height="17"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                     <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
                                 </label>
                                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down_grey" translatesAutoresizingMaskIntoConstraints="NO" id="aFu-Ok-mVy">
-                                    <rect key="frame" x="107" y="25" width="9" height="5"/>
+                                    <rect key="frame" x="102.33333333333333" y="25" width="9" height="5"/>
                                     <constraints>
                                         <constraint firstAttribute="height" constant="5" id="f2v-0M-H3l"/>
                                         <constraint firstAttribute="width" constant="9" id="zTE-EP-L2e"/>
                                     </constraints>
                                 </imageView>
                                 <button opaque="NO" tag="1001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ac9-lB-T0k">
-                                    <rect key="frame" x="0.0" y="0.0" width="121.66666666666667" height="55"/>
+                                    <rect key="frame" x="0.0" y="0.0" width="112.33333333333333" height="55"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                     <state key="normal">
                                         <color key="titleColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
                                     </state>
+                                    <connections>
+                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="IiH-Q8-iJf"/>
+                                    </connections>
                                 </button>
                             </subviews>
                             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -53,27 +56,30 @@
                             </constraints>
                         </view>
                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z8Q-fT-2Vr">
-                            <rect key="frame" x="131.66666666666666" y="0.0" width="121.66666666666666" height="55"/>
+                            <rect key="frame" x="122.33333333333334" y="0.0" width="112.33333333333334" height="55"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="全部状态" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vxK-r7-9sg">
-                                    <rect key="frame" x="29" y="19" width="56" height="17"/>
+                                    <rect key="frame" x="24.333333333333314" y="19" width="56" height="17"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                     <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
                                 </label>
                                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down_grey" translatesAutoresizingMaskIntoConstraints="NO" id="idf-14-rMz">
-                                    <rect key="frame" x="90" y="25" width="9" height="5"/>
+                                    <rect key="frame" x="85.333333333333314" y="25" width="9" height="5"/>
                                     <constraints>
                                         <constraint firstAttribute="width" constant="9" id="2rB-eK-C35"/>
                                         <constraint firstAttribute="height" constant="5" id="PIL-WN-xkd"/>
                                     </constraints>
                                 </imageView>
                                 <button opaque="NO" tag="1002" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="j1t-mT-XyA">
-                                    <rect key="frame" x="0.0" y="0.0" width="121.66666666666667" height="55"/>
+                                    <rect key="frame" x="0.0" y="0.0" width="112.33333333333333" height="55"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                     <state key="normal">
                                         <color key="titleColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="calibratedRGB"/>
                                     </state>
+                                    <connections>
+                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="o6Z-q3-BLc"/>
+                                    </connections>
                                 </button>
                             </subviews>
                             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -89,27 +95,30 @@
                             </constraints>
                         </view>
                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yMy-1B-zxV">
-                            <rect key="frame" x="263.33333333333331" y="0.0" width="121.66666666666669" height="55"/>
+                            <rect key="frame" x="244.66666666666671" y="0.0" width="112.33333333333334" height="55"/>
                             <subviews>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="全部考勤" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Xc-2m-8mt">
-                                    <rect key="frame" x="29" y="19" width="56" height="17"/>
+                                    <rect key="frame" x="24.333333333333314" y="19" width="56" height="17"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                     <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     <nil key="highlightedColor"/>
                                 </label>
                                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="sort_down_grey" translatesAutoresizingMaskIntoConstraints="NO" id="grW-VA-qlz">
-                                    <rect key="frame" x="90" y="25" width="9" height="5"/>
+                                    <rect key="frame" x="85.333333333333314" y="25" width="9" height="5"/>
                                     <constraints>
                                         <constraint firstAttribute="height" constant="5" id="hAG-sG-mv7"/>
                                         <constraint firstAttribute="width" constant="9" id="sqn-jl-TbO"/>
                                     </constraints>
                                 </imageView>
                                 <button opaque="NO" tag="1003" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5J6-Qp-5o7">
-                                    <rect key="frame" x="0.0" y="0.0" width="121.66666666666667" height="55"/>
+                                    <rect key="frame" x="0.0" y="0.0" width="112.33333333333333" height="55"/>
                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                     <state key="normal">
                                         <color key="titleColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
                                     </state>
+                                    <connections>
+                                        <action selector="buttonClickAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="8YM-XU-MyE"/>
+                                    </connections>
                                 </button>
                             </subviews>
                             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -159,13 +168,21 @@
             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <constraints>
                 <constraint firstAttribute="bottom" secondItem="nUQ-28-ciH" secondAttribute="bottom" id="8Ge-mS-YzV"/>
-                <constraint firstAttribute="trailing" secondItem="nUQ-28-ciH" secondAttribute="trailing" id="9yc-y0-4fF"/>
-                <constraint firstItem="nUQ-28-ciH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="igM-Q3-fAI"/>
+                <constraint firstAttribute="trailing" secondItem="nUQ-28-ciH" secondAttribute="trailing" constant="14" id="9yc-y0-4fF"/>
+                <constraint firstItem="nUQ-28-ciH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="14" id="igM-Q3-fAI"/>
                 <constraint firstItem="nUQ-28-ciH" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="yVO-Aa-YHu"/>
             </constraints>
             <nil key="simulatedTopBarMetrics"/>
             <nil key="simulatedBottomBarMetrics"/>
             <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="firstArrow" destination="aFu-Ok-mVy" id="HfH-fU-Kon"/>
+                <outlet property="firstLabel" destination="cfT-LB-SNv" id="fxC-FN-FHH"/>
+                <outlet property="secondArrow" destination="idf-14-rMz" id="vtq-9G-6Dc"/>
+                <outlet property="secondLabel" destination="vxK-r7-9sg" id="fKB-7V-W3z"/>
+                <outlet property="thirdArrow" destination="grW-VA-qlz" id="KLm-di-ir9"/>
+                <outlet property="thirdLabel" destination="9Xc-2m-8mt" id="1q0-e6-Dmr"/>
+            </connections>
             <point key="canvasLocation" x="41.984732824427482" y="-148.94366197183101"/>
         </view>
     </objects>