dev_new_shixunsrepository
杨树林 5 years ago
commit 3a455500a6

@ -109,3 +109,5 @@ gem 'request_store'
# 敏感词汇 # 敏感词汇
gem 'harmonious_dictionary', '~> 0.0.1' 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, homepage_show: params[:homepage_show].present? ? params[:homepage_show] : false,
task_pass: params[:task_pass].present? ? params[:task_pass] : false, task_pass: params[:task_pass].present? ? params[:task_pass] : false,
code_hidden: params[:code_hidden].present? ? params[:code_hidden] : 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) @shixuns_type_check = MirrorRepository.pluck(:type_name,:id)
@ -131,6 +132,7 @@ class Admins::ShixunSettingsController < Admins::BaseController
end end
def setting_params 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
end end

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

@ -11,9 +11,9 @@ class DiscussesController < ApplicationController
# 总数,分页使用 # 总数,分页使用
if @manger 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, disscusses = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s,
:root_id => nil) :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") @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) .select("discusses.*, games.identifier").includes(:user, :praise_treads).limit(LIMIT).offset(offset)
else else

@ -3,93 +3,81 @@ class ExerciseAnswersController < ApplicationController
before_action :get_exercise_question before_action :get_exercise_question
include ExercisesHelper 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 #每一次答案的点击,请求一次,实训题不在这里回答 def create #每一次答案的点击,请求一次,实训题不在这里回答
begin q_type = @exercise_question.question_type #试卷的类型
q_type = @exercise_question.question_type #试卷的类型 choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : ""
choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : "" answer_text = params[:answer_text].present? ? params[:answer_text].strip : "" #为字符串
answer_text = params[:answer_text].present? ? params[:answer_text].strip : "" #为字符串 if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank?
if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank? normal_status(-1,"请选择序号")
normal_status(-1,"请选择序号") else
else ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案
ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案 if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题
if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题 if ea.exists?
if ea.exists? ea.first.update!(exercise_choice_id: choice_id )
ea.first.update!(exercise_choice_id: choice_id ) else
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 #简答题
answer_option = { answer_option = {
:user_id => current_user.id, :user_id => current_user.id,
:exercise_question_id => @exercise_question.id :exercise_question_id => @exercise_question.id,
:exercise_choice_id => choice_id,
:answer_text => ""
} }
if ea.present? #已经回答了的, ex_a = ExerciseAnswer.new(answer_option)
ea.first.update!(answer_text: answer_text) ex_a.save!
else end
answer_option.merge!(answer_text:answer_text) 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 = ExerciseAnswer.new(answer_option)
ex_a.save! ex_a.save!
end end
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 end
rescue Exception => e normal_status(0,"回答成功")
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
end end
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 game_count = Game.where(myshixun_id: @game.myshixun_id).count
discusses = @shixun.discusses 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 discusses_count = discusses.count
@user = @game.owner @user = @game.owner

@ -384,11 +384,11 @@ class GraduationTasksController < ApplicationController
if @task.status == 0 if @task.status == 0
tip_exception("发布时间不能为空") if params[:publish_time].blank? tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_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[:publish_time].to_time <= Time.now
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S") tip_exception("截止时间不能早于当前时间") if params[:end_time].to_time <= Time.now
tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_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 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.publish_time = params[:publish_time]
@task.end_time = params[:end_time] @task.end_time = params[:end_time]

@ -232,7 +232,11 @@ class HacksController < ApplicationController
hacks = Hack.select(select_sql).mine(current_user.id) hacks = Hack.select(select_sql).mine(current_user.id)
else 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 end
# 搜索 # 搜索
if params[:search] if params[:search]

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

@ -787,7 +787,8 @@ class HomeworkCommonsController < ApplicationController
def create_shixun_homework def create_shixun_homework
tip_exception("请至少选择一个实训") if params[:shixun_ids].blank? 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 = [] @homework_ids = []
unless params[:category_id].blank? unless params[:category_id].blank?
@category = @course.course_second_categories.find_by(id: params[:category_id], category_type: "shixun_homework") @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 def publish_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0 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? if params[:detail].blank?
tip_exception("缺少截止时间参数") if params[:end_time].blank? tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now) 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) homeworks = homeworks.published_no_end.includes(:homework_group_settings, :homework_detail_manual, :homework_challenge_settings)
course_students = @course.students course_students = @course.students
charge_group_ids = @course.charge_group_ids(current_user) 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 begin
homeworks.each do |homework| homeworks.each do |homework|

@ -41,7 +41,11 @@ class ItemBanksController < ApplicationController
def destroy def destroy
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
ApplyAction.where(container_type: "ItemBank", container_id: @item.id).destroy_all 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 render_ok
end end
end end

@ -12,13 +12,7 @@ class ItemBasketsController < ApplicationController
end end
def basket_list def basket_list
@single_questions_count = current_user.item_baskets.where(item_type: "SINGLE").count @basket_count = current_user.item_baskets.group(:item_type).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
end end
def create def create

@ -1,6 +1,6 @@
class MemosController < ApplicationController class MemosController < ApplicationController
before_action :require_login, except: [:show, :index] 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 :set_memo, only: [:show, :edit, :update, :destroy, :sticky_or_cancel, :hidden, :more_reply]
before_action :validate_memo_params, only: [:create, :update] before_action :validate_memo_params, only: [:create, :update]
before_action :owner_or_admin, only: [:edit, :update, :destroy] before_action :owner_or_admin, only: [:edit, :update, :destroy]
@ -144,7 +144,7 @@ class MemosController < ApplicationController
def reply def reply
tip_exception("parent_id不能为空") if params[:parent_id].blank? tip_exception("parent_id不能为空") if params[:parent_id].blank?
tip_exception("content不能为空") if params[:content].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 ActiveRecord::Base.transaction do
begin begin

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

@ -724,7 +724,7 @@ class PollsController < ApplicationController
if unified_setting || (course_group_ids.size == 0) if unified_setting || (course_group_ids.size == 0)
tip_exception("发布时间不能为空") if params[:publish_time].blank? tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_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 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 @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_number => q.question_number,
:question_score => q.question_score, :question_score => q.question_score,
:shixun_name => q.shixun_name, :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 exercise_question = new_exercise.exercise_questions.new option
# question_type5实训题其他是非实训题 # question_type5实训题其他是非实训题

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

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

@ -13,6 +13,7 @@ class SubjectsController < ApplicationController
include ApplicationHelper include ApplicationHelper
include SubjectsHelper include SubjectsHelper
include GitCommon include GitCommon
include CustomSortable
def index def index
@tech_system = current_laboratory.subject_repertoires @tech_system = current_laboratory.subject_repertoires
@ -92,7 +93,7 @@ class SubjectsController < ApplicationController
@is_creator = current_user.creator_of_subject?(@subject) @is_creator = current_user.creator_of_subject?(@subject)
@is_manager = @user.manager_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 @courses = @subject.courses if @subject.excellent
@members = @subject.subject_members.includes(:user) @members = @subject.subject_members.includes(:user)
@ -199,7 +200,8 @@ class SubjectsController < ApplicationController
end end
def append_to_stage 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 end
# 添加实训项目 # 添加实训项目
@ -457,30 +459,19 @@ class SubjectsController < ApplicationController
end end
def statistics_info 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 = @data =
if params[:type] == "shixun_info" if params[:type] == "shixun_info"
@subject.subject_shixun_infos @subject.subject_shixun_infos
elsif params[:type] == "user_info" elsif params[:type] == "user_info"
@subject.subject_user_infos @subject.subject_user_infos
else 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 @subject.subject_course_records
end end
@data_count = @data.count
@data = paginate custom_sort(@data, params[:sort_by], params[:sort_direction]) @data = paginate custom_sort(@data, params[:sort_by], params[:sort_direction])
end end

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

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

@ -108,7 +108,7 @@ class Weapps::CoursesController < Weapps::BaseController
def change_member_roles def change_member_roles
@course = current_course @course = current_course
tip_exception("请至少选择一个角色") if params[:roles].reject(&:blank?).blank? 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| params[:user_ids].each do |user_id|
course_members = @course.course_members.where(user_id: 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 current_user.manage_courses
end end
@courses = @courses.not_deleted.not_excellent @courses = @courses.not_deleted.not_excellent
@courses = @courses.where(id: current_laboratory.all_courses)
@course_count = @courses.count @course_count = @courses.count
order_str = "course_members.sticky=1 desc, course_members.sticky_time desc, courses.created_at desc" 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)) @courses = paginate(@courses.order(order_str).includes(:teacher, :school))

@ -15,8 +15,9 @@ class Weapps::SessionsController < Weapps::BaseController
return return
end 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) successful_authentication(user)
end end

@ -19,11 +19,10 @@ class Weapps::VerificationCodesController < Weapps::BaseController
return render_error('请输入正确的邮箱或手机号') return render_error('请输入正确的邮箱或手机号')
end 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 send_type = login =~ /^1\d{10}$/ ? 1 : 8
# 记录验证码
check_verification_code(verification_code, send_type, login) # 发送验证码
send_code(send_type, login)
render_ok render_ok
end end
@ -40,12 +39,21 @@ class Weapps::VerificationCodesController < Weapps::BaseController
return render_error('请输入正确的邮箱或手机号') return render_error('请输入正确的邮箱或手机号')
end 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) code = %W(0 1 2 3 4 5 6 7 8 9)
verification_code = code.sample(6).join 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
end end

@ -2,9 +2,11 @@ module ExerciseQuestionsHelper
def get_exercise_question_info(question,exercise,ex_user,ex_answerer_id) def get_exercise_question_info(question,exercise,ex_user,ex_answerer_id)
answered_content = [] answered_content = []
exercise_answers = question.exercise_answers.search_exercise_answer("user_id",ex_answerer_id) #试卷用户的回答 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) answered_content = exercise_answers.pluck(:exercise_choice_id)
elsif question.question_type == 3 elsif question.question_type == Exercise::COMPLETION
exercise_answers.each do |a| exercise_answers.each do |a|
u_answer = { u_answer = {
"choice_id": a.exercise_choice_id, "choice_id": a.exercise_choice_id,
@ -12,10 +14,10 @@ module ExerciseQuestionsHelper
} }
answered_content.push(u_answer) answered_content.push(u_answer)
end end
elsif question.question_type == 4 elsif question.question_type == Exercise::SUBJECTIVE
answered_content = exercise_answers.pluck(:answer_text) answered_content = exercise_answers.pluck(:answer_text)
end 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 #如果试卷已截止,则可以看到分数,否则不能查看分数 if exercise.exercise_status == 3 #如果试卷已截止,则可以看到分数,否则不能查看分数
shixun_type = 2 shixun_type = 2
else else

@ -16,8 +16,8 @@ module ExercisesHelper
end end
if q_type <= Exercise::JUDGMENT if q_type <= Exercise::JUDGMENT
if answers_content.present? #学生有回答时,分数已经全部存到exercise_answer 表,所以可以直接取第一个值 if answers_content.present? #学生有回答时,分数已经全部存到exercise_answer 表,多选题直接取第一个值,单选题和判断题选最后一个值(考虑并发)
ques_score = answers_content.first.score ques_score = q_type == Exercise::MULTIPLE ? answers_content.first.score : answers_content.last.score
ques_score = ques_score < 0 ? 0.0 : ques_score ques_score = ques_score < 0 ? 0.0 : ques_score
# answer_choice_array = [] # answer_choice_array = []
# answers_content.each do |a| # answers_content.each do |a|
@ -188,7 +188,7 @@ module ExercisesHelper
if ex_ordered if ex_ordered
all_user_answers = effictive_users.pluck(:answer_text) all_user_answers = effictive_users.pluck(:answer_text)
null_stand_choice.each_with_index do |s,index| 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 = 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.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 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 end
if q.question_type <= 2 #为选择题或判断题时 if q.question_type <= 2 #为选择题或判断题时
if answers_content.present? #学生有回答时 if answers_content.present? #学生有回答时
answer_choice_array = [] if q.question_type == 0 || q.question_type == 2 ## 单选、判断题的算分与多选题分开计算
answers_content.each do |a| user_answer = answers_content.last.exercise_choice.choice_position
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 standard_answer = q.exercise_standard_answers.first&.exercise_choice_id
end if standard_answer.present? && user_answer == standard_answer
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
# q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时每个answer的分数均摊。 score1 = score1 + q.question_score
else else
q_score_1 = 0.0 q_score_1 = -1.0
end end
answers_content.update_all(:score => q_score_1) answers_content.last.update!(score: q_score_1)
score1 = score1 + q.question_score
else else
answers_content.update_all(:score => -1.0) answer_choice_array = []
score1 += 0.0 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 end
else else
score1 += 0.0 score1 += 0.0
@ -530,7 +542,7 @@ module ExercisesHelper
exercise_cha_score = 0.0 exercise_cha_score = 0.0
answer_status = 0 answer_status = 0
# if game.status == 2 && game.final_score >= 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 = game.real_score(exercise_cha.question_score)
# exercise_cha_score = exercise_cha.question_score #每一关卡的得分 # exercise_cha_score = exercise_cha.question_score #每一关卡的得分
answer_status = 1 answer_status = 1

@ -851,7 +851,8 @@ module ExportHelper
def make_zip_name(work, file_name="") def make_zip_name(work, file_name="")
Rails.logger.info("######################file_name: #{file_name}") Rails.logger.info("######################file_name: #{file_name}")
# name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_") # 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 end
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[]) def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[])

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

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

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

@ -5,5 +5,5 @@ class GraduationWorkScore < ApplicationRecord
belongs_to :graduation_task belongs_to :graduation_task
has_many :attachments, 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个字符" }
end end

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

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

@ -19,38 +19,26 @@ class ItemBank < ApplicationRecord
end end
def apply? 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 end
def type_string def type_string
result = case item_type case item_type
when "SINGLE" when "SINGLE" then "单选题"
"单选题" when "MULTIPLE" then "多选题"
when "MULTIPLE" when "JUDGMENT" then "判断题"
"多选题" when "COMPLETION" then "填空题"
when "JUDGMENT" when "SUBJECTIVE" then "简答题"
"判断题" when "PRACTICAL" then "实训题"
when "COMPLETION" when "PROGRAM" then "编程题"
"填空题" end
when "SUBJECTIVE"
"简答题"
when "PRACTICAL"
"实训题"
when "PROGRAM"
"编程题"
end
result
end end
def difficulty_string def difficulty_string
result = case difficulty case difficulty
when 1 when 1 then "简单"
"简单" when 2 then "适中"
when 2 when 3 then "困难"
"适中" end
when 3
"困难"
end
result
end end
end end

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

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

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

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

@ -223,7 +223,7 @@ class StudentWork < ApplicationRecord
game_score = adjust_score.score game_score = adjust_score.score
elsif game.present? elsif game.present?
setting = homework_common.homework_group_setting game.user_id 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 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) game_score = answer_open_evaluation ? score : (game.final_score > 0 ? game.real_score(score) : 0)
end end

@ -7,7 +7,7 @@ class StudentWorksScore < ApplicationRecord
has_many :tidings, as: :container, dependent: :destroy has_many :tidings, as: :container, dependent: :destroy
has_many :attachments, 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) } 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(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(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(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]) custom_sort(all_shixuns, params[:sort_by], params[:sort_direction])
end end

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

@ -23,9 +23,10 @@ class ShixunSearchService < ApplicationService
if User.current.admin? || User.current.business? || !User.current.school_id if User.current.admin? || User.current.business? || !User.current.school_id
@shixuns = @shixuns.where(hidden: 0) @shixuns = @shixuns.where(hidden: 0)
else 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
end end
@ -42,18 +43,24 @@ class ShixunSearchService < ApplicationService
@shixuns = @shixuns.where(trainee: params[:diff]) @shixuns = @shixuns.where(trainee: params[:diff])
end end
Rails.logger.info("search_shixun_ids: #{@shixuns.pluck(:id)}")
Shixun.search(keyword, search_options) Shixun.search(keyword, search_options)
end end
private private
def search_options 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 = { model_options = {
includes: [ :shixun_info, :challenges, :subjects, user: { user_extension: :school } ] includes: [ :shixun_info, :challenges, :subjects, user: { user_extension: :school } ]
} }
model_options.merge!(where: { id: @shixuns.pluck(:id) }) 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.merge!(default_options)
model_options model_options
end end

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

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

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

@ -15,11 +15,11 @@ class UpdateHomeworkPublishSettingService < ApplicationService
if params[:unified_setting] || course.course_groups_count == 0 if params[:unified_setting] || course.course_groups_count == 0
tip_exception("发布时间不能为空") if params[:publish_time].blank? tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_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[:publish_time].to_time <= Time.now
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S") tip_exception("截止时间不能早于当前时间") if params[:end_time].to_time <= Time.now
tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_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 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.unified_setting = 1
homework.homework_group_settings.destroy_all 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 %> <% 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"><%= link_to discuss.dis.name, "/tasks/#{identifier}", target: '_blank'%></td>
<td class="text-left content-img"><%= content_safe discuss.content %></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> <td><%= format_time discuss.created_at %></td>
</tr> </tr>
<% end %> <% end %>

@ -71,6 +71,13 @@
<span class="only_view">只看vip</span> <span class="only_view">只看vip</span>
</label> </label>
</div> </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>
</div> </div>
<% end %> <% end %>

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

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

@ -1,7 +1,7 @@
json.single_questions_count @single_questions_count json.single_questions_count @basket_count&.fetch("SINGLE", 0)
json.multiple_questions_count @multiple_questions_count json.multiple_questions_count @basket_count&.fetch("MULTIPLE", 0)
json.judgement_questions_count @judgement_questions_count json.judgement_questions_count @basket_count&.fetch("JUDGMENT", 0)
json.completion_questions_count @completion_questions_count json.completion_questions_count @basket_count&.fetch("COMPLETION", 0)
json.subjective_questions_count @subjective_questions_count json.subjective_questions_count @basket_count&.fetch("SUBJECTIVE", 0)
json.practical_questions_count @practical_questions_count json.practical_questions_count @basket_count&.fetch("PRACTICAL", 0)
json.program_questions_count @program_questions_count 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.array! @results.with_highlights(multiple: true) do |obj, highlights|
json.merge! obj.to_searchable_json json.merge! obj.to_searchable_json
json.challenge_names obj.challenges.pluck(:subject) json.challenge_names obj.challenges.pluck(:subject)
highlights[:description]&.first&.sub!(@reg, '')
# 去除开头标点符号 highlights[:description]&.map{|des| des.gsub(@atta_reg, '')}
reg = /^[,。?:;‘’!“”—……、]/ highlights[:content]&.first&.sub!(@reg, '')
# 附件的替换 highlights[:content]&.map{|des| des.gsub(@atta_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, '')}
json.title highlights.delete(:name)&.join('...') || obj.searchable_title 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.pic url_to_avatar(obj)
json.content highlights json.content highlights
json.level level_to_s(obj.trainee) json.level level_to_s(obj.trainee)
json.subjects obj.subjects.visible.unhidden.uniq do |subject| #if params[:sort] != "wechat_myshixuns_count"
json.(subject, :id, :name) json.subjects obj.subjects.select{ |s| s.status == 2 && s.hidden == 0} do |subject|
end json.(subject, :id, :name)
end
#end
end end
end end

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

@ -6,7 +6,7 @@ json.subject_score @subject.all_score
json.member_count @subject.member_count json.member_count @subject.member_count
json.allow_delete (@subject.status != 2 && @is_creator) || @user.admin? 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_statistics @is_manager
json.allow_send @user.logged? json.allow_send @user.logged?
json.allow_visit @subject.status > 1 || @is_manager 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.business user.business?
json.is_teacher user.user_extension&.teacher? json.is_teacher user.user_extension&.teacher?
json.user_identity user.identity json.user_identity user.identity
json.identity user.user_extension&.identity
json.tidding_count 0 json.tidding_count 0
json.user_phone_binded user.phone.present? json.user_phone_binded user.phone.present?
json.phone user.phone json.phone user.phone

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

@ -1,6 +1,6 @@
class AddIndexForSubjectRecords < ActiveRecord::Migration[5.2] class AddIndexForSubjectRecords < ActiveRecord::Migration[5.2]
def change def change
remove_index :subject_records, :subject_id # remove_index :subject_records, :subject_id
add_index :subject_records, :subject_id, unique: true add_index :subject_records, :subject_id, unique: true
end end
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 task data_statistic: :environment do
puts("---------------------data_statistic_begin") puts("---------------------data_statistic_begin")
Rails.logger.info("---------------------data_statistic_begin") Rails.logger.info("---------------------data_statistic_begin")
subjects = Subject.where(status: 2) subjects = Subject.where(status: 2, hidden: 0)
str = "" str = ""
buffer_size = 0 buffer_size = 0
column_value = "subject_id, study_count, course_study_count, initiative_study, passed_count, course_used_count, " + column_value = "subject_id, study_count, course_study_count, initiative_study, passed_count, course_used_count, " +
"school_used_count, created_at, updated_at" "school_used_count, created_at, updated_at"
subjects.find_each do |subject| subjects.find_in_batches(batch_size: 50) do |s, index|
puts("---------------------data_statistic: #{subject.id}") Parallel.each_with_index(s, in_processes: 4) do |subject|
Rails.logger.info("---------------------data_statistic: #{subject.id}") puts("---------------------data_statistic: #{subject.id}")
data = Subjects::DataStatisticService.new(subject) Rails.logger.info("---------------------data_statistic: #{subject.id}")
study_count = data.study_count data = Subjects::DataStatisticService.new(subject)
next if study_count == 0 study_count = data.study_count
course_study_count = data.course_study_count next if study_count == 0
initiative_study = study_count - course_study_count course_study_count = data.course_study_count
str += ", " unless str.empty? initiative_study = study_count - course_study_count
str += ("(#{subject.id}, #{study_count}, #{course_study_count}, #{initiative_study}, " + str += ", " unless str.empty?
"#{data.passed_count}, #{data.course_used_count}, #{data.school_used_count}, " + str += ("(#{subject.id}, #{study_count}, #{course_study_count}, #{initiative_study}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')") "#{data.passed_count}, #{data.course_used_count}, #{data.school_used_count}, " +
buffer_size += 1 "'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
if buffer_size == 1000 buffer_size += 1
sql = "REPLACE INTO subject_records(#{column_value}) VALUES #{str}" if buffer_size == 1000 || subjects.count == (index+1)
puts sql sql = "REPLACE INTO subject_records(#{column_value}) VALUES #{str}"
ActiveRecord::Base.connection.execute sql puts sql
str = "" ActiveRecord::Base.connection.execute sql
buffer_size = 0 str = ""
buffer_size = 0
end
end end
end end
if buffer_size > 0 if buffer_size > 0
@ -42,28 +44,31 @@ namespace :subjects do
task course_info_statistic: :environment do task course_info_statistic: :environment do
puts("---------------------course_info_statistic_begin") puts("---------------------course_info_statistic_begin")
Rails.logger.info("---------------------course_info_statistic_begin") Rails.logger.info("---------------------course_info_statistic_begin")
subjects = Subject.where(status: 2) subjects = Subject.where(status: 2, hidden: 0)
str = "" str = ""
buffer_size = 0 buffer_size = 0
column_value = "subject_id, school_id, school_name, course_count, student_count, choice_shixun_num, " + column_value = "subject_id, school_id, school_name, course_count, student_count, choice_shixun_num, " +
"choice_shixun_frequency, created_at, updated_at" "choice_shixun_frequency, created_at, updated_at"
subjects.find_each do |subject|
puts("---------------------course_info_statistic: #{subject.id}") subjects.find_in_batches(batch_size: 50) do |s|
Rails.logger.info("---------------------course_info_statistic: #{subject.id}") Parallel.each(s, in_processes: 4) do |subject|
data = Subjects::CourseUsedInfoService.call(subject) puts("---------------------course_info_statistic: #{subject.id}")
data.each do |key| Rails.logger.info("---------------------course_info_statistic: #{subject.id}")
next if key[:school_id].nil? data = Subjects::CourseUsedInfoService.call(subject)
str += ", " unless str.empty? Parallel.map_with_index(data) do |key, index|
str += ("(#{subject.id}, #{key[:school_id]}, '#{key[:school_name]}', #{key[:course_count]}, " + next if key[:school_id].nil?
"#{key[:student_count]}, #{key[:choice_shixun_num]}, #{key[:choice_shixun_frequency]}, " + str += ", " unless str.empty?
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')") str += ("(#{subject.id}, #{key[:school_id]}, '#{key[:school_name]}', #{key[:course_count]}, " +
buffer_size += 1 "#{key[:student_count]}, #{key[:choice_shixun_num]}, #{key[:choice_shixun_frequency]}, " +
if buffer_size == 1000 "'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
sql = "REPLACE INTO subject_course_records(#{column_value}) VALUES #{str}" buffer_size += 1
puts sql if buffer_size == 1000 || (index + 1) == data.size
ActiveRecord::Base.connection.execute sql sql = "REPLACE INTO subject_course_records(#{column_value}) VALUES #{str}"
str = "" puts sql
buffer_size = 0 ActiveRecord::Base.connection.execute sql
str = ""
buffer_size = 0
end
end end
end end
end end
@ -79,29 +84,31 @@ namespace :subjects do
task shixun_info_statistic: :environment do task shixun_info_statistic: :environment do
puts("---------------------shixun_info_statistic_begin") puts("---------------------shixun_info_statistic_begin")
Rails.logger.info("---------------------shixun_info_statistic_begin") Rails.logger.info("---------------------shixun_info_statistic_begin")
subjects = Subject.where(status: 2) subjects = Subject.where(status: 2, hidden: 0)
str = "" str = ""
buffer_size = 0 buffer_size = 0
column_value = "subject_id, shixun_id, stage, shixun_name, challenge_count, course_count, " + 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" "school_count, used_count, passed_count, evaluate_count, passed_ave_time, created_at, updated_at"
subjects.find_each(batch_size: 100) do |subject| subjects.find_in_batches(batch_size: 50) do |s|
puts("---------------------shixun_info_statistic: #{subject.id}") Parallel.each_with_index(s, in_processes: 4) do |subject|
Rails.logger.info("---------------------shixun_info_statistic: #{subject.id}") puts("---------------------shixun_info_statistic: #{subject.id}")
data = Subjects::ShixunUsedInfoService.call(subject) Rails.logger.info("---------------------shixun_info_statistic: #{subject.id}")
data.each do |key| data = Subjects::ShixunUsedInfoService.call(subject)
next if key[:shixun_id].nil? data.each_with_index do |key, index|
str += ", " unless str.empty? next if key[:shixun_id].nil?
str += ("(#{subject.id}, #{key[:shixun_id]}, '#{key[:stage]}', '#{key[:name]}', #{key[:challenge_count]}, " + str += ", " unless str.empty?
"#{key[:course_count]}, #{key[:school_count]}, #{key[:used_count]}, #{key[:passed_count]}, " + str += ("(#{subject.id}, #{key[:shixun_id]}, '#{key[:stage]}', '#{key[:name]}', #{key[:challenge_count]}, " +
"#{key[:evaluate_count]}, #{key[:passed_ave_time]}, " + "#{key[:course_count]}, #{key[:school_count]}, #{key[:used_count]}, #{key[:passed_count]}, " +
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')") "#{key[:evaluate_count]}, #{key[:passed_ave_time]}, " +
buffer_size += 1 "'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
if buffer_size == 1000 buffer_size += 1
sql = "REPLACE INTO subject_shixun_infos(#{column_value}) VALUES #{str}" if buffer_size == 1000 || (index+1) == data.size
puts sql sql = "REPLACE INTO subject_shixun_infos(#{column_value}) VALUES #{str}"
ActiveRecord::Base.connection.execute sql puts sql
str = "" ActiveRecord::Base.connection.execute sql
buffer_size = 0 str = ""
buffer_size = 0
end
end end
end end
end end
@ -117,27 +124,29 @@ namespace :subjects do
task user_info_statistic: :environment do task user_info_statistic: :environment do
puts("---------------------user_info_statistic_begin") puts("---------------------user_info_statistic_begin")
Rails.logger.info("---------------------user_info_statistic_begin") Rails.logger.info("---------------------user_info_statistic_begin")
subjects = Subject.where(status: 2) subjects = Subject.where(status: 2, hidden: 0)
str = "" str = ""
buffer_size = 0 buffer_size = 0
column_value = "user_id, subject_id, username, passed_myshixun_count, passed_games_count, " + column_value = "user_id, subject_id, username, passed_myshixun_count, passed_games_count, " +
"code_line_count, evaluate_count, cost_time, created_at, updated_at" "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}") subjects.find_in_batches(batch_size: 50) do |s|
data = Subjects::UserUsedInfoService.call(subject) Parallel.each_with_index(s, in_processes: 4) do |subject, index|
data.each do |key| puts("---------------------user_info_statistic: #{subject.id}")
next if key[:user_id].nil? data = Subjects::UserUsedInfoService.call(subject)
str += ", " unless str.empty? data.each do |key|
str += ("(#{key[:user_id]}, #{subject.id}, '#{key[:name]}', '#{key[:passed_myshixun_count]}', " + next if key[:user_id].nil?
"#{key[:passed_games_count]}, #{key[:code_line_count]}, #{key[:evaluate_count]}, #{key[:cost_time]}, " + str += ", " unless str.empty?
"'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')") str += ("(#{key[:user_id]}, #{subject.id}, '#{key[:name].gsub(/'/, '"')}', #{key[:passed_myshixun_count]}, " +
buffer_size += 1 "#{key[:passed_games_count]}, #{key[:code_line_count]}, #{key[:evaluate_count]}, #{key[:cost_time]}, " +
if buffer_size == 1000 "'#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')")
sql = "REPLACE INTO subject_user_infos(#{column_value}) VALUES #{str}" buffer_size += 1
puts sql if buffer_size == 1000 || (index+1 == data.size)
ActiveRecord::Base.connection.execute sql sql = "REPLACE INTO subject_user_infos(#{column_value}) VALUES #{str}"
str = "" ActiveRecord::Base.connection.execute sql
buffer_size = 0 str = ""
buffer_size = 0
end
end end
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 namespace :zip_pack do
desc "手工打包作品" desc "手工打包作品"
OUTPUT_FOLDER = "#{Rails.root}/files/archiveZip" OUTPUT_FOLDER = "#{Rails.root}/files/archiveZip"
task :shixun_pack => :environment do task :shixun_pack => :environment do
if ENV['args'] if ENV['class'] && ENV['ids']
homework_ids = ENV['args'].split(",").map(&:to_i) parallel_size = ENV['parallel_size'] || 2
homeworks = HomeworkCommon.where(id: homework_ids) parallel_size = parallel_size.to_i
homeworks.includes(:score_student_works).each do |homework| env_ids = ENV['ids'].split(",").map(&:to_i)
out_file_name = "#{Time.now.strftime("%Y%m%d%H%M%S").to_s}-#{homework.course_id}-#{homework.name}.zip" folders = []
out_file_name.gsub!(" ", "-") if ENV['class'] == "Course"
out_file_name.gsub!("/", "_") 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}" puts "下载路径: #{folders.join(",")}"
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name)) 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 homeworks.includes(:score_student_works).each do |homework|
pdfs = [] out_file_name = "#{Time.now.strftime("%Y%m%d%H%M%S").to_s}-#{homework.course_id}-#{homework.name}.zip"
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zip| out_file_name.gsub!(" ", "-")
student_works.find_each.map do |student_work| out_file_name.gsub!("/", "_")
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)
zip.get_output_stream('FILE_NOTICE.txt'){|os| os.write("文件重复:#{export.filename}") } zipfile_name = "#{folder}/#{out_file_name}"
next
end student_works = homework.score_student_works
end
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 end
zipfile = zipfile_name
else
zipfile = {:message => "no file"}
end 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 end
end end
# 执行示例 bundle exec rake zip_pack:homework_attach_pack args=123
task :homework_attach_pack => :environment do task :homework_attach_pack => :environment do
include ExportHelper include ExportHelper
if ENV['args'] if ENV['args']
@ -61,7 +95,4 @@ namespace :zip_pack do
end end
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 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-codemirror": "^1.0.0",
"react-codemirror2": "^6.0.0", "react-codemirror2": "^6.0.0",
"react-content-loader": "^3.1.1", "react-content-loader": "^3.1.1",
"react-cookies": "^0.1.1",
"react-dev-utils": "^5.0.0", "react-dev-utils": "^5.0.0",
"react-dom": "^16.9.0", "react-dom": "^16.9.0",
"react-hot-loader": "^4.0.0", "react-hot-loader": "^4.0.0",
@ -176,6 +177,7 @@
"compression-webpack-plugin": "^1.1.12", "compression-webpack-plugin": "^1.1.12",
"concat": "^1.0.3", "concat": "^1.0.3",
"happypack": "^5.0.1", "happypack": "^5.0.1",
"mockjs": "^1.1.0",
"node-sass": "^4.12.0", "node-sass": "^4.12.0",
"reqwest": "^2.0.5", "reqwest": "^2.0.5",
"webpack-bundle-analyzer": "^3.0.3", "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;} .-relative { position: relative;}
.-bg-white { background-color: #eee;} .-bg-white { background-color: #eee;}
.split-panel.-handle .split-panel--second { padding-left: 2px;} .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; .task-answer-view { position: absolute; top: 0; right: 0; bottom: 0;left: 0; display: flex;
flex-direction: column; border-top: 1px solid #515151;} flex-direction: column; border-top: 1px solid #515151;}
.-vertical { flex-direction: column;box-flex-direction: column;-webkit-flex-direction: column;} .-vertical { flex-direction: column;box-flex-direction: column;-webkit-flex-direction: column;}

@ -1134,6 +1134,12 @@
<div class="code-name">&amp;#xe7f9;</div> <div class="code-name">&amp;#xe7f9;</div>
</li> </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"> <li class="dib">
<span class="icon iconfont">&#xe6ee;</span> <span class="icon iconfont">&#xe6ee;</span>
<div class="name">20从属连接</div> <div class="name">20从属连接</div>
@ -1866,6 +1872,18 @@
<div class="code-name">&amp;#xe719;</div> <div class="code-name">&amp;#xe719;</div>
</li> </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> </ul>
<div class="article markdown"> <div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2> <h2 id="unicode-">Unicode 引用</h2>
@ -3572,6 +3590,15 @@
</div> </div>
</li> </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"> <li class="dib">
<span class="icon iconfont icon-congshulianjie"></span> <span class="icon iconfont icon-congshulianjie"></span>
<div class="name"> <div class="name">
@ -4670,6 +4697,24 @@
</div> </div>
</li> </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> </ul>
<div class="article markdown"> <div class="article markdown">
<h2 id="font-class-">font-class 引用</h2> <h2 id="font-class-">font-class 引用</h2>
@ -6171,6 +6216,14 @@
<div class="code-name">#icon-gengduo1</div> <div class="code-name">#icon-gengduo1</div>
</li> </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"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-congshulianjie"></use> <use xlink:href="#icon-congshulianjie"></use>
@ -7147,6 +7200,22 @@
<div class="code-name">#icon-jiashang1</div> <div class="code-name">#icon-jiashang1</div>
</li> </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> </ul>
<div class="article markdown"> <div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2> <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": "e7f9",
"unicode_decimal": 59385 "unicode_decimal": 59385
}, },
{
"icon_id": "5327531",
"name": "过滤器",
"font_class": "guolvqi",
"unicode": "e71b",
"unicode_decimal": 59163
},
{ {
"icon_id": "5379378", "icon_id": "5379378",
"name": "20从属连接", "name": "20从属连接",
@ -2146,6 +2153,20 @@
"font_class": "jiashang1", "font_class": "jiashang1",
"unicode": "e719", "unicode": "e719",
"unicode_decimal": 59161 "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="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" /> <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="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> </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;} .-relative { position: relative;}
.-bg-white { background-color: #eee;} .-bg-white { background-color: #eee;}
.split-panel.-handle .split-panel--second { padding-left: 2px;} .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; .task-answer-view { position: absolute; top: 0; right: 0; bottom: 0;left: 0; display: flex;
flex-direction: column; border-top: 1px solid #515151;} flex-direction: column; border-top: 1px solid #515151;}
.-vertical { flex-direction: column;box-flex-direction: column;-webkit-flex-direction: column;} .-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=”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"> <meta name="theme-color" content="#000000">

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

@ -5,6 +5,7 @@ import md5 from 'md5';
import { requestProxy } from "./indexEduplus2RequestProxy"; import { requestProxy } from "./indexEduplus2RequestProxy";
import { broadcastChannelOnmessage ,SetAppModel, isDev, queryString } from 'educoder'; import { broadcastChannelOnmessage ,SetAppModel, isDev, queryString } from 'educoder';
import { notification } from 'antd'; import { notification } from 'antd';
import cookie from 'react-cookies';
import './index.css'; import './index.css';
const $ = window.$; const $ = window.$;
const opens ="79e33abd4b6588941ab7622aed1e67e8"; 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 开发期多个身份切换 // TODO 开发期多个身份切换
let debugType ="" let debugType =""
@ -82,9 +95,36 @@ export function initAxiosInterceptors(props) {
// proxy = "https://testeduplus2.educoder.net" // proxy = "https://testeduplus2.educoder.net"
//proxy="http://47.96.87.25:48080" //proxy="http://47.96.87.25:48080"
proxy="https://pre-newweb.educoder.net" 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-newweb.educoder.net"
proxy="https://test-jupyterweb.educoder.net" // proxy="https://test-jupyterweb.educoder.net"
//proxy="http://192.168.2.63:3001" //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控制避免用户通过双击等操作发出重复的请求 // 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
// 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制 // 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制
@ -94,7 +134,7 @@ export function initAxiosInterceptors(props) {
requestMap[keyName] = false; requestMap[keyName] = false;
} }
//响应前的设置
axios.interceptors.request.use( axios.interceptors.request.use(
config => { config => {
// config.headers['Content-Type']= 'no-cache' // config.headers['Content-Type']= 'no-cache'
@ -109,6 +149,56 @@ export function initAxiosInterceptors(props) {
// proxy = 'http://localhost:3000' // 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) { if (config.url.indexOf(proxy) != -1 || config.url.indexOf(':') != -1) {
return config 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 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 , 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'; , getTaskUrlById as getTaskUrlById, TEST_HOST ,htmlEncode as htmlEncode ,getupload_git_file as getupload_git_file} from './UrlTool';
export {setmiyah as setmiyah} from './Component'; export {setmiyah as setmiyah} from './Component';
export { default as queryString } from './UrlTool2'; 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