多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# ClassWrong.md # ## 1. 错题列表 *D:\wamp\www\ketang.test\weike\protected\controllers\ClassWrongController.php* ``` /** * 错题列表 * TODO 未实现区分快捷试卷, 未实现小题型ID * @throws Exception * @author wuzhc 2018-02-06 */ public function actionGetLists() { $userID = $this->getSession()->fdUserID; $classID = RequestUtils::getNormalRequest('classID'); $subjectID = RequestUtils::getNormalRequest('subjectID'); $aliasID = RequestUtils::getNormalRequest('aliasID'); // 小题型ID $begin = RequestUtils::getNormalRequest('begin'); // 单位毫秒 $end = RequestUtils::getNormalRequest('end'); // 单位毫秒 $len = RequestUtils::getNormalRequest('len', 10); $start = RequestUtils::getNormalRequest('start', 0); $sort = RequestUtils::getNormalRequest('sort', 'date_desc'); $totalInit = RequestUtils::getNormalRequest('totalInit', 0); if (!$classID || !$subjectID) { throw new Exception('参数错误'); } $classIDs = $this->getClassIDs(); if ($classID) { if (!in_array($classID, $classIDs)) { ResponseUtils::json(null, 1, '非本人班级不能查看'); } } // 条件 $args = array( 'begin' => $begin, 'end' => $end, 'classID' => $classID, 'subjectID' => $subjectID, // 'alias' => $aliasID, 'right' => WK::EXER_RECORD_WRONG, // 错题 'scene' => array_keys($this->scene), ); // 总数 $total = null; if ($totalInit == 1) { $total = V2WrongService::factory()->getWrongTotalFromMongo($args); if ($total == 0) { ResponseUtils::json(array( 'data' => array( 'list' => array(), 'total' => 0 ) )); } } // 列表 $args = array_merge($args, array( 'len' => $len, 'start' => $start, 'sort' => $sort, )); $res = V2WrongService::factory()->getWrongsFromMongo($args); if (!$res['result']) { ResponseUtils::json(array('data' => array())); } $data = array(); foreach ($res['result'] as $r) { /** @var Exercise $exercise */ $exercise = Exercise::model()->with('diff')->findByPk($r['exid']); if (!$exercise) { continue; } $temp = array(); $temp['id'] = $exercise->id; $temp['cid'] = $exercise->fdContentID; $temp['date'] = date('Y-m-d H:i:s', $r['date']->sec); $temp['errorNum'] = $r['count']; $temp['typeID'] = $exercise->fdExerciseTypeID; $temp['alias'] = Yii::app()->params['EXERCISETYPEALIAS'][$exercise->fdAlias]; $temp['diff'] = $exercise->diff->fdValue; $temp['text'] = $exercise->fdText; $temp['isFavorite'] = V2ContentService::factory() ->handelFavorite(WK::FAVOR_CHECK, WK::QUESBANK_TYPEID, $exercise->id, $userID) ? 1 : 0; $data['list'][] = $temp; } ResponseUtils::json(array('data' => $data, 'total' => $total)); } ``` ## 2. 总数 *D:\wamp\www\ketang.test\weike\protected\service\service2\V2WrongService.php* ``` /** * 从mongo获取错题总数 * @param $args * @author wuzhc 2018-01-16 * @return bool */ public function getWrongTotalFromMongo($args) { $query = array(); // 学校 if ($args['schoolID']) { $query['school'] = (int)$args['schoolID']; } // 班级 if (!empty($args['classID'])) { if (is_numeric($args['classID'])) { $query['class'] = (int)$args['classID']; } elseif (is_array($args['classID'])) { $query['class'] = array('$in' => $args['classID']); } } // 场景 if (!empty($args['scene'])) { if (is_numeric($args['scene'])) { $query['scene'] = (int)$args['scene']; } elseif (is_array($args['scene'])) { $query['scene'] = array('$in' => $args['scene']); } } // tag if (!empty($args['tagID'])) { $query['tags.tv'] = (int)$args['tagID']; } if (!empty($args['tagType'])) { $query['tags.tid'] = (int)$args['tagType']; } // 正确或错误 if (isset($args['right'])) { $query['right'] = (int)$args['right']; } // 科目 if (!empty($args['subjectID'])) { $query['subject'] = (int)$args['subjectID']; } // 年级 if (!empty($args['gradeID'])) { $query['grade'] = (int)$args['gradeID']; } // 时间 if ($args['begin'] && $args['end']) { $query['date'] = array( '$gte' => new MongoDate($args['begin'] / 1000), '$lte' => new MongoDate($args['end'] / 1000), ); } // 是否为快捷试卷 if (is_numeric($args['isQuickExam'])) { $query['isQuickExam'] = (int)$args['isQuickExam']; } // 题目小题型 todo 类型不一致,暂时用in解决,后期应该统一为int类型 if ($args['exerAlias']) { $query['exerAlias'] = array( '$in' => array((string)$args['exerAlias'], (int)$args['exerAlias']) ); } /** @var EMongoClient $mongo */ $mongo = Yii::app()->mongodb; $collection = $mongo->selectCollection('exer_record'); $res = $collection->aggregate(array( array('$match' => $query), array('$group' => array('_id' => '$exid')), array('$group' => array('_id' => '', 'total' => array('$sum' => 1))), )); return $res['result'] ? $res['result'][0]['total'] : 0; } ``` ## 3. 列表 ``` /** * 从mongo获取错题列表 * @param $args * @return array * @author wuzhc 2017-11-01 */ public function getWrongsFromMongo($args) { /** @var EMongoClient $mongo */ $mongo = Yii::app()->mongodb; $collection = $mongo->selectCollection('exer_record'); // 管道 $pipeline = array(); // 学校 if ($args['schoolID']) { $match['$match']['school'] = (int)$args['schoolID']; } // 班级 if (!empty($args['classID'])) { if (is_numeric($args['classID'])) { $match['$match']['class'] = (int)$args['classID']; } elseif (is_array($args['classID'])) { $match['$match']['class'] = array('$in' => $args['classID']); } } // 场景 if (!empty($args['scene'])) { if (is_numeric($args['scene'])) { $match['$match']['scene'] = (int)$args['scene']; } elseif (is_array($args['scene'])) { $match['$match']['scene'] = array('$in' => $args['scene']); } } // tag if (!empty($args['tagID'])) { $match['$match']['tags.tv'] = (int)$args['tagID']; } if (!empty($args['tagType'])) { $match['$match']['tags.tid'] = (int)$args['tagType']; } // 正确或错误 if (isset($args['right'])) { $match['$match']['right'] = (int)$args['right']; } // 科目 if (!empty($args['subjectID'])) { $match['$match']['subject'] = (int)$args['subjectID']; } // 年级 if (!empty($args['gradeID'])) { $match['$match']['grade'] = (int)$args['gradeID']; } // 时间 if ($args['begin'] && $args['end']) { $match['$match']['date'] = array( '$gte' => new MongoDate($args['begin'] / 1000), '$lte' => new MongoDate($args['end'] / 1000), ); } // 是否为快捷试卷 if (is_numeric($args['isQuickExam'])) { $match['$match']['isQuickExam'] = (int)$args['isQuickExam']; } // 题目小题型 todo 类型不一致,暂时用in解决,后期应该统一为int类型 if ($args['exerAlias']) { $match['$match']['exerAlias'] = array( '$in' => array((string)$args['exerAlias'], (int)$args['exerAlias']) ); } if (!empty($match)) { array_push($pipeline, $match); } $group['$group'] = array( '_id' => array( 'exid' => '$exid', ), 'count' => array( '$sum' => 1 ), 'date' => array( '$max' => '$date' ), 'aeid' => array( '$max' => '$aeid' ), 'grade' => array( '$addToSet' => '$grade' ), 'subject' => array( '$addToSet' => '$subject' ), ); array_push($pipeline, $group); $project['$project'] = array( 'exid' => '$_id.exid', 'grade' => '$grade', 'date' => '$date', 'count' => '$count', 'subject' => '$subject', 'aeid' => '$aeid' ); array_push($pipeline, $project); if (!empty($args['sort'])) { // 格式errors_desc或error_asc list($field, $mode) = explode('_', $args['sort'], 2); if ($field == 'errors') { // 按错题数量排序 $sort['$sort'] = array( 'count' => strcasecmp($mode, 'desc') ? 1 : -1, '_id' => -1 ); } elseif ($field == 'date') { // 按最近错题时间排序 $sort['$sort'] = array( 'date' => strcasecmp($mode, 'desc') ? 1 : -1, '_id' => -1 ); } if (isset($sort)) { array_push($pipeline, $sort); } } if (!empty($args['start'])) { $skip['$skip'] = (int)$args['start']; array_push($pipeline, $skip); } if (!empty($args['len'])) { $limit['$limit'] = (int)$args['len']; array_push($pipeline, $limit); } return $collection->aggregate($pipeline); } ```