内部课程

一、主要控制器介绍

一级模块 二级模块 对应控制器
课程列表 主控制器 XLInsideCourseListViewController
课程列表 下拉筛选框 XLEnterpriseCourseListShowMoreTypeView
课程详情 主控制器 XLHomeCourseDeailController
课程详情 章节列表子控制器 XLCourseContentViewController
课程详情 课程评论子控制器 XLCourseChatViewNewController
课程详情 课程介绍子控制器 XLCourseChatViewController

二、主要跳转逻辑

内部课程_第1张图片
截屏2020-07-02上午10.08.41.png

三、接口请求

所属模块 接口描述 接口关键字
课程列表 获取筛选框列表数据 InsideCourseTypeList
课程列表 根据筛选框获取课程列表数据 requestEnterpriseCourseWithCourseTypeID
课程详情 获取课程详情 xlcourseGetChapterWare
课程详情 更新课件观看进度 xlupdateStudyCourseProgress
课程介绍 获取推荐课程 CourseRecommendList
课程章节 获取课件目录 xlcourseGetChapterWareList
课程章节 判断课程是否加入考试 xlcourseJoinExam
课程章节 获取课程分组 xlcourseGetChapters
课程章节 获取分组下课件目录 xlcourseGetChapterWareList
课程章节 获取课件详情 xlcourseGetChapterWare
课程章节 更新课件观看进度 xlupdateStudyCourseProgress
评论 获取评论列表 xlcourseComments
评论 添加课程评论 xlcourseAddComent
评论 添加回复评论 xlcourseReplyComent
评论 点赞或取消 xlcourseLiked

四、代码设计

1.课程列表

①.页面设计

主要页面有以下几个

页面描述 页面名称
列表页 tableView
筛选框 moreTypeView
顶部已选择分类 collectionView

②.关键代码逻辑与设计

进入课程列表后,请求接口有两个:

//获取下级列表
- (void)loadCourseNextTypeList:(XLClassifyModel *)clasfyModel{
    [self.typeArray removeAllObjects];
    NSDictionary *parmDict=@{@"parentId":@(clasfyModel.CourseTypeID),@"name":@""};
    [[XLNetworkManager sharedManager] InsideCourseTypeList:parmDict progress:nil success:^(XLResponse * _Nonnull xlResponse) {
        if (xlResponse.successDataObject) {
            NSArray *secArray= xlResponse.successDataObject;
            [secArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                __block XLClassifyModel *cModel=[XLClassifyModel modelWithDictionary:obj];
                [self.typeArray addObject:cModel];
            }];
            if (self.moreTypeView) {
                [self.moreTypeView reloadAllData:nil];
            }
        }
    } failure:^(XLResponsError * _Nonnull error) {
        
    } formate:nil];
}
//获取课程列表
- (void)loadData {
    _pageIndex = 1;
    [[XLNetworkManager sharedManager] requestEnterpriseCourseWithCourseTypeID:_courseTypeID CourseClassifyID:@"" Keyword:@"" DepartmentID:@"0" PageIndex:@(_pageIndex).stringValue andType:@"0" success:^(XLResponse * _Nonnull xlResponse) {
        self.dataListArray = [NSMutableArray arrayWithArray:xlResponse.dataObject[@"Data"]];
        if (self.dataListArray.count > 0) {
            self.tableView.hidden = NO;
            self.emptyView.hidden = YES;
            [self.tableView reloadData];
            [self.tableView.mj_header endRefreshing];
            if (self.dataListArray.count < 10) {
                [self.tableView.mj_footer endRefreshingWithNoMoreData];
            }else{
                [self.tableView.mj_footer endRefreshing];
            }
        }else{
            self.tableView.hidden = YES;
            self.emptyView.hidden = NO;
        }

    } failure:^(XLResponsError * _Nonnull error) {
        
    }];
    
}

当用户"点击下级分类"弹出筛选界面,再次点击某一分类操作时会触发回调方法:

- (void)selectTypeModel:(XLClassifyModel *)xlmodel isLoadList:(BOOL )loadList{
}

并且进行下级子分类的数据请求

//获取下级列表
- (void)loadCourseNextTypeList:(XLClassifyModel *)clasfyModel{
    [self.typeArray removeAllObjects];
    NSDictionary *parmDict=@{@"parentId":@(clasfyModel.CourseTypeID),@"name":@""};
    [[XLNetworkManager sharedManager] InsideCourseTypeList:parmDict progress:nil success:^(XLResponse * _Nonnull xlResponse) {
        if (xlResponse.successDataObject) {
            NSArray *secArray= xlResponse.successDataObject;
            [secArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                __block XLClassifyModel *cModel=[XLClassifyModel modelWithDictionary:obj];
                [self.typeArray addObject:cModel];
            }];
            if (self.moreTypeView) {
                [self.moreTypeView reloadAllData:nil];
            }
        }
    } failure:^(XLResponsError * _Nonnull error) {
        
    } formate:nil];
}

如有下级子分类:“继续筛选下一级”按钮为可点击状态。
如无下级子分类:“继续筛选下一级”按钮为不可点击状态。
点击确认选择:通过选中分类再次进行列表数据请求,刷新tableview。

2.课程详情

①.页面设计

主要页面有以下几个

页面描述 页面名称 备注
顶部视频或者文档显示区域 courseTopHeadView
三个切换tab scrollTabView
pageviewcontroller内容 subContentView
课程介绍 courceSumViewController 子控制器
课程目录 courseContentViewController 子控制器
课程评论 courseChatViewController 子控制器

②.关键代码逻辑与设计

  • 进入课程播放页,请求课程详情
//获取课程详情
-(void)loadCourseDetail:(NSInteger)courseid
{
    [[XLNetworkManager sharedManager] xlcourseEnterpriseDetail:@{@"courseID":[NSNumber numberWithInteger:self.courseId?self.courseId:0]} progress:nil success:^(XLResponse * _Nonnull xlResponse) {
        XLLog(@"%@",(NSArray *)xlResponse.successDataObject);
        if (xlResponse.successDataObject) {
            NSDictionary *backDict=(NSDictionary*)xlResponse.successDataObject;
            self.courseModel=[XLCourseModel modelWithClassDic:backDict[@"c"] modelClass:@"XLCourseModel"];
            self.courseTopHeadView.dataModel=self.courseModel;
//            刷新简介和标题
            XLCourceSumViewController *sumViewController=(XLCourceSumViewController *)self.ctrollerArray[0];
            [sumViewController freshView:self.courseModel];
            XLLog(@"%@",xlResponse.successDataObject);
        }else{
            if ([xlResponse.responseError.errMsg isEqualToString:@"权限错误"]) {
                [XLHudManager showTextWithNoimage:@"该课程已下架"];
                [self noDataAction];
            }else{
                [XLHudManager showTextWithNoimage:xlResponse.responseError.errMsg];
            }
        }
    } failure:^(XLResponsError * _Nonnull error) {
        
    } formate:nil];
    
}

获取课程目录

//课程目录相关的东西
-(void)loadCourseCata:(NSInteger)courseid
{
    [[XLNetworkManager sharedManager] xlcourseGetChapters:@{@"courseID":[NSNumber numberWithInteger:courseid]} progress:nil success:^(XLResponse * _Nonnull xlResponse) {
        XLLog(@"%@",(NSArray *)xlResponse.successDataObject);
        if (xlResponse.successDataObject) {
            NSArray *backArray=(NSArray*)xlResponse.successDataObject;
            if (backArray.count>0) {
                NSDictionary *dict=backArray[0];
                XLCourseCataModel *model=[XLCourseCataModel modelWithClassDic:dict modelClass:@"XLCourseCataModel"];
                [self loadCourseWareList:model.ChapterID section:0];
            }
        }else{
            [XLHudManager showTextWithNoimage:xlResponse.responseError.errMsg];
        }
    } failure:^(XLResponsError * _Nonnull error) {
        
    } formate:nil];
    
}

根据请求的数据,头部视图显示对应内容,如果是pdf或world课件,隐藏视频播放器,点击后跳转课件浏览器。如果是视频、音频,则显示视频播放器,并且自动播放视频、音频 。相关代码逻辑请查看此方法:

- (void)setWareModel:(XLChapWareModel *)wareModel
{
}
  • 首次进入课程详情页,为了优化用户体验,目录、评论子控制器不会请求数据。当用户左右滑动到目录、评论对应子控制器时候,才会进行对应数据请求及页面逻辑显示。

  • 章节目录
    默认展开第一个分组,且只展开一个分组。
    首页判断是否加入考试,以此来控制底部“课后测试”按钮的显示与隐藏。相关代码逻辑请查看此方法:

#pragma mark  判断是否加入考试
-(void)examJudge{
}

主要接口请求有以下两个方法:

//获取课程分组
-(void)loadCourseCata:(NSInteger)courseid
{
}
//获取分组下课件目录
-(void)loadCourseWareList:(NSInteger)chapterId section:(NSInteger)loadSection
{
}

cell点击逻辑:如果是pdf或者world文档,点击cell即视为该课程学习完成,调用更新课程进度方法,并且刷新UI,课件变为已完成阅读状态。更新课件进度方法如下(内部逻辑省略,请自行查看):

#pragma mark更新进度
-(void)updateProgressWithCourseID:(NSInteger)courseID model:(XLChapWareModel *)model cataModel:(XLCourseCataModel*)cataModel index:(NSInteger)index{
}

如果是视频课件,视频播放完毕后会接收到来自主控制的通知事件,更新UI,课件变为已完成状态

//接收通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeChannelNoti:) name:@"PlayDone" object:nil];

//通知调用方法
#pragma mark视频播放完成
- (void)changeChannelNoti:(NSNotification *)noti
{
    XLChapWareModel *model = [XLChapWareModel new];
    model = self.curWareModel;
    model.enpriseProgressModel.Progress = 100;
    [self.readArr addObject:model];
    [self.contentTableView reloadData];
}

课件名称如果过长,则自动滚动,逻辑在XLCourseConTableCell子视图
label自动滚动控件为QWorseRaceLamp
固定课件名称label宽度为200

#define titleLabelWidth   200

根据课件的字符串转化成长度,对比字符串长度以及label最大宽度,控制课件名称是否自动滚动,关键代码如下:

   if (self.mainWidth > titleLabelWidth) {
            [self.animationLabel startAnimation];
        }
  • 评论
    评论控制器设计成依靠tableview实现
    评论区分一级评论和二级评论,其中:一级评论为用户对课程直接评论,二级评论是用户对用户评论。
    自定义头部视图用于显示一级评论,cell用于显示二级评论。
    二级评论默认只展示一条数据,如有多条数据,点击‘展开更多回复内容’,显示全部二级评论,对应逻辑如下:
#pragma mark  展开更多
-(void)showMoreReplyButtonActionWithSection:(NSInteger)section row:(NSInteger)row{
    [self.unFoldArray addObject:[NSNumber numberWithInteger:section]];
    [self.mainTableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
}

发表评论区分课程评论和回复评论:
课程评论实现为如下方法:

#pragma mark 添加课程评论
-(void)addAplyCommonActionWith:(NSString *)content{
}

回复评论参考如下方法:

-(void)addAplyUserActionWithContent:(NSString *)content model:(XLReplyModel *)model{
}

点赞的接口实现在对应的view中,动画实现及UI刷新在评论主控制器中实现。

#pragma mark  头部视图点赞
-(void)likeButtonActionWithSection:(NSInteger)section{
    NSLog(@"点赞第%ld行",section);
    [UIView setAnimationsEnabled:NO]; // 或者[UIView setAnimationsEnabled:NO];
    [self.mainTableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationNone];
    [UIView setAnimationsEnabled:YES]; // 或者[UIView setAnimationsEnabled:YES];
}
#pragma mark  cell点赞
-(void)likeButtonActionWithSection:(NSInteger)section row:(NSInteger)row{
    [UIView setAnimationsEnabled:NO]; // 或者[UIView setAnimationsEnabled:NO];
    NSLog(@"点赞第%ld行 第%ld个",section,row);
    [self.mainTableView reloadRow:row inSection:section withRowAnimation:UITableViewRowAnimationNone];
    [UIView setAnimationsEnabled:YES]; // 或者[UIView setAnimationsEnabled:YES];
}

点赞动画不能在子视图中实现,子视图传递代理方法,将点赞按钮对于主屏幕的坐标传递给主控制器

#pragma mark 头部点赞动画
-(void)headerLikeAnimationWithRect:(CGRect)rect{
    [self zanAnimationWithRect:rect];
}
#pragma mark  cell点赞动画
-(void)likeAnimationWithRect:(CGRect)rect{
    [self zanAnimationWithRect:rect];
}

你可能感兴趣的:(内部课程)