dev_new_shixunsrepository
杨树林 5 years ago
commit 3a455500a6

@ -109,3 +109,5 @@ gem 'request_store'
# 敏感词汇
gem 'harmonious_dictionary', '~> 0.0.1'
gem 'parallel', '~> 1.19', '>= 1.19.1'

@ -17,7 +17,8 @@ class Admins::ShixunSettingsController < Admins::BaseController
homepage_show: params[:homepage_show].present? ? params[:homepage_show] : false,
task_pass: params[:task_pass].present? ? params[:task_pass] : false,
code_hidden: params[:code_hidden].present? ? params[:code_hidden] : false,
vip: params[:vip].present? ? params[:vip] : false
vip: params[:vip].present? ? params[:vip] : false,
is_wechat_support: params[:is_wechat_support].present? ? params[:is_wechat_support] : false
}
@shixuns_type_check = MirrorRepository.pluck(:type_name,:id)
@ -131,6 +132,7 @@ class Admins::ShixunSettingsController < Admins::BaseController
end
def setting_params
params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,:code_hidden,:vip,:page_no,:id,tag_repertoires:[])
params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,
:code_hidden,:vip,:page_no,:id, :is_wechat_support, tag_repertoires:[])
end
end

@ -53,7 +53,7 @@ class CollegesController < ApplicationController
homeworks = HomeworkCommon.where(:homework_type => 4, :course_id => course_ids.map(&:id))
un_shixun_work_count = homeworks.where("publish_time > '#{Time.now}' or publish_time is null").count
shixun_work_count = homeworks.size - un_shixun_work_count
student_count = StudentsForCourse.where(:course_id => course_ids.map(&:id)).count
student_count = CourseMember.where(course_id: course_ids.map(&:id), role: 4).count
myshixun_ids = StudentWork.select("myshixun_id").where("homework_common_id in (#{homeworks.map(&:id).join(',').strip == "" ? -1 : homeworks.map(&:id).join(',')}) and myshixun_id is not null")
complete_myshixun = Myshixun.select("id").where(:status => 1, :id => myshixun_ids.map(&:myshixun_id)).size
all_myshixun = Myshixun.select("id").where(:id => myshixun_ids.map(&:myshixun_id)).size
@ -105,7 +105,7 @@ class CollegesController < ApplicationController
@courses = paginate courses
course_ids = @courses.map(&:id)
@student_count = StudentsForCourse.where(course_id: course_ids).group(:course_id).count
@student_count = CourseMember.where(course_id: course_ids, role: 4).group(:course_id).count
@shixun_work_count = HomeworkCommon.where(homework_type: 4, course_id: course_ids).group(:course_id).count
@attachment_count = Attachment.where(container_id: course_ids, container_type: 'Course').group(:container_id).count
@message_count = Message.joins(:board).where(boards: { parent_id: 0, course_id: course_ids }).group('boards.course_id').count

@ -182,7 +182,7 @@ class CoursesController < ApplicationController
CreateSubjectCourseStudentJob.perform_later(@course.id) if @course.subject && @course.subject.subject_appointments.count > 0
rescue => e
uid_logger_error(e.message)
tip_exception("调用失败")
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -394,6 +394,7 @@ class CoursesController < ApplicationController
# 教师列表以及教师搜索
def teachers
tip_exception(403, "无权限访问") if @course.excellent && @user_course_identity > Course::ASSISTANT_PROFESSOR
@search_str = params[:search].present? ? params[:search].strip : ""
if @course.try(:id) != 1309 || current_user.admin_or_business? || current_user.try(:id) == 15582
@ -850,6 +851,8 @@ class CoursesController < ApplicationController
# 学生列表(包括各个子分班的学生列表)及搜索
def students
tip_exception(403, "无权限访问") if @course.excellent && @user_course_identity > Course::ASSISTANT_PROFESSOR
search = params[:search].present? ? params[:search].strip : nil
order = params[:order].present? ? params[:order].to_i : 1
sort = params[:sort].present? ? params[:sort] : "asc"
@ -1346,6 +1349,7 @@ class CoursesController < ApplicationController
def search_slim
courses = current_user.manage_courses.not_deleted.processing
courses = courses.where(id: current_laboratory.all_courses)
keyword = params[:keyword].to_s.strip
if keyword.present?

@ -11,9 +11,9 @@ class DiscussesController < ApplicationController
# 总数,分页使用
if @manger
@disscuss_count = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).count
disscusses = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s,
:root_id => nil)
@disscuss_count = disscusses.count
@discusses = disscusses.joins("left join games on discusses.challenge_id = games.challenge_id and discusses.user_id = games.user_id")
.select("discusses.*, games.identifier").includes(:user, :praise_treads).limit(LIMIT).offset(offset)
else

@ -3,93 +3,81 @@ class ExerciseAnswersController < ApplicationController
before_action :get_exercise_question
include ExercisesHelper
# model validation error
rescue_from ActiveRecord::RecordInvalid do |ex|
render_error(ex.record.errors.full_messages.join(','))
end
# form validation error
rescue_from ActiveModel::ValidationError do |ex|
render_error(ex.model.errors.full_messages.join(','))
end
def create #每一次答案的点击,请求一次,实训题不在这里回答
begin
q_type = @exercise_question.question_type #试卷的类型
choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : ""
answer_text = params[:answer_text].present? ? params[:answer_text].strip : "" #为字符串
if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank?
normal_status(-1,"请选择序号")
else
ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案
if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题
if ea.exists?
ea.first.update!(exercise_choice_id: choice_id )
else
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id,
:exercise_choice_id => choice_id,
:answer_text => ""
}
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
elsif q_type == Exercise::MULTIPLE #多选题的
choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : []
ea_ids = ea.pluck(:exercise_choice_id)
common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id
new_ids = (choice_ids - common_answer_ids).uniq # 新增的id
old_ids = (ea_ids - common_answer_ids).uniq #没有选择的,则删掉
if new_ids.size > 0
new_ids.each do |e|
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id,
:exercise_choice_id => e,
:answer_text => ""
}
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
end
if old_ids.size > 0
ea_answer = ea.search_answer_users("exercise_choice_id",old_ids)
ea_answer.destroy_all
end
elsif q_type == Exercise::COMPLETION #填空题
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id,
:exercise_choice_id => choice_id,
:answer_text => answer_text
}
ea_answer = ea.search_answer_users("exercise_choice_id",choice_id)
if ea.present? && ea_answer.present?
ea_answer.update!(answer_option)
else
ex_new = ExerciseAnswer.new(answer_option)
ex_new.save!
end
elsif q_type == Exercise::SUBJECTIVE #简答题
q_type = @exercise_question.question_type #试卷的类型
choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : ""
answer_text = params[:answer_text].present? ? params[:answer_text].strip : "" #为字符串
if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank?
normal_status(-1,"请选择序号")
else
ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案
if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题
if ea.exists?
ea.first.update!(exercise_choice_id: choice_id )
else
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id,
:exercise_choice_id => choice_id,
:answer_text => ""
}
if ea.present? #已经回答了的,
ea.first.update!(answer_text: answer_text)
else
answer_option.merge!(answer_text:answer_text)
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
elsif q_type == Exercise::MULTIPLE #多选题的
choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : []
question_choice_ids = @exercise_question.exercise_choices.pluck(:id)
ea_ids = ea.pluck(:exercise_choice_id)
common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id
new_ids = (choice_ids - common_answer_ids).uniq # 新增的id
old_ids = (ea_ids - common_answer_ids).uniq #没有选择的,则删掉
if new_ids.size > 0
new_ids.each do |e|
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id,
:exercise_choice_id => e,
:answer_text => "",
:choice_index => question_choice_ids.index(e).to_i + 1 # choice的序号
}
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
end
normal_status(0,"回答成功")
if old_ids.size > 0
ea_answer = ea.search_answer_users("exercise_choice_id",old_ids)
ea_answer.destroy_all
end
elsif q_type == Exercise::COMPLETION #填空题
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id,
:exercise_choice_id => choice_id,
:answer_text => answer_text,
:choice_index => choice_id
}
ea_answer = ea.search_answer_users("exercise_choice_id",choice_id)
if ea.present? && ea_answer.present?
ea_answer.first.update!(answer_option)
else
ex_new = ExerciseAnswer.new(answer_option)
ex_new.save!
end
elsif q_type == Exercise::SUBJECTIVE #简答题
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id
}
if ea.present? #已经回答了的,
ea.first.update!(answer_text: answer_text)
else
answer_option.merge!(answer_text:answer_text)
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
normal_status(0,"回答成功")
end
end

File diff suppressed because it is too large Load Diff

@ -26,7 +26,7 @@ class GamesController < ApplicationController
game_count = Game.where(myshixun_id: @game.myshixun_id).count
discusses = @shixun.discusses
discusses = discusses.where('hidden = false OR user_id = :user_id', user_id: current_user.id) unless current_user.admin?
discusses = discusses.where('hidden = false OR user_id = :user_id', user_id: current_user.id) unless current_user.admin_or_business?
discusses_count = discusses.count
@user = @game.owner

@ -384,11 +384,11 @@ class GraduationTasksController < ApplicationController
if @task.status == 0
tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_time].blank?
tip_exception("发布时间不能早于当前时间") if params[:publish_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_time]
tip_exception("发布时间不能早于当前时间") if params[:publish_time].to_time <= Time.now
tip_exception("截止时间不能早于当前时间") if params[:end_time].to_time <= Time.now
tip_exception("截止时间必须晚于发布时间") if params[:publish_time].to_time >= params[:end_time].to_time
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
@course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day
@task.publish_time = params[:publish_time]
@task.end_time = params[:end_time]

@ -232,7 +232,11 @@ class HacksController < ApplicationController
hacks = Hack.select(select_sql).mine(current_user.id)
else
# 全部包括已经发布的,和我的未发布的
hacks = Hack.select(select_sql).published.opening.or(Hack.select(select_sql).unpublish.mine(current_user.id))
if current_user.admin_or_business?
hacks = Hack.select(select_sql)
else
hacks = Hack.select(select_sql).published.opening.or(Hack.select(select_sql).unpublish.mine(current_user.id))
end
end
# 搜索
if params[:search]

@ -26,14 +26,14 @@ class HelpsController < ApplicationController
def feedback
if params[:url].blank?
content = "<p>[#{params[:question_kind]}]</p></p>#{params[:description]}"
content = "[#{params[:question_kind]}]<br>#{params[:description]}<br>"
if params[:attachment_ids]
params[:attachment_ids].each do |attachment_id|
content += "![](/api/attachments/#{attachment_id})"
content += "![](/api/attachments/#{attachment_id})<br>"
end
end
else
content = "<p>[#{params[:question_kind]}]</p><p>问题页面网址:#{params[:url]}</p>#{params[:description]}"
content = "[#{params[:question_kind]}]<br>问题页面网址:#{params[:url]}<br>#{params[:description]}"
end
ActiveRecord::Base.transaction do

@ -787,7 +787,8 @@ class HomeworkCommonsController < ApplicationController
def create_shixun_homework
tip_exception("请至少选择一个实训") if params[:shixun_ids].blank?
shixuns = Shixun.where(id: params[:shixun_ids]).reorder("id desc")
order_ids = params[:shixun_ids].size > 0 ? params[:shixun_ids].reverse.join(',') : -1
shixuns = Shixun.where(id: params[:shixun_ids]).order("field(id, #{order_ids})")
@homework_ids = []
unless params[:category_id].blank?
@category = @course.course_second_categories.find_by(id: params[:category_id], category_type: "shixun_homework")
@ -909,7 +910,7 @@ class HomeworkCommonsController < ApplicationController
def publish_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
group_ids = params[:group_ids]&.reject(&:blank?)
group_ids = params[:group_ids]&.reject(&:blank?).map(&:to_i)
if params[:detail].blank?
tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
@ -1048,7 +1049,8 @@ class HomeworkCommonsController < ApplicationController
homeworks = homeworks.published_no_end.includes(:homework_group_settings, :homework_detail_manual, :homework_challenge_settings)
course_students = @course.students
charge_group_ids = @course.charge_group_ids(current_user)
end_groups = charge_group_ids & params[:group_ids] if params[:group_ids]
group_ids = params[:group_ids]&.reject(&:blank?).map(&:to_i)
end_groups = charge_group_ids & group_ids if group_ids
begin
homeworks.each do |homework|

@ -41,7 +41,11 @@ class ItemBanksController < ApplicationController
def destroy
ActiveRecord::Base.transaction do
ApplyAction.where(container_type: "ItemBank", container_id: @item.id).destroy_all
@item.destroy!
if @item.item_type == "PROGRAM"
@item.container&.destroy!
else
@item.destroy!
end
render_ok
end
end

@ -12,13 +12,7 @@ class ItemBasketsController < ApplicationController
end
def basket_list
@single_questions_count = current_user.item_baskets.where(item_type: "SINGLE").count
@multiple_questions_count = current_user.item_baskets.where(item_type: "MULTIPLE").count
@judgement_questions_count = current_user.item_baskets.where(item_type: "JUDGMENT").count
@completion_questions_count = current_user.item_baskets.where(item_type: "COMPLETION").count
@subjective_questions_count = current_user.item_baskets.where(item_type: "SUBJECTIVE").count
@practical_questions_count = current_user.item_baskets.where(item_type: "PRACTICAL").count
@program_questions_count = current_user.item_baskets.where(item_type: "PROGRAM").count
@basket_count = current_user.item_baskets.group(:item_type).count
end
def create

@ -1,6 +1,6 @@
class MemosController < ApplicationController
before_action :require_login, except: [:show, :index]
before_action :check_account, only: [:new, :create]
before_action :check_account, only: [:new, :create, :reply]
before_action :set_memo, only: [:show, :edit, :update, :destroy, :sticky_or_cancel, :hidden, :more_reply]
before_action :validate_memo_params, only: [:create, :update]
before_action :owner_or_admin, only: [:edit, :update, :destroy]
@ -144,7 +144,7 @@ class MemosController < ApplicationController
def reply
tip_exception("parent_id不能为空") if params[:parent_id].blank?
tip_exception("content不能为空") if params[:content].blank?
tip_exception("内容不能超过1000字符") if params[:content].length > 1000
tip_exception("内容不能超过2000字符") if params[:content].length > 2000
ActiveRecord::Base.transaction do
begin

@ -62,8 +62,8 @@ class MessagesController < ApplicationController
end
def reply
return normal_status(2, "回复内容不能为空") if params[:content].blank?
return normal_status(2, "回复内容不能超过1000字符") if params[:content].length > 1000
return normal_status(-1, "回复内容不能为空") if params[:content].blank?
return normal_status(-1, "回复内容不能超过2000字符") if params[:content].length > 2000
@reply = Message.create!(board: @message.board, root_id: @message.root_id || @message.id,
author: current_user, parent: @message,
message_detail_attributes: {

@ -724,7 +724,7 @@ class PollsController < ApplicationController
if unified_setting || (course_group_ids.size == 0)
tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_time].blank?
tip_exception("截止时间不能早于发布时间") if params[:publish_time].to_time > params[:end_time].to_time
tip_exception("截止时间必须晚于发布时间") if params[:publish_time].to_time >= params[:end_time].to_time
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:end_time].to_time > @course.end_date.end_of_day

@ -259,7 +259,8 @@ class QuestionBanksController < ApplicationController
:question_number => q.question_number,
:question_score => q.question_score,
:shixun_name => q.shixun_name,
:shixun_id => q.shixun_id
:shixun_id => q.shixun_id,
:is_ordered => q.is_ordered
}
exercise_question = new_exercise.exercise_questions.new option
# question_type5实训题其他是非实训题

@ -1,5 +1,9 @@
class ShixunListsController < ApplicationController
def index
# 去除开头标点符号
@reg = /^[,。?:;‘’!“”—……、]/
# 附件的替换
@atta_reg = /!\[.*]\(\/api\/attachments\/\d+\)/
@results = ShixunSearchService.call(search_params, current_laboratory)
end

@ -25,6 +25,7 @@ class ShixunsController < ApplicationController
before_action :special_allowed, only: [:send_to_course, :search_user_courses]
before_action :shixun_marker, only: [:new, :create]
before_action :validate_wachat_support, only: [:shixun_exec]
skip_before_action :check_sign, only: [:download_file]
## 获取课程列表
@ -290,13 +291,13 @@ class ShixunsController < ApplicationController
new_challenge.attributes = challenge.attributes.dup.except("id","shixun_id","user_id", "challenge_tags_count")
new_challenge.user_id = User.current.id
new_challenge.shixun_id = @new_shixun.id
new_challenge.save!
new_challenge.save!(validate: false)
# 同步参考答案
challenge.challenge_answers.each do |answer|
new_answer = ChallengeAnswer.new
new_answer.attributes = answer.attributes.dup.except("id","challenge_id")
new_answer.challenge_id = new_challenge.id
new_answer.save!
new_answer.save!(validate: false)
end
if challenge.st == 0 # 评测题
# 同步测试集
@ -305,7 +306,7 @@ class ShixunsController < ApplicationController
new_test_set = TestSet.new
new_test_set.attributes = test_set.attributes.dup.except("id","challenge_id")
new_test_set.challenge_id = new_challenge.id
new_test_set.save!
new_test_set.save!(validate: false)
end
end
# 同步关卡标签
@ -1185,4 +1186,11 @@ private
md5.hexdigest
end
def validate_wachat_support
if (params[:wechat].present? && !@shixun.is_wechat_support?)
tip_exception(-5, "..")
end
end
end

@ -13,6 +13,7 @@ class SubjectsController < ApplicationController
include ApplicationHelper
include SubjectsHelper
include GitCommon
include CustomSortable
def index
@tech_system = current_laboratory.subject_repertoires
@ -92,7 +93,7 @@ class SubjectsController < ApplicationController
@is_creator = current_user.creator_of_subject?(@subject)
@is_manager = @user.manager_of_subject?(@subject)
# 合作团队
@shixuns = @subject.shixuns.published.pluck(:id)
# @shixuns = @subject.shixuns.published.pluck(:id)
@courses = @subject.courses if @subject.excellent
@members = @subject.subject_members.includes(:user)
@ -199,7 +200,8 @@ class SubjectsController < ApplicationController
end
def append_to_stage
@shixuns = Shixun.where(id: params[:shixun_id]).order("id desc")
order_ids = params[:shixun_id].size > 0 ? params[:shixun_id].join(',') : -1
@shixuns = Shixun.where(id: params[:shixun_id]).order("field(id, #{order_ids})")
end
# 添加实训项目
@ -457,30 +459,19 @@ class SubjectsController < ApplicationController
end
def statistics_info
# data = Subjects::DataStatisticService.new(@subject)
# Rails.logger.info("study_count: #{data.study_count}")
# Rails.logger.info("course_study_count: #{ data.course_study_count}")
# Rails.logger.info("passed_count: #{data.passed_count}")
# Rails.logger.info("course_used_count: #{data.course_used_count}")
# Rails.logger.info("school_used_count: #{data.school_used_count}")
# data_1 = Subjects::CourseUsedInfoService.call(@subject)
# Rails.logger.info("study_count: #{data_1}")
# data_2 = Subjects::ShixunUsedInfoService.call(@subject)
# Rails.logger.info("study_count: #{data_2}")
# data_3 = Subjects::UserUsedInfoService.call(@subject)
# Rails.logger.info("study_count: #{data_3}")
@data =
if params[:type] == "shixun_info"
@subject.subject_shixun_infos
elsif params[:type] == "user_info"
@subject.subject_user_infos
else
select_sql = "id, count(subject_course_records.id) total, sum(course_count) course_count, sum(student_count) student_count, " +
"sum(choice_shixun_num) choice_shixun_num, sum(choice_shixun_frequency) choice_shixun_frequency"
@total = @subject.subject_course_records.select("#{select_sql}").first
@subject.subject_course_records
end
@data_count = @data.count
@data = paginate custom_sort(@data, params[:sort_by], params[:sort_direction])
end

@ -9,18 +9,18 @@ class Users::InterestsController < Users::BaseController
extension = current_user.user_extension || current_user.build_user_extension
return render_error('请选择职业') unless %w(teacher student professional).include?(identity)
interest_ids = Array.wrap(params[:interest_ids]).map(&:to_i)
return render_error('请选择兴趣') if interest_ids.blank?
# interest_ids = Array.wrap(params[:interest_ids]).map(&:to_i)
# return render_error('请选择兴趣') if interest_ids.blank?
ActiveRecord::Base.transaction do
extension.update_column(:identity, identity)
# 兴趣
UserInterest.bulk_insert(:user_id, :repertoire_id) do |worker|
(Repertoire.pluck(:id) & interest_ids).each do |repertoire_id|
worker.add(user_id: current_user.id, repertoire_id: repertoire_id)
end
end
# UserInterest.bulk_insert(:user_id, :repertoire_id) do |worker|
# (Repertoire.pluck(:id) & interest_ids).each do |repertoire_id|
# worker.add(user_id: current_user.id, repertoire_id: repertoire_id)
# end
# end
end
render_ok

@ -21,6 +21,8 @@ class Weapps::CodeSessionsController < Weapps::BaseController
Rails.logger.info("[Weapp] code: #{params[:code]}")
user_info = Wechat::Weapp.decrypt(result['session_key'], params[:encrypted_data], params[:iv])
# user_info.delete(:nickName)
# 老用户,已绑定
open_user = OpenUsers::Wechat.find_by(uid: user_info['unionId'])
if open_user.present? && open_user.user
@ -29,7 +31,7 @@ class Weapps::CodeSessionsController < Weapps::BaseController
end
set_session_unionid(user_info['unionId'])
user_info['nickname'] = user_info['nickName']
# user_info['nickname'] = user_info['nickName']
session[:wechat_user_extra] = user_info
end

@ -108,7 +108,7 @@ class Weapps::CoursesController < Weapps::BaseController
def change_member_roles
@course = current_course
tip_exception("请至少选择一个角色") if params[:roles].reject(&:blank?).blank?
tip_exception("不能具有老师、助教两种角色") if params[:roles].include?("PROFESSOR") && params[:roles].include?("ASSISTANT_PROFESSOR")
tip_exception("教师、助教角色只能二选一") if params[:roles].include?("PROFESSOR") && params[:roles].include?("ASSISTANT_PROFESSOR")
params[:user_ids].each do |user_id|
course_members = @course.course_members.where(user_id: user_id)

@ -16,6 +16,7 @@ class Weapps::HomesController < Weapps::BaseController
current_user.manage_courses
end
@courses = @courses.not_deleted.not_excellent
@courses = @courses.where(id: current_laboratory.all_courses)
@course_count = @courses.count
order_str = "course_members.sticky=1 desc, course_members.sticky_time desc, courses.created_at desc"
@courses = paginate(@courses.order(order_str).includes(:teacher, :school))

@ -15,8 +15,9 @@ class Weapps::SessionsController < Weapps::BaseController
return
end
# session[:wechat_user_extra].delete(:nickName)
# 绑定微信号
OpenUsers::Wechat.create!(user: user, uid: session_unionid, extra: session[:wechat_user_extra]) if user.wechat_open_user.blank?
OpenUsers::Wechat.create!(user: user, uid: session_unionid) if user.wechat_open_user.blank?
successful_authentication(user)
end

@ -19,11 +19,10 @@ class Weapps::VerificationCodesController < Weapps::BaseController
return render_error('请输入正确的邮箱或手机号')
end
code = %W(0 1 2 3 4 5 6 7 8 9)
verification_code = code.sample(6).join
send_type = login =~ /^1\d{10}$/ ? 1 : 8
# 记录验证码
check_verification_code(verification_code, send_type, login)
# 发送验证码
send_code(send_type, login)
render_ok
end
@ -40,12 +39,21 @@ class Weapps::VerificationCodesController < Weapps::BaseController
return render_error('请输入正确的邮箱或手机号')
end
send_type = login =~ /^1\d{10}$/ ? 2 : 3
# 发送验证码
send_code(send_type, login)
render_ok
end
def send_code send_type, login
code = %W(0 1 2 3 4 5 6 7 8 9)
verification_code = code.sample(6).join
send_type = login =~ /^1\d{10}$/ ? 2 : 3
# 记录验证码
check_verification_code(verification_code, send_type, login)
sign = Digest::MD5.hexdigest("#{OPENKEY}#{login}")
tip_exception(501, "请求不合理") if sign != params[:smscode]
render_ok
check_verification_code(verification_code, send_type, login)
end
end

@ -2,9 +2,11 @@ module ExerciseQuestionsHelper
def get_exercise_question_info(question,exercise,ex_user,ex_answerer_id)
answered_content = []
exercise_answers = question.exercise_answers.search_exercise_answer("user_id",ex_answerer_id) #试卷用户的回答
if question.question_type <= 2
if question.question_type == Exercise::SINGLE || question.question_type == Exercise::JUDGMENT
answered_content << exercise_answers.last&.exercise_choice_id if exercise_answers.present?
elsif question.question_type == Exercise::MULTIPLE
answered_content = exercise_answers.pluck(:exercise_choice_id)
elsif question.question_type == 3
elsif question.question_type == Exercise::COMPLETION
exercise_answers.each do |a|
u_answer = {
"choice_id": a.exercise_choice_id,
@ -12,10 +14,10 @@ module ExerciseQuestionsHelper
}
answered_content.push(u_answer)
end
elsif question.question_type == 4
elsif question.question_type == Exercise::SUBJECTIVE
answered_content = exercise_answers.pluck(:answer_text)
end
if question.question_type == 5 && ex_user.present? && ex_user.commit_status == 1 #存在实训题,且用户已提交了的,如果实训题只做了一半就关闭,则相当于不要了
if question.question_type == Exercise::PRACTICAL && ex_user.present? && ex_user.commit_status == 1 #存在实训题,且用户已提交了的,如果实训题只做了一半就关闭,则相当于不要了
if exercise.exercise_status == 3 #如果试卷已截止,则可以看到分数,否则不能查看分数
shixun_type = 2
else

@ -16,8 +16,8 @@ module ExercisesHelper
end
if q_type <= Exercise::JUDGMENT
if answers_content.present? #学生有回答时,分数已经全部存到exercise_answer 表,所以可以直接取第一个值
ques_score = answers_content.first.score
if answers_content.present? #学生有回答时,分数已经全部存到exercise_answer 表,多选题直接取第一个值,单选题和判断题选最后一个值(考虑并发)
ques_score = q_type == Exercise::MULTIPLE ? answers_content.first.score : answers_content.last.score
ques_score = ques_score < 0 ? 0.0 : ques_score
# answer_choice_array = []
# answers_content.each do |a|
@ -188,7 +188,7 @@ module ExercisesHelper
if ex_ordered
all_user_answers = effictive_users.pluck(:answer_text)
null_stand_choice.each_with_index do |s,index|
s_choice_text = null_stand_text[index]
s_choice_text = null_stand_text[index].to_s.strip
user_count = 0
# user_count = user_count + effictive_users.where("exercise_choice_id = ? and answer_text = ?",s,s_choice_text).pluck(:user_id).uniq.size
user_count = user_count + effictive_users.select{|answer| answer.exercise_choice_id == s && answer.answer_text == s_choice_text}.size
@ -441,30 +441,42 @@ module ExercisesHelper
end
if q.question_type <= 2 #为选择题或判断题时
if answers_content.present? #学生有回答时
answer_choice_array = []
answers_content.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
#TODO: 旧版多选题的标准答案是放在一个里面的新版又做成了一个题有多个标准答案exercise_choice_id存放的是标准答案的位置..
if q.question_type == 1 && standard_answer.size == 1
standard_answer = standard_answer.first.to_s.split("").map(&:to_i).sort
end
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
if standard_answer.size > 0
if q.question_type == 0 || q.question_type == 2 ## 单选、判断题的算分与多选题分开计算
user_answer = answers_content.last.exercise_choice.choice_position
standard_answer = q.exercise_standard_answers.first&.exercise_choice_id
if standard_answer.present? && user_answer == standard_answer
q_score_1 = q.question_score
# q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时每个answer的分数均摊。
score1 = score1 + q.question_score
else
q_score_1 = 0.0
q_score_1 = -1.0
end
answers_content.update_all(:score => q_score_1)
score1 = score1 + q.question_score
answers_content.last.update!(score: q_score_1)
else
answers_content.update_all(:score => -1.0)
score1 += 0.0
answer_choice_array = []
answers_content.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
#TODO: 旧版多选题的标准答案是放在一个里面的新版又做成了一个题有多个标准答案exercise_choice_id存放的是标准答案的位置..
if q.question_type == 1 && standard_answer.size == 1
standard_answer = standard_answer.first.to_s.split("").map(&:to_i).sort
end
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
if standard_answer.size > 0
q_score_1 = q.question_score
# q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时每个answer的分数均摊。
else
q_score_1 = 0.0
end
answers_content.update_all(:score => q_score_1)
score1 = score1 + q.question_score
else
answers_content.update_all(:score => -1.0)
score1 += 0.0
end
end
else
score1 += 0.0
@ -530,7 +542,7 @@ module ExercisesHelper
exercise_cha_score = 0.0
answer_status = 0
# if game.status == 2 && game.final_score >= 0
if game.final_score > 0 && game.end_time && game.end_time < exercise_end_time
if game.final_score > 0 && (game.end_time.nil? || game.end_time < exercise_end_time)
exercise_cha_score = game.real_score(exercise_cha.question_score)
# exercise_cha_score = exercise_cha.question_score #每一关卡的得分
answer_status = 1

@ -851,7 +851,8 @@ module ExportHelper
def make_zip_name(work, file_name="")
Rails.logger.info("######################file_name: #{file_name}")
# name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_")
"#{work&.homework_common.course&.user_group_name(work.user_id)}_#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
course = work.is_a?(StudentWork) ? work&.homework_common&.course : work&.graduation_task&.course
"#{course&.user_group_name(work.user_id)}_#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
end
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[])

@ -1,12 +1,12 @@
module ShixunsHelper
def level_to_s(level)
%W(初级 中级 高级 顶)[level-1]
%W(初级 中级 中高级 高)[level-1]
end
#难度
def diff_to_s(trainee)
%W(初级学员 中级学员 高级学员 顶级学员)[trainee-1]
%W(初级学员 中级学员 中高级学员 高级学员)[trainee-1]
end
#1. 未发布
@ -24,6 +24,8 @@ module ShixunsHelper
"已发布"
when 3
"已关闭"
when -1
"已删除"
end
end

@ -1,10 +1,10 @@
module SubjectsHelper
# 实训路径的发布状态
def publish_status subject, is_manager, user, shixuns
def publish_status subject, is_manager, user
status = -1
if is_manager
status = 0 if subject.status == 0 && shixuns.count > 0
status = 0 if subject.status == 0
status = 1 if subject.status == 1
status = 2 if subject.status == 2 && user.admin?
end

@ -13,7 +13,7 @@ class Discuss < ApplicationRecord
belongs_to :challenge, optional: true
validate :validate_sensitive_string
validates :content, length: { maximum: 1000, too_long: "不能超过1000个字符" }
validates :content, length: { maximum: 2000, too_long: "不能超过2000个字符" }
after_create :send_tiding

@ -5,5 +5,5 @@ class GraduationWorkScore < ApplicationRecord
belongs_to :graduation_task
has_many :attachments, as: :container, dependent: :destroy
validates :comment, length: { maximum: 1000, too_long: "不能超过1000个字符" }
validates :comment, length: { maximum: 2000, too_long: "不能超过2000个字符" }
end

@ -23,7 +23,6 @@ class Hack < ApplicationRecord
belongs_to :sub_discipline
has_one :item_bank, as: :container, dependent: :destroy
has_one :examination_bank, as: :container, dependent: :destroy
scope :published, -> { where(status: 1) }
scope :unpublish, -> { where(status: 0) }

@ -1,6 +1,6 @@
class HackSet < ApplicationRecord
validates_length_of :input, maximum: 1000, message: "不能超过5000个字符"
validates_length_of :output, maximum: 1000, message: "不能超过5000个字符"
validates_length_of :input, maximum: 1000, message: "不能超过1000个字符"
validates_length_of :output, maximum: 1000, message: "不能超过1000个字符"
validates :input, presence: { message: "测试集输入不能为空" }
validates :output, presence: { message: "测试集输出不能为空" }
validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个测试集的输入不能相同"

@ -19,38 +19,26 @@ class ItemBank < ApplicationRecord
end
def apply?
!public && ApplyAction.where(container_type: "ItemBank", container_id: id, status: 0).exists?
!public && ApplyAction.exists?(container_type: "ItemBank", container_id: id, status: 0)
end
def type_string
result = case item_type
when "SINGLE"
"单选题"
when "MULTIPLE"
"多选题"
when "JUDGMENT"
"判断题"
when "COMPLETION"
"填空题"
when "SUBJECTIVE"
"简答题"
when "PRACTICAL"
"实训题"
when "PROGRAM"
"编程题"
end
result
case item_type
when "SINGLE" then "单选题"
when "MULTIPLE" then "多选题"
when "JUDGMENT" then "判断题"
when "COMPLETION" then "填空题"
when "SUBJECTIVE" then "简答题"
when "PRACTICAL" then "实训题"
when "PROGRAM" then "编程题"
end
end
def difficulty_string
result = case difficulty
when 1
"简单"
when 2
"适中"
when 3
"困难"
end
result
case difficulty
when 1 then "简单"
when 2 then "适中"
when 3 then "困难"
end
end
end

@ -26,7 +26,7 @@ class JournalsForMessage < ApplicationRecord
# "is_comprehensive_evaluation", # 1 教师评论、2 匿评、3 留言
# "hidden", 隐藏、
validates :notes, length: { maximum: 1000, too_long: "不能超过1000个字符" }
validates :notes, length: { maximum: 2000, too_long: "不能超过2000个字符" }
after_create :send_tiding

@ -1,5 +1,5 @@
class MessageDetail < ApplicationRecord
belongs_to :message, :touch => true
validates :content, length: { maximum: 5000, too_long: "内容不能超过5000个字符" }
validates :content, length: { maximum: 10000, too_long: "内容不能超过10000个字符" }
end

@ -18,7 +18,8 @@ module Searchable::Shixun
status: status,
myshixuns_count: myshixuns_count,
created_at: created_at,
publish_time: publish_time
publish_time: publish_time,
is_wechat_support: is_wechat_support
}.merge!(searchable_user_data)
.merge!(searchable_challenge_data)
end

@ -276,8 +276,8 @@ class Shixun < ApplicationRecord
case trainee
when 1 then '初级学员'
when 2 then '中级学员'
when 3 then '高级学员'
when 4 then '级学员'
when 3 then '高级学员'
when 4 then '级学员'
else ''
end
end
@ -286,8 +286,8 @@ class Shixun < ApplicationRecord
case trainee
when 1 then '初级'
when 2 then '中级'
when 3 then '高级'
when 4 then '级'
when 3 then '高级'
when 4 then '级'
else ''
end
end

@ -223,7 +223,7 @@ class StudentWork < ApplicationRecord
game_score = adjust_score.score
elsif game.present?
setting = homework_common.homework_group_setting game.user_id
if game.status == 2 && ((game.end_time && game.end_time < setting.end_time) || (homework_common.allow_late && game.end_time && game.end_time < homework_common.late_time))
if game.status == 2 && ((game.end_time && setting.end_time && game.end_time < setting.end_time) || (homework_common.allow_late && homework_common.late_time && game.end_time && game.end_time < homework_common.late_time))
answer_open_evaluation = homework_common.homework_detail_manual.answer_open_evaluation
game_score = answer_open_evaluation ? score : (game.final_score > 0 ? game.real_score(score) : 0)
end

@ -7,7 +7,7 @@ class StudentWorksScore < ApplicationRecord
has_many :tidings, as: :container, dependent: :destroy
has_many :attachments, as: :container, dependent: :destroy
validates :comment, length: { maximum: 1000, too_long: "不能超过1000个字符" }
validates :comment, length: { maximum: 2000, too_long: "不能超过2000个字符" }
scope :shixun_comment, lambda { where(is_ultimate: 0) }

@ -51,6 +51,7 @@ class Admins::ShixunSettingsQuery < ApplicationQuery
all_shixuns = all_shixuns.where(task_pass: params[:task_pass]) if params[:task_pass]
all_shixuns = all_shixuns.where(code_hidden: params[:code_hidden]) if params[:code_hidden]
all_shixuns = all_shixuns.where(vip: params[:vip]) if params[:vip]
all_shixuns = all_shixuns.where(is_wechat_support: params[:is_wechat_support]) if params[:is_wechat_support]
custom_sort(all_shixuns, params[:sort_by], params[:sort_direction])
end

@ -64,7 +64,7 @@ class GitService
end
def parse_return(body)
logger.info("--uri_exec: .....res is #{body}")
#logger.info("--uri_exec: .....res is #{body}")
content = JSON.parse(body)
if content["code"] != 0

@ -23,9 +23,10 @@ class ShixunSearchService < ApplicationService
if User.current.admin? || User.current.business? || !User.current.school_id
@shixuns = @shixuns.where(hidden: 0)
else
none_shixun_ids = ShixunSchool.where("school_id != #{User.current.school_id}").pluck(:shixun_id)
shixun_ids = ShixunSchool.where(school_id: User.current.school_id).pluck(:shixun_id)
shixun_ids = shixun_ids.reject(&:blank?).length == 0 ? -1 : shixun_ids.join(",")
@shixuns = @shixuns.where.not(id: none_shixun_ids).where(hidden: 0, status: 2, public: 2).or(@shixuns.where(id: User.current.shixuns))
@shixuns = @shixuns.where("use_scope = 0 or id in (#{shixun_ids})").unhidden.publiced.or(@shixuns.where(id: User.current.shixuns))
end
end
@ -42,18 +43,24 @@ class ShixunSearchService < ApplicationService
@shixuns = @shixuns.where(trainee: params[:diff])
end
Rails.logger.info("search_shixun_ids: #{@shixuns.pluck(:id)}")
Shixun.search(keyword, search_options)
end
private
def search_options
order =
if sort_str == "wechat_myshixuns_count"
{"is_wechat_support" => "desc", "myshixuns_count" => order_str}
else
{sort_str => order_str}
end
model_options = {
includes: [ :shixun_info, :challenges, :subjects, user: { user_extension: :school } ]
}
model_options.merge!(where: { id: @shixuns.pluck(:id) })
model_options.merge!(order: {sort_str => order_str})
model_options.merge!(order: order)
model_options.merge!(default_options)
model_options
end

@ -21,17 +21,19 @@ class Subjects::CourseUsedInfoService < ApplicationService
# choice_shixun_num: 选用该课程实训的个数(去重)
# choice_shixun_frequency: 选用该课程实训的次数
course_info = []
schools.map do |school|
name = school.name
course_count = school.course_count
student_count = school.courses.joins(:course_members).where(course_members: {role: 4, course_id: course_ids}).size
shixun_ids = school.courses.joins(homework_commons: :homework_commons_shixun)
.where(homework_commons: {id: homework_common_ids})
.pluck("homework_commons_shixuns.shixun_id")
choice_shixun_frequency = shixun_ids.size
choice_shixun_num = shixun_ids.uniq.size
course_info << {school_id: school.id, school_name: name, course_count: course_count, student_count: student_count,
choice_shixun_num: choice_shixun_num, choice_shixun_frequency: choice_shixun_frequency}
schools.find_in_batches do |s|
Parallel.each(s) do |school|
name = school.name
course_count = school.course_count
student_count = school.courses.joins(:course_members).where(course_members: {role: 4, course_id: course_ids}).size
shixun_ids = school.courses.joins(homework_commons: :homework_commons_shixun)
.where(homework_commons: {id: homework_common_ids})
.pluck("homework_commons_shixuns.shixun_id")
choice_shixun_frequency = shixun_ids.size
choice_shixun_num = shixun_ids.uniq.size
course_info << {school_id: school.id, school_name: name, course_count: course_count, student_count: student_count,
choice_shixun_num: choice_shixun_num, choice_shixun_frequency: choice_shixun_frequency}
end
end
course_info
end

@ -10,20 +10,23 @@ class Subjects::ShixunUsedInfoService < ApplicationService
stages.each do |stage|
position = stage.position
shixuns = stage.shixuns.includes(myshixuns: :games, homework_commons: :course)
shixuns.each_with_index do |shixun, index|
stage = "#{position}-#{index+1}"
name = shixun.name
myshixuns = shixun.myshixuns
challenge_count = shixun.challenges_count
course_count = shixun.homework_commons.map{|hc| hc.course_id}.uniq.size
school_count = shixun.homework_commons.map{|hc| hc.course&.school_id}.uniq.size
used_count = shixun.myshixuns_count
passed_count = myshixuns.select{|m| m.status == 1}.size
evaluate_count = myshixuns.map{|m| m.output_times }.sum
passed_ave_time = passed_count > 0 ? myshixuns.map{|m| m.total_cost_time}.sum : 0
shixun_infos << {stage: stage, name: name, challenge_count: challenge_count, course_count: course_count,
school_count: school_count, used_count: used_count, passed_count: passed_count,
evaluate_count: evaluate_count, passed_ave_time: passed_ave_time, shixun_id: shixun.id}
shixuns.find_in_batches(batch_size: 1000) do |s|
Parallel.each_with_index(s, in_processes: 2) do |shixun, index|
stage = "#{position}-#{index+1}"
name = shixun.name
myshixuns = shixun.myshixuns
challenge_count = shixun.challenges_count
course_count = shixun.homework_commons.map{|hc| hc.course_id}.uniq.size
school_count = shixun.homework_commons.map{|hc| hc.course&.school_id}.uniq.size
used_count = shixun.myshixuns_count
passed_count = myshixuns.select{|m| m.status == 1}.size
evaluate_count = myshixuns.map{|m| m.output_times }.sum
passed_ave_time = passed_count > 0 ? myshixuns.map{|m| m.total_cost_time}.sum : 0
shixun_infos << {stage: stage, name: name, challenge_count: challenge_count, course_count: course_count,
school_count: school_count, used_count: used_count, passed_count: passed_count,
evaluate_count: evaluate_count, passed_ave_time: passed_ave_time, shixun_id: shixun.id}
end
end
end
shixun_infos

@ -1,6 +1,8 @@
class Subjects::UserUsedInfoService < ApplicationService
require 'parallel'
attr_reader :subject, :shixun_ids
def initialize(subject)
@subject = subject
@shixun_ids = subject.shixuns.pluck(:id)
@ -9,19 +11,22 @@ class Subjects::UserUsedInfoService < ApplicationService
def call
users_info = []
users = User.includes(myshixuns: :games).where(myshixuns: {shixun_id: shixun_ids}, games: {status: 2})
users.each do |user|
myshixuns = user.myshixuns.select{|m| shixun_ids.include?(m.shixun_id)}
name = "#{user.lastname}#{user.firstname}"
passed_myshixun_count = myshixuns.select{|m| m.status == 1}.size
passed_games_count = myshixuns.map{|m| m.games.select{|g| g.status == 2}.size }.size
code_line_count = 0
evaluate_count = myshixuns.map{|m| m.output_times }.sum
cost_time = myshixuns.map{|m|m.total_cost_time }.sum
users_info << {user_id: user.id, name: name, passed_myshixun_count: passed_myshixun_count,
passed_games_count: passed_games_count, code_line_count: code_line_count,
evaluate_count: evaluate_count, cost_time: cost_time}
users = User.includes(myshixuns: :games).where(myshixuns: {shixun_id: shixun_ids}, games: {status: 2}, users: {is_test: false})
users.find_in_batches(batch_size: 500) do |u|
Parallel.each(u, in_processes: 2) do |user|
myshixuns = user.myshixuns.select{|m| shixun_ids.include?(m.shixun_id)}
name = "#{user.lastname}#{user.firstname}"
passed_myshixun_count = myshixuns.select{|m| m.status == 1}.size
passed_games_count = myshixuns.map{|m| m.games.select{|g| g.status == 2}.size }.size
code_line_count = 0
evaluate_count = myshixuns.map{|m| m.output_times }.sum
cost_time = myshixuns.map{|m|m.total_cost_time }.sum
users_info << {user_id: user.id, name: name, passed_myshixun_count: passed_myshixun_count,
passed_games_count: passed_games_count, code_line_count: code_line_count,
evaluate_count: evaluate_count, cost_time: cost_time}
end
end
users_info
end

@ -15,11 +15,11 @@ class UpdateHomeworkPublishSettingService < ApplicationService
if params[:unified_setting] || course.course_groups_count == 0
tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_time].blank?
tip_exception("发布时间不能早于当前时间") if params[:publish_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_time]
tip_exception("发布时间不能早于当前时间") if params[:publish_time].to_time <= Time.now
tip_exception("截止时间不能早于当前时间") if params[:end_time].to_time <= Time.now
tip_exception("截止时间必须晚于发布时间") if params[:publish_time].to_time >= params[:end_time].to_time
tip_exception("截止时间不能晚于课堂结束时间(#{course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
course.end_date.present? && params[:end_time] > course.end_date.end_of_day
course.end_date.present? && params[:end_time].to_time > course.end_date.end_of_day
homework.unified_setting = 1
homework.homework_group_settings.destroy_all

@ -16,7 +16,7 @@
<% identifier = Game.find_by(challenge_id: discuss.challenge_id, user_id: discuss.user_id)&.identifier %>
<td class="text-left"><%= link_to discuss.dis.name, "/tasks/#{identifier}", target: '_blank'%></td>
<td class="text-left content-img"><%= content_safe discuss.content %></td>
<td><%= discuss.user.show_real_name %></td>
<td><%= link_to discuss.user.show_real_name, "/users/#{discuss.user.login}", target: '_blank' %></td>
<td><%= format_time discuss.created_at %></td>
</tr>
<% end %>

@ -71,6 +71,13 @@
<span class="only_view">只看vip</span>
</label>
</div>
<div class="mr-5">
<label for="is_wechat_support">
<%= check_box_tag :is_wechat_support, !@sort_json[:is_wechat_support],@sort_json[:is_wechat_support], class:"shixun-settings-select" %>
<span class="only_view">只看小程序可用</span>
</label>
</div>
</div>
</div>
<% end %>

@ -15,7 +15,7 @@
<th>
操作
<div class="setting-chosen">
ssh/隐藏/首页/跳关/隐藏目录/vip
ssh/隐藏/首页/跳关/隐藏目录/vip/小程序
</div>
</th>
</thead>

@ -49,6 +49,7 @@
<%= check_box_tag :task_pass,!shixun.task_pass,shixun.task_pass,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"跳关"%>
<%= check_box_tag :code_hidden,!shixun.code_hidden,shixun.code_hidden,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"隐藏目录"%>
<%= check_box_tag :vip,!shixun.vip,shixun.vip,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"vip"%>
<%= check_box_tag :is_wechat_support,!shixun.is_wechat_support?,shixun.is_wechat_support?,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"小程序可用"%>
</td>
<script>

@ -3,4 +3,5 @@ json.game @game
json.shixun @shixun
json.shixun_env @env
json.shixun_image @shixun.main_mirror_name
json.shixun_tags @shixun_tags

@ -1,7 +1,7 @@
json.single_questions_count @single_questions_count
json.multiple_questions_count @multiple_questions_count
json.judgement_questions_count @judgement_questions_count
json.completion_questions_count @completion_questions_count
json.subjective_questions_count @subjective_questions_count
json.practical_questions_count @practical_questions_count
json.program_questions_count @program_questions_count
json.single_questions_count @basket_count&.fetch("SINGLE", 0)
json.multiple_questions_count @basket_count&.fetch("MULTIPLE", 0)
json.judgement_questions_count @basket_count&.fetch("JUDGMENT", 0)
json.completion_questions_count @basket_count&.fetch("COMPLETION", 0)
json.subjective_questions_count @basket_count&.fetch("SUBJECTIVE", 0)
json.practical_questions_count @basket_count&.fetch("PRACTICAL", 0)
json.program_questions_count @basket_count&.fetch("PROGRAM", 0)

@ -4,25 +4,21 @@ json.shixun_list do
json.array! @results.with_highlights(multiple: true) do |obj, highlights|
json.merge! obj.to_searchable_json
json.challenge_names obj.challenges.pluck(:subject)
# 去除开头标点符号
reg = /^[,。?:;‘’!“”—……、]/
# 附件的替换
atta_reg = /!\[.*]\(\/api\/attachments\/\d+\)/
highlights[:description]&.first&.sub!(reg, '')
highlights[:description]&.map{|des| des.gsub(atta_reg, '')}
highlights[:content]&.first&.sub!(reg, '')
highlights[:content]&.map{|des| des.gsub(atta_reg, '')}
highlights[:description]&.first&.sub!(@reg, '')
highlights[:description]&.map{|des| des.gsub(@atta_reg, '')}
highlights[:content]&.first&.sub!(@reg, '')
highlights[:content]&.map{|des| des.gsub(@atta_reg, '')}
json.title highlights.delete(:name)&.join('...') || obj.searchable_title
json.description highlights[:description]&.join('...') || Util.extract_content(obj.description)[0..300]&.gsub(atta_reg, '')
json.description highlights[:description]&.join('...') || Util.extract_content(obj.description)[0..300]&.gsub(@atta_reg, '')
json.pic url_to_avatar(obj)
json.content highlights
json.level level_to_s(obj.trainee)
json.subjects obj.subjects.visible.unhidden.uniq do |subject|
json.(subject, :id, :name)
end
#if params[:sort] != "wechat_myshixuns_count"
json.subjects obj.subjects.select{ |s| s.status == 2 && s.hidden == 0} do |subject|
json.(subject, :id, :name)
end
#end
end
end

@ -8,6 +8,7 @@ if shixun.can_copy
json.fork_num shixun.fork_count
end
json.id shixun.id
json.identifier shixun.identifier
json.name shixun.name
json.stu_num shixun.myshixuns_count

@ -6,7 +6,7 @@ json.subject_score @subject.all_score
json.member_count @subject.member_count
json.allow_delete (@subject.status != 2 && @is_creator) || @user.admin?
json.publish_status publish_status(@subject, @is_manager, @user, @shixuns)
json.publish_status publish_status(@subject, @is_manager, @user)
json.allow_statistics @is_manager
json.allow_send @user.logged?
json.allow_visit @subject.status > 1 || @is_manager

@ -0,0 +1,8 @@
json.status 0
json.message "success"
json.data do
json.subject_info @subject.subject_record
json.other_info @data
json.total_count @data_count
json.total @total
end

@ -7,6 +7,7 @@ json.admin user.admin?
json.business user.business?
json.is_teacher user.user_extension&.teacher?
json.user_identity user.identity
json.identity user.user_extension&.identity
json.tidding_count 0
json.user_phone_binded user.phone.present?
json.phone user.phone

@ -613,7 +613,6 @@ a级情片
大史纪
戴相龙
弹劾
登辉
邓笑贫
迪里夏提
地下教会

@ -1,6 +1,6 @@
class AddIndexForSubjectRecords < ActiveRecord::Migration[5.2]
def change
remove_index :subject_records, :subject_id
# remove_index :subject_records, :subject_id
add_index :subject_records, :subject_id, unique: true
end
end

@ -0,0 +1,50 @@
class Migrate3176ExerciseScore < ActiveRecord::Migration[5.2]
def calculate_student_score(exercise,user)
score5 = 0.0 #实训题
exercise_end_time = exercise.end_time
exercise_questions = exercise.exercise_questions.includes(:exercise_standard_answers,:exercise_shixun_challenges)
exercise_questions.each do |q|
if q.question_type == 5
q.exercise_shixun_challenges.each do |exercise_cha|
game = Game.user_games(user.id,exercise_cha.challenge_id)&.first #当前用户的关卡
if game.present?
exercise_cha_score = 0.0
answer_status = 0
# if game.status == 2 && game.final_score >= 0
if game.final_score > 0 && (game.end_time.nil? || game.end_time < exercise_end_time)
exercise_cha_score = game.real_score(exercise_cha.question_score)
# exercise_cha_score = exercise_cha.question_score #每一关卡的得分
answer_status = 1
end
ex_shixun_answer_content = exercise_cha.exercise_shixun_answers.find_by(user_id:user.id,exercise_question_id:q.id)
if ex_shixun_answer_content.present? && !(ex_shixun_answer_content.score >0) #把关卡的答案存入试卷的实训里
ex_shixun_answer_content.update_attributes!(score:exercise_cha_score.round(1),status:answer_status)
end
score5 += exercise_cha_score
else
score5 += 0.0
end
end
end
end
score5
end
def change
exercise = Exercise.find_by(id: 3176)
if exercise
exercise_users = exercise.exercise_users.where("start_at is not null")
exercise_users.each do |exercise_user|
calculate_score = calculate_student_score(exercise, exercise_user.user)
subjective_score = exercise_user.subjective_score
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = calculate_score + total_score_subjective_score
if exercise_user.end_at.present?
exercise_user.update_attributes!(score:total_score,objective_score:calculate_score)
end
puts exercise_user.id
end
end
end
end

@ -0,0 +1,49 @@
class Migrate3517ExerciseScore < ActiveRecord::Migration[5.2]
def calculate_student_score(exercise,user)
score5 = 0.0 #实训题
exercise_end_time = exercise.end_time
exercise_questions = exercise.exercise_questions.includes(:exercise_standard_answers,:exercise_shixun_challenges)
exercise_questions.each do |q|
if q.question_type == 5
q.exercise_shixun_challenges.each do |exercise_cha|
game = Game.user_games(user.id,exercise_cha.challenge_id)&.first #当前用户的关卡
if game.present?
exercise_cha_score = 0.0
answer_status = 0
# if game.status == 2 && game.final_score >= 0
if game.final_score > 0 && (game.end_time.nil? || game.end_time < exercise_end_time)
exercise_cha_score = game.real_score(exercise_cha.question_score)
# exercise_cha_score = exercise_cha.question_score #每一关卡的得分
answer_status = 1
end
ex_shixun_answer_content = exercise_cha.exercise_shixun_answers.find_by(user_id:user.id,exercise_question_id:q.id)
if ex_shixun_answer_content.present? && !(ex_shixun_answer_content.score >0) #把关卡的答案存入试卷的实训里
ex_shixun_answer_content.update_attributes!(score:exercise_cha_score.round(1),status:answer_status)
end
score5 += exercise_cha_score
else
score5 += 0.0
end
end
end
end
score5
end
def change
exercise = Exercise.find_by(id: 3517)
if exercise
exercise_users = exercise.exercise_users.where("start_at is not null")
exercise_users.each do |exercise_user|
calculate_score = calculate_student_score(exercise, exercise_user.user)
subjective_score = exercise_user.subjective_score
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = calculate_score + total_score_subjective_score
if exercise_user.end_at.present?
exercise_user.update_attributes!(score:total_score,objective_score:calculate_score)
end
puts exercise_user.id
end
end
end
end

@ -0,0 +1,5 @@
class AddWecharSupportForShixuns < ActiveRecord::Migration[5.2]
def change
add_column :shixuns, :is_wechat_support, :boolean, :default => false
end
end

@ -0,0 +1,25 @@
class MigrateCouresMemberGroup < ActiveRecord::Migration[5.2]
def change
course_ids = [377, 657, 715, 777, 973, 1093, 1131, 1180, 1309, 1920, 2037, 2346, 2354, 2493, 2752, 2920, 3000,
3141, 3240, 3350, 3351, 3353, 3387, 3533, 3796]
courses = Course.where(id: course_ids)
courses.each do |course|
group_ids = course.course_groups.pluck(:id) + [0]
course.course_members.where.not(course_group_id: group_ids).each do |member|
if CourseGroup.where(course_id: course.id, name: member.course_group_name).exists?
new_group = CourseGroup.where(course_id: course.id, name: member.course_group_name).first
else
# position = CourseGroup.where(course_id: course.id).order("position desc").first&.position.to_i + 1
new_group = course.course_groups.create!(name: member.course_group_name)
course.exercise_group_settings.where(course_group_id: member.course_group_id).update_all(course_group_id: new_group.id)
course.attachment_group_settings.where(course_group_id: member.course_group_id).update_all(course_group_id: new_group.id)
HomeworkGroupReview.where(homework_common_id: course.homework_commons.pluck(:id)).where(course_group_id: member.course_group_id).update_all(course_group_id: new_group.id)
course.homework_group_settings.where(course_group_id: member.course_group_id).update_all(course_group_id: new_group.id)
end
member.update!(course_group_id: new_group.id)
end
end
end
end

@ -0,0 +1,14 @@
class MigrateCoureGroupPosition < ActiveRecord::Migration[5.2]
def change
course_ids = [377, 657, 715, 777, 973, 1093, 1131, 1180, 1309, 1920, 2037, 2346, 2354, 2493, 2752, 2920, 3000,
3141, 3240, 3350, 3351, 3353, 3387, 3533, 3796]
courses = Course.where(id: course_ids)
courses.each do |course|
CourseGroup.where(course_id: course.id).reorder("position ASC, CONVERT(course_groups.name USING gbk) COLLATE gbk_chinese_ci ASC").each_with_index do |group, index|
group.update!(position: index+1)
end
end
end
end

@ -0,0 +1,8 @@
class ModifyWechatSupportForShixuns < ActiveRecord::Migration[5.2]
def change
name = ["Python基础", "C语言基础", "C++基础", "Java"]
shixuns = Shixun.includes(:tag_repertoires)
.where(tag_repertoires: {name: name}, shixuns: {status: 2, hide_code: false})
shixuns.update_all(is_wechat_support: true)
end
end

@ -0,0 +1,17 @@
class AddChoiceIndexToExerciseAnswers < ActiveRecord::Migration[5.2]
def change
add_column :exercise_answers, :choice_index, :integer, default: 1
multi_questions = ExerciseQuestion.where(question_type: 1)
multi_questions.includes(:exercise_choices, :exercise_answers).find_each do |question|
exercise_answers = question.exercise_answers
exercise_answers.find_each do |answer|
choice_index = question.exercise_choices.pluck(:id).index(answer.exercise_choice_id).to_i + 1
answer.update_column('choice_index', choice_index)
end
puts "multi_questions: #{question.id}"
end
ExerciseAnswer.joins(:exercise_question).where(exercise_questions: {question_type: 3}).update_all("choice_index = exercise_choice_id")
end
end

@ -0,0 +1,13 @@
class AddChoiceIndexUniqIndexToExerciseAnswers < ActiveRecord::Migration[5.2]
def change
sql = %Q(delete from exercise_answers where (exercise_question_id, user_id, choice_index) in
(select * from (select exercise_question_id, user_id, choice_index from exercise_answers group by exercise_question_id, user_id, choice_index having count(*) > 1) a)
and id not in (select * from (select max(id) from exercise_answers group by exercise_question_id, user_id, choice_index having count(*) > 1 order by id) b))
ActiveRecord::Base.connection.execute sql
add_index :exercise_answers, [:exercise_question_id, :user_id, :choice_index], name: 'exercise_user_choice_index', unique: true
remove_index :exercise_answers, name: :exercise_choice_index
end
end

@ -0,0 +1,13 @@
class Modify1WechatSupportForShixuns < ActiveRecord::Migration[5.2]
def change
shixuns = Shixun.joins(:challenges).where(is_wechat_support: true, status: 2)
.select("shixuns.*, challenges.path path")
shixuns.each do |shixun|
if shixun.path && shixun.path.split("").count > 1
shixun.update_attribute(:is_wechat_support, false)
end
end
Shixun.joins(:challenges).where(challenges: {st: 1}).update_all(is_wechat_support: false)
end
end

@ -4,30 +4,32 @@ namespace :subjects do
task data_statistic: :environment do
puts("---------------------data_statistic_begin")
Rails.logger.info("---------------------data_statistic_begin")
subjects = Subject.where(status: 2)
subjects = Subject.where(status: 2, hidden: 0)
str = ""
buffer_size = 0
column_value = "subject_id, study_count, course_study_count, initiative_study, passed_count, course_used_count, " +
"school_used_count, created_at, updated_at"
subjects.find_each do |subject|
puts("---------------------data_statistic: #{subject.id}")
Rails.logger.info("---------------------data_statistic: #{subject.id}")
data = Subjects::DataStatisticService.new(subject)
study_count = data.study_count
next if study_count == 0
course_study_count = data.course_study_count
initiative_study = study_count - course_study_count
str += ", " unless str.empty?
str += ("(#{subject.id}, #{study_count}, #{course_study_count}, #{initiative_study}, " +
"#{data.passed_count}, #{data.course_used_count}, #{data.school_used_count}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1
if buffer_size == 1000
sql = "REPLACE INTO subject_records(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
subjects.find_in_batches(batch_size: 50) do |s, index|
Parallel.each_with_index(s, in_processes: 4) do |subject|
puts("---------------------data_statistic: #{subject.id}")
Rails.logger.info("---------------------data_statistic: #{subject.id}")
data = Subjects::DataStatisticService.new(subject)
study_count = data.study_count
next if study_count == 0
course_study_count = data.course_study_count
initiative_study = study_count - course_study_count
str += ", " unless str.empty?
str += ("(#{subject.id}, #{study_count}, #{course_study_count}, #{initiative_study}, " +
"#{data.passed_count}, #{data.course_used_count}, #{data.school_used_count}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1
if buffer_size == 1000 || subjects.count == (index+1)
sql = "REPLACE INTO subject_records(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
end
end
end
if buffer_size > 0
@ -42,28 +44,31 @@ namespace :subjects do
task course_info_statistic: :environment do
puts("---------------------course_info_statistic_begin")
Rails.logger.info("---------------------course_info_statistic_begin")
subjects = Subject.where(status: 2)
subjects = Subject.where(status: 2, hidden: 0)
str = ""
buffer_size = 0
column_value = "subject_id, school_id, school_name, course_count, student_count, choice_shixun_num, " +
"choice_shixun_frequency, created_at, updated_at"
subjects.find_each do |subject|
puts("---------------------course_info_statistic: #{subject.id}")
Rails.logger.info("---------------------course_info_statistic: #{subject.id}")
data = Subjects::CourseUsedInfoService.call(subject)
data.each do |key|
next if key[:school_id].nil?
str += ", " unless str.empty?
str += ("(#{subject.id}, #{key[:school_id]}, '#{key[:school_name]}', #{key[:course_count]}, " +
"#{key[:student_count]}, #{key[:choice_shixun_num]}, #{key[:choice_shixun_frequency]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1
if buffer_size == 1000
sql = "REPLACE INTO subject_course_records(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
subjects.find_in_batches(batch_size: 50) do |s|
Parallel.each(s, in_processes: 4) do |subject|
puts("---------------------course_info_statistic: #{subject.id}")
Rails.logger.info("---------------------course_info_statistic: #{subject.id}")
data = Subjects::CourseUsedInfoService.call(subject)
Parallel.map_with_index(data) do |key, index|
next if key[:school_id].nil?
str += ", " unless str.empty?
str += ("(#{subject.id}, #{key[:school_id]}, '#{key[:school_name]}', #{key[:course_count]}, " +
"#{key[:student_count]}, #{key[:choice_shixun_num]}, #{key[:choice_shixun_frequency]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1
if buffer_size == 1000 || (index + 1) == data.size
sql = "REPLACE INTO subject_course_records(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
end
end
end
end
@ -79,29 +84,31 @@ namespace :subjects do
task shixun_info_statistic: :environment do
puts("---------------------shixun_info_statistic_begin")
Rails.logger.info("---------------------shixun_info_statistic_begin")
subjects = Subject.where(status: 2)
subjects = Subject.where(status: 2, hidden: 0)
str = ""
buffer_size = 0
column_value = "subject_id, shixun_id, stage, shixun_name, challenge_count, course_count, " +
"school_count, used_count, passed_count, evaluate_count, passed_ave_time, created_at, updated_at"
subjects.find_each(batch_size: 100) do |subject|
puts("---------------------shixun_info_statistic: #{subject.id}")
Rails.logger.info("---------------------shixun_info_statistic: #{subject.id}")
data = Subjects::ShixunUsedInfoService.call(subject)
data.each do |key|
next if key[:shixun_id].nil?
str += ", " unless str.empty?
str += ("(#{subject.id}, #{key[:shixun_id]}, '#{key[:stage]}', '#{key[:name]}', #{key[:challenge_count]}, " +
"#{key[:course_count]}, #{key[:school_count]}, #{key[:used_count]}, #{key[:passed_count]}, " +
"#{key[:evaluate_count]}, #{key[:passed_ave_time]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1
if buffer_size == 1000
sql = "REPLACE INTO subject_shixun_infos(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
subjects.find_in_batches(batch_size: 50) do |s|
Parallel.each_with_index(s, in_processes: 4) do |subject|
puts("---------------------shixun_info_statistic: #{subject.id}")
Rails.logger.info("---------------------shixun_info_statistic: #{subject.id}")
data = Subjects::ShixunUsedInfoService.call(subject)
data.each_with_index do |key, index|
next if key[:shixun_id].nil?
str += ", " unless str.empty?
str += ("(#{subject.id}, #{key[:shixun_id]}, '#{key[:stage]}', '#{key[:name]}', #{key[:challenge_count]}, " +
"#{key[:course_count]}, #{key[:school_count]}, #{key[:used_count]}, #{key[:passed_count]}, " +
"#{key[:evaluate_count]}, #{key[:passed_ave_time]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1
if buffer_size == 1000 || (index+1) == data.size
sql = "REPLACE INTO subject_shixun_infos(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
end
end
end
end
@ -117,27 +124,29 @@ namespace :subjects do
task user_info_statistic: :environment do
puts("---------------------user_info_statistic_begin")
Rails.logger.info("---------------------user_info_statistic_begin")
subjects = Subject.where(status: 2)
subjects = Subject.where(status: 2, hidden: 0)
str = ""
buffer_size = 0
column_value = "user_id, subject_id, username, passed_myshixun_count, passed_games_count, " +
"code_line_count, evaluate_count, cost_time, created_at, updated_at"
subjects.find_each(batch_size: 50) do |subject|
puts("---------------------user_info_statistic: #{subject.id}")
data = Subjects::UserUsedInfoService.call(subject)
data.each do |key|
next if key[:user_id].nil?
str += ", " unless str.empty?
str += ("(#{key[:user_id]}, #{subject.id}, '#{key[:name]}', '#{key[:passed_myshixun_count]}', " +
"#{key[:passed_games_count]}, #{key[:code_line_count]}, #{key[:evaluate_count]}, #{key[:cost_time]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1
if buffer_size == 1000
sql = "REPLACE INTO subject_user_infos(#{column_value}) VALUES #{str}"
puts sql
ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
subjects.find_in_batches(batch_size: 50) do |s|
Parallel.each_with_index(s, in_processes: 4) do |subject, index|
puts("---------------------user_info_statistic: #{subject.id}")
data = Subjects::UserUsedInfoService.call(subject)
data.each do |key|
next if key[:user_id].nil?
str += ", " unless str.empty?
str += ("(#{key[:user_id]}, #{subject.id}, '#{key[:name].gsub(/'/, '"')}', #{key[:passed_myshixun_count]}, " +
"#{key[:passed_games_count]}, #{key[:code_line_count]}, #{key[:evaluate_count]}, #{key[:cost_time]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
buffer_size += 1
if buffer_size == 1000 || (index+1 == data.size)
sql = "REPLACE INTO subject_user_infos(#{column_value}) VALUES #{str}"
ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
end
end
end
end

@ -1,51 +1,85 @@
# 执行示例 bundle exec rake zip_pack:shixun_pack args=123,2323
# 执行示例 bundle exec rake zip_pack:shixun_pack class=Course ids=123,2323 parallel_size=4
# 执行示例 bundle exec rake zip_pack:shixun_pack class=HomeworkCommon ids=123,2323
namespace :zip_pack do
desc "手工打包作品"
OUTPUT_FOLDER = "#{Rails.root}/files/archiveZip"
task :shixun_pack => :environment do
if ENV['args']
homework_ids = ENV['args'].split(",").map(&:to_i)
homeworks = HomeworkCommon.where(id: homework_ids)
homeworks.includes(:score_student_works).each do |homework|
out_file_name = "#{Time.now.strftime("%Y%m%d%H%M%S").to_s}-#{homework.course_id}-#{homework.name}.zip"
out_file_name.gsub!(" ", "-")
out_file_name.gsub!("/", "_")
if ENV['class'] && ENV['ids']
parallel_size = ENV['parallel_size'] || 2
parallel_size = parallel_size.to_i
env_ids = ENV['ids'].split(",").map(&:to_i)
folders = []
if ENV['class'] == "Course"
courses = Course.where(id: env_ids)
courses.each do |course|
homeworks = course.practice_homeworks.homework_published
new_dir_name = "#{course.name.to_s.strip}_#{Time.now.strftime("%Y%m%d%H%M%S").to_s}"
new_dir_name.gsub!(" ", "-")
new_dir_name.gsub!("/", "_")
new_folder = "#{OUTPUT_FOLDER}/#{new_dir_name}"
zip_homework_pdf homeworks, new_folder, parallel_size
folders << new_folder
end
else
homeworks = HomeworkCommon.where(id: env_ids)
new_dir_name = "#{homeworks.first&.course&.name.to_s.strip}_#{Time.now.strftime("%Y%m%d%H%M%S").to_s}"
new_dir_name.gsub!(" ", "-")
new_dir_name.gsub!("/", "_")
new_folder = "#{OUTPUT_FOLDER}/#{new_dir_name}"
zip_homework_pdf homeworks, new_folder, parallel_size
folders << new_folder
end
zipfile_name = "#{OUTPUT_FOLDER}/#{out_file_name}"
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
puts "下载路径: #{folders.join(",")}"
end
end
student_works = homework.score_student_works
def zip_homework_pdf homeworks, folder, parallel_size
Dir.mkdir(folder) unless File.directory?(folder)
if student_works.size > 0
pdfs = []
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zip|
student_works.find_each.map do |student_work|
export = ExportShixunReportService.new(homework, student_work)
pdf = export.to_pdf
pdfs << pdf
begin
zip.add(export.filename, pdf.path)
puts "out: #{export.filename}_#{pdf.path}"
rescue => ex
Rails.logger.error(ex.message)
homeworks.includes(:score_student_works).each do |homework|
out_file_name = "#{Time.now.strftime("%Y%m%d%H%M%S").to_s}-#{homework.course_id}-#{homework.name}.zip"
out_file_name.gsub!(" ", "-")
out_file_name.gsub!("/", "_")
zip.get_output_stream('FILE_NOTICE.txt'){|os| os.write("文件重复:#{export.filename}") }
next
end
end
zipfile_name = "#{folder}/#{out_file_name}"
student_works = homework.score_student_works
if student_works.size > 0
pdfs = []
file_paths = []
student_works.find_in_batches(batch_size: 500) do |sw|
Parallel.each(sw, in_threads: parallel_size) do |student_work|
export = ExportShixunReportService.new(homework, student_work)
pdf = export.to_pdf
pdfs << pdf
file_paths << {filename: export.filename, path: pdf.path}
puts "out: #{export.filename}_#{pdf.path}"
end
zipfile = zipfile_name
else
zipfile = {:message => "no file"}
end
puts "out: #{zipfile}"
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zip|
file_paths.each do |pdf|
begin
zip.add(pdf[:filename], pdf[:path])
rescue => ex
Rails.logger.error(ex.message)
zip.get_output_stream('FILE_NOTICE.txt'){|os| os.write("文件重复:#{export.filename}") }
next
end
end
end
else
zipfile = {:message => "no file"}
end
end
end
# 执行示例 bundle exec rake zip_pack:homework_attach_pack args=123
task :homework_attach_pack => :environment do
include ExportHelper
if ENV['args']
@ -61,7 +95,4 @@ namespace :zip_pack do
end
end
def filename_for_content_disposition(name)
request.env['HTTP_USER_AGENT'] =~ %r{MSIE|Trident|Edge} ? ERB::Util.url_encode(name) : name
end
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

@ -75,6 +75,7 @@
"react-codemirror": "^1.0.0",
"react-codemirror2": "^6.0.0",
"react-content-loader": "^3.1.1",
"react-cookies": "^0.1.1",
"react-dev-utils": "^5.0.0",
"react-dom": "^16.9.0",
"react-hot-loader": "^4.0.0",
@ -176,6 +177,7 @@
"compression-webpack-plugin": "^1.1.12",
"concat": "^1.0.3",
"happypack": "^5.0.1",
"mockjs": "^1.1.0",
"node-sass": "^4.12.0",
"reqwest": "^2.0.5",
"webpack-bundle-analyzer": "^3.0.3",

@ -1269,7 +1269,7 @@ input.knowledge_frame{height:28px;line-height:28px;border:none;background:#f3f5f
.-relative { position: relative;}
.-bg-white { background-color: #eee;}
.split-panel.-handle .split-panel--second { padding-left: 2px;}
.split-panel--second { overflow: hidden;}
/* .split-panel--second { overflow: hidden;} */
.task-answer-view { position: absolute; top: 0; right: 0; bottom: 0;left: 0; display: flex;
flex-direction: column; border-top: 1px solid #515151;}
.-vertical { flex-direction: column;box-flex-direction: column;-webkit-flex-direction: column;}

@ -1134,6 +1134,12 @@
<div class="code-name">&amp;#xe7f9;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe71b;</span>
<div class="name">过滤器</div>
<div class="code-name">&amp;#xe71b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6ee;</span>
<div class="name">20从属连接</div>
@ -1866,6 +1872,18 @@
<div class="code-name">&amp;#xe719;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe71c;</span>
<div class="name">初始化</div>
<div class="code-name">&amp;#xe71c;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe71e;</span>
<div class="name">测试集</div>
<div class="code-name">&amp;#xe71e;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
@ -3572,6 +3590,15 @@
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-guolvqi"></span>
<div class="name">
过滤器
</div>
<div class="code-name">.icon-guolvqi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-congshulianjie"></span>
<div class="name">
@ -4670,6 +4697,24 @@
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-chushihua"></span>
<div class="name">
初始化
</div>
<div class="code-name">.icon-chushihua
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-ceshiji"></span>
<div class="name">
测试集
</div>
<div class="code-name">.icon-ceshiji
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
@ -6171,6 +6216,14 @@
<div class="code-name">#icon-gengduo1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-guolvqi"></use>
</svg>
<div class="name">过滤器</div>
<div class="code-name">#icon-guolvqi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-congshulianjie"></use>
@ -7147,6 +7200,22 @@
<div class="code-name">#icon-jiashang1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-chushihua"></use>
</svg>
<div class="name">初始化</div>
<div class="code-name">#icon-chushihua</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-ceshiji"></use>
</svg>
<div class="name">测试集</div>
<div class="code-name">#icon-ceshiji</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1293,6 +1293,13 @@
"unicode": "e7f9",
"unicode_decimal": 59385
},
{
"icon_id": "5327531",
"name": "过滤器",
"font_class": "guolvqi",
"unicode": "e71b",
"unicode_decimal": 59163
},
{
"icon_id": "5379378",
"name": "20从属连接",
@ -2146,6 +2153,20 @@
"font_class": "jiashang1",
"unicode": "e719",
"unicode_decimal": 59161
},
{
"icon_id": "12826208",
"name": "初始化",
"font_class": "chushihua",
"unicode": "e71c",
"unicode_decimal": 59164
},
{
"icon_id": "12826211",
"name": "测试集",
"font_class": "ceshiji",
"unicode": "e71e",
"unicode_decimal": 59166
}
]
}

@ -572,6 +572,9 @@ Created by iconfont
<glyph glyph-name="gengduo1" unicode="&#59385;" d="M104 376m-104 0a104 104 0 1 1 208 0 104 104 0 1 1-208 0ZM920 376m-104 0a104 104 0 1 1 208 0 104 104 0 1 1-208 0ZM512 384m-160 0a160 160 0 1 1 320 0 160 160 0 1 1-320 0Z" horiz-adv-x="1024" />
<glyph glyph-name="guolvqi" unicode="&#59163;" d="M908.6 761.3c6.5-15.5 3.8-28.8-8-39.7L620.9 441.9V21c0-15.8-7.4-27.1-22.1-33.5-4.9-2-9.7-2.9-14.2-2.9-10.3 0-18.7 3.6-25.5 10.7L413.8 140.8c-7.2 7.2-10.7 15.7-10.7 25.5V441.9L123.4 721.6c-11.7 11-14.3 24.2-8 39.7 6.5 14.8 17.5 22.1 33.5 22.1H875c16 0.1 27.2-7.3 33.6-22.1z" horiz-adv-x="1024" />
<glyph glyph-name="congshulianjie" unicode="&#59118;" d="M844.8 230.4a128 128 0 0 1-125.44-102.4H358.4a102.4 102.4 0 0 0 0 204.8h307.2a153.6 153.6 0 0 1 0 307.2H304.64a128 128 0 1 1 0-51.2H665.6a102.4 102.4 0 0 0 0-204.8H358.4a153.6 153.6 0 0 1 0-307.2h360.96a128 128 0 1 1 125.44 153.6z m0-204.8a76.8 76.8 0 1 0 76.8 76.8 76.8 76.8 0 0 0-76.8-76.8z" horiz-adv-x="1024" />
@ -938,6 +941,12 @@ Created by iconfont
<glyph glyph-name="jiashang1" unicode="&#59161;" d="M512-128C228.693333-128 0 100.693333 0 384S228.693333 896 512 896s512-228.693333 512-512-228.693333-512-512-512z m0 989.866667C249.173333 861.866667 34.133333 646.826667 34.133333 384s215.04-477.866667 477.866667-477.866667 477.866667 215.04 477.866667 477.866667S774.826667 861.866667 512 861.866667zM699.733333 332.8h-375.466666c-20.48 0-34.133333 13.653333-34.133334 34.133333s13.653333 34.133333 34.133334 34.133334h375.466666c20.48 0 34.133333-13.653333 34.133334-34.133334s-13.653333-34.133333-34.133334-34.133333zM512 145.066667c-20.48 0-34.133333 13.653333-34.133333 34.133333V554.666667c0 20.48 13.653333 34.133333 34.133333 34.133333s34.133333-13.653333 34.133333-34.133333v-375.466667c0-20.48-13.653333-34.133333-34.133333-34.133333z" horiz-adv-x="1024" />
<glyph glyph-name="chushihua" unicode="&#59164;" d="M511.682434-128A468.457376 468.457376 0 0 0 44.559694 340.457376a66.73182 66.73182 0 0 0 133.46364 0A333.6591 333.6591 0 1 1 511.682434 675.451113a330.989827 330.989827 0 0 1-235.785764-98.095776 66.73182 66.73182 0 0 0-111.2197 66.73182l60.503517 203.309612a66.798552 66.798552 0 1 0 128.125094-37.814698l-9.564894-31.808835A468.234937 468.234937 0 1 0 511.682434-128zM600.658194 183.41516h-133.46364a66.73182 66.73182 0 0 0-66.73182 66.73182V472.58638a66.73182 66.73182 0 0 0 133.46364 0v-155.70758h66.73182a66.73182 66.73182 0 0 0 0-133.46364z" horiz-adv-x="1024" />
<glyph glyph-name="ceshiji" unicode="&#59166;" d="M536.332172 333.97898a75.330291 75.330291 0 0 0-29.985844 6.338471l-463.195967 207.95061a73.136205 73.136205 0 0 0 0 133.351681l463.195967 207.95061a73.136205 73.136205 0 0 0 59.971688 0l463.195966-207.95061a73.136205 73.136205 0 0 0 0-133.351681l-463.195966-207.95061a75.330291 75.330291 0 0 0-29.985844-6.338471zM251.832333 614.822008L536.332172 487.321224l284.499838 127.500784L536.332172 742.56658zM536.332172 102.868571a73.136205 73.136205 0 0 0-31.204781 7.069834l-463.195967 219.408615a73.184963 73.184963 0 0 0 62.409562 132.376532L536.332172 257.429752l431.259823 215.020443a73.136205 73.136205 0 0 0 65.33501-130.913807l-463.195966-230.866621a73.136205 73.136205 0 0 0-33.398867-7.801196zM536.332172-127.99805a73.136205 73.136205 0 0 0-31.204781 7.069833l-463.195967 219.408616a73.136205 73.136205 0 0 0 62.409562 131.888957L536.332172 26.319343l431.259823 215.264231a73.136205 73.136205 0 0 0 65.33501-130.913807l-463.195966-230.866621A73.136205 73.136205 0 0 0 536.332172-127.99805z" horiz-adv-x="1073" />
</font>

Before

Width:  |  Height:  |  Size: 381 KiB

After

Width:  |  Height:  |  Size: 383 KiB

@ -145,7 +145,7 @@ input.knowledge_frame{height:28px;line-height:28px;border:none;background:#f3f5f
.-relative { position: relative;}
.-bg-white { background-color: #eee;}
.split-panel.-handle .split-panel--second { padding-left: 2px;}
.split-panel--second { overflow: hidden;}
/* .split-panel--second { overflow: hidden;} */
.task-answer-view { position: absolute; top: 0; right: 0; bottom: 0;left: 0; display: flex;
flex-direction: column; border-top: 1px solid #515151;}
.-vertical { flex-direction: column;box-flex-direction: column;-webkit-flex-direction: column;}

@ -17,6 +17,7 @@
<meta name=”Description” Content=”EduCoder翻转课堂教学模式颠覆了传统教学模式让教师与学生的关系由“权威”变成了“伙伴”。将学习的主动权转交给学生使学生可个性化化学学生的学习主体得到了彰显。”>
<meta name=”Description” Content=”EduCoder实训项目为单个知识点关卡实践训练帮助学生巩固单一弱点强化学习。 >
<meta name=”Description” Content=”EduCoder实践教学平台各类大赛为进一步提高各类学生综合运用高级语言程序设计能力培养创新意识和实践探索精神发掘优秀软件人才。 >
<meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3">
<meta name="theme-color" content="#000000">

@ -366,6 +366,11 @@ const JupyterTPI = Loadable({
loader: () => import('./modules/tpm/jupyter'),
loading: Loading
});
// 微信代码编辑器
const WXCode = Loadable({
loader: () => import('./modules/wxcode'),
loading: Loading
});
// //个人竞赛报名
// const PersonalCompetit = Loadable({
// loader: () => import('./modules/competition/personal/PersonalCompetit.js'),
@ -823,6 +828,11 @@ class App extends Component {
render={
(props) => (<Headplugselection {...this.props} {...props} {...this.state} />)
}/>
<Route path="/wxcode/:identifier?" component={WXCode}
render={
(props)=>(<WXCode {...this.props} {...props} {...this.state}></WXCode>)
}
/>
<Route exact path="/"
// component={ShixunsHome}
render={

@ -5,6 +5,7 @@ import md5 from 'md5';
import { requestProxy } from "./indexEduplus2RequestProxy";
import { broadcastChannelOnmessage ,SetAppModel, isDev, queryString } from 'educoder';
import { notification } from 'antd';
import cookie from 'react-cookies';
import './index.css';
const $ = window.$;
const opens ="79e33abd4b6588941ab7622aed1e67e8";
@ -24,6 +25,18 @@ function locationurl(list){
}
function setCookier(){
const _params = window.location.search;
if (_params) {
let _search = _params.split('?')[1];
_search.split('&').forEach(item => {
console.log(item);
const _arr = item.split('=');
cookie.save('_educoder_session',_arr[0]);
cookie.save('autologin_trustie',_arr[1]);
});
}
}
// TODO 开发期多个身份切换
let debugType =""
@ -82,9 +95,36 @@ export function initAxiosInterceptors(props) {
// proxy = "https://testeduplus2.educoder.net"
//proxy="http://47.96.87.25:48080"
proxy="https://pre-newweb.educoder.net"
proxy="https://test-newweb.educoder.net"
// proxy="https://test-jupyterweb.educoder.net"
// proxy="https://test-newweb.educoder.net"
proxy="https://test-jupyterweb.educoder.net"
// proxy="https://test-jupyterweb.educoder.net"
//proxy="http://192.168.2.63:3001"
try {
const str =window.location.pathname;
if(str.indexOf("/wxcode") !== -1){
// console.log("开始重写cookis");
const _params = window.location.search;
// console.log("1111");
if (_params) {
// console.log("22222");
let _search = _params.split('?')[1];
_search.split('&').forEach(item => {
const _arr = item.split('=');
if(_arr[0]==='_educoder_session'){
cookie.save('_educoder_session',_arr[1],{ path: '/' });
cookie.save('_educoder_session',_arr[1], { domain: '.educoder.net', path: '/'});
}else{
cookie.save('autologin_trustie',_arr[1],{ path: '/' });
cookie.save('autologin_trustie',_arr[1], { domain: '.educoder.net', path: '/'});
}
});
}
}
}catch (e) {
}
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
// 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制
@ -94,7 +134,7 @@ export function initAxiosInterceptors(props) {
requestMap[keyName] = false;
}
//响应前的设置
axios.interceptors.request.use(
config => {
// config.headers['Content-Type']= 'no-cache'
@ -109,6 +149,56 @@ export function initAxiosInterceptors(props) {
// proxy = 'http://localhost:3000'
// }
// ---------------------------------------------
// console.log("开始请求了");
// console.log(config.url);
// console.log(window.location.pathname);
//
// try {
// const str =window.location.pathname;
// if(str.indexOf("/wxcode") !== -1){
// // console.log("开始重写cookis");
// const _params = window.location.search;
// // console.log("1111");
// if (_params) {
// // console.log("22222");
// let _search = _params.split('?')[1];
// var _educoder_sessionmys="";
// var autologin_trusties="";
// _search.split('&').forEach(item => {
// const _arr = item.split('=');
// if(_arr[0]==='_educoder_session'){
// cookie.save('_educoder_session',_arr[1], { domain: '.educoder.net', path: '/'});
// _educoder_sessionmys=_arr[1];
// }else{
// cookie.save('autologin_trustie',_arr[1], { domain: '.educoder.net', path: '/'});
// autologin_trusties=_arr[1];
// }
// });
// try {
// const autlogins= `_educoder_session=${_educoder_sessionmys}; autologin_trustie=${autologin_trusties} `;
// config.params = {'Cookie': autlogins}
// config.headers['Cookie'] =autlogins;
// // console.log("设置了cookis");
// } catch (e) {
//
// }
// try {
// const autloginysls= `_educoder_session=${_educoder_sessionmys}; autologin_trustie=${autologin_trusties} `;
// config.params = {'autloginysls': autloginysls}
// config.headers['Cookie'] =autloginysls;
// // console.log("设置了cookis");
// }catch (e) {
//
// }
// }
// }
// }catch (e) {
//
// }
if (config.url.indexOf(proxy) != -1 || config.url.indexOf(':') != -1) {
return config
}

@ -5,6 +5,7 @@
export { getImageUrl as getImageUrl, getRandomNumber as getRandomNumber,getUrl as getUrl, publicSearchs as publicSearchs,getRandomcode as getRandomcode,getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl,getUploadActionUrltwo as getUploadActionUrltwo ,getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
, getTaskUrlById as getTaskUrlById, TEST_HOST ,htmlEncode as htmlEncode ,getupload_git_file as getupload_git_file} from './UrlTool';
export {setmiyah as setmiyah} from './Component';
export { default as queryString } from './UrlTool2';

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save