🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 展示效果 http://weike.test/index.php?r=teachingV3/review/sReviewList ![](./img/2018-11-19_110011.png) ![](./img/2018-11-19_110315.png) ## 控制器代码 **D:\wamp\www\xue.test\xuetang\protected\modules\teachingV3\controllers\ReviewController.php** ``` /** * 学生回顾列表 * @author liupf 2016/9/27 */ public function actionSReviewList() { $this->layout = "//version2/layouts/main_center_v3"; $userID = $this->getSession()->fdUserID; $schoolMap = UserService::factory()->getSchoolMapByUserID($userID); if(!$schoolMap) $this->redirect_msgBox($this->createUrl('/'), array('msg'=>'未加入学校')); $classes = ClassService::factory()->getAllClassByUserID($userID,WK::CLASS_CLASS); $classList = array(); if($classes){ foreach($classes as $class){ $classList[]=array( 'id' => $class->id, 'title' => $class->fdName ); } } $classIDArr = ArrayUtils::getColumn($classList,'id'); $schoolTypeArr = SchoolService::factory()->getSchoolType($schoolMap->fdSchoolID); $subjectIDArr = array(); if($schoolTypeArr){ foreach($schoolTypeArr as $schoolType) $subjectIDArr = array_merge($subjectIDArr,Yii::app()->params['PARAGRAPH_SUB_INDEX'][$schoolType]); } $subjectIDArr = array_unique($subjectIDArr); if($subjectIDArr){ foreach($subjectIDArr as $subjectID){ $teachings = V3TeachService::factory()->getTeachings(array( 'subjectID' => $subjectID, 'classID' => $classIDArr, )); if($teachings){ $subjectList[]=array( 'id' => $subjectID, 'title' => Yii::app()->params['SUBJECT_ARR'][$subjectID] ); } } } $this->render("sReviewList",array( 'classList'=>CJSON::encode($classList), //班级 'subjectList'=>CJSON::encode($subjectList?:array()), //科目 )); } ``` 接口: ``` /** * 获取学生课堂记录 * classID 班级ID 可选 * subjectID 科目ID 可选 * keyword 关键字 可选 * start 需要获取数据的开始位置 可选,默认是0 * len 需要获取数据的结束位置 可选,默认是10 * @author liupf 2016/9/28 */ public function actionStuRecord(){ $classID = RequestUtils::getNormalRequest('classID'); $subjectID = RequestUtils::getNormalRequest('subjectID'); $keyword = RequestUtils::getNormalRequest('keyword'); $start = RequestUtils::getNormalRequest('start')?:0; $len = RequestUtils::getNormalRequest('len')?:10; $subjectInt = RequestUtils::getNormalRequest('subjectInt'); if(!$classID) ResponseUtils::json(null,1,'failure'); $condition = array('classID'=> $classID,'isOver'=> true); $data = array(); if($subjectInt){ $data['subjectList'] = V3TeachService::factory()->getSubjectDistribute($condition); } $condition['subjectID'] = $subjectID; $condition['prepareName'] = $keyword; $condition['with'] = array('content','content.v2version','content.period'); $total = V3TeachService::factory()->countTeaching($condition); $data['total'] = $total; $data['record'] = array(); !$total && ResponseUtils::json(array('data'=>$data)); $condition['order'] = 't.id DESC'; $condition['limit'] = intval($len); $condition['offset'] = intval($start); $teachings = V3TeachService::factory()->getTeachings($condition); $data['record'] = $this->_processTeachings($teachings); ResponseUtils::json(array('data'=>$data)); } ``` 完善接口返回的信息 ``` /** * @param $teachings * @return array * @author liupf 2016/9/28 */ private function _processTeachings($teachings) { $teachingList=array(); foreach($teachings as $teaching){ $records = V3TeachService::factory()->getStudentRecords(array('teachingID'=>$teaching->id)); $studentIDArr= $records?ArrayUtils::getColumn($records,'fdStudentID'):array(); $studentIDArr= array_unique($studentIDArr); $teachingList[]=array( 'teachingID'=> $teaching->id, 'prepareID' => $teaching->fdPrepareID, 'title' => $teaching->content->fdName, 'period' => $teaching->content->period->fdValue, 'className' => V2ClassService::factory()->getClass(array('id'=>$teaching->fdClassID))->fdName, 'subject' => Yii::app()->params['SUBJECT_ARR'][$teaching->fdSubjectID], 'version' => wkeVersion::model()->findByPk($teaching->content->v2version->fdValue)->fdName, 'start' => DateTimeUtils::date2MillSecond($teaching->fdStart), 'end' => $teaching->fdEnd ? DateTimeUtils::date2MillSecond($teaching->fdEnd):$teaching->fdEnd, 'tags' => V3RelevanceService::factory()->getTags($teaching->fdPrepareID), 'teacherName'=>UserService::factory()->getShowName($teaching->fdTeacherID, 'ketang'), 'studentInClass'=>count($studentIDArr), 'prepareType'=> V3PrepareService::factory()->getPrepareTypeName($teaching->fdPrepareID), ); } return $teachingList; } ``` 数据格式: ``` { "total": "54", "record": [{ "teachingID": "5256", "prepareID": "1528022", "title": "1.1 正数和负数", "period": "1", "className": "一年级50班", "subject": "数学", "version": "人教版", "start": 1488075419000, "end": null, "tags": [{ "id": 41489, "title": "七年级上册", "level": 1 }, { "id": 41490, "title": "第一章 有理数", "level": 2 }, { "id": 41491, "title": "1.1 正数和负数", "level": 3 }], "teacherName": "测试老师1", "studentInClass": 0, "prepareType": "新授课" },] } ``` 条件查询方法 **D:\wamp\www\weike.test\weiketest\protected\service\service3\V3TeachService.php** ``` private function _findTeaching($args) { $criteria = new CDbCriteria(); $with = array(); if($args['distinct']){ $criteria->distinct = $args['distinct']; } CDbUtils::addCondition($criteria, 't.id', $args['id']); CDbUtils::addCondition($criteria, 't.fdClassID', $args['classID']); CDbUtils::addCondition($criteria, 't.fdTeacherID', $args['teacherID']); CDbUtils::addCondition($criteria, 't.fdPrepareID', $args['prepareID']); CDbUtils::addCondition($criteria, 't.fdGradeID', $args['gradeID']); /*by liupf 2016/9/28 */ CDbUtils::addCondition($criteria, 't.fdSubjectID', $args['subjectID']); // add by wuzhc 2018-03-21 0正常,1删除 if(is_numeric($args['status'])){ CDbUtils::addCondition($criteria, 't.fdStatus', intval($args['status'])); } if($args['studentID']){ $criteria->together =true; $with[] = 'record'; CDbUtils::addCondition($criteria, 'record.fdStudentID', $args['studentID']); } //检测改班级是否还在上课状态 if($args['flag']){ $criteria->addCondition('t.fdStart>DATE_SUB(now(),INTERVAL '.WK::WMPC_CLASS_TIME.' MINUTE )'); $criteria->addCondition('t.fdEnd is NULL') ; } /*by liupf 2016/10/18 */ if($args['schoolID']){ $with[] = 'class' ; CDbUtils::addCondition($criteria, 'class.fdSchoolID', $args['schoolID']); } if($args['year']){ $with[] = 'class' ; CDbUtils::addCondition($criteria, 'class.fdYear', $args['year']); } if(isset($args['classStatus'])){ $with[] = 'class' ; CDbUtils::addCondition($criteria, 'class.fdStatus', $args['classStatus']); } if($args['group'] == 1){//以科目分组 $criteria->group = 't.fdSubjectID'; $criteria->select = 't.fdSubjectID,count(*) as total'; } if($args['group'] == 2){ $criteria->group = 't.fdClassID'; $criteria->select = 't.fdClassID,count(*) as total'; } if($args['prepareName']){ $with[]='content'; $criteria->addSearchCondition('content.fdName',$args['prepareName']); } if($args['keyword'] || (0===$args['keyword'] || '0'===$args['keyword'])){ $with[]='user'; $with[]='content'; $criteria->addCondition("content.fdName LIKE '%".$args['keyword']."%' OR user.fdRealName LIKE '%".$args['keyword']."%'"); } if($args['teacherName']){ $with[]='user'; $criteria->addSearchCondition('user.fdRealName',$args['teacherName']); } if($args['start'] || $args['begin']){ $criteria->addCondition('t.fdStart >= :start') ; $criteria->params[':start'] = $args['start'] ?:$args['begin']; } if($args['end']){ $criteria->addCondition('t.fdStart <= :end') ; $criteria->params[':end'] = $args['end'] ; } if($args['isOver']){ $criteria->addCondition('t.fdStart<DATE_SUB(now(),INTERVAL '.WK::WMPC_CLASS_TIME.' MINUTE ) OR t.fdEnd IS NOT NULL'); } if($args['hasDispenseExam']){ $with[] = 'operations' ; $criteria->addCondition('operations.fdTypeID = '.WK::DISPENSE_EXAM_DO.' AND operations.fdValue > 0') ; } $args['hasSubjectID'] && $criteria->addCondition('t.fdSubjectID>0 AND t.fdSubjectID<17'); $args['hasGradeID'] && $criteria->addCondition('t.fdGradeID>0 AND t.fdGradeID<14'); if($args['select']) $criteria->select = $args['select'] ; /*by liupf 2016/10/18 */ if($args['order']) $criteria->order = $args['order']; if($args['groupBy']) $criteria->group = $args['groupBy']; $criteria->with = array_unique(array_merge($with, (array)$args['with'])); $args['limit'] and $criteria->limit = $args['limit']; $args['offset'] and $criteria->offset = $args['offset']; return $criteria; } ``` 生成的SQL: ``` SELECT `t`.`id` AS `t0_c0`, `t`.`fdClassID` AS `t0_c1`, `t`.`fdTeacherID` AS `t0_c2`, `t`.`fdPrepareID` AS `t0_c3`, `t`.`fdSubjectID` AS `t0_c4`, `t`.`fdGradeID` AS `t0_c5`, `t`.`fdStart` AS `t0_c6`, `t`.`fdEnd` AS `t0_c7`, `t`.`fdNote` AS `t0_c8`, `t`.`fdReview` AS `t0_c9`, `t`.`fdStatus` AS `t0_c10`, `content`.`id` AS `t1_c0`, `content`.`idString` AS `t1_c1`, `content`.`fdName` AS `t1_c2`, `content`.`fdEnglish` AS `t1_c3`, `content`.`fdTypeID` AS `t1_c4`, `content`.`fdUserID` AS `t1_c5`, `content`.`fdSchoolTypeID` AS `t1_c6`, `content`.`fdSubjectID` AS `t1_c7`, `content`.`fdKindID` AS `t1_c8`, `content`.`fdAcronym` AS `t1_c9`, `content`.`fdPinyin` AS `t1_c10`, `content`.`fdProviderID` AS `t1_c11`, `content`.`fdCpID` AS `t1_c12`, `content`.`fdOperatorID` AS `t1_c13`, `content`.`fdApproverID` AS `t1_c14`, `content`.`fdApprove` AS `t1_c15`, `content`.`fdCreate` AS `t1_c16`, `content`.`fdExpire` AS `t1_c17`, `content`.`fdModify` AS `t1_c18`, `content`.`fdAdapt` AS `t1_c19`, `content`.`fdHot` AS `t1_c20`, `content`.`fdBornID` AS `t1_c21`, `content`.`fdSync` AS `t1_c22`, `content`.`fdCommentID` AS `t1_c23`, `content`.`fdDisabled` AS `t1_c24`, `content`.`fdMongoSync` AS `t1_c25`, `content`.`fdStatStatus` AS `t1_c26`, `v2version`.`fdValue` AS `t2_c5`, `v2version`.`id` AS `t2_c0`, `period`.`fdValue` AS `t3_c5`, `period`.`id` AS `t3_c0` FROM `wkwke`.`tbTeachingV3` `t` LEFT OUTER JOIN `wkctn`.`tbContent` `content` ON ( `t`.`fdPrepareID` = `content`.`id` ) LEFT OUTER JOIN `wkctn`.`tbInteger` `v2version` ON ( `v2version`.`fdContentID` = `content`.`id` ) LEFT OUTER JOIN `wkctn`.`tbInteger` `period` ON ( `period`.`fdContentID` = `content`.`id` ) WHERE(((t.fdClassID =2) AND (content.fdName LIKE "%正数%"))AND (t.fdStart < DATE_SUB(now(), INTERVAL 120 MINUTE)OR t.fdEnd IS NOT NULL)) AND (v2version.fdAttributeID = 38) AND (period.fdAttributeID = 379) ORDER BY t.id DESC LIMIT 10 ``` ## 视图 **D:\wamp\www\weike.test\weiketest\protected\modules\teachingV3\views\review\sReviewList.php** ``` <div class="v3-content pb20"> <!--面包削导航--> <div class="f18 font-y gray2 pt20 pb20"><a href="javaScript:">首页</a><span class="ml15 mr15">&gt;</span><span>课堂回顾</span></div> <!--面包削导航 end--> <!--内容--> <div class="w clr"> <!--选择--> <div class="w clr mb10"> <div class="fl w760"> <div class="w"> <div class="fl font-y f15 fb mr10 mt3">按班级查找:</div> <ul class="fl w640 clr js_class_choise"> <li class="border1 h25 lh25 tc pl10 pr10 pointer fl mr15 mb10 bg5 white border_green" data-id="">全部</li> </ul> </div> <div class="w"> <div class="fl font-y f15 fb mr10 mt3">按科目查找:</div> <ul class="fl w640 clr js_subject_choise"> <li class="border1 h25 lh25 tc pl10 pr10 pointer fl mr15 mb10 bg5 white border_green" data-id="">全部</li> </ul> </div> </div> <div class="fr"> <input id="search-input" type="text" class="inputText fl w200" placeholder="输入课程名称查找" style="padding:3px 30px 3px 5px;"> <input id="search-btn" type="button" class="fl inputText_searchBtn mt3" title="搜索"> </div> </div> <!--选择 end--> <div class="w"> <!--列表--> <div class="w pr min_h300" id="list"> <img src="/public/pc/images/loading.gif" alt="ajax-loader" style="position:absolute;top:50%;left:50%;margin-top:-16px;margin-left:-16px;"> </div> <!--列表 end--> <!--分页--> <div class="w mt30 mb10 clr" id="page"> <ul class="tc paging bc"> <li class="gray">共有100条记录</li> <li class="paging_but paging_off"><a href="javaScript:">上一页</a></li> <li class="page"><a class="currentPage" href="JavaScript:void(0)">1</a></li> <li class="page"><a href="JavaScript:void(0)" onclick="getData('2','10')">2</a></li> <li class="page"><a href="JavaScript:void(0)" onclick="getData('3','10')">3</a></li> <li class="page"><a href="JavaScript:void(0)" onclick="getData('4','10')">4</a></li> <li class="page"><a href="JavaScript:void(0)" onclick="getData('5','10')">5</a></li> <li class="paging_but"><a onclick="getData('2','10')" href="javaScript:">下一页</a></li> <li>(1/48)</li> <li><input type="text" class="w30 h30 box-sizing tc" onkeyup="value=value.replace(/[^\d]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"></li> <li class="paging_but"><a href="javaScript:">跳转</a></li> </ul> </div> <!--分页 end--> </div> </div> <!--内容 end--> </div> <script type="text/javascript" src="<?php echo Yii::app()->request->baseUrl; ?>/public/common/js/showBox.js"></script> <script type="text/javascript" src="<?php echo Yii::app()->request->baseUrl; ?>/public/ketang/js/upload-page.js"></script> <script type="text/javascript" src="<?php echo Yii::app()->request->baseUrl; ?>/public/js/timeformate.js"></script> <script type="text/javascript"> $(function() { var classList = <?php echo $classList;?>; var subjectList = <?php echo $subjectList;?>; var loading = '<img src="/public/pc/images/loading.gif" alt="ajax-loader" style="position:absolute;top:50%;left:50%;margin-top:-16px;margin-left:-16px;">', notips = '<p class="f24 orange font-y tc" style="height:300px;line-height:300px;">暂无内容!</p>'; var ajaxAbort = {}, page; function ajaxDeal(options, scallback, ecallback) { var tajax = $.ajax({ url: options.url, type: options.type || "GET", dataType: options.dataType || "json", data: options.data || {}, success: function(result) { // console.log(options.url, result); if (result.status == 0 || result.msg=='success') { scallback(result); } else if (result.status == 401) { $.showBox({"contents": "请先登录", callBack: function() { window.location.href = "<?php echo $this->createUrl('//');?>"; }}); } else { ecallback && ecallback(result); } }, error: function(error) { ecallback && ecallback(error); } }); if (options.ajax) { ajaxAbort[options.ajax] && ajaxAbort[options.ajax].abort(); ajaxAbort[options.ajax] = tajax; } } // 课堂记录模板(单个) function recordTmp(obj) { var url = obj.prepareID && obj.teachingID ? ('<?php echo $this->createUrl("review/sReview")?>&prepareID=' + obj.prepareID + '&teachingID=' + obj.teachingID) : "javaScript:void(0)"; var tags = obj.tags || [], used = obj.end && obj.start ? (obj.end - obj.start) / 1000 : (2 * 3600); var second = used % 60, minute = parseInt(used / 60); tags.sort(function(a, b){return a.level - b.level;}); return '<div class="v3-lesson-index-listOne clr">' + '<div class="fl w540">' + '<h3>' + '<a href="' + url + '" target="_blank">' + '<span class="f16 fb vm font-y">【第' + (obj.period || 1) + '课时】' + (obj.title || "未知") + ' </span>' + '<span class="classType">' + (obj.prepareType || "新授课") + '</span>' + '</a>' + '</h3>' + '<div class="mt20 clr gray">' + '<div class="fl">' + (obj.subject || "未知科目") + '(' + (obj.version || "未知版本") + ')' + (tags[0] ? tags[0].title || "未知教材" : "未知教材") + ' | ' + (tags[1] ? tags[1].title || "" : "") + ' ' + (tags[2] ? tags[2].title || "" : "") + ' ' + (tags[3] ? tags[3].title || "" : "") + '</div>' + '</div>' + '</div>' + '<div class="fr">' + '<div class="tr">' + '<span class="v3-review-peoIcon"></span>' + '<span class="vm ml10">出勤' + (obj.studentInClass || "0")+ '人</span>' + '<span class="v3-review-timeIcon ml30"></span>' + '<span class="vm ml10">用时' + (minute < 10 ? "0" + minute : minute) + '分' + (second < 10 ? "0" + second : second) + '秒</span>' + '</div>' + '<div class="tr f13 mt20 gray">' + '<span>【' + (obj.teacherName || "未知教师") + '】</span>' + '<span class="ml20">【' + (obj.className ||"未知班级") + '】</span>' + '<span class="ml20">上课时间:' + (obj.start ? timeFormat(obj.start, "yyyy年MM月dd日HH:mm") : "未知") + '</span>' + '</div>' + '</div>' + '</div>'; } // 获取课堂回顾记录分页 function getRecords(pa) { page = new UpLoadPage({ len: 10, $el: $("#page"), callback: getRecordHandle, params: { pa: pa || {}, $list: $("#list"), url: "<?php echo $this->createUrl('review/stuRecord');?>" } }); page.init(); } // 获取课堂回顾记录回调 function getRecordHandle(pa) { var $list = pa.$list; var pdata = pa.pa; pdata.start = pa.start; pdata.len = pa.len; $list.html(loading); ajaxDeal({ url: pa.url, data: pdata, ajax: "reAbort" }, function(data) { data = data.data || {}; var list = data.record || []; if (list.length > 0) { var html = ""; for (var i = 0, len = list.length; i < len; i++) { html += recordTmp(list[i]); } $list.html(html); pa.page.setPage(data.total); } else { $list.html(notips); } }, function(error) { if (error.statusText != "abort") { $list.html(notips); } }); } // 搜索回调 function searchHandle() { getRecords({ classID: $(".js_class_choise li.border_green").data("id"), subjectID: $(".js_subject_choise li.border_green").data("id"), keyword: $("#search-input").val() }); } // 初始化 ~function init() { var html = ''; for (var i = 0, len = classList.length; i < len; i++) { html += '<li class="border1 h25 lh25 tc pl10 pr10 pointer fl mr15 mb10 ' + (i == 0 ? 'bg5 white border_green' : '') + '" data-id="' + classList[i].id + '">' + classList[i].title + '</li>'; } $(".js_class_choise").html(html); var shtml = '<li class="border1 h25 lh25 tc pl10 pr10 pointer fl mr15 mb10 bg5 white border_green" data-id="">全部</li>'; for (var i = 0, len = subjectList.length; i < len; i++) { shtml += '<li class="border1 h25 lh25 tc pl10 pr10 pointer fl mr15 mb10" data-id="' + subjectList[i].id + '">' + subjectList[i].title + '</li>'; } $(".js_subject_choise").html(shtml); getRecords({ classID: classList[0].id }); }(); // 切换班级 $(".js_class_choise").on('click', 'li', function() { if ($(this).hasClass('.border_green')) return false; $(this).addClass('bg5 white border_green').siblings('li').removeClass('bg5 white border_green'); getRecords({ subjectID: $(".js_subject_choise li.border_green").data("id"), classID: $(this).data("id") }); }); // 切换学科 $(".js_subject_choise").on('click', 'li', function() { if ($(this).hasClass('.border_green')) return false; $(this).addClass('bg5 white border_green').siblings('li').removeClass('bg5 white border_green'); getRecords({ subjectID: $(this).data("id"), classID: $(".js_class_choise li.border_green").data("id") }); }); // 搜素按钮点击事件 $("#search-btn").on("click", function() { searchHandle(); }); // 搜索输入回车响应 $("#search-input").on("keypress", function() { if (event.which == 13){ searchHandle(); } }); }) </script> ``` ## 运行逻辑 ![](./img/2018-11-19_112446.png) ![](./img/2018-11-19_112709.png) ![](./img/2018-11-19_112734.png) ![](./img/2018-11-19_112755.png) ![](./img/2018-11-19_112903.png)