class PollsController < ApplicationController # before_action :check_poll_status 问卷的发消息和定时任务没有做 before_action :require_login, :check_auth,except: [:index] before_action :find_course, except: [:show,:poll_setting,:commit_setting,:edit,:update,:start_answer,:commit_poll, :commit_result,:poll_lists,:cancel_publish,:cancel_publish_modal,:common_header] before_action :get_poll_and_course, only: [:show,:poll_setting,:commit_setting,:edit,:update,:start_answer, :commit_poll,:commit_result,:poll_lists,:cancel_publish, :cancel_publish_modal,:common_header] before_action :user_course_identity before_action :is_course_teacher, except: [:index,:start_answer,:poll_setting,:commit_poll,:commit_result,:poll_lists,:common_header] #判断是否为课堂老师 before_action :check_user_status before_action :is_course_public, only: [:set_public] before_action :check_user_on_answer, only: [:show,:start_answer,:commit_poll,:poll_lists] #判断当前用户在问卷的权限/老师是否属于分班的权限 before_action :validate_params, only: [:create,:update] before_action :validates_multi_ids, only: [:publish,:end_poll,:destroys,:set_public,:join_poll_banks] before_action :check_poll_setting_status,only: [:commit_setting] before_action :get_questions_count ,only: [:start_answer,:show,:commit_result,:edit] before_action :check_user_id_start_answer,only: [:start_answer] before_action :check_poll_question_complete,only: [:commit_poll] #问卷提交前来判断问题是否完成 before_action :check_poll_commit_result,only: [:commit_result] # before_action :get_all_polls_commit, only: [:commit_result] #该问卷全部的用户 before_action :get_left_banner_id, only:[:common_header,:start_answer,:new,:edit,:index] include PollsHelper def index ActiveRecord::Base.transaction do begin # 按发布时间或创建时间排序 @polls_all = @course.polls member_show_polls = @polls_all.publish_or_not # 已发布的或已截止的问卷 @current_user_ = current_user @course_status = @course.is_end ? 0 : 1 # 课堂是否结束 @course_is_public = @course.is_public # 课堂的学生人数 @course_all_members = @course.students #当前课堂的全部学生 @current_student = @course_all_members.find_by(user_id: current_user.id) #当前用户是否为课堂的学生 # polls的不同用户群体的显示 if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教 @is_teacher_or = 1 @polls = @polls_all #老师能看到全部的问卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同) elsif @user_course_identity == Course::STUDENT # 2为课堂成员,能看到统一设置的和自己班级的 @is_teacher_or = 2 @member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id,默认为0 if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的) @polls = member_show_polls.size > 0 ? member_show_polls.public_or_unset : [] else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷 # 已发布 当前用户班级分组的 试卷id not_poll_ids = @course.poll_group_settings.poll_group_not_published.where("course_group_id = #{@member_group_id}").pluck(:poll_id) @polls = member_show_polls.where.not(id: not_poll_ids) end else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁 @is_teacher_or = 0 @polls = member_show_polls.public_or_unset end if @polls.count > 0 if params[:type].present? choose_type = params[:type] poll_setting_ids = [] if @is_teacher_or != 2 @polls = @polls.where("polls_status = #{choose_type}") else case choose_type when 1 poll_setting_ids = @course.poll_group_settings.where("course_group_id = #{@member_group_id}").poll_group_not_published.pluck(:poll_id) when 2 poll_setting_ids = @course.poll_group_settings.where("course_group_id = #{@member_group_id}") .where("publish_time is not null and publish_time <= ? and end_time > ?",Time.now,Time.now).pluck(:poll_id) when 3 poll_setting_ids = @course.poll_group_settings.where("course_group_id = #{@member_group_id}").poll_group_ended.pluck(:poll_id) end unified_setting_ids = @polls.public_or_unset.where("polls_status = #{choose_type}").pluck(:id) ex_ids = (poll_setting_ids + unified_setting_ids).uniq @polls = @polls.where(id: ex_ids) end end if params[:search].present? search_type = params[:search].to_s.strip @polls = @polls.poll_search(search_type) end # 分页 @polls_select_count = @polls.size @polls = @polls.order( "IF(ISNULL(publish_time),0,1), publish_time DESC,created_at DESC") @page = params[:page] || 1 @limit = params[:limit] || 15 @polls = @polls.page(@page).per(@limit) @polls = @polls&.includes(:published_settings) else @polls = [] end @polls_count = @polls_all.size # 全部页面,需返回 @polls_unpublish_counts = @polls_all.poll_by_status(1).size #未发布的问卷数 @polls_published_counts = @polls_count - @polls_unpublish_counts # 已发布的问卷数 @course_all_members_count = @course_all_members.size #当前课堂的学生数 rescue Exception => e uid_logger_error(e.message) tip_exception(e.message) raise ActiveRecord::Rollback end end end def new ActiveRecord::Base.transaction do begin @poll = Poll.new rescue Exception => e uid_logger_error(e.message) tip_exception("问卷创建失败!") raise ActiveRecord::Rollback end end end # polls_status 问卷状态,1为创建成功,但未发布;2为已发布;3表示已截止 # show_result true则在截止时间之后对课堂成员公开答题统计,0则不公开,默认为true # is_public true 为公开/ false为私有,默认为false # exercise_bank_id 试卷的id # unified_setting true 统一设置 / false为分班设置,默认为true # un_anonymous 是否实名,默认为false,即不公开 def create ActiveRecord::Base.transaction do begin poll_name = params[:polls_name] poll_desc = params[:polls_description] poll_options = { :polls_name => poll_name, :polls_description => poll_desc, :user_id => current_user.id, :course_id => @course.id, :polls_status => 1, :polls_type => "Course", } @poll = Poll.create(poll_options) rescue Exception => e uid_logger_error(e.message) tip_exception("问卷创建失败!") raise ActiveRecord::Rollback end end end def edit ActiveRecord::Base.transaction do begin rescue Exception => e uid_logger_error(e.message) tip_exception("页面请求失败!") raise ActiveRecord::Rollback end end end def update ActiveRecord::Base.transaction do begin poll_name = params[:polls_name] poll_des = params[:polls_description] poll_params = { :polls_name => poll_name, :polls_description => poll_des } @poll.update_attributes(poll_params) normal_status(0,"问卷更新成功!") rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") raise ActiveRecord::Rollback end end end #show页面应该是老师的题型预览页面及问题/答案的编辑,老师页面的 def show ActiveRecord::Base.transaction do begin if @user_course_identity < Course::STUDENT @is_teacher_or = 1 else @is_teacher_or = 0 end rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") raise ActiveRecord::Rollback end end end def common_header ActiveRecord::Base.transaction do begin if @user_course_identity > Course::ASSISTANT_PROFESSOR @is_teacher_or = 0 @user_poll_answer = @poll.check_user_votes_status(current_user) else @is_teacher_or = 1 @user_poll_answer = 3 #教师页面 end @poll_status = @poll.get_poll_status(current_user) poll_id_array = [@poll.id] @poll_publish_count = get_user_permission_course(poll_id_array,2).count #是否存在已发布的 @poll_unpublish_count = get_user_permission_course(poll_id_array,1).count #是否存在未发布的 if (@poll_publish_count == 0) && (@poll_unpublish_count == 0) #即表示没有分班 if @poll_status == 1 @poll_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候 elsif @poll_status == 2 @poll_publish_count = 1 #试卷未发布,且课堂没有分班的时候 end end rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") raise ActiveRecord::Rollback end end end #立即发布的弹窗内容 def publish_modal ActiveRecord::Base.transaction do begin poll_ids = params[:check_ids] if poll_ids.count > 0 @course_groups = get_user_permission_course(poll_ids,1) else @course_groups = [] end rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") raise ActiveRecord::Rollback end end end #首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。 def publish tip_exception("缺少截止时间参数") if params[:end_time].blank? tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day) ActiveRecord::Base.transaction do begin check_ids = Poll.where(id: params[:check_ids]) ex_end_time = params[:end_time].blank? ? Time.at(((1.month.since.to_i)/3600.0).ceil * 3600) : params[:end_time].to_time check_ids.each do |poll| if poll.unified_setting pl_status = poll.polls_status #则为试卷的状态 else pl_status = poll.poll_group_settings.find_in_poll_group("course_group_id",params[:group_ids]).poll_group_not_published.present? ? 1 : 0 #立即发布针对分组设置的全部未发布的班级才生效 end if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过 g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么poll的统一设置需修改 if g_course user_course_groups = @course.charge_group_ids(current_user) if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则问卷不用分组,且问卷设定为统一设置,否则则分组设置 poll.poll_group_settings.destroy_all poll_unified = true e_time = ex_end_time else poll_unified = false g_course.each do |i| poll_group_setting = poll.poll_group_settings.find_in_poll_group("course_group_id",i).first #根据课堂分班的id,寻找问卷所在的班级 if poll_group_setting #如果该问卷分组存在,则更新,否则新建 poll_group_setting.update_attributes(publish_time:Time.now,end_time:ex_end_time) else p_course_group = { :poll_id => poll.id, :course_group_id => i, :course_id => poll.course.id, :publish_time => Time.now, :end_time => ex_end_time, } new_poll_group = poll.poll_group_settings.new p_course_group new_poll_group.save end end e_time = poll.poll_group_settings.end_time_present.map(&:end_time).max # group_ids = params[:group_ids] end else poll.poll_group_settings.destroy_all poll_unified = true e_time = ex_end_time end poll_status = set_poll_status(Time.now,e_time) poll_params = { :publish_time => Time.now, :end_time => e_time, :polls_status => poll_status, :unified_setting => poll_unified } poll.update_attributes(poll_params) if poll.course_acts.size == 0 poll.course_acts << CourseActivity.new(:user_id => poll.user_id,:course_id => poll.course_id) end PollPublishNotifyJob.perform_later(poll.id, g_course) end end normal_status(0, "问卷发布成功!") ## 需添加发送消息的接口,稍后添加 rescue Exception => e uid_logger_error(e.message) tip_exception("问卷发布失败") raise ActiveRecord::Rollback end end end #立即截止的弹窗内容 def end_poll_modal ActiveRecord::Base.transaction do begin poll_ids = params[:check_ids] if poll_ids.count > 0 @course_groups = get_user_permission_course(poll_ids,3) else @course_groups = [] end rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") raise ActiveRecord::Rollback end end end # 首页批量或单独 立即截止,截止时间为当前时间 def end_poll ActiveRecord::Base.transaction do begin check_ids = Poll.where(id: params[:check_ids]) check_ids.each do |poll| poll_status = poll.get_poll_status(current_user) if poll_status == 2 #跳过已截止的或未发布的 g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么poll的统一设置需修改,poll_group_settings if g_course # 如果问卷之前是统一设置且分班参数与课堂的分班数不一致,则变为非统一设置,同时创建poll_group_settings if poll.unified_setting && g_course.length != @course.course_groups_count poll.poll_group_settings.destroy_all @course.course_groups.each do |group| poll.poll_group_settings << PollGroupSetting.new(poll_id: poll.id, course_group_id: group.id, course_id: @course.id, publish_time: poll.publish_time, end_time: poll.end_time) end else poll_unified = poll.unified_setting #这个作为初始化的值是否要好点呢?-hs end poll_users = poll_unified ? poll.poll_users : poll.poll_users.joins("join course_members on poll_users.user_id = course_members.user_id").where(course_members: {course_group_id: g_course, role: 4}) poll_group_setting = poll.poll_group_settings old_poll_groups = poll_group_setting.find_in_poll_group("course_group_id",g_course) #问卷分组的截止时间更改 old_poll_groups.update_all(:end_time => Time.now) new_end_time = poll_group_setting.end_time_present.map(&:end_time) # 问卷结束时间不为空的 new_end_time_s = new_end_time.size > 0 ? new_end_time.max : Time.now new_poll_status = set_poll_status(poll.publish_time,new_end_time_s) poll.update_attributes(:end_time => new_end_time_s,:polls_status => new_poll_status,:unified_setting => poll_unified) elsif poll.unified_setting poll_users = poll.poll_users poll.update_attributes(:polls_status => 3, :end_time => Time.now) end poll_users = poll_users.where("commit_status = 0 and start_at is not null") poll_users.update_all(:commit_status => 1, :end_at => Time.now) end end normal_status(0, "问卷截止成功!") rescue Exception => e uid_logger_error(e.message) tip_exception("立即截止失败!") raise ActiveRecord::Rollback end end end #撤销发布的弹窗内容 def cancel_publish_modal ActiveRecord::Base.transaction do begin poll_ids = [@poll.id] if poll_ids.count > 0 @course_groups = get_user_permission_course(poll_ids,2) else @course_groups = [] end rescue Exception => e uid_logger_error(e.message) tip_exception("没有权限") raise ActiveRecord::Rollback end end end # 撤销发布,仅指当前的问卷 def cancel_publish ActiveRecord::Base.transaction do begin g_course = params[:group_ids] if !@poll.unified_setting #如果问卷为分班设置,且传入的班级id存在 if g_course.present? course_group_ids = @course.course_members.course_find_by_ids("course_group_id",g_course).pluck(:user_id).uniq #传入班级的全部学生人数 all_poll_settings = @poll.poll_group_settings.find_in_poll_group("course_group_id",g_course) #根据传入的班级id来获取问卷的分组设置 all_poll_settings.destroy_all #问卷的设置文件全部删除 # @poll.poll_users.find_by_group_ids(course_group_ids).destroy_all #问卷的提交信息 poll_question_ids = @poll.poll_questions.pluck(:id) #问卷的全部问卷 PollVote.find_current_vote("user_id",course_group_ids).find_current_vote("poll_question_id",poll_question_ids).destroy_all poll_user_options = { :commit_status => 0, :start_at => nil, :end_at => nil } @poll.poll_users.find_by_group_ids(course_group_ids).update_all(poll_user_options) #试卷的用户全部更新为未答题状态 poll_groups = @poll.poll_group_settings if poll_groups.present? #是否还有问卷的发布分组,如果有的话,则是根据发布规则取最大和最小值 unified_setting = false e_time_present = poll_groups.end_time_present.map(&:end_time) p_time_present = poll_groups.publish_time_present.map(&:publish_time) e_time = e_time_present.size > 0 ? e_time_present.max : nil p_time = p_time_present.size > 0 ? p_time_present.min : nil poll_status = 1 if p_time.nil? #发布时间为空,则表示问卷未发布 poll_status = 1 elsif p_time.present? && e_time.present? poll_status = set_poll_status(p_time,e_time) end else unified_setting = true p_time = nil e_time = nil poll_status = 1 end poll_options = { :unified_setting => unified_setting, :polls_status => poll_status, :publish_time => p_time, :end_time => e_time } @poll.update_attributes(poll_options) normal_status(0,"分班问卷撤销发布成功!") else normal_status(-1,"请选择撤销发布班级!") end else poll_user_options = { :commit_status => 0, :start_at => nil, :end_at => nil } @poll.poll_users.update_all(poll_user_options) poll_question_ids = @poll.poll_questions.pluck(:id) PollVote.find_current_vote("poll_question_id",poll_question_ids).destroy_all poll_new_params = { :polls_status => 1, :publish_time => nil, :end_time => nil, :unified_setting => true } @poll.update_attributes(poll_new_params) @poll.poll_group_settings.destroy_all normal_status(0,"问卷撤销发布成功!") ## @poll.tidings.destroy_all 用户的发送消息全部删除,因接口未定,所以先注释 ## 需添加发送消息的接口,稍后添加 end rescue Exception => e uid_logger_error(e.message) tip_exception("问卷撤销发布失败!") raise ActiveRecord::Rollback end end end # 首页批量或单独删除 def destroys ActiveRecord::Base.transaction do begin check_ids = Poll.where(id:params[:check_ids]) check_ids.each do |poll| if poll.present? poll.destroy end end normal_status(0, "问卷已删除成功!") rescue Exception => e uid_logger_error(e.message) tip_exception("问卷删除失败!") raise ActiveRecord::Rollback end end end # 设为公开 def set_public ActiveRecord::Base.transaction do begin check_ids = Poll.where(id:params[:check_ids]) check_ids.each do |poll| poll.update_attribute('is_public', true) end normal_status(0, "问卷已设为公开!") rescue Exception => e uid_logger_error(e.message) tip_exception("问卷设为公开失败!") raise ActiveRecord::Rollback end end end ## 加入题库 def join_poll_banks ActiveRecord::Base.transaction do begin check_ids = Poll.where(id: params[:check_ids]) check_ids.each do |poll| current_ex_bank = current_user.exercise_banks.find_by_container(poll.id,"Poll").first if current_ex_bank.present? #当前用户的选择问卷是否已加入习题库,存在则更新习题库和问题库,否则新建习题库和问题库 ex_params = { :name => poll.polls_name, :description => poll.polls_description, :course_list_id => poll.course.try(:course_list_id) } current_ex_bank.update_attributes(ex_params) question_bank = QuestionBank.ques_by_container(current_ex_bank.id,current_ex_bank.container_type) #该习题库是否存在于问题库里 ques_params = { :name => current_ex_bank.name, :course_list_id => current_ex_bank.course_list_id } question_bank.first.update_attributes(ques_params) if question_bank.present? current_ex_bank.exercise_bank_questions.destroy_all # 更新后,习题库的问题全部删除,后续重新再建 else ex_params = { :name => poll.polls_name, :description => poll.polls_description, :user_id => current_user.id, :is_public => 0, :course_list_id => poll.course.try(:course_list_id), :container_id => poll.id, :container_type => "Poll", :quotes => 1 } current_ex_bank= ExerciseBank.new ex_params if current_ex_bank.save #如果习题库保存成功,则会创建问题库question_bank ques_params = { :name => current_ex_bank.name, :container_id => current_ex_bank.id, :container_type => current_ex_bank.container_type, :quotes => current_ex_bank.quotes, :user_id => current_ex_bank.user_id, :is_public => current_ex_bank.is_public, :course_list_id => current_ex_bank.course_list_id } question_bank = QuestionBank.new ques_params question_bank.save end end # 问卷的问题的输入 poll.poll_questions.each do |f| option = { :question_title => f.question_title, :question_type => f.question_type, :is_necessary => f.is_necessary, :question_number => f.question_number, :max_choices => f.max_choices, :min_choices => f.min_choices } exercise_bank_question = current_ex_bank.exercise_bank_questions.new option exercise_bank_question.save ## 问卷答案的输入 f.poll_answers.each do |a| choice_option = { :choice_position => a.answer_position, :choice_text => a.answer_text } exercise_bank_c = exercise_bank_question.exercise_bank_choices.new choice_option exercise_bank_c.save end end end normal_status(0, "题库更新成功!") rescue Exception => e uid_logger_error(e.message) tip_exception("题库更新失败!") raise ActiveRecord::Rollback end end end # 我的问卷题库 def my_polls ActiveRecord::Base.transaction do begin ## 我的问卷题库 @current_user_exercises = current_user.exercise_banks.find_by_c_type("Poll") if @current_user_exercises.present? if params[:search].present? search_type = params[:search].to_s.strip @current_user_exercises = @current_user_exercises.exercise_bank_search(search_type) end page = params[:page] || 1 limit = params[:limit] || 15 @my_exercises_count = @current_user_exercises.size @current_user_exercises = @current_user_exercises.page(page).per(limit) else @current_user_exercises = [] end rescue Exception => e uid_logger_error(e.message) tip_exception("题库调用失败!") raise ActiveRecord::Rollback end end end # 公共的问卷题库 def public_polls ActiveRecord::Base.transaction do begin if current_user.is_certification_teacher @user_certification = 1 #用户已通过认证 @public_exercises = ExerciseBank.find_by_c_type("Poll").public_exercises if @public_exercises.present? if params[:search].present? search_type = params[:search].to_s.strip @public_exercises = @public_exercises.exercise_bank_search(search_type) end page = params[:page] || 1 limit = params[:limit] || 15 @public_exercises_count = @public_exercises.size @public_exercises = @public_exercises.page(page).per(limit) else @public_exercises_count = 0 @public_exercises = [] end else @user_certification = 0 #用户未通过认证 @public_exercises_count = 0 @public_exercises = [] end rescue Exception => e uid_logger_error(e.message) tip_exception("题库调用失败!") raise ActiveRecord::Rollback end end end # 设置页面,先返回问卷的状态 def poll_setting ActiveRecord::Base.transaction do begin @user_permission = 2 @user_course_groups = @course.teacher_group(current_user.id) #当前老师的分班 @being_setting_course_ids = @poll.poll_published_ids(current_user.id) #当前用户已发布的班级的id @user_published_setting = @poll.poll_group_settings.find_in_poll_group("course_group_id",@being_setting_course_ids) poll_ids = [@poll.id] @poll_publish_count = get_user_permission_course(poll_ids,2).count rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") raise ActiveRecord::Rollback end end end #问卷设置提交 def commit_setting ActiveRecord::Base.transaction do begin error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。 course_group_ids = @course.charge_group_ids(current_user) #当前老师的班级id数组 poll_status = @poll.get_poll_status(current_user) if poll_status == 1 && course_group_ids.size > 0 # 问卷未发布,且老师的分班大于1 ,才可以修改统一设置,否则按poll默认的来处理 unified_setting = params[:unified_setting] else unified_setting = @poll.unified_setting end show_result = params[:show_result] ? 1 : 0 un_anonymous = params[:un_anonymous] ? true : false # 统一设置或者分班为0,则更新问卷,并删除问卷分组 if unified_setting || (course_group_ids.size == 0) params_publish_time = params[:publish_time].present? ? params[:publish_time].to_time : nil params_end_time = nil if params[:end_time].blank? if params_publish_time.present? params_end_time = params_publish_time + 30.days end else params_end_time = params[:end_time].to_time end # params_end_time = params[:end_time].present? ? params[:end_time].to_time : nil if poll_status == 2 && @poll.publish_time != params_publish_time normal_status(-1,"不允许修改发布时间") elsif poll_status == 3 && (@poll.end_time != params_end_time || @poll.publish_time != params_publish_time) normal_status(-1,"不允许修改发布时间") elsif params_publish_time.present? && params_end_time.present? && params_end_time < params_publish_time normal_status(-1,"截止时间不能小于发布时间") else #发布时间小于当前时间,则poll显示为未发布,当截止时间大于当前时间,则显示为已截止 poll_status_n = set_poll_status(params_publish_time,params_end_time) poll_params = { :unified_setting => unified_setting, :show_result => show_result, :un_anonymous => un_anonymous, :polls_status => poll_status_n, :publish_time => params_publish_time, :end_time => params_end_time } @poll.update_attributes(poll_params) @poll.poll_group_settings.destroy_all normal_status(0, "问卷设置成功!") end else params_times = params[:publish_time_groups] #分班返回的json数组{"publish_time_groups":[{"course_group_id":["1","2"],"publish_time":"xx","end_time":"xxx"}]} poll_groups = @poll.poll_group_settings.find_in_poll_group("course_id",@course.id) #当前课堂问卷的班级全部分班信息 poll_groups_ids = poll_groups.pluck(:course_group_id) #问卷的全部分班id total_common = params_times.map{|k| k[:course_group_id]}.sum #传入的所有分组的分班id total_common_group = poll_groups_ids & total_common #传入的分班与问卷已存在的分班的交集 old_poll_groups = poll_groups_ids - total_common_group #后来传入的分班里,没有了的班级,即需要删除 params_times.each do |t| course_id = t[:course_group_id] #为数组,可能会设置分班为各个班级id的数组 poll_publish_time = t[:publish_time].present? ? t[:publish_time].to_time : nil # poll_end_time = t[:end_time].present? ? t[:end_time].to_time : nil poll_end_time = nil if t[:end_time].blank? if poll_publish_time.present? poll_end_time = poll_publish_time + 30.days end else poll_end_time = t[:end_time].to_time end poll_group = poll_groups.find_in_poll_group("course_group_id",course_id) #判断该分班是否存在 if poll_group.present? && poll_group.first.end_time <= Time.now && (poll_end_time != poll_group.first.end_time || poll_publish_time != poll_group.first.publish_time) #已截止且时间改变的,则提示错误 error_count += 1 end if poll_group.present? && poll_group.first.publish_time < Time.now && poll_publish_time != poll_group.first.publish_time error_count += 1 end if error_count == 0 common_group = poll_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的 new_group_ids = course_id - common_group #新传入的班级id if common_group.size > 0 #传入的参数存在已发布的分班 poll_group_params = { :publish_time => poll_publish_time, :end_time => poll_end_time } poll_group = poll_groups.find_in_poll_group("course_group_id",common_group) the_group_setting = poll_group.first if the_group_setting.present? the_group_setting_status = set_poll_status(the_group_setting.publish_time,the_group_setting.end_time) if the_group_setting_status == 2 poll_group_params = { :publish_time => the_group_setting.publish_time, :end_time => poll_end_time } elsif the_group_setting_status == 3 poll_group_params = { :publish_time => the_group_setting.publish_time, :end_time => the_group_setting.end_time } end end poll_group.update_all(poll_group_params) end if new_group_ids.size > 0 new_group_ids.each do |c| poll_group_params = { :poll_id => @poll.id, :course_group_id => c, :course_id => @course.id, :publish_time => poll_publish_time, :end_time => poll_end_time } new_poll_group = PollGroupSetting.new(poll_group_params) new_poll_group.save end end end end if error_count > 0 error_count == 0 normal_status(-1,"已发布/已截止的问卷不允许修改时间") else if old_poll_groups.size > 0 old_all_poll_groups = poll_groups.find_in_poll_group("course_group_id",old_poll_groups) old_all_poll_groups.destroy_all end #问卷更新为poll_group_setting的发布时间最小,截止时间最大 e_time_present = poll_groups.end_time_present.map(&:end_time) p_time_present = poll_groups.publish_time_present.map(&:publish_time) e_time = e_time_present.size > 0 ? e_time_present.max : nil p_time = p_time_present.size > 0 ? p_time_present.min : nil poll_status = 1 if p_time.nil? #发布时间为空,则表示问卷未发布 poll_status = 1 elsif p_time.present? && e_time.present? poll_status = set_poll_status(p_time,e_time) end poll_params = { :unified_setting => unified_setting, :show_result => show_result, :un_anonymous => un_anonymous, :polls_status => poll_status, :publish_time => p_time, :end_time => e_time } @poll.update_attributes(poll_params) if @poll.polls_status == 2 if @poll.course_acts.size == 0 @poll.course_acts << CourseActivity.new(:user_id => @poll.user_id,:course_id => @poll.course_id) end end normal_status(0, "问卷设置成功!") end end rescue Exception => e uid_logger_error(e.message) tip_exception("提交出现错误!") raise ActiveRecord::Rollback end end end # 开始答题,如答案提交后则不可再修改, 问卷截止后或提交后,该页面不可再次点击 def start_answer ActiveRecord::Base.transaction do begin poll_user_current = PollUser.where(user_id:@poll_current_user_id,poll_id:@poll.id)&.first #查找当前用户是否有过答题 @poll_status = @poll.get_poll_status(current_user) if poll_user_current.blank? if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候,不创建poll_user表,理论上老师是不能进入答题的 poll_user_params = { :user_id => @poll_current_user_id, :poll_id => @poll.id, :start_at => Time.now, :commit_status => 0 } PollUser.create(poll_user_params) end elsif poll_user_current.start_at.nil? poll_user_current.update_attributes(:start_at => Time.now) end if @user_course_identity < Course::STUDENT || (@poll_status == 3) || (poll_user_current.present? && poll_user_current.commit_status == 1) @user_poll_status = 1 #当前用户为老师/问卷已截止/问卷已提交不可编辑 else @user_poll_status = 0 #可编辑 end @answer_status = [] question_answered = 0 # 判断是否已经回答还是新建的回答 @poll_questions.each do |q| ques_vote = q.poll_votes.find_current_vote("user_id",@poll_current_user_id) if ques_vote.present? ques_status = 1 question_answered += 1 else ques_status = 0 end answer_status = { :ques_id => q.id, :ques_number => q.question_number, :ques_status => ques_status } @answer_status = @answer_status.push(answer_status) end rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") raise ActiveRecord::Rollback end end end # 用户提交问卷 def commit_poll ActiveRecord::Base.transaction do begin @poll_multi_questions = @poll.poll_questions.where(question_type:2).select(:id,:max_choices,:min_choices,:question_number) error_question = [] @poll_multi_questions.each do |q| poll_user_votes = current_user.poll_votes.where(poll_question_id:q.id)&.size if q.max_choices.present? && (poll_user_votes > q.max_choices) error_messages = "第#{q.question_number}题:超过最大选项限制" elsif q.min_choices.present? && (poll_user_votes < q.min_choices) error_messages = "第#{q.question_number}题:不得少于最小选项限制" else error_messages = nil end error_question.push(error_messages) end error_question = error_question.reject(&:blank?) if error_question.reject(&:blank?).length > 0 normal_status(-1, "#{error_question.join("\n")}") else poll_user_current = @poll.poll_users.find_by_group_ids(current_user.id).first poll_user_params = { :commit_status => 1, :end_at => Time.now } poll_user_current.update_attributes(poll_user_params) normal_status(0, "问卷提交成功!") end ## 需添加发送消息的接口,稍后添加 rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") raise ActiveRecord::Rollback end end end #问卷的统计结果 def commit_result ActiveRecord::Base.transaction do begin @poll_users = @poll.all_poll_users(current_user.id) @poll_commit_ids = @poll_users.commit_by_status(1).pluck(:user_id) #问卷提交用户的id @page = params[:page] || 1 @limit = params[:limit] || 10 @poll_export_questions = @poll_questions @poll_questions = @poll_questions.page(@page).per(@limit) if params[:format] == "xlsx" if @user_course_identity > Course::ASSISTANT_PROFESSOR tip_exception(403,"无权限操作") elsif (@poll.polls_status == 1) || (@poll_export_questions.size == 0) || (@poll_commit_ids.size == 0) normal_status(-1,"暂无用户提交") else respond_to do |format| format.xlsx{ polls_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@poll.polls_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" polls_user_commit = poll_commit_result(@poll,@poll_export_questions,@poll_users,@poll_commit_ids) render xlsx: "#{polls_export_name_.strip.first(30)}",template: "polls/commit_result.xlsx.axlsx",locals: {polls_user_commit:polls_user_commit} } end end end rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") raise ActiveRecord::Rollback end end end #问卷的答题列表 def poll_lists ActiveRecord::Base.transaction do begin poll_ids = [@poll.id] @poll_list_status = @poll.get_poll_status(current_user) @poll_publish_count = get_user_permission_course(poll_ids,2).count @poll_unpublish_count = get_user_permission_course(poll_ids,1).count @course_all_members = @course.students @poll_group_counts = @course.course_groups_count if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的问卷 @poll_current_user_status = 0 @poll_users_list = @poll.all_poll_users(current_user.id) #该老师分班的全部学生 get_poll_answers(@poll_users_list, @poll_list_status) if @poll_list_status == 1 @poll_course_groups =[] else poll_common_ids = @poll.poll_published_ids(current_user.id) @poll_course_groups = @course.get_ex_published_course(poll_common_ids) end if @poll_list_status == 1 @poll_users_list = [] end elsif @user_course_identity > Course::ASSISTANT_PROFESSOR @poll_all_users = @poll.get_poll_exercise_users get_poll_answers(@poll_all_users, @poll_list_status) # 未答和已答的 @poll_course_groups = [] #当为学生的时候,不显示分班情况 @poll_current_user_status = 1 #当前用户的状态,为学生 poll_current_user = @poll_all_users.find_by_group_ids(current_user.id) #当前用户是否开始做问卷(提交/未提交/没做) if poll_current_user.present? && @poll_list_status != 1 #当前为学生或者有过答题的(提交/未提交),且问卷已发布的 @poll_users_list = poll_current_user.distinct else @poll_users_list = [] end else @poll_all_users = @poll.get_poll_exercise_users get_poll_answers(@poll_all_users, @poll_list_status) # 未答和已答的 @poll_current_user_status = 2 #当前用户非课堂成员 @poll_users_list = [] end if @poll_users_list.present? && @poll_users_list.count > 0 @poll_users_count = @poll_users_list.count #当前显示的全部成员数量 else @poll_users_count = 0 end if @poll_unanswers < 0 @poll_unanswers = 0 end #筛选/分类,排序 order = params[:order] # b_sort = params[:sort] || "desc" choose_type = params[:commit_status] group_id = params[:poll_group_id] search_content = params[:search] if @poll_users_list.present? && @poll_users_list.count > 0 #答题状态的选择 # if choose_type.present? @poll_users_list = @poll_users_list.commit_by_status(choose_type) end #班级的选择 if group_id.present? poll_students = @course_all_members.course_find_by_ids("course_group_id",group_id) # 问卷所分班的全部人数 user_ids = poll_students.pluck(:user_id).reject(&:blank?) @poll_users_list = @poll_users_list.find_by_group_ids(user_ids) end #搜索 if search_content.present? @poll_users_list = @poll_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{search_content}%", "%#{search_content}%") end poll_users_joins = @poll_users_list.joins(user: :user_extension) if order == "student_id" @poll_users_list = poll_users_joins.order("user_extensions.student_id DESC") else @poll_users_list = poll_users_joins.order("end_at DESC") end @poll_users_size = @poll_users_list.count # 分页 page = params[:page] || 1 limit = params[:limit] || 20 @poll_users_list = @poll_users_list.page(page).per(limit) else @poll_users_list = [] @poll_users_size = 0 end @current_user = current_user rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") raise ActiveRecord::Rollback end end end private def is_course_teacher unless @user_course_identity < Course::STUDENT #为老师/助教/管理员 tip_exception("403", "") end end def validate_params normal_status(-1, "问卷标题不能为空!") if params[:polls_name].blank? normal_status(-1, "问卷标题不能超过60个字符") if (params[:polls_name].present? && params[:polls_name].length > 60) normal_status(-1, "问卷描述不能超过100个字符") if (params[:polls_description].present? && params[:polls_description].length > 100) end def poll_params params.require(:poll).permit(:polls_name,:polls_status,:publish_time,:end_time,:polls_description, :show_result,:exercise_bank_id,:is_public,:unified_setting,:un_anonymous) end # 获得问卷及课堂 def get_poll_and_course @poll = Poll.find_by(id: params[:id]) if @poll.blank? tip_exception(404) else @course = @poll.course tip_exception(404) if @course.blank? end end # 当前课堂及用户的判断 def check_user_status unless @course.is_public == 1 || (@course.is_public == 0 && @user_course_identity < Course::NORMAL) #课堂的成员/管理员才可以 tip_exception(403) end end # 在设置问卷公开前,需判断课堂是否公开 def is_course_public unless @course.is_public == 1 # 0为私有,1为公开 tip_exception(403) end end ## 判断开始答题页面的用户权限 def check_user_on_answer poll_status = @poll.get_poll_status(current_user) if @user_course_identity == Course::STUDENT && poll_status == 1 #问卷未发布,且当前用户不为老师/管理员 normal_status(-1, "未发布问卷!") elsif @user_course_identity > Course::STUDENT && (!@poll.is_public || (@poll.is_public && !@poll.unified_setting)) ##不为课堂成员,且问卷不为公开的,或问卷公开,但是不是统一设置的 normal_status(-1, "问卷暂未公开!") end end def check_unified_setting?(poll) #问卷是否统一设置,如为分班设置,当前用户是否在班级内 if !poll.unified_setting #如果为分班设置,则需判断用户是否在班级内 poll_group_settings = poll.poll_group_settings.pluck(:course_group_id) member = @course.course_members.course_find_by_ids("user_id",current_user.id) member_group_id = member.pluck(:course_group_id).uniq if (member_group_id & poll_group_settings).size > 0 || @user_course_identity < Course::STUDENT true else false end else true end end def validates_multi_ids if params[:check_ids].blank? || params[:check_ids].count <= 0 normal_status(-1, "请选择问卷!") elsif params[:check_ids].count > 15 normal_status(-1, "最多只能选择15条数据!") end end def set_poll_status(publish_time,end_time) time_now_i = Time.now if publish_time.present? && end_time.present? && publish_time <= time_now_i && end_time > time_now_i 2 elsif publish_time.nil? || (publish_time.present? && publish_time > time_now_i) 1 elsif end_time.present? && end_time <= time_now_i 3 # elsif end_time.present? && publish_time.present? && end_time < publish_time # normal_status(-1,"时间设置错误!") else 1 end end def get_questions_count @poll_questions = @poll.poll_questions.order("question_number ASC") @poll_questions_count = @poll_questions&.size # 全部的题目数 @poll_question_singles = @poll_questions.ques_count(1).size # 单选题 @poll_question_doubles = @poll_questions.ques_count(2).size # 多选题 @poll_question_mains = @poll_questions.ques_count(3).size #主观题 @poll_questions = @poll_questions&.includes(:poll_answers,:poll_votes).distinct end def check_poll_question_complete #commit_poll 的权限 poll_user_current = @poll.poll_users.find_by_group_ids(current_user.id).first poll_status = @poll.get_poll_status(current_user) if @user_course_identity < Course::STUDENT || (poll_status == 3) || (poll_user_current.present? && poll_user_current.commit_status == 1) normal_status(-1,"用户没有权限!") #老师/管理员在提交时没有权限 else necessary_answer = 0 poll_questions = @poll.poll_questions necessary_question = poll_questions.ques_necessary # 问卷必答的问题 necessary_question.each do |q| user_vote = q.poll_votes.find_current_vote("user_id",current_user.id) vote_answer_id = user_vote.pluck(:poll_answer_id).reject(&:blank?).size vote_text_count = user_vote.pluck(:vote_text).reject(&:blank?).size if vote_answer_id == 0 && vote_text_count == 0 necessary_answer += 1 end end if necessary_answer > 0 normal_status(-1,"问卷提交失败,有#{necessary_answer}个未答的必答题!") end end end def check_poll_commit_result poll_status = @poll.get_poll_status(current_user) commit_poll_user = @poll.poll_users.find_by_group_ids(current_user.id).commit_by_status(1) #当前用户已提交问卷的 unless (@user_course_identity < Course::STUDENT) || ((@poll.show_result == 1) && (poll_status == 3) && commit_poll_user.present?) normal_status(-1,"没有权限!") #当前为老师/问卷公开统计,且问卷已截止,且用户有过回答的 end end def check_user_id_start_answer #判断用户在开始答题时,是否有用户id传入,如果为老师,则id必需,否则为当前用户的id user_login = params[:login] # @poll_current_user_id = params[:user_id] if user_login.blank? && @user_course_identity < Course::STUDENT #id不存在,且当前为老师/管理员等 normal_status(-1,"请输入学生登陆名!") else @answer_user = User.find_by(login:user_login) if @answer_user.blank? normal_status(404,"答题用户不存在") else @poll_current_user_id = @answer_user.id || current_user.id end end end def get_all_polls_commit @poll_questions = @poll.poll_questions.order("question_number ASC") @poll_commit_ids = @poll.poll_users.commit_by_status(1).pluck(:user_id) #问卷提交用户的id # 全部页面,需返回 @poll_questions_count = @poll_questions.size end def get_user_permission_course(poll_ids,status) #获取用户权限范围内的已发布/未发布 poll_status = status.to_i unpublish_group = [] user_groups_id = @course.charge_group_ids(current_user) all_polls = Poll.where(id:poll_ids) all_polls.each do |poll| if poll.present? if poll.unified_setting poll_user_status = poll.get_poll_status(current_user) #当前用户的能看到的试卷 if poll_user_status == poll_status || poll_status == 3 #未发布的情况 unpublish_group = unpublish_group + user_groups_id else unpublish_group = [] end # unpublish_group = unpublish_group + user_groups_id else poll_all_group_settings = poll.poll_group_settings poll_group_settings = poll_all_group_settings.poll_group_published.pluck(:course_group_id).uniq #问卷设置已发布的班级 if poll_status == 1 unpublish_group = user_groups_id - poll_group_settings elsif poll_status == 3 poll_ended_groups = poll_all_group_settings.poll_group_ended.pluck(:course_group_id).uniq poll_and_user = user_groups_id & poll_group_settings #用户已设置的分班 unpublish_group = unpublish_group + poll_and_user - poll_ended_groups #已发布的全部班级减去截止的全部班级 else poll_and_user = user_groups_id & poll_group_settings #用户已设置的分班 unpublish_group = unpublish_group + poll_and_user end end end end unpublish_group = unpublish_group.uniq if unpublish_group.size > 0 course_groups = CourseGroup.by_group_ids(unpublish_group) else course_groups = [] end course_groups end def check_poll_setting_status publish_course = params[:publish_time_groups] unified_setting = params[:unified_setting] if @course.is_end normal_status(-1,"课堂已结束不能再修改!") elsif unified_setting poll_group_settings = @poll.poll_group_settings if poll_group_settings.present? p_time_present = poll_group_settings.publish_time_present.map(&:publish_time).min if p_time_present < Time.now normal_status(-1,"设置失败,存在已发布的分班!") end elsif params[:publish_time].blank? normal_status(-1,"发布时间不允许为空") end elsif unified_setting.present? && !unified_setting #非统一设置,分班不能为空 if publish_course.present? course_ids = publish_course.map{|a| a[:course_group_id]}.sum publish_t = publish_course.map{|a| a[:publish_time]} if course_ids.include?(nil) || course_ids.count == 0 normal_status(-1,"请选择分班!") elsif publish_t.include?(nil) || publish_t.count == 0 normal_status(-1,"发布时间不允许为空") end else normal_status(-1,"请选择分班!") end end end def get_left_banner_id left_banner_content = @course.course_modules.search_by_module_type("poll") if left_banner_content.present? @left_banner_id = left_banner_content.first.id @left_banner_name = left_banner_content.first.module_name else tip_exception(404) end end #问卷的统计结果的导出 def poll_commit_result(poll,poll_questions,poll_users,poll_commit_ids) sub_commit = [] user_commit = [] poll_users_info = %w(序号) poll_ques_titles = poll_questions.pluck(:question_title).map {|k| ActionController::Base.helpers.strip_tags(k) if k.present?} poll_un_anony = poll.un_anonymous if poll_un_anony #是否匿名,默认为false user_info = %w(登陆名 真实姓名 邮箱 学号) else user_info = [] end poll_users_info = poll_users_info + user_info + poll_ques_titles poll_questions.each do |q| if q.question_type != 3 #问题不为主观题 question_vote_user = q.poll_votes.find_current_vote("user_id",poll_commit_ids)&.size #该问题的有效填写量 sheet_row = ["第#{q.question_number}题"] #选择题答案选项的数组 sheet_answer_row = ["小计"] #选择题回答的答案人数,数组 sheet_answer_percent = ["比例"] sheet_answer_useful = ["本题有效填写人次",question_vote_user] q.poll_answers.each do |a| #问卷的答案选项 answer_users_count = a.poll_votes.find_current_vote("user_id",poll_commit_ids)&.size answer_percent = (question_vote_user == 0) ? "0.0%" : "#{((answer_users_count / question_vote_user.to_f)*100).round(1).to_s}%" sheet_row.push(a.answer_text) sheet_answer_row.push(answer_users_count) sheet_answer_percent.push(answer_percent) end sheet_sub_commit = { sub_title: sheet_row, sub_user_votes:[sheet_answer_row,sheet_answer_percent,sheet_answer_useful] } sub_commit.push(sheet_sub_commit) else #主观题答案 user_votes= [] main_show_row = ["第#{q.question_number}题", q.question_title ] q.poll_votes.each_with_index do |v,index| #主观题的答案 q_poll_vote = [(index+1), v.vote_text.present? ? v.vote_text : "--"] user_votes.push(q_poll_vote) end sheet_sub_commit = { sub_title: main_show_row, sub_user_votes:user_votes } sub_commit.push(sheet_sub_commit) end end #each_with_index poll_users.includes(user: [:user_extension,:poll_votes]).each_with_index do |u,index| u_user = u.user user_answer_array = [] poll_questions.each do |q| user_poll_votes = u_user.poll_votes.find_current_vote("poll_question_id",q.id) if user_poll_votes.present? user_poll_answer_ids = user_poll_votes.pluck(:poll_answer_id).reject(&:blank?) user_poll_vote_texts = user_poll_votes.pluck(:vote_text).reject(&:blank?) if user_poll_answer_ids.count > 0 answer_content = q.poll_answers.find_answer_by_custom("id",user_poll_answer_ids) if user_poll_answer_ids.count >1 u_answer = answer_content.pluck(:answer_text).join(";") else u_answer = answer_content.first.answer_text end elsif user_poll_vote_texts.count > 0 if user_poll_vote_texts.count > 1 u_answer = user_poll_vote_texts.join(";") else u_answer = user_poll_vote_texts.first end else u_answer = "--" end else u_answer = "--" end user_answer_array.push(u_answer) end user_cell = [index+1] if poll_un_anony user_login = u_user.login user_name = u_user.real_name.present? ? u_user.real_name : "--" user_student_id = u_user.student_id.present? ? u_user.student_id : "--" user_cell += [user_login,user_name, u_user.mail, user_student_id] end all_user_cell = user_cell + user_answer_array user_commit.push(all_user_cell) end { poll_users_info:poll_users_info, sub_commit:sub_commit, user_commit:user_commit } end end