<?php /** * 试卷-答卷表 * @author: houyingcai * @email: 594609175@qq.com * @date : 2017-05-19 17:51:32 * @version $Id$ */ namespace Common\Service; use Common\Common\AttachOperation; use Common\Common\Cache; use Common\Common\ExamHelper; use Common\Common\Integral; use Common\Common\Lcs; use Common\Common\User; use Common\Common\Department; use Common\Common\TaskCenter; use Common\Common\Train; use Common\Model\AnswerDetailExtendModel; use Common\Model\AnswerDetailModel; use Common\Model\AnswerModel; use Common\Model\CountModel; use Common\Model\LikeModel; use Common\Model\MedalModel; use Common\Model\MedalRecordModel; use Common\Model\MedalRelationModel; use Common\Model\PaperModel; use Common\Model\RightModel; use Common\Model\SnapshotModel; use Common\Model\StatisticsModel; use Common\Model\TopicModel; use Common\Model\AnswerAttachModel; use Common\Common\StudyMap; use VcySDK\Member; use VcySDK\Service; class AnswerService extends AbstractService { // 考试通过 const PASS = 1; // 考试不通过 const UNPASS = 0; // 不发送消息 const NOT_NEED_SEND_MSG = 0; // 手动阅卷发送阅卷信息 const SEND_MSG_FOR_MARKING_USER = 1; // 手动阅卷系统阅卷成绩出来 const SEND_MSG_FOR_JOIN_EXAM_USER = 2; // 初始批阅状态 const DEFAULT_MARK_STATUS = 0; // 答卷正常状态 const START_TYPE_INITIAL = 0; // 答卷异常状态 const START_TYPE_END = 1; /** @var AnswerAttachModel */ public $_answer_attach_model; /** $var StatisticsModel */ public $_statistics_model; /** @var AnswerDetailModel */ protected $_answer_detail_model; /** @var TopicModel */ protected $_topic_model; /** @var SnapshotModel */ protected $_snapshot_model; /** @var LikeModel */ protected $_like_model; /** @var MedalModel */ protected $_medal_model; /** @var MedalRelationModel */ protected $_medal_relation_model; /** @var MedalRecordModel */ protected $_medal_record_model; /** @var PaperModel */ protected $paper_model; /** @var RightModel */ protected $_right_model; /** @var AnswerDetailExtendModel */ protected $_answer_detail_extend_model; // 构造方法 public function __construct() { $this->_d = new AnswerModel(); $this->_like_model = new LikeModel(); $this->_answer_detail_model = new AnswerDetailModel(); $this->paper_model = new PaperModel(); $this->_snapshot_model = new SnapshotModel(); $this->_topic_model = new TopicModel(); $this->_medal_model = new MedalModel(); $this->_right_model = new RightModel(); $this->_medal_relation_model = new MedalRelationModel(); $this->_medal_record_model = new MedalRecordModel(); $this->_answer_attach_model = new AnswerAttachModel(); $this->_statistics_model = new StatisticsModel(); $this->_answer_detail_extend_model = new AnswerDetailExtendModel(); parent::__construct(); } /** * 查询考试排名数据 * * @param int $ep_id 试卷ID * @param string $uid 用户ID * @param int $page 页码 * @param int $limit 每页条数 * * @return array */ public function answer_list_all($ep_id = 0, $uid = '', $page = 1, $limit = 10) { $cache = &Cache::instance(); $rank_data = []; try { // 获取当前试卷缓存信息 $rank_data = $cache->get('Common.Exam_Rank_List_' . $ep_id); } catch (\Exception $e) { \Think\Log::record($e); } // 用户信息 $users = []; // 缓存数据为空 if (empty($rank_data)) { // 查询条件:当前试卷,已批阅状态 $conds = ['ep_id' => $ep_id, 'answer_status' => self::READ_OVER]; // 排序:成绩倒序,时间正序 $order_option = ['my_score' => 'DESC', 'my_time' => 'ASC']; // 查询字段 $fields = 'uid,ea_id,my_score,my_time'; // 查询考试成绩列表 $data = $this->_d->list_by_conds($conds, null, $order_option, $fields); // 获取用户信息 $uids = array_filter(array_unique(array_column($data, 'uid'))); sort($uids); $userlist = $this->getUser($uids); $k = 1; foreach ($data as $v) { if (!array_key_exists($v['uid'], $rank_data)) { // 排名 $v['ranking'] = $k; $user = $userlist[$v['uid']]; $v['memID'] = $user['memUid'] ? $user['memUid'] : ''; $v['memUsername'] = $user['memUsername'] ? $user['memUsername'] : ''; $v['memFace'] = $user['memFace'] ? $user['memFace'] : ''; $rank_data[$v['uid']] = $v; $k++; } continue; } unset($data); // 将排名列表存入缓存 $cache->set('Common.Exam_Rank_List_' . $ep_id, $rank_data); } $start = ($page - 1) * $limit; // 取待返数据 $list = array_slice($rank_data, $start, $limit); // 获取我的排名 $rank_data = array_combine_by_key($rank_data, 'uid'); $ranking = 0; if (isset($rank_data[$uid]['ranking']) && !empty($rank_data[$uid]['ranking'])) { $ranking = $rank_data[$uid]['ranking']; } // 答卷id集合 $ea_ids = array_column($list, 'ea_id'); // 获取我的点赞数据 $my_like_data = $this->_like_model->list_by_conds(['ea_id' => $ea_ids, 'uid' => $uid]); // 我的点赞答卷id集合 $my_like_ea_ids = array_unique(array_column($my_like_data, 'ea_id')); // 获取点赞数 $like_fields = 'ea_id,count(ea_id) as likes'; $likes_data = $this->_like_model->getLikeCount($ea_ids, $like_fields); // ea_id为键,likes为值 $likes = array_column($likes_data, 'likes', 'ea_id'); $result = []; foreach ($list as $v) { // 答卷id $v['ea_id'] = intval($v['ea_id']); // 点赞数 $v['likes'] = array_key_exists($v['ea_id'], $likes) ? $likes[$v['ea_id']]['likes'] : 0; // 是否点赞 $v['is_like'] = in_array($v['ea_id'], $my_like_ea_ids) ? self::SUCCES_STATE : self::FALSE_STATE; unset($v['uid']); $result[] = $v; } // 缓存不为空,$users为空 if (empty($users[$uid])) { // 获取用户数据 $users = $this->getUser([$uid]); } return [ 'ranking' => $ranking, 'memFace' => $users[$uid]['memFace'], 'total' => count($rank_data), 'list' => $result ]; } /** * 获取所有人的排名信息 * * @param int $ep_id * * @return array */ public function get_rank_all_list($ep_id = 0) { // 查询条件:当前试卷,已批阅状态 $conds = ['ep_id' => $ep_id, 'answer_status' => self::READ_OVER]; // 排序:成绩倒序,时间正序 $order_option = ['my_score' => 'DESC', 'my_time' => 'ASC']; // 查询字段 $fields = 'uid,ea_id,my_score,my_time'; // 查询考试成绩列表 $data = $this->_d->list_by_conds($conds, null, $order_option, $fields); // 获取用户信息 $uids = array_filter(array_unique(array_column($data, 'uid'))); sort($uids); $userlist = $this->getUser($uids); $data_new = []; $k = 1; foreach ($data as $v) { if (!array_key_exists($v['uid'], $data_new)) { // 排名 $v['ranking'] = $k; $user = $userlist[$v['uid']]; $v['memID'] = $user['memUid'] ? $user['memUid'] : ''; $v['memUsername'] = $user['memUsername'] ? $user['memUsername'] : ''; $v['memFace'] = $user['memFace'] ? $user['memFace'] : ''; $data_new[$v['uid']] = $v; $k++; } continue; } unset($data); return $data_new; } /** * 获取答卷详情 * @author: 蔡建华 * * @param array $params 传入参数 * @param array $user 当前用户 * @param array $answer 用户答卷记录 * @param array $paper 试卷信息 * @return array|bool */ public function answer_detail_info($params = [], $user = [], $answer = [], $paper = []) { $obj_id = 0; if (isset($params['customtask_id']) && $params['customtask_id']) { // 任务id $obj_id = intval($params['customtask_id']); } elseif (isset($params['plan_id']) && $params['plan_id']) { // 培训计划id $obj_id = intval($params['plan_id']); } // 考试答题用时为0:该考试尚未交卷 if ($answer['my_time'] == 0) { E('_ERR_REPEAT_SUBMINT_END'); } // 如果传递的参数为空,则获取答题记录中的任务、培训ID if (empty($obj_id)) { $obj_id = intval($answer['obj_id']); } // 判断用户是否有权限访问“任务类”数据 if (PaperService::TASK_TYPE == $paper['exam_type']) { // 任务 $taskCenter = &TaskCenter::instance(); $taskCenter->checkCustomtaskRight($obj_id, $answer['ep_id'], $user); } // 判断用户是否有权限访问“线下培训”数据 if (PaperService::TRAIN_TYPE == $paper['exam_type']) { // 培训计划 $train = &Train::instance(); $train->checkCustomTrainRight($obj_id, $answer['ep_id'], $user); } if (self::EC_CLOSE_STATES == $paper['cate_status']) { // 试卷分类被禁用:试卷被禁用 E('_ERR_DATA_EXAM_DEL'); } // 试卷状态 $ep_status = $this->paper_status($paper['exam_status'], $paper['begin_time'], $paper['end_time']); if (in_array($ep_status, [self::STATUS_END, self::STATUS_STOP])) { // 考试已结束或者已终止,则返回的查看权限为考试结束的权限 $is_see_after = $paper['is_see_after_over']; } else { // 如果考试未结束,则返回的权限为答卷完成的权限 $is_see_after = $paper['is_see_after_submit']; } // 答卷id $ea_id = $answer['ea_id']; // 答题列表 $my_answer_detail_list = $this->_answer_detail_model->list_by_conds(['ea_id' => $ea_id]); // 答对的试题数据 $pass_answers = array_filter($my_answer_detail_list, function ($v) { return $v['is_pass'] == self::MY_PASS; }); // 做对题数 $my_success_num = count($pass_answers); // 答错的题数(总答题数-作对的题数) $my_error_num = count($my_answer_detail_list) - $my_success_num; // 我的排名 $ranking = $this->get_my_rank($answer['ep_id'], $answer['uid'], $obj_id); $list = []; if ($is_see_after >= 2) { // 如果权限为对错可见或者解析可见,则查询答卷情况格式化(全部解析) $list = $this->get_answer_detail($my_answer_detail_list, self::ANSWER_TYPE_ALL_ANALYSIS); } // 剩余补考次数 $makeup_total = 0; // 当前试卷待阅卷状态的记录数 $marking_count = 0; if (self::OPEN_MAKEUP == $paper['is_open_makeup']) { // 如果开启了补考,此处需要查询已经补考的次数 $makeup_num = $this->_d->count_by_conds(['ep_id' => $answer['ep_id'], 'uid' => $answer['uid'], 'is_makeup' => self::IS_MAKEUP, 'my_time>?' => 0]); // 计算剩余补考次数 $makeup_total = $paper['makeup_num'] - $makeup_num; if ($makeup_total < 0) { $makeup_total = 0; } // 查询待批阅的答卷记录数 $marking_count = $this->_d->count_by_conds(['ep_id' => $answer['ep_id'], 'uid' => $answer['uid'], 'answer_status' => self::READ_WAITING]); } // 查询未交卷的记录数 $no_submit_count = $this->_d->count_by_conds(['ep_id' => $answer['ep_id'], 'uid' => $answer['uid'], 'my_time' => 0]); return [ 'ea_id' => intval($answer['ea_id']), 'ep_id' => intval($answer['ep_id']), 'ep_status' => $ep_status, 'my_score' => $answer['my_score'], 'my_time' => $answer['my_time'], 'my_error_num' => $my_error_num, 'memUid' => $user['memUid'], 'memFace' => User::instance()->avatar($user['memUid'], $user), 'ranking' => $ranking, 'my_is_pass' => intval($answer['my_is_pass']), 'paper_type' => intval($paper['paper_type']), 'exam_type' => intval($paper['exam_type']), 'marking_type' => intval($paper['marking_type']), 'is_see_after' => intval($is_see_after), // 可见性权限设置 'is_open_makeup' => intval($paper['is_open_makeup']), // 是否开启补考 'makeup_num' => $makeup_total, // 剩余补考次数 'makeup_start_time' => $paper['makeup_start_time'], 'makeup_end_time' => $paper['makeup_end_time'], 'marking_count' => intval($marking_count), // 待批阅的答卷记录数 'no_submit_count' => $no_submit_count, 'list' => $list ]; } /** * 获取我的考试排名 * * @param int $ep_id 试卷ID * @param string $uid 用户ID * @param int $obj_id 任务id或培训安排id * * @return int|string 我的排名 */ public function get_my_rank($ep_id = 0, $uid = '', $obj_id = 0) { // 我的排名 $ranking = 0; $cache = &Cache::instance(); // 常规考试,排名从缓存读取 if (empty($obj_id)) { $rank_data = []; try { // 获取当前试卷缓存信息 $rank_data = $cache->get('Common.Exam_Rank_List_' . $ep_id); } catch (\Exception $e) { \Think\Log::record($e); } // 缓存数据为空 if (empty($rank_data)) { // 查询考试成绩列表 $conditions = [ 'ep_id' => $ep_id, 'answer_status' => self::READ_OVER // 已批阅 ]; $page_option = null; // 排序方式:成绩倒序,用时正序 $order_option = ['my_score' => 'DESC', 'my_time' => 'ASC']; // 查询字段 $fields = 'uid,ea_id,my_score,my_time'; // 按照成绩倒序查询已批阅的回答记录列表 $data = $this->_d->list_by_conds($conditions, $page_option, $order_option, $fields); // 获取用户信息 $uids = array_filter(array_unique(array_column($data, 'uid'))); sort($uids); $users = $this->getUser($uids); // 排名列表 $data_new = []; $k = 1; foreach ($data as $v) { // 用户不在新数组中,加入新数组, if (!array_key_exists($v['uid'], $data_new)) { // 因为成绩是按照倒序排列的,此处只取每个用户的第一条记录,即为用户的最高分 $v['ranking'] = $k; // 排名 $user_info = $users[$v['uid']]; $v['memUsername'] = $user_info['memUsername'] ? $user_info['memUsername'] : ''; $v['memFace'] = $user_info['memFace'] ? $user_info['memFace'] : ''; $data_new[$v['uid']] = $v; $k++; } continue; } // 将排名列表存入缓存 $cache->set('Common.Exam_Rank_List_' . $ep_id, $rank_data); } $rank_data = array_combine_by_key($rank_data, 'uid'); if (isset($rank_data[$uid]['ranking']) && !empty($rank_data[$uid]['ranking'])) { // 我的排名 $ranking = $rank_data[$uid]['ranking']; } return $ranking; } // 查询条件 $conditions = [ 'ep_id' => $ep_id, 'obj_id' => $obj_id, 'answer_status' => self::READ_OVER, // 已批阅 ]; // 查询字段 $fields = 'uid,ea_id,my_score,my_time'; // 排序方式:成绩倒序,用时正序 $order_option = ['my_score' => 'DESC', 'my_time' => 'ASC']; // 如果是线下培训或者任务类,查询当前试卷的考试记录列表 $data = $this->_d->list_by_conds($conditions, null, $order_option, $fields); // 排名数据列表 $data_new = []; $k = 1; $ranking = 0; foreach ($data as $v) { // 用户不在新数组中,加入新数组 if (!array_key_exists($v['uid'], $data_new)) { $v['ranking'] = $k; $data_new[$v['uid']] = $v; if ($uid == $v['uid']) { // 如果找到当前用户的排名 $ranking = $k; break; } $k++; } continue; } unset($data); return $ranking; } /** * 开始考试 * * @author: 蔡建华 * @param array $data 试卷信息数据 * @param string $uid 用户ID * @param int $data_type 考试类型(1;常规,2:任务,3:培训) * @param int $obj_id 培训计划或者任务ID * @param int $is_makeup 是否是补考(0:否,1:是) * * @return array|bool */ public function paper_start_exam($data = [], $uid = '', $data_type = 1, $obj_id = 0, $is_makeup = 0) { $ep_id = $data['ep_id']; $is_old = $data['is_old']; $ep_type = $data['ep_type']; // 组装考试开始基本数据 $base = [ 'ep_id' => $ep_id, 'uid' => $uid, 'my_begin_time' => MILLI_TIME, 'paper_info' => serialize($data), 'my_time' => 0, 'my_error_num' => 0, 'my_is_pass' => 0, 'is_makeup' => $is_makeup, 'data_type' => $data_type, 'obj_id' => $obj_id ]; // 随机抽取 if (self::TOPIC_RANDOM == $ep_type) { $answer_temp_serv = new AnswerTempService(); // 根据试卷ID从临时答卷表获取答卷 $snapshot = $answer_temp_serv->get_answer_temp($ep_id); if (empty($snapshot)) { // 实例化试卷Service $paper = new PaperService(); // 兼容老数据 if ($is_old == self::OLD_DATA_STATE) { $snapshot = $paper->get_temp_list_by_epid($ep_id, 1); // 0:后台抽题,1:前台抽题 } else { // 题库信息 $bank_topic_data = unserialize($data['bank_topic_data']); //题库ID集合 $bank_ids = array_column($bank_topic_data, 'eb_id'); // 选题规则 $rule_data = []; if (!empty($data['rule'])) { $rule_data = unserialize($data['rule']); } // 按照题库题目类型抽题 $snapshot = $paper->random_rule_topic($bank_ids, $data, $bank_topic_data, $rule_data); } } // 按照单选、多选、判断、问答、语音重新组合数组 $singles = $multiples = $judgments = $questions = $voices = []; foreach ($snapshot as $key => $val) { // 单选 if (self::TOPIC_TYPE_SINGLE == $val['et_type']) { $singles[] = $val; } // 多选 if (self::TOPIC_TYPE_MULTIPLE == $val['et_type']) { $multiples[] = $val; } // 判断 if (self::TOPIC_TYPE_JUDGMENT == $val['et_type']) { $judgments[] = $val; } // 问答 if (self::TOPIC_TYPE_QUESTION == $val['et_type']) { $questions[] = $val; } // 语音 if (self::TOPIC_TYPE_VOICE == $val['et_type']) { $voices[] = $val; } } $snapshot = array_merge($singles, $multiples, $judgments, $questions, $voices); } else { // 获取从快照组获取题 $snapshot = $this->_snapshot_model->list_by_conds(['ep_id' => $ep_id]); if (self::UPSET_TOPIC_YES == $data['is_upset_topic']) { // 如果开启试题打乱 shuffle($snapshot); } } // 获取试题失败 if (empty($snapshot)) { E('_ERR_BANK_TOPIC_FAILED'); } $topic = []; try { // 开始事务 $this->start_trans(); // 插入考试信息 $ea_id = $this->_d->insert($base); foreach ($snapshot as $key => $value) { if (array_key_exists('er_id', $value)) { // 随机快照表 $esr_id = $value['er_id']; } elseif (array_key_exists('es_id', $value)) { // 试卷照表 $esr_id = $value['es_id']; } else { // 题库 $esr_id = 0; } // 考试试题拼接数据 if ($ep_type == self::TOPIC_RANDOM) { $order_num = $key + 1; } else { $order_num = $value['order_num']; } $option_index = ''; if (self::UPSET_OPTION_YES == $data['is_upset_option'] && in_array($value['et_type'], [self::TOPIC_TYPE_SINGLE, self::TOPIC_TYPE_MULTIPLE])) { // 如果开启了选项打乱且题目是单选或者多选,则此处需要打乱题目选项 $exam_help = new ExamHelper(); // 打乱选项,返回值为打乱的选项(如:A,C,B,D) $option_index = $exam_help->options_shuffle($value['options']); } $val = [ 'et_type' => $value['et_type'], 'ea_id' => $ea_id, 'order_num' => intval($order_num), 'is_pass' => 0, 'score' => $value['score'], 'my_score' => 0, 'paper_type' => $data['paper_type'], //试卷使用类型(0:测评试卷,1:模拟试卷) 'ep_id' => $data['ep_id'], 'esr_id' => $esr_id, 'et_id' => $value['et_id'], 'option_index' => $option_index ]; $topic[] = $val; } if (self::UPSET_TOPIC_YES == $data['is_upset_topic']) { // 如果开启了试题打乱 // 打乱试题数组 shuffle($topic); $topic_index = 1; foreach ($topic as &$topinfo) { // 重组题目顺序 $topinfo['order_num'] = $topic_index; $topic_index++; } unset($topinfo); } // 插入试题 $this->_answer_detail_model->insert_all($topic); // 开始创建答卷试题 $this->commit(); } catch (\Exception $e) { $this->rollback(); E('_ERR_ADD_EXAM_FAILED'); return false; } // 返回答卷ID return ['ea_id' => $ea_id]; } /** * 获取考试参与人员列表 * * @author: 侯英才 * @param array $conds 查询条件参数列表 * @param array $page_option 分页参数 * @param array $order_option 排序参数 * @param string $fields 返回字段 * * @return array|bool */ public function get_mock_join_list($conds, $page_option = null, $order_option = [], $fields = '*') { try { return $this->_d->get_mock_answer_list($conds, $page_option, $order_option, $fields); } catch (\Exception $e) { E($e->getCode() . ':' . $e->getMessage()); return false; } } /** * 统计考试参与人员总数 * @author: 侯英才 * @param array $conds 查询条件参数列表 * @return array|bool */ public function count_mock_answer($conds) { try { return $this->_d->count_mock_answer($conds); } catch (\Exception $e) { E($e->getCode() . ':' . $e->getMessage()); return false; } } /** * 获取试卷记录 * * @author: 蔡建华 * @param array $params 请求参数 * @param string $uid 用户id * @param int $type 0:不分页;1:分页 * * @return array|bool */ public function test_record_list($params = [], $uid = '', $type = 0) { // 试卷id $ep_id = intval($params['ep_id']); // 试卷id为空 if (!$ep_id) { E('_EMPTY_EP_ID'); } $obj_id = 0; // 任务id if (isset($params['customtask_id']) && $params['customtask_id']) { $obj_id = intval($params['customtask_id']); } elseif (isset($params['plan_id']) && $params['plan_id']) { // 培训计划id $obj_id = intval($params['plan_id']); } // 获取我的答卷数据 $info = $this->get_answer_info($ep_id, $uid, $obj_id); // 获取用户详情(为了兼容后台管理Apicp/Answer/JoinRecord接口,用户名、头像字段改为username、avatar) $user_info = $this->getUser([$uid]); $info['username'] = $user_info[$uid]['memUsername']; $info['avatar'] = $user_info[$uid]['memFace']; // 数据分页 if ($type) { // 判断分页参数是否为空,为空赋默认值 $page = !empty($params['page']) ? intval($params['page']) : self::DEFAULT_PAGE; $limit = !empty($params['limit']) ? intval($params['limit']) : self::DEFAULT_LIMIT; // 分页 list($start, $limit) = page_limit($page, $limit); // 分页参数 $page_option = [$start, $limit]; // 排序:发布时间倒序 $order_option['created'] = 'DESC'; // 答题记录查询条件(模拟考试有初始化=0和已批阅=3两种状态,只查已批阅状态,) $condition = [ 'ep_id' => $ep_id, 'uid' => $uid, 'answer_status' => self::READ_OVER, ]; // 任务或培训ID存在 if ($obj_id) { $condition['obj_id'] = $obj_id; } $total = $this->count_by_conds($condition); // get_answer_info里面如果答卷数据为空,会抛错"尚未参加考试",所以此处列表必有数据 $list = $this->list_by_conds($condition, $page_option, $order_option); } else { // 数据不分页 // 不分页,直接取我的答卷数据返回的列表 $list = $info['my_answer_list_all']; // 总数 $total = $limit = count($list); // 页码 $page = 1; } unset($info['my_answer_list_all']); $result = [ 'page' => intval($page), 'limit' => intval($limit), 'total' => intval($total), 'list' => $this->format_testRecord($list) // 格式化模拟记录 ]; return array_merge($info, $result); } /** * 模拟试卷详情列表 * * @author: 蔡建华 * @param string $ep_id 试卷ID * @param string $uid 用户ID * @param int $obj_id 任务、培训ID * * @return array|bool */ public function get_answer_info($ep_id = '', $uid = '', $obj_id = 0) { // 答题记录查询条件(模拟考试有初始化=0和已批阅=3两种状态,只查已批阅状态,) $condition = [ 'ep_id' => $ep_id, 'uid' => $uid, 'answer_status' => self::READ_OVER, ]; // 任务或培训ID存在 if ($obj_id) { $condition['obj_id'] = $obj_id; } // 分页 $page_option = null; // 排序:发布时间倒序 $order_option['created'] = 'DESC'; // 查询字段 $fields = 'ea_id,uid,ep_id,my_score,my_time,my_is_pass,paper_info,answer_status,my_begin_time'; // 查询当前用户试卷的答题记录 $my_answer_list_all = $this->_d->list_by_conds($condition, $page_option, $order_option, $fields); // 答题记录为空:尚未参加考试 if (empty($my_answer_list_all)) { E('_ERR_MY_VISIT_NO'); } // 试卷信息 $info = unserialize($my_answer_list_all[0]['paper_info']); // 不是模拟试卷 if ($info['paper_type'] != self::SIMULATION_PAPER_TYPE) { E('_ERR_SIMULATION_PAPER_TYPE'); } // 试卷状态 $ep_status = $this->paper_status($info['exam_status'], $info['begin_time'], $info['end_time']); // 历史最高成绩 $high_score = max(array_column($my_answer_list_all, 'my_score')); // 累计模拟考试次数 $exam_times = count($my_answer_list_all); // 通过考试的答卷数据 $pass_answers = array_filter($my_answer_list_all, function ($v) { return $v['my_is_pass'] == self::PASS; }); // 模拟考试通过次数(及格次数) $pass_times = count($pass_answers); // 我的排名 $ranking = $this->get_my_rank($ep_id, $uid); return [ 'high_score' => $high_score, 'pass_times' => intval($pass_times), 'ep_status' => $ep_status, 'exam_times' => intval($exam_times), 'exam_type' => intval($info['exam_type']), 'ranking' => intval($ranking), 'my_answer_list_all' => $my_answer_list_all ]; } /** * @author: 蔡建华 * * 格式化模拟详情页面 * * @param array $data * * @return array */ public function format_testRecord($data = []) { $result = []; foreach ($data as $key => $val) { $result[$key] = [ 'ea_id' => intval($val['ea_id']), 'my_score' => $val['my_score'], 'my_time' => $val['my_time'], 'my_begin_time' => $val['my_begin_time'], 'status' => $val['answer_status'] ]; } return $result; } /** * 判断试卷状态 * * @author: 蔡建华 * @param $ea_id int 答卷ID * @param $uid string 用户ID * * @return array|bool */ public function paper_answer_status($ea_id = 0, $uid = '') { //获取答卷信息 $ea_data = $this->get_by_conds(['ea_id' => $ea_id, 'uid' => $uid]); // 答卷信息不存在 if (empty($ea_data)) { E('_ERR_MY_VISIT_NO'); } // 查询试卷信息 $ep_id = $ea_data['ep_id']; $paper = $this->paper_model->get($ep_id); // 判断试卷状态,其中包括分类状态和试卷状态 if (self::EC_CLOSE_STATES == $paper['cate_status'] || self::PAPER_STOP == $paper['exam_status']) { E('_ERR_EC_CLOSE_STATES'); } // 你已经交卷无法答题 if ($ea_data['answer_status'] >= self::READ_WAITING) { E('_ERR_SUBMIT_ANSWER'); } // 我的考试开始时间 $my_begin_time = $ea_data['my_begin_time']; // 分钟 $paper_time = to_milli_time($paper['paper_time'] * 60); $time = MILLI_TIME; // 时间到了交卷 $end_time = $my_begin_time + $paper_time; if ($time > $paper['end_time'] || $time > $end_time) { $this->submit_papers($ea_id, $uid); E('_ERR_EC_EXIT_FINISH'); } // 考试结束时间大于时间结束时间 if ($end_time > $paper['end_time']) { $left_time = $paper['end_time'] - $time; // 考试结束时间小与时间结束时间 } else { $left_time = $end_time - $time; } return [ 'ep_name' => $paper['ep_name'], 'marking_type' => $paper['marking_type'], 'exam_type' => $paper['exam_type'], 'paper_type' => $paper['paper_type'], 'left_time' => $left_time, // 返回倒计时 'my_begin_time' => $my_begin_time, 'paper_time' => $paper['paper_time'], 'end_time' => $paper['end_time'] ]; } /** * 根据条件读取数据 * * @author: 侯英才 * @param array $conds 查询条件数组 * @param array $order_option 排序数组 * @param String $fields 查询字段 * * @return array|bool */ public function get_by_conds($conds, $order_option = [], $fields = '*') { try { return $this->_d->get_by_conds($conds, $order_option, $fields); } catch (\Exception $e) { E($e->getCode() . ':' . $e->getMessage()); return false; } } /** * 自动提交试卷 * * @author: 蔡建华 * @param int $ea_id 答卷ID * @param int $uid 用户ID * @param array $award * @param int $type 交卷类型 0,自动交卷 1手动交卷 * @param array $score_list 积分策略返回值 * * @return bool */ public function submit_papers($ea_id = 0, $uid = 0, &$award = [], $type = 0, &$score_list = []) { // 判断答卷ID是否为空 if (!$ea_id) { E('_EMPTY_EA_ID'); } // 判断用户ID不能为空 if (!$uid) { E('_EMPTY_UID'); } //获取答卷信息 $ea_data = $this->get_by_conds(['ea_id' => $ea_id, 'uid' => $uid]); // 答卷信息不存在 if (empty($ea_data)) { E('_ERR_MY_VISIT_NO'); } $ep_id = $ea_data['ep_id']; $paper = $this->paper_model->get_by_conds(['ep_id' => $ep_id]); $time = MILLI_TIME; if (self::EC_CLOSE_STATES == $paper['cate_status'] || self::PAPER_STOP == $paper['exam_status']) { E('_ERR_EC_CLOSE_STATES'); } // 你已经交卷 if ($ea_data['answer_status'] > 0) { E('_ERR_REPEAT_SUBMIT_EXAM'); } // 分钟 $paper_time = to_milli_time($paper['paper_time'] * 60); // 我的考试开始时间 $my_begin_time = $ea_data['my_begin_time']; // 时间到了交卷 $end_time = $my_begin_time + $paper_time; if ($time <= $paper['end_time'] && $time <= $end_time) { $submit = 1; //提前交卷 $my_time = ($time - $my_begin_time); } else { $submit = 2; //时间到自动交卷 if ($end_time > $paper['end_time']) { $my_time = ($paper['end_time'] - $my_begin_time); } else { $my_time = ($end_time - $my_begin_time); } } $marking_type = $paper['marking_type']; $count = 0; // 交卷处理 try { // 开始事务 $this->start_trans(); // 未作答的处理成已批阅 0分 $this->_answer_detail_model->update_by_conds([ 'marking_status' => self::NO_DO_MK_STATE, 'is_status' => self::NO_DO_MK_STATE, 'ea_id' => $ea_id ], [ 'marking_status' => self::DO_MK_STATE, 'my_score' => 0, 'is_pass' => self::NO_MY_PASS ]); $this->update_paper_join_count($paper, $marking_type, $ep_id, $uid); // 测评试卷手动阅卷 if (self::MANUAL_MARKING_TYPE == $marking_type && self::EVALUATION_PAPER_TYPE == $paper['paper_type']) { // 查询已经作答且未批阅 $count = $this->_answer_detail_model->count_by_conds([ 'marking_status' => self::NO_DO_MK_STATE, 'is_status' => self::DO_STATE, 'ea_id' => $ea_id, 'et_type' => [self::TOPIC_TYPE_QUESTION, self::TOPIC_TYPE_VOICE] ]); } // 手动阅卷有主观题 if ($count > 0) { // 手动阅卷 $this->update( ['ea_id' => $ea_id], ['my_time' => $my_time, 'my_end_time' => $my_begin_time + $my_time, 'answer_status' => self::READ_WAITING] ); // 发送消息给阅卷人 $result_status = self::SEND_MSG_FOR_MARKING_USER; } else { // 算分函数 $my_score = $this->_answer_detail_model->get_score(['ea_id' => $ea_id, 'marking_status' => 1]); // 判断是否通过 if ($paper['pass_score'] > $my_score) { $my_is_pass = 0; } else { $my_is_pass = 1; } $this->update( ['ea_id' => $ea_id], [ 'my_is_pass' => $my_is_pass, // 是否通过 'my_time' => $my_time, // 用时 'my_end_time' => $my_begin_time + $my_time, //交卷时间 'my_score' => $my_score, // 分数 'answer_status' => self::READ_OVER, // 已阅卷 'marking_time' => MILLI_TIME // 阅卷时间 ] ); // 积分策略业务ID=应用目录_数据ID $businessid = sprintf('%s_%s', APP_DIR, $ep_id); // 调用积分策略 $score_list = $this->get_score_list($uid, $paper, $my_score, $my_is_pass, $businessid); if (self::MANUAL_MARKING_TYPE == $marking_type && self::EVALUATION_PAPER_TYPE == $paper['paper_type']) { // 考试成绩已出,发送消息 $result_status = self::SEND_MSG_FOR_JOIN_EXAM_USER; } else { // 不发送消息 $result_status = self::NOT_NEED_SEND_MSG; } } $this->commit(); } catch (\Exception $e) { $this->rollback(); E('_ERR_SUBMIT_FAIL'); return false; } //添加积分勋章接口 $this->paper_statistics($paper, $uid); // 添加积分勋章接口 $this->medal($ep_id, $uid, $award); // 手动阅卷发送阅卷信息 if (self::SEND_MSG_FOR_MARKING_USER == $result_status) { $this->send_cms_answer($ea_id, AnswerService::MARKING_USER_MSG); } elseif (self::SEND_MSG_FOR_JOIN_EXAM_USER == $result_status) { // 手动阅卷系统阅卷成绩出来 $this->send_cms_answer($ea_id, AnswerService::MARKING_RESULT_MSG); } // 时间到自动交卷 if (!$type && self::MANUAL_MARKING_TYPE == $submit) { E('_ERR_AUTO_SUBMIT_TIME'); } return true; } /** * 统计参加考试与未参加考试的人 * * @param array $paper 试卷信息数组 * @param int $marking_type 试卷类型 * @param int $ep_id 试卷ID * * @param string $uid 考生uid */ public function update_paper_join_count($paper = [], $marking_type = 0, $ep_id = 0, $uid = '') { // 未参与人员 $unjoin_count = $paper['unjoin_count'] - 1; if ($unjoin_count < 0) { $unjoin_count = 0; } // 已参与人员 $join_count = $paper['join_count'] + 1; if ($marking_type == self::MANUAL_MARKING_TYPE) { // 如果是测评试卷,参与人加1 $this->paper_model->update_by_conds(['ep_id' => $ep_id], ['join_count' => $join_count, 'unjoin_count' => $unjoin_count]); } else { // 判断模拟试卷是否已有交卷记录 $submit_count = $this->get_by_conds(['ep_id' => $ep_id, 'uid' => $uid, 'answer_status>?' => self::READ_WAITING]); if (!$submit_count) { $this->paper_model->update_by_conds(['ep_id' => $ep_id], ['join_count' => $join_count, 'unjoin_count' => $unjoin_count]); } } } /** * 根据积分策略获取积分 * * @param string $uid 答卷人ID * @param array $paper 试卷信息 * @param int $my_score 我的得分 * @param int $my_is_pass 是否通过考试(0=未通过,1=通过) * @param string $businessid 积分策略业务ID * * @return array|mixed */ public function get_score_list($uid = '', $paper = [], $my_score = 0, $my_is_pass = 0, $businessid = '') { $score_list = []; if (self::INTEGRAL_ACTION_TYPE_NO == $paper['integral_action_type'] && self::CREDIT_ACTION_TYPE_FALSE == $paper['credit_action_type']) { // 如果不启用策略 return $score_list; } // 初始化积分模型 $integral = new Integral(); $count = new CountModel(); // 此处查询通过次数 $num_data = $count->get_by_conds(['uid' => $uid, 'paper_type' => $paper['paper_type']]); // 组织策略规则 $triggerTypes = [ [ 'triggerKey' => 'exam_score', // 考试分数 'value' => intval($my_score), 'remark' => '考试分数' ], [ 'triggerKey' => 'exam_score_range', //考试分数区间 'value' => intval($my_score), 'remark' => '考试分数区间' ] ]; if (!empty($num_data) && !empty($my_is_pass)) { // 如果是模拟试卷,先查一下是否有已通过的记录 if (self::SIMULATION_PAPER_TYPE == $paper['paper_type']) { $answer_serv = new AnswerModel(); $pass_total = $answer_serv->count_by_conds([ 'uid' => $uid, 'ep_id' => $paper['ep_id'], 'my_is_pass' => 1 ]); // 如果不存在答题通过记录,则加次数 if ($pass_total == 0) { $u_conds = [ 'uid' => $uid, 'paper_type' => $paper['paper_type'] ]; $pass_num = $num_data['num'] + 1; $count->update_by_conds($u_conds, ['num' => $pass_num]); $triggerTypes[] = [ 'triggerKey' => 'pass_num', // 通过试卷数 'value' => intval($pass_num), 'remark' => '通过试卷数' ]; } } else { // 测评试卷 // 如果记录存在并且通过考试,则按条件进行数据更新 $u_conds = [ 'uid' => $uid, 'paper_type' => $paper['paper_type'] ]; $pass_num = $num_data['num'] + 1; $count->update_by_conds($u_conds, ['num' => $pass_num]); $triggerTypes[] = [ 'triggerKey' => 'pass_num', // 通过试卷数 'value' => intval($pass_num), 'remark' => '通过试卷数' ]; } } elseif (empty($num_data) && !empty($my_is_pass)) { // 如果记录不存在并且通过考试,则插入记录 $pass_num = 1; $i_data = [ 'uid' => $uid, 'paper_type' => $paper['paper_type'], 'num' => $pass_num ]; $count->insert($i_data); $triggerTypes[] = [ 'triggerKey' => 'pass_num', // 通过试卷数 'value' => intval($pass_num), 'remark' => '通过试卷数' ]; } // 如果开始通过 if ($my_is_pass) { $triggerTypes[] = [ 'triggerKey' => 'pass', // 通过 'value' => 1, 'remark' => '通过考试' ]; } // 是否触发策略(默认不触发) $is_score_flag = false; // 初始化触发策略参数 $triggers = []; // 开启积分策略 if (in_array($paper['integral_action_type'], [self::INTEGRAL_ACTION_TYPE_DEFAULT, self::INTEGRAL_ACTION_TYPE_MY])) { $is_score_flag = true; $triggers[] = [ 'miType' => 'mi_type0', 'businessStrategyId' => $paper['integral_strategyid'] ? $paper['integral_strategyid'] : '', ]; } // 开启学分策略 if (in_array($paper['credit_action_type'], [self::CREDIT_ACTION_TYPE_DEFAULT, self::CREDIT_ACTION_TYPE_CUSTOMIZE])) { $is_score_flag = true; $triggers[] = [ 'miType' => 'mi_type1', 'businessStrategyId' => $paper['credit_strategyid'] ? $paper['credit_strategyid'] : '', ]; } // 触发策略 if ($is_score_flag) { // 默认为测评试卷 $businessAct = 'official_exam'; // 如果是模拟试卷 if (self::SIMULATION_PAPER_TYPE == $paper['paper_type']) { $businessAct = 'mock_exam'; } foreach ($triggers as $k => $trigger) { $triggers[$k]['triggerTypes'] = $triggerTypes; } // 组装积分策略请求参数 $integral_param = [ 'memUid' => $uid, 'businessId' => $businessid, 'businessKey' => 'exam_center', 'businessAct' => $businessAct, 'triggers' => $triggers, ]; $score_list = $integral->changeScore($integral_param); } return $score_list; } /** * 更新参与未参与人数 * * @author: 蔡建华 * @param $data array 试题 * * @param $uid string 用户ID */ public function paper_statistics($data = [], $uid = '') { $count = $this->_d->count_by_conds(['ep_id' => $data['ep_id'], 'uid' => $uid, 'my_time>?' => 0]); if (!$count) { if (!$data['unjoin_count']) { $data['unjoin_count'] = 1; } $this->paper_model->update_by_paper( ['ep_id' => $data['ep_id']], ['join_count' => $data['join_count'] + 1, 'unjoin_count' => $data['unjoin_count'] - 1] ); } } /** * 考试激励处理 * * @author: 蔡建华 * @param int $ep_id 试卷ID * @param string $uid 用户ID * @param array &$award 返回数据 * * @return bool */ public function medal($ep_id, $uid = '', &$award = []) { // 获取用户信息 $userServ = &User::instance(); $user = $userServ->getByUid($uid); // 获取用户权限 $rightServ = new RightService(); $right = $rightServ->get_by_right($user); $data['right'] = $right; $data['er_type'] = self::RIGHT_MEDAL; $medal = $this->_medal_model->fetch_all_medal($data); // 查询出相关激励 if (empty($medal)) { return true; } // 获取符合条件的激励IDS $em_ids = array_column($medal, 'em_id'); // 查询激励关系列表 $list = $this->_medal_relation_model->list_by_conds(['em_id' => $em_ids]); // 如果存在符合条件激励 if (empty($list)) { return true; } // 获取激励列表IDS $em_id_arr = array_column($list, 'em_id'); // 如果查询出激励IDS if (empty($em_id_arr)) { return true; } // 初始化勋章 $integral = new Integral(); // 获取勋章列表 $integral_list = $integral->listMedal(); // 获取激励列表 $integral_key_list = array_combine_by_key($integral_list, 'im_id'); // 获取激励列表 $result = $this->_medal_model->list_by_conds(['em_id' => $em_id_arr]); // 实例化积分勋章 $integralUtil = &Integral::instance(); // 遍历激励列表 foreach ($result as $val) { // 获取当前用户是否已经领取过当期激励 $count = $this->_medal_record_model->count_by_conds(['uid' => $uid, 'em_id' => $val['em_id']]); // 如果已领取积分或者勋章 if ($count) { continue; } // 查询勋章对应关系 $relate_total = $this->_medal_relation_model->count_by_conds(['ep_id' => $ep_id, 'em_id' => $val['em_id']]); // 如果没有对应关系 if (!$relate_total) { continue; } // 查出对应ep_list $em_list = $this->_medal_relation_model->list_by_conds(['em_id' => $val['em_id']]); $ep_ids = array_column($em_list, 'ep_id'); // 答题列表 $score_list = $this->_d->list_by_conds([ 'ep_id' => $ep_ids, 'uid' => $uid, 'my_score >= ?' => $val['em_score'] ]); // 获取分数的epids $score_ep_ids = array_unique(array_column($score_list, 'ep_id')); // 判断满足条件的次数 if (count($score_ep_ids) >= $val['em_number']) { // 获取勋章 if (self::EC_MEDAL_TYPE_MEDAL == $val['em_type']) { $integralUtil->endowMedal($val['im_id'], $uid, $user['memUsername']); $params = [ 'name' => $integral_key_list[$val['im_id']]['name'], 'url' => '', 'uids' => [$uid], 'power_type' => self::ENDOW_END, 'title' => $val['title'] ]; $this->send_msg($params, self::ENDOW_END); // 激励信息 $award[] = [ 'award_id' => intval($val['em_id']), // 激励ID 'award_action' => strval($val['title']), // 激励行为 'description' => strval($val['em_desc']), // 描述 'award_type' => intval($val['em_type']), // 激励类型(1=勋章;2=积分) 'medals' => [ 'im_id' => intval($val['im_id']), // 勋章ID 'icon' => strval($integral_key_list[$val['im_id']]['icon']), // 勋章图标URL或者前端路径 'icon_type' => intval($integral_key_list[$val['im_id']]['icon_type']), // 勋章图标来源(1=用户上传;2=系统预设) 'name' => strval($integral_key_list[$val['im_id']]['name']), // 勋章名称 'desc' => strval($integral_key_list[$val['im_id']]['desc']), // 勋章描述 ], 'integral' => intval($val['em_integral']), // 积分 ]; // 满足次数加入记录 $this->_medal_record_model->insert([ 'uid' => $uid, 'em_id' => $val['em_id'] ]); } } } return true; } /** * 发送考试消息 * * @param int $ea_id * @param int $type */ public function send_cms_answer($ea_id = 0, $type = 0) { $ea_data = $this->get_by_conds(['ea_id' => $ea_id]); $ep_id = $ea_data['ep_id']; $paper = $this->paper_model->get_by_conds(['ep_id' => $ep_id]); switch ($type) { case self::MARKING_RESULT_MSG: // 获取阅卷人信息 $user = User::instance()->getByUid($ea_data['marking_uid']); $params = [ 'name' => $paper['ep_name'], 'is_cover_open' => $paper['is_cover_open'], 'img_id' => $paper['cover_id'], 'my_end_time' => $ea_data['marking_time'], 'user_name' => $ea_data['marking_uid'] ? $user['memUsername'] : '系统阅卷', 'uids' => ['memID' => $ea_data['uid']], 'ea_id' => $ea_id, 'id' => $ep_id, 'obj_id' => $ea_data['obj_id'] ]; $this->send_msg($params, self::MARKING_RESULT_MSG); break; case self::MARKING_USER_MSG: if (self::EVALUATION_PAPER_TYPE == $paper['paper_type'] && self::MANUAL_MARKING_TYPE == $paper['marking_type']) { // 获取权限 $right = $this->_d_right->list_by_conds([ 'epc_id' => $ep_id, 'er_type' => self::RIGHT_MARKING ]); $uids = array_column($right, 'uid'); // 获取用户信息 $user = User::instance()->getByUid($ea_data['uid']); $params = [ 'name' => $paper['ep_name'], 'is_cover_open' => $paper['is_cover_open'], 'img_id' => $paper['cover_id'], 'user_name' => $paper['is_open_anonymous_marking'] == self::OPEN_ANONYMOUS_MARKING ? '匿名' : $user['memUsername'], 'user_time' => $ea_data['my_end_time'], 'exam_type' => $paper['exam_type'], 'uids' => $uids, 'ea_id' => $ea_id, 'id' => $ep_id ]; $this->send_msg($params, self::MARKING_USER_MSG); } break; } } /** * 判断试卷状态 * * @author: 蔡建华 * @param $ea_id int 答卷ID * @param $uid string 用户ID * * @return array|bool */ public function paper_answer_status_new($ea_id = 0, $uid = '') { //获取答卷信息 $ea_data = $this->get_by_conds(['ea_id' => $ea_id, 'uid' => $uid]); // 答卷信息不存在 if (empty($ea_data)) { E('_ERR_MY_VISIT_NO'); } // 查询试卷信息 $ep_id = $ea_data['ep_id']; $paper = $this->paper_model->get($ep_id); // 判断试卷状态,其中包括分类状态和试卷状态 if (self::EC_CLOSE_STATES == $paper['cate_status'] || self::PAPER_STOP == $paper['exam_status']) { E('_ERR_EC_CLOSE_STATES'); } // 你已经交卷无法答题 if ($ea_data['answer_status'] >= self::READ_WAITING) { E('_ERR_SUBMIT_ANSWER'); } // 我的考试开始时间 $my_begin_time = $ea_data['my_begin_time']; // 分钟 $paper_time = to_milli_time($paper['paper_time'] * 60); $time = MILLI_TIME; // 时间到了交卷 $end_time = $my_begin_time + $paper_time; if ($time > $paper['end_time'] || $time > $end_time) { E('_ERR_EC_EXIT_FINISH'); } // 考试结束时间大于时间结束时间 if ($end_time > $paper['end_time']) { $left_time = $paper['end_time'] - $time; // 考试结束时间小与时间结束时间 } else { $left_time = $end_time - $time; } return [ 'ep_name' => $paper['ep_name'], 'exam_type' => $paper['exam_type'], 'marking_type' => $paper['marking_type'], 'paper_type' => $paper['paper_type'], // 返回倒计时 'left_time' => $left_time, 'my_begin_time' => $my_begin_time, 'paper_time' => $paper['paper_time'], 'end_time' => $paper['end_time'] ]; } /** * 自动提交试卷 * * @author: 何岳龙 * @param int $ea_id 答卷ID * @param int $uid 用户ID * @param array $paper 试卷详情 * * @return bool */ public function stop_submit_papers($ea_id = 0, $uid = 0, $paper = []) { // 判断答卷ID是否为空 if (!$ea_id) { return false; } // 判断用户ID不能为空 if (!$uid) { return false; } //获取答卷信息 $ea_data = $this->get_by_conds(['ea_id' => $ea_id, 'uid' => $uid]); // 答卷信息不存在 if (empty($ea_data)) { return false; } $ep_id = $ea_data['ep_id']; $time = MILLI_TIME; // 你已经交卷 if (PaperService::READ_OVER == $ea_data['answer_status']) { return false; } // 分钟 $paper_time = to_milli_time($paper['paper_time'] * 60); // 我的考试开始时间 $my_begin_time = $ea_data['my_begin_time']; // 时间到了交卷 $end_time = $my_begin_time + $paper_time; if ($time <= $paper['end_time'] && $time <= $end_time) { // 提前交卷 $my_time = ($time - $my_begin_time); } else { // 时间到自动交卷 if ($end_time > $paper['end_time']) { $my_time = ($paper['end_time'] - $my_begin_time); } else { $my_time = ($end_time - $my_begin_time); } } $marking_type = $paper['marking_type']; // 交卷处理 try { // 开始事务 $this->start_trans(); // 未作答的处理成已批阅 0分 $this->_answer_detail_model->update_by_conds([ 'marking_status' => self::NO_DO_MK_STATE, 'is_status' => self::DO_PASS_STATE, 'ea_id' => $ea_id ], [ 'marking_status' => self::DO_MK_STATE, 'my_score' => 0 ]); // 更新未读人员数已读人员数 $this->update_paper_join_count($paper, $marking_type, $ep_id, $uid); $my_is_pass = 0; // 未通过 $my_score = 0; // 我的得分 $this->update( ['ea_id' => $ea_id], [ 'my_is_pass' => $my_is_pass, // 是否通过 'my_time' => $my_time, // 用时 'my_end_time' => $my_begin_time + $my_time, //交卷时间 'my_score' => $my_score, // 分数 'answer_status' => self::READ_OVER, // 已阅卷 'marking_time' => MILLI_TIME, // 阅卷时间 ] ); // 积分策略业务ID=应用目录_数据ID $businessid = sprintf('%s_%s', APP_DIR, $paper['ep_id']); // 调用积分策略 $this->get_score_list($uid, $paper, $my_score, $my_is_pass, $businessid); $this->commit(); } catch (\Exception $e) { $this->rollback(); return false; } // 更新参与未参与人数 $this->paper_statistics($paper, $uid); // 添加积分勋章接口(此处因为都是0分,所以不会触发发勋章) // $this->medal($ep_id, $uid, $award); return true; } /** * 【微信端】 提交题目试卷验证 * * @author: 何岳龙 * @param array $params * @param string $uid * * @return bool */ public function end_time_validation($params = [], $uid = '') { // 获取答卷详情 $answer_info = $this->_answer_detail_model->get($params['ead_id']); // 获取得分详情 $info = $this->_d->get($answer_info['ea_id']); // 获取试卷详情 $paper_info = $this->paper_model->get($info['ep_id']); // 如果考试考生考试开始时间+考试时长大于结束时间 if (($info['my_begin_time'] + (to_milli_time($paper_info['paper_time'] * 60))) > $paper_info['end_time']) { // 如果当前时间大于或者等于结束时间 if ($paper_info['end_time'] <= MILLI_TIME) { // 交卷 $this->submit_papers($answer_info['ea_id'], $uid); return false; } } else { // 如果当前时间大于开始的结束时间 if (MILLI_TIME >= ($info['my_begin_time'] + (to_milli_time($paper_info['paper_time'] * 60)))) { // 交卷 $this->submit_papers($answer_info['ea_id'], $uid); return false; } } return true; } /** * 批阅详情函数 * * 蔡建华 * @param int $ep_id 试卷ID * @param string $uid 阅卷人ID * * @return bool|array */ public function marking_detail($ep_id, $uid = '') { $paper = $this->paper_model->get($ep_id); if (empty($paper)) { E('_EMPTY_EXAM_DELETED'); } // 判断试卷类型 if ($paper['paper_type'] != self::EVALUATION_PAPER_TYPE) { E('_ERR_EVALUATION_PAPER_TYPE'); } // 判断用户是否有权进行操作 $count = $this->_right_model->count_by_conds([ 'epc_id' => $ep_id, 'er_type' => self::RIGHT_MARKING, 'uid' => $uid ]); if (!$count) { E('_ERR_MARKING_NO_QUIT'); } // 当前试卷的批阅题数 if (self::TOPIC_CUSTOMER == $paper['ep_type']) { // 自主选题,批阅题数从快照表中获取 $marking_topics = $this->_snapshot_model->count_by_conds([ 'ep_id' => $ep_id, 'et_type' => [self::TOPIC_TYPE_QUESTION, self::TOPIC_TYPE_VOICE], ]); } else { // 非自主选题,批阅题数从出题规则中获取 $paper_rule = unserialize($paper['rule']); $marking_topics = $paper_rule['question_count'] + $paper_rule['voice_count']; } // 待批阅人数 $marking_waiting_users = $this->_d->count_by_conds([ 'ep_id' => $ep_id, 'answer_status' => self::READ_WAITING, ]); // 是否是首次批阅 $is_first = $this->_d->count_by_conds([ 'ep_id' => $ep_id, 'marking_uid' => $uid, ]); // 组装格式化数据 $arr = [ 'ep_id' => $paper['ep_id'], 'ep_name' => $paper['ep_name'], // 试卷名称 'total_score' => $paper['total_score'], // 考试总分 'pass_score' => $paper['pass_score'], // 及格分数 'topic_count' => intval($paper['topic_count']), // 总题数 'paper_time' => $paper['paper_time'], // 考试时长 'begin_time' => $paper['begin_time'], // 开始时间 'end_time' => $paper['end_time'], // 结束时间 'intro' => $paper['intro'], // 考试说明 'marking_topics' => intval($marking_topics), // 批阅题数 'marking_waiting_users' => intval($marking_waiting_users), // 待批阅人数 'check_status' => !$is_first ? self::FIRST_MARKING_PAPER : self::SECOND_MARKING_PAPER, // 批阅状态(1:首页批阅,2:再次批阅) 'exam_type' => intval($paper['exam_type']), ]; // 封面图片 if (self::IS_COVER_PIC_OPEN == $paper['is_cover_open']) { $arr['cover_url'] = $this->format_cover($paper['cover_id']); } else { $arr['cover_url'] = ''; } return $arr; } /** * 阅卷交卷接口 * * 蔡建华 * @param array $params 参数 * @param string $uid 用户ID * * @return bool */ public function marking_submit($params = [], $uid = '') { $ea_id = $params['ea_id']; // 答卷ID不能为空 if (!$ea_id) { E('_EMPTY_EA_ID'); } // 查询答卷记录 $data = $this->_d->get($ea_id); // 考试记录是否存在 if (empty($data)) { E('_EMPTY_MARKING_INFO'); } $ep_id = $data['ep_id']; $paper = $this->paper_model->get($ep_id); if (empty($paper)) { E('_EMPTY_EXAM_DELETED'); } // 判断试卷类型 if ($paper['paper_type'] != self::EVALUATION_PAPER_TYPE) { E('_ERR_EVALUATION_PAPER_TYPE'); } // 不是手动阅卷 if (self::AUTO_MARKING_TYPE == $paper['marking_type']) { E('_ERR_MARKING_PAPER_TYPE'); } // 阅卷是否在阅卷 if (self::READ_OVER == $data['answer_status']) { E('_ERR_MARKING_FINISH'); } // 判断阅卷人不相同 if ($data['marking_uid'] != $uid) { E('_ERR_MARKING_NOT_SOME'); } // 未作答的处理成已批阅 0分 $this->_answer_detail_model->update_by_conds([ 'marking_status' => self::NO_DO_MK_STATE, 'is_status' => self::NO_DO_MK_STATE, "ea_id" => $ea_id ], [ 'marking_status' => self::DO_MK_STATE, 'my_score' => 0 ]); // 查询没有批阅的状态 $count = $this->_answer_detail_model->count_by_conds([ 'marking_status' => self::NO_DO_MK_STATE, 'ea_id' => $ea_id ]); // 是否有尚未批阅的题 if ($count) { E('_ERR_CAN_NOT_FAILED'); } // 计算总分数 $my_score = $this->_answer_detail_model->get_score([ 'ea_id' => $ea_id, 'marking_status' => self::DO_MK_STATE ]); try { // 开始事务 $this->start_trans(); // 判断是否通过 if ($paper['pass_score'] > $my_score) { // 未通过 $my_is_pass = 0; } else { // 通过 $my_is_pass = 1; } // 积分策略业务ID=应用目录_数据ID $businessid = sprintf('%s_%s', APP_DIR, $ep_id); // 调用积分策略( 此处uid必须传答卷人ID) $this->get_score_list($data['uid'], $paper, $my_score, $my_is_pass, $businessid); // 阅卷交卷算分 $this->_d->update_by_conds(['ea_id' => $ea_id], [ 'my_score' => $my_score, 'my_is_pass' => $my_is_pass, 'answer_status' => self::READ_OVER, 'marking_time' => MILLI_TIME ]); $this->commit(); } catch (\Exception $e) { $this->rollback(); return false; } // 考试激励规则调用 $this->paper_statistics($paper, $data['uid']); $award = []; // 添加积分勋章接口 $this->medal($paper['ep_id'], $data['uid'], $award); return true; } /** * 通过试卷IDS查询对应试卷已参与人员统计列表 * * @param array $ep_ids 试卷IDS * * @return array */ public function list_by_total($ep_ids = []) { // 如果试卷IDS为空 if (empty($ep_ids)) { return []; } // 获取列表 $list = $this->_d->list_by_total($ep_ids); return $list; } /** * 执行自定义查询SQL语句(安装应用回调时用) * @author 侯英才 * @param string $sql 执行的SQL语句 * @return mixed */ public function query($sql) { return $this->_d->query($sql); } /** * 执行自定义非查询SQL语句(安装应用回调时用) * * @author 侯英才 * @param string $sql 执行的SQL语句 * * @return mixed */ public function execute($sql) { return $this->_d->execute($sql); } /** * 组装查询条件 * * @param $paper array 试卷信息 * @param $params array 传入的参数 * * @return array 返回组装完成的条件数组 */ public function get_conditions($paper, $params) { // 查询条件初始化 $conditions = [ 'ep_id' => $paper['ep_id'], 'my_time > ?' => 0 ]; // 部门、岗位、角色的用户id交集 $djr_uids = $this->get_dp_job_role_uids($params, $paper['ep_id']); if (!empty($djr_uids)) { $conditions['uid'] = $djr_uids; } return $conditions; } /** * 根据部门、岗位、角色、员工名称获取用户的id集合 * * @param array $params * + dpIds -部门ID数组 * + memJob -岗位ID * + memRole -角色ID * + memUsername -员工名称 * @param int $ep_id 试卷ID * * @return array */ public function get_dp_job_role_uids($params, $ep_id) { // 部门、岗位、角色的用户id交集 $djr_uids = []; $user = User::instance(); // 【部门】 if (isset($params['dpIds']) && !empty($params['dpIds']) && is_array($params['dpIds'])) { $params_dpids = $params['dpIds']; $dpServ = &Department::instance(); // 取子级部门ID $child_ids = $dpServ->list_childrens_by_cdid($params_dpids); // 合并部门ID $dp_ids = array_merge($params_dpids, array_values($child_ids)); $dp_conds = ['dpIdList' => $dp_ids]; $dp_users = $user->listAll($dp_conds); if (!empty($dp_users)) { // 选择部门下的员工id集合 $d_uids = array_column($dp_users, 'memUid'); } else { $d_uids = [0]; } // 组装查询条件 $dp_uids = $this->get_uids($ep_id, $d_uids); if (!empty($djr_uids)) { $djr_uids = array_intersect($djr_uids, $dp_uids); if (empty($djr_uids)) { // 空查询所有 为了避免查询所有传入0 $djr_uids = [0]; } } else { $djr_uids = $dp_uids; } } // 【岗位】 if (isset($params['memJob']) && $params['memJob']) { $job_ids = [$params['memJob']]; $job_conds = [ 'jobIdList' => $job_ids ]; // 获取岗位的员工列表 $job_users = $user->listAll($job_conds); if (!empty($job_users)) { // 选择岗位下的员工id集合 $j_uids = array_column($job_users, 'memUid'); } else { $j_uids = [0]; } // 组装查询条件 $job_uids = $this->get_uids($ep_id, $j_uids); if (!empty($djr_uids)) { $djr_uids = array_intersect($djr_uids, $job_uids); if (empty($djr_uids)) { // 空查询所有 为了避免查询所有传入0 $djr_uids = [0]; } } else { $djr_uids = $job_uids; } } // 【角色】 if (isset($params['memRole']) && $params['memRole']) { $role_ids = [$params['memRole']]; // 查询条件:角色id数组 $role_conds = ['roleIdList' => $role_ids]; // 获取角色的员工列表 $role_users = $user->listAll($role_conds); if (!empty($role_users)) { // 角色的员工id集合 $r_uids = array_column($role_users, 'memUid'); } else { $r_uids = [0]; } // 组装查询条件 $role_uids = $this->get_uids($ep_id, $r_uids); if (!empty($djr_uids)) { $djr_uids = array_intersect($djr_uids, $role_uids); if (empty($djr_uids)) { // 空查询所有 为了避免查询所有传入0 $djr_uids = [0]; } } else { $djr_uids = $role_uids; } } // 【标签】 if (isset($params['memTag']) && $params['memTag']) { $tag_ids = [$params['memTag']]; // 查询条件:标签id数组 $tag_conds = ['tagIdList' => $tag_ids]; // 获取标签的员工列表 $tag_users = $user->listAll($tag_conds); if (!empty($tag_users)) { // 标签的员工id集合 $r_uids = array_column($tag_users, 'memUid'); } else { $r_uids = [0]; } // 组装查询条件 $tag_uids = $this->get_uids($ep_id, $r_uids); if (!empty($djr_uids)) { $djr_uids = array_intersect($djr_uids, $tag_uids); if (empty($djr_uids)) { // 空查询所有 为了避免查询所有传入0 $djr_uids = [0]; } } else { $djr_uids = $tag_uids; } } // 【员工名称】 if (isset($params['memUsername']) && $params['memUsername']) { $user_conds = ['memUsername' => $params['memUsername']]; // 查询 $sel_users = $user->listAll($user_conds); // 检索员工存在 if (!empty($sel_users)) { // 员工id $memUserids = array_column($sel_users, 'memUid'); } else { // 空查询所有 为了避免查询所有传入0 $memUserids = [0]; } if (!empty($djr_uids)) { $djr_uids = array_intersect($djr_uids, $memUserids); if (empty($djr_uids)) { // 空查询所有 为了避免查询所有传入0 $djr_uids = [0]; } } else { $djr_uids = $memUserids; } } return $djr_uids; } /** * 组装查询条件-部门、岗位或角色下答卷的员工id集合 * * @param $ep_id string 试卷id * @param $jr_uids array 岗位或角色下的员工id * * @return mixed 员工id */ public function get_uids($ep_id, $jr_uids) { // 返回结果初始化 $res = []; // 答卷的员工id集合 $an_conds = [ 'ep_id' => $ep_id, 'my_time > ?' => 0 ]; $joins = $this->list_by_conds($an_conds); if (!empty($joins)) { // 答卷的员工id集合 $join_uids = array_unique(array_column($joins, 'uid')); // 选择岗位/角色下的答卷的员工id(取交集) $res_uids = array_intersect($jr_uids, $join_uids); if (!empty($res_uids)) { $res = $res_uids; } else { $res = [0]; } } return $res; } /** * 根据键值查找数组 * * @param array $arr 待查找数组 * @param string $key 键 * @param string $val 值 * * @return array|mixed */ public function seekarr($arr = [], $key, $val) { // 初始化返回数组 $data = []; foreach ($arr as $v) { $str = json_encode($v); preg_match_all("/\{[^\{]*\"" . $key . "\"\:\"" . $val . "\"[^\}]*\}/", $str, $m); // 键值匹配 if ($m && $m[0]) { foreach ($m[0] as $va) { $res = json_decode($va, true); array_push($data, $res); } } } return $data; } /** * * * @param $ep_id int 试卷ID * @param $paper array 试卷信息 * @param $params array 参数 * * @return int */ public function get_un_total($ep_id, $paper, $params) { $conds = [ 'epc_id' => $ep_id, 'er_type' => AnswerService::RIGHT_PAPER ]; // 获取未参与考试人员列表 $unjoin_data = $this->get_unjoin_data($conds, $ep_id, $paper['is_all']); // 未参加人的列表 $unjoin_list = $unjoin_data['unjoin_list']; // 【部门】 if (isset($params['dpIds']) && !empty($params['dpIds']) && is_array($params['dpIds'])) { $params_dpids = $params['dpIds']; $dpServ = &Department::instance(); // 取子级部门ID $dp_ids = $dpServ->list_childrens_by_cdid($params_dpids, true); sort($dp_ids); $conditions['dpIdList'] = $dp_ids; } // 【岗位】 if (isset($params['memJob']) && $params['memJob']) { $conditions['jobIdList'] = [$params['memJob']]; } // 【角色】 if (isset($params['memRole']) && $params['memRole']) { $conditions['roleIdList'] = [$params['memRole']]; } // 【标签】 if (isset($params['memTag']) && $params['memTag']) { $conditions['tagIdList'] = [$params['memTag']]; } // 【员工名称】 if (isset($params['memUsername']) && $params['memUsername']) { $conditions['memUsername'] = $params['memUsername']; } // 如果存在查询条件 if (!empty($conditions)) { $user_select_list = User::instance()->listAllBasic($conditions); if (!empty($user_select_list)) { $unjoin_list = array_intersect($unjoin_list, array_column($user_select_list, 'memUid')); } else { $unjoin_list = []; } } $total = 0; if (!empty($unjoin_list)) { sort($unjoin_list); // 实例化 $member = new Member(Service::instance()); $member_conds = [ 'memUids' => $unjoin_list, ]; // 获取未读人员列表 $list = $member->listAll($member_conds); // 总人数 $total = $list['total']; } return $total; } /** * 获取考试未参与考试人员列表及人数 * * @author: 侯英才 * @param array $conds 查询权限条件 * @param int $ep_id 试卷ID * @param int $is_all 是否是全公司 * * @return array -返回参数 * + unjoin_list -未参与人列表 * + join_count -已参与人总数 */ public function get_unjoin_data($conds, $ep_id, $is_all = 0) { $right_serv = new RightService(); // 参与考试的权限范围 if ($is_all != self::AUTH_ALL) { $rights = $right_serv->list_by_conds($conds); // 格式化权限范围 $right_view = $right_serv->format_db_data($rights); } $right_view['is_all'] = $is_all; // 获取要参加考试的全部人员 $all_join = $right_serv->list_uids_by_right($right_view); // 已经参加了考试的人员 $join = $this->_d->list_by_conds(['ep_id' => $ep_id, 'my_time > ?' => 0]); $join = array_column($join, 'uid'); $join = array_unique($join); // 初始未参加考试人员 $unjoin = []; // 遍历全部邀请人员 foreach ($all_join as $key => $uid) { // 如果不在已参加的人员中 if (!in_array($uid, $join) && !empty($uid)) { $unjoin[] = $uid; } } // 已参与总人数 $join_count = count($join); return [ 'unjoin_list' => $unjoin, // 未参与列表 'join_list' => $join, 'join_count' => (int)$join_count, // 已参与人数 ]; } /** * 组装查询条件 * * @param $paper array 试卷信息 * @param $params array 传入的参数 * * @return array 返回组装完成的条件数组 */ public function get_unjoin_conditions($paper, $params) { // 查询条件初始化 $conditions['ep_id'] = $paper['ep_id']; // 部门、岗位、角色的用户id交集 $djr_uids = $this->get_dp_job_role_uids($params, $paper['ep_id']); if (!empty($djr_uids)) { $conditions['uid'] = $djr_uids; } return $conditions; } /** * 交卷-全部试题 * @param array $params 参数 * + int $ea_id 答卷id * + int $uid 用户id * + array $qa_list 答题列表 * + Int $data_type 考试类型(1:常规试卷,2:任务类,3:线下培训) * + Int $obj_id 任务、培训ID * @param array $award 激励返回 * @param array $answer_info 答卷数据(answer表详情) * * @return mixed */ public function submit_all($params = [], &$award = [], $answer_info = []) { // 答卷信息 $ea_id = $params['ea_id']; // 试卷id $ep_id = $answer_info['ep_id']; // 试卷信息 $paper = $this->paper_model->get($ep_id); // 答卷信息不存在 if (empty($paper)) { E('_EMPTY_PAPER_DATA'); } // 试卷为禁止状态 if (self::EC_CLOSE_STATES == $paper['cate_status']) { E('_ERR_EC_CLOSE_STATES'); } // 已经交卷 if ($answer_info['answer_status'] > 0) { E('_ERR_REPEAT_SUBMIT_EXAM'); } // 当前毫秒时间 $now_time = MILLI_TIME; // 考试时长 $paper_time = to_milli_time($paper['paper_time'] * 60); // 判断用户是否有权限访问“学习地图类”数据 if (PaperService::OTHER_TYPE == $paper['exam_type']) { $map_id = $params['map_id']; $path_id = $params['path_id']; if (!empty($map_id) && !empty($path_id)) { $mapServ = new StudyMap($map_id); $mapServ->checkRight($path_id, $ep_id, $params['user_info'], $app = ''); } } if (self::IS_MAKEUP == $answer_info['is_makeup']) { // 如果是补考,考试结束时间为补考结束时间 $paper_end_time = $paper['makeup_end_time']; } else { // 如果不是补考 if (self::NOMAL_TYPE == $paper['exam_type']) { // 常规试卷 $paper_end_time = $paper['end_time']; } else { // 任务类,线下培训类 $paper_end_time = $answer_info['my_begin_time'] + $paper_time; } } // 考生考试开始时间 $my_begin_time = $answer_info['my_begin_time']; // 考生交卷截止时间 $answer_end_time = $my_begin_time + $paper_time; // 提前交卷 if ($now_time <= $answer_end_time && $now_time <= $paper_end_time) { // 考生用时 $my_time = $now_time - $my_begin_time; } else { // 到截止时间交卷 // 考生在考试结束时间之后交卷 if ($answer_end_time > $paper_end_time) { // 考生用时:考试结束时间-考生考试开始时间 $my_time = $paper_end_time - $my_begin_time; } else { // 考生在考试结束时间之前交卷 // 考试用时:考试交卷截止时间-考生考试开始时间 $my_time = $answer_end_time - $my_begin_time; } } // 交卷所需数据 $data = [ 'uid' => $answer_info['uid'], 'ea_id' => $ea_id, 'paper' => $paper, 'my_time' => $my_time, 'my_begin_time' => $my_begin_time, 'data_type' => $params['data_type'], // 数据类型 'obj_id' => $params['obj_id'] // 任务、培训ID ]; // 处理交卷 $score_list为积分策略返回值 $this->do_submit($data, $params['qa_list'], $result_status, $score_list, $answer_info['is_makeup']); // 如果不是补考 if (self::IS_MAKEUP != $answer_info['is_makeup']) { // 更新考试已参加与未参加人数 $this->paper_statistics($paper, $answer_info['uid']); // 添加积分勋章接口,返回激励、积分策略信息$award $this->medal($ep_id, $answer_info['uid'], $award); } // 手动阅卷发送阅卷信息 if (self::SEND_MSG_FOR_MARKING_USER == $result_status) { $this->send_cms_answer($ea_id, AnswerService::MARKING_USER_MSG); } elseif (self::SEND_MSG_FOR_JOIN_EXAM_USER == $result_status) { // 手动阅卷系统阅卷成绩出来(过滤其他类型) if (PaperService::OTHER_TYPE != $paper['exam_type']) { $this->send_cms_answer($ea_id, AnswerService::MARKING_RESULT_MSG); } } return [ 'res' => true, 'score_list' => $score_list ]; } /** * 交卷 * @param array $data 函数所需数据 * @param array $qa_list 答题列表 * @param int $result_status 手动阅卷状态 * @param array $score_list 积分策略返回数据 * @param int $is_makeup 是否是补考(0:否,1:是) * * @return bool */ public function do_submit($data = [], $qa_list = [], &$result_status = 0, &$score_list = [], $is_makeup = 0) { // 答卷id $ea_id = $data['ea_id']; // 答卷详情列表 $detail_conds['ea_id'] = $ea_id; $answer_detail_list = $this->_answer_detail_model->list_by_conds($detail_conds); $answer_detail_list = array_combine_by_key($answer_detail_list, 'ead_id'); // 阅卷类型(1:自动阅卷 2:手动阅卷) $marking_type = $data['paper']['marking_type']; // 试卷id $ep_id = $data['paper']['ep_id']; // 根据试卷id获取题目扩展信息列表 $answer_detail_extend_list = $this->_answer_detail_extend_model->list_by_conds(['ep_id' => $ep_id]); $answer_detail_extend_list = array_combine_by_key($answer_detail_extend_list, 'et_id'); // 交卷 try { // 开始事务 $this->start_trans(); // 题目类型:问答题、语音题 $et_types = [ self::TOPIC_TYPE_QUESTION, self::TOPIC_TYPE_VOICE ]; // 手动阅卷主观题数量 $count = 0; // 回答中的图片附件 $at_ids = []; // 循环处理答题列表 foreach ($qa_list as $key => $val) { // 题目扩展信息 $extend_info = $answer_detail_extend_list[$answer_detail_list[$val['ead_id']]['et_id']]; // 题目详情 $et_detail = unserialize($extend_info['et_detail']); // 获取答案字符串 $answer = $this->get_answer($val, $et_detail); // 空答案,更改状态为不通过、未作答、已批阅,得分为0 if (!$answer) { // 组装更新数据 $un_data = [ 'my_answer' => '', 'my_score' => 0, 'is_pass' => self::NO_MY_PASS, // 答题状态 0未作答(没有卵用,代码中未使用此判断作答状态,而是使用的is_status) 1已通过 [2未通过] 'is_status' => self::DO_PASS_STATE, // 作答状态 [0未作答] 1已作答 'marking_status' => self::DO_MK_STATE // 批阅状态 0待批阅 [1已批阅] ]; $this->_answer_detail_model->update($val['ead_id'], $un_data); } else { $option_index = $answer_detail_list[$val['ead_id']]['option_index']; // 如果该题目启用了选项打乱 if (!empty($option_index)) { $exam_help = new ExamHelper(); // 装换用户提交的答案为标准题目选项对应的答案 $answer = $exam_help->change_option_save($answer, $option_index); } // 提交的答案不为空,保存答案 // ============= 事物 写入不能再方法内 ===================== // 更新答案、答题状态 $de_data = [ 'my_answer' => $answer, 'is_status' => self::MY_PASS // 答题状态:已作答 ]; $res = $this->_answer_detail_model->update($val['ead_id'], $de_data); if ($et_detail['et_type'] == self::TOPIC_TYPE_VOICE) { // 如果是语音题,并且答案是不为空的,取出其中的附件ID $my_answer = unserialize($answer); foreach ($my_answer as $at_info) { // 如果回答中含有图片 if ($at_info['type'] == self::ANSWER_TYPE_IMG) { // 取出图片ID $at_ids[] = $at_info['opt']; } } } // 更新成功 if ($res) { // 计算试题分数 $ead_id = $val['ead_id']; $et_type = $et_detail['et_type']; $detail_data = $this->_answer_detail_model->get($ead_id); // 手动阅卷 && 题目类型是问答或语音 if (self::MANUAL_MARKING_TYPE == $marking_type && in_array($et_type, $et_types) ) { // do nothing } else { // 自动阅卷 $arr = $this->get_topic_score($detail_data); $arr['marking_status'] = self::DO_MK_STATE; // 批阅状态 0待批阅 [1已批阅],此处默认已批阅 $this->_answer_detail_model->update($ead_id, $arr); } } // ====================================================== } // 开启手动阅卷 && 测评试卷 && 答案不为空 && 问答题或语音题 if (self::MANUAL_MARKING_TYPE == $marking_type && self::EVALUATION_PAPER_TYPE == $data['paper']['paper_type'] && $answer && in_array($et_detail['et_type'], $et_types) ) { $count++; } } // 答卷表待更新数据 $read_data = [ 'my_time' => $data['my_time'], 'my_end_time' => $data['my_begin_time'] + $data['my_time'] ]; // 通知uc附件使用情况 $attrch_serv = new AttachOperation(); $attrch_serv->insert_attach( APP_DIR, 'paper', $ep_id, ['attach_ids' => $at_ids] ); // 手动阅卷主观题存在(循环中,只有【开启手动阅卷】的【测评试卷】才会加数量,所以这里直接用这个数量判断就可以) if ($count) { // 追加答卷表待更新数据 $read_data['answer_status'] = self::READ_WAITING; // 批阅状态:待批阅 $result_status = self::SEND_MSG_FOR_MARKING_USER; // 手动阅卷发送阅卷信息 } else { // 自动阅卷,直接出分,并更新状态是否已通过考试 // 计算已批阅的总分 $score_conds = [ 'ea_id' => $ea_id, 'marking_status' => self::DO_MK_STATE // 批阅状态 0待批阅 [1已批阅] ]; // 考试得分 $my_score = $this->_answer_detail_model->get_score($score_conds); // 及格分大于得分 if ($data['paper']['pass_score'] > $my_score) { // 不通过 $my_is_pass = self::UNPASS; } else { // 通过 $my_is_pass = self::PASS; } // 追加答卷表待更新数据 $read_data['my_score'] = $my_score; $read_data['my_is_pass'] = $my_is_pass; $read_data['answer_status'] = self::READ_OVER; // 批阅状态 0初始化 1待批阅 2批阅中 [3已批阅] $read_data['marking_time'] = MILLI_TIME; // 开启手动阅卷 && 测评试卷 if (self::MANUAL_MARKING_TYPE == $marking_type && self::EVALUATION_PAPER_TYPE == $data['paper']['paper_type'] ) { // 手动阅卷系统阅卷成绩出来 $result_status = self::SEND_MSG_FOR_JOIN_EXAM_USER; } else { // 不发送消息 $result_status = self::NOT_NEED_SEND_MSG; } if ($data['paper']['exam_type'] == self::NOMAL_TYPE) { // 积分策略业务ID=应用目录_数据ID $businessid = sprintf('%s_%s', APP_DIR, $data['paper']['ep_id']); $read_data['businessid'] = $businessid; if (self::IS_MAKEUP != $is_makeup) { // 不是补考,调用积分策略 $score_list = $this->get_score_list($data['uid'], $data['paper'], $my_score, $my_is_pass, $businessid); } } else { $read_data['businessid'] = ''; } } // 更新答卷表数据 $read_cond['ea_id'] = $ea_id; $read_data['data_type'] = $data['data_type']; // 数据类型(1:常规试卷,2:任务类,3:线下培训) $read_data['obj_id'] = $data['obj_id']; // 任务、培训ID // 此处查询是否存在最高分 $top_score = $this->get_by_conds(['ep_id' => $ep_id, 'is_score_top' => self::IS_SCORE_TOP_TRUE, 'uid' => $data['uid'], 'answer_status' => self::READ_OVER]); // 默认不是最高分 $is_score_top = self::IS_SCORE_TOP_FALSE; if (empty($top_score)) { // 如果之前的最高分记录为空,设置为最高分 $is_score_top = self::IS_SCORE_TOP_TRUE; } elseif ($top_score['my_score'] < $read_data['my_score']) { // 如果之前的最高分小于当前得分,设置为最高分 $is_score_top = self::IS_SCORE_TOP_TRUE; // 将之前的最高分记录置为非最高分 $this->update($top_score['ea_id'], ['is_score_top' => self::IS_SCORE_TOP_FALSE]); } $read_data['is_score_top'] = $is_score_top; // 是否最高分 $this->update($read_cond, $read_data); $this->commit(); } catch (\Exception $e) { $this->rollback(); E('_ERR_SUBMIT_FAIL'); return false; } return true; } /** * 获取答案字符串 * @param array $val 答案数据 * @param array $et_detail 题目详情 * * @return array|string 答案字符串 */ public function get_answer($val = [], $et_detail = []) { $str_answer = ''; // 多选题 if (self::TOPIC_TYPE_MULTIPLE == $et_detail['et_type']) { $answer = []; if (isset($val['my_answer']) && !empty($val['my_answer'])) { $answer = array_filter(array_column($val['my_answer'], 'opt')); } if (!empty($answer)) { foreach ($answer as $key => &$value) { $value = strtoupper(trim($value)); } sort($answer); $str_answer = implode(',', $answer); } } elseif (self::TOPIC_TYPE_QUESTION == $et_detail['et_type'] || self::TOPIC_TYPE_SINGLE == $et_detail['et_type'] || self::TOPIC_TYPE_JUDGMENT == $et_detail['et_type'] ) { // 问答、单选、判断题 $str_answer = ''; if (isset($val['my_answer']) && !empty($val['my_answer'])) { $answer = array_filter(array_column($val['my_answer'], 'opt')); $str_answer = implode(',', $answer); // 单选题 if (self::TOPIC_TYPE_SINGLE == $et_detail['et_type'] && $answer[0]) { // 答案转大写 $str_answer = strtoupper(trim($answer[0])); } } } else { // 语音题 // 语音答案 $attach_cond['ead_id'] = $val['ead_id']; $answerattr = $this->_answer_attach_model->list_by_conds($attach_cond); // 媒体文件顺序编号 $order_ids = array_column($answerattr, 'order_id'); if ($val['my_answer']) { $answer_arr = []; foreach ($val['my_answer'] as $k => $v) { // 语音答题 if (self::ANSWER_TYPE_VOICE == $v['type']) { // 媒体文件存在 if ($v['opt'] && in_array($v['opt'], $order_ids)) { $answer_arr[] = $v; } } else { // 其他 $answer_arr[] = $v; } } // 答案不为空 if (!empty($answer_arr)) { // 答案序列化 $str_answer = serialize($answer_arr); } } } return $str_answer; } /** * 题目分数正确 * * @author: 蔡建华 * @param array $data 题目信息 * * @return array 返回 分数和答案是否正确 */ protected function get_topic_score($data = []) { if (empty($data['my_answer'])) { $my_score = 0; $is_pass = self::NO_MY_PASS; } else { // 题目扩展信息查询条件 $conditions_extend = [ 'et_id' => intval($data['et_id']), // 题目id 'ep_id' => intval($data['ep_id']) // 试卷id ]; // 获取题目扩展信息 $answer_detail_extend = $this->_answer_detail_extend_model->get_by_conds($conditions_extend); $et_detail = unserialize($answer_detail_extend['et_detail']); $et_type = $et_detail['et_type']; // 如果是选择题或者多选题 if (self::TOPIC_TYPE_SINGLE == $et_type || self::TOPIC_TYPE_MULTIPLE == $et_type) { $answer = explode(',', $et_detail['answer']); // 循环我的回答,判断我的回答里有没有不在答案里的 $my_answer_arr = explode(',', $data['my_answer']); $my_answer_arr = array_filter($my_answer_arr); $my_score = $data['score']; // 得分,默认是有分数的 $is_pass = self::MY_PASS; // 已作答 foreach ($my_answer_arr as $v) { // 如果我的回答不在答案里,就是错的 if (!in_array($v, $answer)) { $my_score = 0; $is_pass = self::NO_MY_PASS; break; } } /* * 如果我的回答里没有不在答案里的,再判断下我的回答数量和答案数量是否一致 * 数量一致就是正确的,否则就是少选了 */ if ($my_score > 0 && count($my_answer_arr) != count($answer)) { $my_score = 0; $is_pass = self::NO_MY_PASS; } } elseif (self::TOPIC_TYPE_JUDGMENT == $et_type) { // 如果是判断题 $my_answer = trim($data['my_answer']); if ($et_detail['answer'] == $my_answer) { $my_score = $data['score']; $is_pass = self::MY_PASS; } else { $my_score = 0; if (empty($my_answer)) { // 未作答,但是注意!!!这里的is_pass没有被用来判断是否作答,而是使用is_status判断的,所以这里其实是无意义的 $is_pass = self::DO_PASS_STATE; } else { $is_pass = self::NO_MY_PASS; } } } elseif (self::TOPIC_TYPE_VOICE == $et_type) { // 如果是语音题 // 存在答案就认为得满分,不存在则为0 $my_score = $data['score']; $is_pass = self::MY_PASS; } else { $my_answer = trim($data['my_answer']); // 如果是问答题 if (self::KEYWORD_OPEN == $et_detail['match_type']) { // 匹配关键字方式 $my_score = $this->_key_question_score($et_detail['answer_keyword'], $my_answer, $data['score']); // 得满分算回答正确,否则为回答错误 if ($my_score == $data['score']) { $is_pass = self::MY_PASS; } else { $is_pass = self::NO_MY_PASS; } } else { // 覆盖率方式 $is_pass = $this->_coverage_question_score($et_detail['answer'], $et_detail['answer_coverage'], $my_answer); $my_score = $is_pass === true ? $data['score'] : 0; // 得满分算回答正确,否则为回答错误 if ($my_score == $data['score']) { $is_pass = self::MY_PASS; } else { $is_pass = self::NO_MY_PASS; } } } } return [ 'is_pass' => $is_pass, 'my_score' => $my_score ]; } /** * @author: 蔡建华 * * 计算问答题关键字匹配方式的分数 * @param array $keywords 关键字数组 * @param string $my_answer 我的回答 * @param int $score 总分数 * * @return int 得分 */ public function _key_question_score($keywords, $my_answer, $score) { $my_score = 0; // 最后得分 $match_all = true; // 是否全部匹配 // 循环关键字 foreach ($keywords as $v) { $keyWord = trim($v['keyword']); // 正则匹配关键字 if (preg_match("/{$keyWord}/", $my_answer)) { $percent = (float)((int)$v['percent'] / 100.00); $my_score += $score * $percent; } else { // 有一个不匹配就记录全部匹配为false $match_all = false; } } // 如果全部匹配,就返回满分,否则返回对应的分数 return $match_all === true ? $score : $my_score; } /** * @author: 蔡建华 * * 计算问答题覆盖率方式的分数 * @param string $sys_answer 答案 * @param string $answer_coverage 合格覆盖率 * @param string $my_answer 我的回答 * * @return boolean 我的回答的覆盖率满足合格覆盖率返回true,否则返回false */ public function _coverage_question_score($sys_answer, $answer_coverage, $my_answer) { $answer_coverage = (float)(intval($answer_coverage) / 100.0); // 当类型为问答题,进行文本比对 $user_answer = str_replace(["\r\n", "\r", "\n"], " ", $my_answer); $user_answer = preg_replace("/\s(?=\s)/", "\\1", $user_answer); $sys_answer = str_replace(["\r\n", "\r", "\n"], " ", $sys_answer); $sys_answer = preg_replace("/\s(?=\s)/", "\\1", $sys_answer); // 实例化对比类 $lcs = new Lcs(); // 我的答案的覆盖率 $coverage = $lcs->getSimilar($user_answer, $sys_answer); return $coverage >= $answer_coverage; } /** * 保存答卷 * @param array $val 答案 * @param array $et_detail 题目详情 * @param int $marking_type 试卷类型(1:自动阅卷 2:手动阅卷) * * @return bool */ public function save_answer($val = [], $et_detail = [], $marking_type = self::AUTO_MARKING_TYPE) { // 获取答案字符串 $str_answer = $this->get_answer($val, $et_detail); // 答案不为空,更新答卷信息 if ($str_answer) { // 更新答案、答题状态 $de_cond['ead_id'] = $val['ead_id']; $de_data = [ 'my_answer' => $str_answer, 'is_status' => self::MY_PASS // 答题通过 ]; $res = $this->_answer_detail_model->update_by_conds($de_cond, $de_data); // 更新成功 if ($res) { // 计算试题分数 $this->get_answer_score($val['ead_id'], $marking_type, $et_detail['et_type']); } return $res; } else { return false; } } /** * 试题分数计算 * * @author: 蔡建华 * @param $ead_id int 答卷ID * @param int $marking_type 1自动阅卷 2手动阅卷 * @param int $et_type 题型 * * @return int 返回分数 */ protected function get_answer_score($ead_id = 0, $marking_type = 0, $et_type = 0) { $data = $this->_answer_detail_model->get($ead_id); if (self::MANUAL_MARKING_TYPE == $marking_type && in_array($et_type, [self::TOPIC_TYPE_VOICE, self::TOPIC_TYPE_QUESTION]) ) { return false; } // 自动阅卷 $arr = $this->get_topic_score($data); $arr['marking_status'] = self::DO_MK_STATE; $this->_answer_detail_model->update_by_conds(['ead_id' => $ead_id], $arr); return true; } /** * 判断试卷状态 * * @author: 蔡建华 * @param $ea_id int 答卷ID * @param $uid string 用户ID * @param $data_type int 数据类型(1:常规考试,2:任务类,3:线下培训) * @param $obj_id int 任务、培训ID * * @return array|bool */ public function answer_status($ea_id = 0, $uid = '', $data_type = 1, $obj_id = 0) { // 初始化答卷状态 $start_type = self::START_TYPE_INITIAL; // 用户答卷查询 $condition = ['ea_id' => $ea_id, 'uid' => $uid, 'obj_id' => $obj_id]; // 获取答卷信息 $ea_data = $this->get_by_conds($condition); // 答卷信息不存在 if (empty($ea_data)) { E('_ERR_MY_VISIT_NO'); } // 查询试卷信息 $ep_id = $ea_data['ep_id']; $paper = $this->paper_model->get($ep_id); // 你已经交卷无法答题 if ($ea_data['answer_status'] >= self::READ_WAITING) { // 已经交卷 $start_type = self::START_TYPE_END; } // 我的考试开始时间 $my_begin_time = $ea_data['my_begin_time']; // 试卷时长 $paper_time = $paper['paper_time'] * 60 * 1000; $time = MILLI_TIME; // 结束时间 $end_time = $my_begin_time + $paper_time; // 判断试卷状态,其中包括分类状态和试卷状态 (这里的试卷状态 0初始化,1草稿,2已发布,3终止) if (self::EC_CLOSE_STATES == $paper['cate_status'] || self::PAPER_STOP == $paper['exam_status']) { $start_type = self::START_TYPE_END; } // 如果考试时间到 if (($paper['exam_type'] == self::NOMAL_TYPE && $time > $paper['end_time'] || $time > $end_time) || ($paper['exam_type'] != self::NOMAL_TYPE && $time > $end_time)) { $start_type = self::START_TYPE_END; // 答卷信息 $answer_info = $this->get($ea_id); // 阅卷状态 if ($answer_info['answer_status'] == 0) { // 查询条件:答卷id $conds = ['ea_id' => $ea_id]; // 全部题目数量 $my_error_num = $this->_answer_detail_model->count_by_conds($conds); // 此处查询是否存在最高分 $top_score = $this->get_by_conds(['ep_id' => $answer_info['ep_id'], 'is_score_top' => self::IS_SCORE_TOP_TRUE, 'uid' => $answer_info['uid'], 'answer_status' => self::READ_OVER]); // 默认不是最高分 $is_score_top = self::IS_SCORE_TOP_FALSE; if (empty($top_score)) { // 设置为最高分 $is_score_top = self::IS_SCORE_TOP_TRUE; } // 交卷分数 $data = [ 'answer_status' => self::READ_OVER, 'my_is_pass' => self::UNPASS, 'my_score' => 0, 'is_score_top' => $is_score_top, 'my_error_num' => $my_error_num, 'my_time' => $end_time - $my_begin_time, 'my_end_time' => $end_time, 'data_type' => $data_type, // 数据类型 'obj_id' => $obj_id // 任务、培训ID ]; // 交卷 $num = $this->update_by_conds($condition, $data); // 交卷成功 if ($num) { // 试卷使用类型(0:测评试卷,1:模拟试卷) $paper_type = $paper['paper_type']; // 是否更新参与人数(0=不更新,1=更新) $is_update_join = 0; // 测评试卷 if (self::EVALUATION_PAPER_TYPE == $paper_type) { // 更新 $is_update_join = 1; // 常规任务埋点:考试完成(测评试卷只要参加考试并交卷就算完成) if (PaperService::TASK_TYPE == $paper['exam_type'] && $obj_id) { $params = [ 'uid' => $uid, 'customtask_id' => $obj_id, 'app_data_id' => $ep_id, 'action_key' => 'exam_pass', 'description' => '考试完成', ]; $taskCenter = &TaskCenter::instance(); $taskCenter->triggerCustomtask($params); } } elseif (self::SIMULATION_PAPER_TYPE == $paper_type) { // 模拟试卷 // 交卷次数 $condition = [ 'ep_id' => $ep_id, 'uid' => $uid, 'answer_status' => self::READ_OVER, // 已批阅 'data_type' => self::NOMAL_TYPE, // 常规考试 ]; $answer_count = $this->_d->count_by_conds($condition); // 模拟试卷第一次交卷 if (1 == $answer_count) { // 更新 $is_update_join = 1; } } // 更新参与人数 if ($is_update_join) { // 已参与人数加1,未参与人数减1 $update_data = [ 'join_count' => $paper['join_count'] + 1, 'unjoin_count' => $paper['unjoin_count'] - 1 ]; $this->paper_model->update($ep_id, $update_data); } // 培训id不为空, 类型为线下培训 if ($obj_id && PaperService::TRAIN_TYPE == $data_type) { $Train = &Train::instance(); $Train->syncTrainStatus($obj_id, $ep_id); } } } } // 考试结束时间大于时间结束时间 if ($end_time > $paper['end_time']) { $left_time = $paper['end_time'] - $time; // 考试结束时间小与时间结束时间 } else { $left_time = $end_time - $time; } return [ 'ep_name' => $paper['ep_name'], 'marking_type' => $paper['marking_type'], 'paper_type' => $paper['paper_type'], 'left_time' => $left_time, // 返回倒计时 'my_begin_time' => $my_begin_time, 'paper_time' => $paper['paper_time'], 'end_time' => $paper['end_time'], 'start_type' => intval($start_type) ]; } /** * 判断补考试卷状态 * * @author: 蔡建华 * @param $ea_id int 答卷ID * @param $uid string 用户ID * @param $paper array 试卷数据 * * @return array|bool */ public function answer_status_makeup($ea_id = 0, $uid = '', $paper = []) { // 初始化答卷状态 $start_type = self::START_TYPE_INITIAL; // 用户答卷查询 $condition = ['ea_id' => $ea_id, 'uid' => $uid]; // 获取答卷信息 $ea_data = $this->get_by_conds($condition); // 答卷信息不存在 if (empty($ea_data)) { E('_ERR_MY_VISIT_NO'); } // 你已经交卷无法答题 if ($ea_data['answer_status'] >= self::READ_WAITING) { // 已经交卷 E('_ERR_SUBMIT_ANSWER'); } // 我的考试开始时间 $my_begin_time = $ea_data['my_begin_time']; // 试卷时长 $paper_time = $paper['paper_time'] * 60 * 1000; $time = MILLI_TIME; // 结束时间 $end_time = $my_begin_time + $paper_time; if (self::EC_CLOSE_STATES == $paper['cate_status']) { // 判断试卷状态,其中包括分类状态禁用 E('_ERR_DATA_EXAM_DEL'); } // 如果考试时间到 if ($time > $paper['makeup_end_time'] || $time > $end_time) { // 答卷信息 $answer_info = $this->get($ea_id); // 阅卷状态 if ($answer_info['answer_status'] == 0) { // 查询条件:答卷id $conds = ['ea_id' => $ea_id]; // 全部题目数量 $my_error_num = $this->_answer_detail_model->count_by_conds($conds); // 此处查询是否存在最高分 $top_score = $this->get_by_conds(['ep_id' => $answer_info['ep_id'], 'is_score_top' => self::IS_SCORE_TOP_TRUE, 'uid' => $answer_info['uid'], 'answer_status' => self::READ_OVER]); // 默认不是最高分 $is_score_top = self::IS_SCORE_TOP_FALSE; if (empty($top_score)) { // 设置为最高分 $is_score_top = self::IS_SCORE_TOP_TRUE; } // 交卷分数 $data = [ 'answer_status' => self::READ_OVER, 'my_is_pass' => self::UNPASS, 'my_score' => 0, 'is_score_top' => $is_score_top, 'my_error_num' => $my_error_num, 'my_time' => $end_time - $my_begin_time, 'my_end_time' => $end_time, 'data_type' => self::NOMAL_TYPE, // 数据类型 'obj_id' => 0 // 任务、培训ID ]; // 交卷 $this->update($ea_id, $data); } E('_ERR_AUTO_SUBMIT_TIME'); } // 考试结束时间大于时间结束时间 if ($end_time > $paper['makeup_end_time']) { $left_time = $paper['makeup_end_time'] - $time; // 考试结束时间小与时间结束时间 } else { $left_time = $end_time - $time; } return [ 'ep_name' => $paper['ep_name'], 'marking_type' => $paper['marking_type'], 'paper_type' => $paper['paper_type'], 'left_time' => $left_time, // 返回倒计时 'my_begin_time' => $my_begin_time, 'paper_time' => $paper['paper_time'], 'end_time' => $paper['makeup_end_time'], 'start_type' => intval($start_type) ]; } /** * 删除答卷记录重新考试 * * @param $ep_id int 试卷ID * @param $conds array 条件 * * @return bool */ public function delete_answer($ep_id, $conds) { $list = $this->_d->list_by_conds($conds); if (empty($list)) { E('_EMPTY_ANSWER_PAPER'); } $user_uids = array_unique(array_column($list, 'uid')); $paper = $this->paper_model->get($ep_id); $ep_status = $this->paper_status($paper['exam_status'], $paper['begin_time'], $paper['end_time']); if (self::STATUS_ING != $ep_status) { E('_ERR_RESET_PAPER'); } // 已参加人数减去要删除的 $join_count = $paper['join_count'] - count($user_uids); // 未参加人数减去要删除的 $unjoin_count = $paper['unjoin_count'] + count($user_uids); // 要删除的答卷 $ea_ids = array_column($list, 'ea_id'); // 查询要删除的试题 $detail_list = $this->_answer_detail_model->list_by_conds(['ea_id' => $ea_ids]); if (empty($ea_ids)) { E('_EMPTY_EA_ID'); } $et_ids = array_column($detail_list, 'et_id'); try { // 开始事务 $this->start_trans(); // 删除答卷信息 $rel = $this->_d->delete_by_conds(['ea_id' => $ea_ids]); if (!$rel) { $this->rollback(); E('_ERR_DELETE_ANSWER_FAILE'); } // 更新试卷的参加人数 $rel = $this->paper_model->update_by_conds( ['ep_id' => $ep_id], ['join_count' => $join_count, 'unjoin_count' => $unjoin_count] ); if (!$rel) { $this->rollback(); E('_ERR_UPDATE_JOIN_PEOPLE'); } // 数据减去使用次数 if ($et_ids) { $rel = $this->_topic_model->MinusIncNum(['et_id' => $et_ids]); if (!$rel) { $this->rollback(); E('_ERR_UPDATE_TOPICS'); } } // 删除答卷详情 $rel = $this->_answer_detail_model->delete_by_conds(['ea_id' => $ea_ids]); if (!$rel) { $this->rollback(); E('_ERR_UPDATE_ANSWER_DETAIL'); } $this->commit(); } catch (\Think\Exception $e) { $this->rollback(); E('_ERR_DELETE_FAILE'); } catch (\Exception $e) { $this->rollback(); E('_ERR_DELETE_FAILE'); } // 发送消息 $params = [ 'name' => $paper['ep_name'], 'begin_time' => $paper['begin_time'], 'end_time' => $paper['end_time'], 'uids' => $user_uids, 'id' => $paper['ep_id'] ]; // 封面图片 if (self::IS_COVER_PIC_OPEN == $paper['is_cover_open']) { $params['img_id'] = $paper['cover_id']; } else { $params['img_id'] = ''; } $this->send_msg($params, self::RESET_USER_MSG); return true; } /** * 获取批阅列表 * * @param array $conds 查询条件 * @param array $page_option 分页 * @param array $order_option 排序 * * @return array|bool */ public function list_marking_paper($conds, $page_option = [], $order_option = []) { try { return $this->_d->list_marking_paper($conds, $page_option, $order_option); } catch (\Exception $e) { E($e->getCode() . ':' . $e->getMessage()); return false; } } /** * 统计批阅列表总数 * * @param array $conds 查询条件 * * @return array|bool */ public function count_marking_paper($conds) { try { return $this->_d->count_marking_paper($conds); } catch (\Exception $e) { E($e->getCode() . ':' . $e->getMessage()); return false; } } /** * 根据条件查询测评考试的参与人总数 * @param array $conds * @return mixed */ public function count_by_where($conds = []) { return $this->_d->count_mock_answer($conds); } /** * 根据条件分页查询测评考试的参与记录 * @param array $conds * @param null $page_option * @param array $order_by * @param string $fields * @return array|bool */ public function list_by_where($conds = [], $page_option = null, $order_by = [], $fields = '*') { return $this->_d->get_mock_answer_list($conds, $page_option, $order_by, $fields); } }