Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_cxt2
caishi 5 years ago
commit 62feed09d9

@ -115,7 +115,7 @@ $(document).on('turbolinks:load', function(){
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/for_option.json',
url: '/api/schools/search.json',
dataType: 'json',
data: function(params){
return { keyword: params.term };

@ -0,0 +1,90 @@
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-select-school-modal');
if ($modal.length > 0) {
var $link = null;
var $form = $modal.find('form.admin-select-school-form');
var multiple = $form.data('multiple');
$form.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择',
multiple: multiple,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/search.json',
dataType: 'json',
data: function (params) {
return {keyword: params.term};
},
processResults: function (data) {
return {results: data.schools}
}
},
templateResult: function (item) {
if (!item.id || item.id === '') return item.text;
var html = "<span>" + item.name + "<span class='ml-4 font-12'>";
if(item.province){ html += item.province }
html += "</span></span>";
return $(html);
},
templateSelection: function (item) {
if (item.id) {
}
return item.name || item.text;
}
});
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
school_ids: {
required: true
}
},
messages: {
school_ids: {
required: '请选择'
}
}
});
$modal.on('show.bs.modal', function(event){
$link = $(event.relatedTarget);
});
$modal.on('hide.bs.modal', function(){
$form.find('.error').html('');
$form.find('.school-select').select2('val', ' ');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if($form.valid()){
var url = $form.data('url');
var schoolIds = $form.find('#school_ids').val();
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: { school_ids: schoolIds },
success: function(){
$.notify({ message: '操作成功' });
$modal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
}
});

@ -9,7 +9,7 @@ $(document).on('turbolinks:load', function () {
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/for_option.json',
url: '/api/schools/search.json',
dataType: 'json',
data: function (params) {
return {keyword: params.term};

@ -0,0 +1,38 @@
class Admins::CustomersController < Admins::BaseController
helper_method :current_partner
def index
default_sort('created_at', 'desc')
customers = Admins::CustomerQuery.call(params.merge(partner_id: current_partner.id))
@customers = paginate(customers.preload(:school))
end
def create
params[:school_ids] = Array.wrap(params[:school_ids])
school_ids = School.where(id: params[:school_ids]).pluck(:id)
ActiveRecord::Base.transaction do
school_ids.each do |school_id|
next if current_partner.customers.exists?(school_id)
customer = Customer.create!(school_id: school_id)
current_partner.partner_customers.create!(customer: customer)
end
end
render_ok
end
def destroy
current_partner.customers.find(params[:id]).destroy!
render_delete_success
end
private
def current_partner
@_current_partner ||= Partner.find(params[:partner_id])
end
end

@ -87,7 +87,6 @@ class Admins::MirrorRepositoriesController < Admins::BaseController
end
def check_shixun_mirrors!
return
return unless request.format.html?
Admins::CheckShixunMirrorsService.call

@ -0,0 +1,29 @@
class Admins::PartnersController < Admins::BaseController
def index
default_sort('created_at', 'desc')
partners = Admins::PartnerQuery.call(params)
@partners = paginate(partners.preload(:school))
end
def create
params[:school_ids] = Array.wrap(params[:school_ids])
school_ids = School.where(id: params[:school_ids]).pluck(:id)
exist_school_ids = Partner.where(school_id: school_ids).pluck(:school_id)
Partner.bulk_insert(*%i[school_id created_at updated_at]) do |worker|
(school_ids - exist_school_ids).each do |school_id|
worker.add(school_id: school_id)
end
end
render_ok
end
def destroy
Partner.find(params[:id]).destroy!
render_delete_success
end
end

@ -1,8 +1,7 @@
class Admins::ShixunSettingsController < Admins::BaseController
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
default_sort('created_at', 'desc')
shixun_settings = Admins::ShixunSettingsQuery.call(params)
@editing_shixuns = shixun_settings.where(status:0).size

@ -107,7 +107,7 @@ class ExerciseAnswersController < ApplicationController
normal_status(-1,"已提交/已结束的试卷不允许修改!")
else
if (@exercise_user_status == Exercise::DEADLINE && @exercise_user.commit_status == 0) || (@exercise.time > 0 && @exercise_user.start_at.present? && ((@exercise_user.start_at + @exercise.time.to_i.minutes) < Time.now))
objective_score = calculate_student_score(@exercise,current_user)[:total_score]
objective_score = calculate_student_score(@exercise,current_user,Time.now)[:total_score]
subjective_score = @exercise_user.subjective_score < 0.0 ? 0.0 : @exercise_user.subjective_score
total_score = objective_score + subjective_score
commit_option = {

@ -886,7 +886,7 @@ class ExercisesController < ApplicationController
ex_user_ids = exercise_users.pluck(:id)
EndExerciseCalculateJob.perform_later(ex_user_ids,exercise)
EndExerciseCalculateJob.perform_later(ex_user_ids,exercise,Time.now.to_s)
# exercise_users.each do |user|
# if user.commit_status == 0 && user.start_at.present?
# objective_score = calculate_student_score(exercise,user.user)[:total_score]
@ -1019,59 +1019,57 @@ class ExercisesController < ApplicationController
#学生开始答题页面
def start_answer
ActiveRecord::Base.transaction do
begin
ex_users_current = ExerciseUser.where(user_id:@exercise_current_user_id,exercise_id:@exercise.id) #不能用@exercise.exercise_users因为exercise_users删除时只是状态改变未删除
@exercise_user_current = ex_users_current&.first
if ex_users_current.exists?
if @exercise_user_current.start_at.blank?
@exercise_user_current.update_attribute("start_at",Time.now)
end
else
if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候不创建exercise_user表理论上老师是不能进入答题的
exercise_user_params = {
:user_id => @exercise_current_user_id,
:exercise_id => @exercise.id,
:start_at => Time.now
}
exercise_user_current = ExerciseUser.new(exercise_user_params)
exercise_user_current.save
end
begin
ex_users_current = ExerciseUser.where(user_id:@exercise_current_user_id,exercise_id:@exercise.id) #不能用@exercise.exercise_users因为exercise_users删除时只是状态改变未删除
@exercise_user_current = ex_users_current&.first
if ex_users_current.exists?
if @exercise_user_current.start_at.blank?
@exercise_user_current.update_attribute("start_at",Time.now)
end
@t_user_exercise_status = @exercise.get_exercise_status(current_user)
@user_left_time = nil
if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) ||
(ex_users_current.exists? && @exercise_user_current.commit_status == 1)
@user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑
else
@user_left_time = get_exercise_left_time(@exercise,current_user)
@user_exercise_status = 0 #可编辑
else
if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候不创建exercise_user表理论上老师是不能进入答题的
exercise_user_params = {
:user_id => @exercise_current_user_id,
:exercise_id => @exercise.id,
:start_at => Time.now
}
exercise_user_current = ExerciseUser.new(exercise_user_params)
exercise_user_current.save
end
end
@t_user_exercise_status = @exercise.get_exercise_status(current_user)
@exercise_questions = @exercise.exercise_questions
if @exercise.question_random
@exercise_questions = @exercise_questions.order("RAND()")
else
@exercise_questions = @exercise_questions.order("question_number ASC")
end
# 判断问题是否已回答还是未回答
@exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges,
:exercise_shixun_answers,
:exercise_answers,
:exercise_standard_answers)
@user_left_time = nil
if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) ||
(ex_users_current.exists? && @exercise_user_current.commit_status == 1)
@user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑
else
@user_left_time = get_exercise_left_time(@exercise,current_user)
@user_exercise_status = 0 #可编辑
end
if @t_user_exercise_status == Exercise::DEADLINE
get_each_student_exercise(@exercise.id,@exercise_questions,@exercise_current_user_id)
end
get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,@t_user_exercise_status)
@exercise_questions = @exercise.exercise_questions
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
if @exercise.question_random
@exercise_questions = @exercise_questions.order("RAND()")
else
@exercise_questions = @exercise_questions.order("question_number ASC")
end
# 判断问题是否已回答还是未回答
@exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges,
:exercise_shixun_answers,
:exercise_answers,
:exercise_standard_answers)
if @t_user_exercise_status == Exercise::DEADLINE
get_each_student_exercise(@exercise.id,@exercise_questions,@exercise_current_user_id)
end
get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,@t_user_exercise_status)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -1084,14 +1082,23 @@ class ExercisesController < ApplicationController
@shixun_undo = 0
@ques_undo = 0
ex_answer_time = @exercise.time.to_i
@ex_end_time = @exercise.get_exercise_end_time(current_user.id)
if ex_answer_time > 0
exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id)
if exercise_end_time.present?
ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at
@ex_end_time = ex_end_times + ex_answer_time.minutes
end
if ex_answer_time > 0 #有剩余时间的时候
user_left_time = get_exercise_left_time(@exercise,current_user)
@ex_end_time = Time.now + user_left_time.to_i.seconds
else
@ex_end_time = @exercise.get_exercise_end_time(current_user.id)
end
# @ex_end_time = @exercise.get_exercise_end_time(current_user.id)
# if ex_answer_time > 0
# left_answer_time = Time.now + ex_answer_time.minutes #判断试卷的倒计时和截止时间哪个先到
# if left_answer_time < @ex_end_time
# exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id)
# if exercise_end_time.present?
# ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at
# @ex_end_time = ex_end_times + ex_answer_time.minutes
# end
# end
# end
@exercise_questions.each do |q|
if q.question_type == Exercise::PRACTICAL #当为实训题时
user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id)
@ -1116,6 +1123,7 @@ class ExercisesController < ApplicationController
# 学生提交试卷
def commit_exercise
tip_exception(0, "试卷截止时间已到,系统已自动提交") if @answer_committed_user.commit_status == 1
ActiveRecord::Base.transaction do
begin
can_commit_exercise = false
@ -1131,7 +1139,7 @@ class ExercisesController < ApplicationController
can_commit_exercise = true
end
if can_commit_exercise
objective_score = calculate_student_score(@exercise,current_user)[:total_score]
objective_score = calculate_student_score(@exercise,current_user,Time.now)[:total_score]
subjective_score = @answer_committed_user.subjective_score
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = objective_score + total_score_subjective_score
@ -1195,7 +1203,6 @@ class ExercisesController < ApplicationController
#答题列表
def exercise_lists
ActiveRecord::Base.transaction do
begin
@current_user_id = current_user.id
exercise_ids = [@exercise.id]
@ -1269,81 +1276,80 @@ class ExercisesController < ApplicationController
if params[:review].present?
review_type = params[:review].first.to_i #已评则数据为1未评则数据为0,前端传过来的为数组
if review_type == 1
@exercise_users_list = teacher_reviews
else
@exercise_users_list = teacher_unreviews
end
@exercise_users_list = teacher_reviews
else
@exercise_users_list = teacher_unreviews
end
end
#答题状态的选择
if params[:commit_status].present?
choose_type = params[:commit_status]
@exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type)
end
#答题状态的选择
if params[:commit_status].present?
choose_type = params[:commit_status]
@exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type)
end
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) #试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids)
end
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) #试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids)
end
#搜索
if params[:search].present?
@exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
#搜索
if params[:search].present?
@exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
exercise_user_joins = @exercise_users_list.joins(user: :user_extension)
exercise_user_joins = @exercise_users_list.joins(user: :user_extension)
if order == "student_id"
@exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}")
elsif order == "score"
@exercise_users_list = exercise_user_joins.order("#{order} #{order_type}")
else
@exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}")
end
if order == "student_id"
@exercise_users_list = exercise_user_joins.order("user_extensions.student_id #{order_type}")
elsif order == "score"
@exercise_users_list = exercise_user_joins.order("#{order} #{order_type}")
else
@exercise_users_list = exercise_user_joins.order("end_at #{order_type}, start_at #{order_type}")
end
@export_ex_users = @exercise_users_list
@export_ex_users = @exercise_users_list
@exercise_users_size = @exercise_users_list.size
@exercise_users_size = @exercise_users_list.size
# 分页
@page = params[:page] || 1
@limit = params[:limit] || 20
@exercise_users_list = @exercise_users_list.page(@page).per(@limit)
else
@exercise_users_list = []
@export_ex_users = @exercise_users_list
@exercise_users_size = 0
end
# 分页
@page = params[:page] || 1
@limit = params[:limit] || 20
@exercise_users_list = @exercise_users_list.page(@page).per(@limit)
else
@exercise_users_list = []
@export_ex_users = @exercise_users_list
@exercise_users_size = 0
end
if params[:format] == "xlsx"
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
elsif @exercise_status == Exercise::UNPUBLISHED
normal_status(-1,"试卷未发布")
elsif (@exercise_users_size == 0) || ( @export_ex_users&.exercise_user_committed.size == 0)
normal_status(-1,"暂无用户提交")
elsif params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
set_export_cookies
get_export_users(@exercise,@course,@export_ex_users)
exercise_export_name_ =
"#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{exercise_export_name_.strip}",template: "exercises/exercise_lists.xlsx.axlsx",locals: {table_columns:@table_columns,exercise_users:@user_columns}
}
end
if params[:format] == "xlsx"
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
elsif @exercise_status == Exercise::UNPUBLISHED
normal_status(-1,"试卷未发布")
elsif (@exercise_users_size == 0) || ( @export_ex_users&.exercise_user_committed.size == 0)
normal_status(-1,"暂无用户提交")
elsif params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
set_export_cookies
get_export_users(@exercise,@course,@export_ex_users)
exercise_export_name_ =
"#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{exercise_export_name_.strip}",template: "exercises/exercise_lists.xlsx.axlsx",locals: {table_columns:@table_columns,exercise_users:@user_columns}
}
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -1382,101 +1388,99 @@ class ExercisesController < ApplicationController
#学生的统计结果
def exercise_result
ActiveRecord::Base.transaction do
begin
exercise_ids = [@exercise.id]
@exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).size #判断是否有已发布的分班
@exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).size #判断是否有未发布的分班
@course_all_members = @course.students #课堂的全部学生
@exercise_all_users = @exercise.exercise_users
ex_common_ids = @exercise.common_published_ids(current_user.id)
@exercise_course_groups = @course.get_ex_published_course(ex_common_ids)
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids)
@course_all_members_count = @exercise_all_users.size
else
@exercise_users_list = @exercise.all_exercise_users(current_user.id)
@course_all_members_count = @exercise_users_list.size
end
@exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户
@exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id
@exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数
@exercise_status = @exercise.get_exercise_status(current_user)
#提交率
if @course_all_members_count == 0
commit_percent = 0.00
min_score = 0.0
max_score = 0.0
average_score = 0.0
fail_counts = 0
pass_counts = 0
good_counts = 0
best_counts = 0
else
commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3)
exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?)
min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0
max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0
total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0
average_score = @exercise_commit_user_counts > 0 ? (total_score.round(1) / @exercise_commit_user_counts).round(1) : 0.0
question_scores = @exercise.question_scores
fail_score = question_scores * 0.6.round(2)
pass_score = question_scores * 0.7.round(2)
good_score = question_scores * 0.9.round(2)
fail_counts = exercise_scores.count{|a| a < fail_score}
pass_counts = exercise_scores.count{|a| a < pass_score && a >= fail_score}
good_counts = exercise_scores.count{|a| a < good_score && a >= pass_score}
best_counts = exercise_scores.count{|a| a >= good_score && a <= question_scores}
end
@counts_array = {
:commit_percent => commit_percent,
:min_score => min_score.to_s,
:max_score => max_score.to_s,
:average_score => average_score.to_s,
:fail_counts => fail_counts,
:pass_counts => pass_counts,
:good_counts => good_counts,
:best_counts => best_counts,
}
begin
exercise_ids = [@exercise.id]
@exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).size #判断是否有已发布的分班
@exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).size #判断是否有未发布的分班
@course_all_members = @course.students #课堂的全部学生
@exercise_all_users = @exercise.exercise_users
ex_common_ids = @exercise.common_published_ids(current_user.id)
@exercise_course_groups = @course.get_ex_published_course(ex_common_ids)
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids)
@course_all_members_count = @exercise_all_users.size
else
@exercise_users_list = @exercise.all_exercise_users(current_user.id)
@course_all_members_count = @exercise_users_list.size
end
@exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户
@exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id
@exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数
@exercise_status = @exercise.get_exercise_status(current_user)
#提交率
if @course_all_members_count == 0
commit_percent = 0.00
min_score = 0.0
max_score = 0.0
average_score = 0.0
fail_counts = 0
pass_counts = 0
good_counts = 0
best_counts = 0
else
commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3)
exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?)
min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0
max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0
total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0
average_score = @exercise_commit_user_counts > 0 ? (total_score.round(1) / @exercise_commit_user_counts).round(1) : 0.0
question_scores = @exercise.question_scores
fail_score = question_scores * 0.6.round(2)
pass_score = question_scores * 0.7.round(2)
good_score = question_scores * 0.9.round(2)
fail_counts = exercise_scores.count{|a| a < fail_score}
pass_counts = exercise_scores.count{|a| a < pass_score && a >= fail_score}
good_counts = exercise_scores.count{|a| a < good_score && a >= pass_score}
best_counts = exercise_scores.count{|a| a >= good_score && a <= question_scores}
end
@counts_array = {
:commit_percent => commit_percent,
:min_score => min_score.to_s,
:max_score => max_score.to_s,
:average_score => average_score.to_s,
:fail_counts => fail_counts,
:pass_counts => pass_counts,
:good_counts => good_counts,
:best_counts => best_counts,
}
@exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_answers,:exercise_standard_answers,:exercise_shixun_challenges,:exercise_shixun_answers)
@exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_answers,:exercise_standard_answers,:exercise_shixun_challenges,:exercise_shixun_answers)
percent_sort = "desc"
percent_sort = "desc"
if params[:sort].present?
percent_sort = params[:sort]
end
# @paging_type = "percent"
# # 按题型排序
# if params[:sort].present?
# @paging_type = params[:sort].to_s
# end
ques_result_all = exercise_commit_result(@exercise_questions,@exercise_commit_user_ids)
if params[:sort].present?
percent_sort = params[:sort]
end
# @paging_type = "percent"
# # 按题型排序
# if params[:sort].present?
# @paging_type = params[:sort].to_s
# end
#默认降序排列
if percent_sort == "desc"
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}.reverse
else
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}
end
ques_result_all = exercise_commit_result(@exercise_questions,@exercise_commit_user_ids)
@exercise_questions_count = @exercise_questions.size
@page = params[:page] || 1
@limit = params[:limit] || 10
@question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
#默认降序排列
if percent_sort == "desc"
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}.reverse
else
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}
end
@exercise_questions_count = @exercise_questions.size
@page = params[:page] || 1
@limit = params[:limit] || 10
@question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
end
end

@ -125,6 +125,9 @@ class MessagesController < ApplicationController
@message.message_detail_attributes = {content: params[:content]}
@message.save!
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
if @board.course.email_notify && params[:email_notify]
notify_course_students @message, @board.course
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -201,4 +204,10 @@ class MessagesController < ApplicationController
def message_params
params.require(:message).permit(:subject, :sticky)
end
def notify_course_students message, course
course.students.includes(:user).each do |student|
UserMailer.course_message_email(student&.user&.mail, message.id).deliver_now if student&.user&.mail
end
end
end

@ -1,9 +1,14 @@
class Oauth::BaseController < ActionController::Base
include RenderHelper
include LoginHelper
include ControllerRescueHandler
skip_before_action :verify_authenticity_token
def auth_failure
render_error(params[:message])
end
private
def session_user_id
@ -15,6 +20,7 @@ class Oauth::BaseController < ActionController::Base
end
def auth_hash
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
request.env['omniauth.auth']
end
end

@ -17,4 +17,13 @@ class SchoolsController < ApplicationController
render_ok(schools: schools.select(:id, :name).as_json)
end
def search
schools = School.all
keyword = params[:keyword].to_s.strip
schools = schools.where('name LIKE ?', "%#{keyword}%") if keyword
schools = paginate(schools)
render_ok(schools: schools.as_json(only: %i[id name province]))
end
end

@ -142,6 +142,9 @@ module ExercisesHelper
right_users_count = 0
#该问题的正确率
if ex.question_type == Exercise::MULTIPLE #多选题
if standard_answer.size == 1 #以前的多选题答案存在一个表里
standard_answer = standard_answer.first.to_s.split("").map(&:to_i)
end
right_user_ids = user_ids
standard_answer.each do |choice_position|
standard_answer_choice_id = ex_choices.select{|ec| ec.choice_position == choice_position}.first&.id
@ -409,12 +412,13 @@ module ExercisesHelper
end
#计算试卷的总分和试卷的答题状态
def calculate_student_score(exercise,user)
def calculate_student_score(exercise,user,end_time)
score1 = 0.0 #选择题/判断题
score2 = 0.0 #填空题
score5 = 0.0 #实训题
ques_stand = [] #问题是否正确
exercise_questions = exercise.exercise_questions.includes(:exercise_answers,:exercise_shixun_answers,:exercise_standard_answers,:exercise_shixun_challenges)
exercise_end_time = end_time || Time.now
exercise_questions = exercise.exercise_questions.includes(:exercise_standard_answers,:exercise_shixun_challenges)
exercise_questions&.each do |q|
begin
if q.question_type != 5
@ -502,7 +506,7 @@ module ExercisesHelper
exercise_cha_score = 0.0
answer_status = 0
# if game.status == 2 && game.final_score >= 0
if game.final_score > 0
if game.final_score > 0 && game.end_time && 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
@ -896,20 +900,21 @@ module ExercisesHelper
if ex_time > 0
exercise_user = exercise.exercise_users.find_by(user_id:user.id)
time_mill = ex_time * 60 #转为秒
exercise_end_time = exercise.end_time.present? ? exercise.end_time.to_i : 0
exercise_end_time = exercise.get_exercise_end_time(user.id) #没有考虑分班的情况
# exercise_end_time = exercise.end_time.present? ? exercise.end_time.to_i : 0
exercise_user_start = exercise_user&.start_at.present? ? exercise_user.start_at.to_i : 0
#用户未开始答题时即exercise_user_start为0
if exercise_user_start == 0
if (exercise_end_time - time_now_i) > time_mill
if (exercise_end_time.to_i - time_now_i) > time_mill
user_left_time = time_mill
else
user_left_time = (exercise_end_time < time_now_i) ? nil : (exercise_end_time - time_now_i)
user_left_time = (exercise_end_time.to_i < time_now_i) ? nil : (exercise_end_time.to_i - time_now_i)
end
else
if (exercise_user_start + time_mill) > exercise_end_time
time_mill = exercise_end_time - exercise_user_start #如果开始答题时间加试卷的限时长大于试卷的截止时间,则以试卷的截止时间到开始答题时间为试卷的限时
if (exercise_user_start + time_mill) > exercise_end_time.to_i
time_mill = exercise_end_time.to_i - exercise_user_start.to_i #如果开始答题时间加试卷的限时长大于试卷的截止时间,则以试卷的截止时间到开始答题时间为试卷的限时
end
exercise_user_left_time = time_now_i - exercise_user_start #用户已回答的时间
exercise_user_left_time = time_now_i - exercise_user_start.to_i #用户已回答的时间
user_left_time = (time_mill < exercise_user_left_time) ? nil : (time_mill - exercise_user_left_time) #当前用户对试卷的回答剩余时间
end
end

@ -5,11 +5,11 @@ class EndExerciseCalculateJob < ApplicationJob
queue_as :default
def perform(ex_user_ids,exercise)
def perform(ex_user_ids,exercise,end_time)
exercise_users = ExerciseUser.where(id: ex_user_ids)
exercise_users.each do |user|
if user.commit_status == 0 && user.start_at.present?
objective_score = calculate_student_score(exercise,user.user)[:total_score]
objective_score = calculate_student_score(exercise,user.user,end_time.to_time)[:total_score]
user_sub_score = user.subjective_score
subjective_score = user_sub_score < 0.0 ? 0.0 : user_sub_score
total_score = objective_score + subjective_score

@ -6,6 +6,7 @@ module OmniAuth
authorize_url: '/oauth2.0/authorize',
token_url: '/oauth2.0/token'
}
option :token_params, { parse: :query }
def request_phase
super
@ -21,7 +22,17 @@ module OmniAuth
end
end
uid { raw_info['openid'].to_s }
uid do
@uid ||= begin
access_token.options[:mode] = :query
access_token.options[:param_name] = :access_token
# Response Example: "callback( {\"client_id\":\"11111\",\"openid\":\"000000FFFF\"} );\n"
response = access_token.get('/oauth2.0/me')
matched = response.body.match(/"openid":"(?<openid>\w+)"/)
matched[:openid]
end
end
info do
{
@ -35,15 +46,10 @@ module OmniAuth
{ raw_info: user_info }
end
def raw_info
access_token.options[:mode] = :query
@raw_info ||= access_token.get('/oauth2.0/me').parsed
end
def user_info
access_token.options[:mode] = :query
params = { oauth_consumer_key: options.client_id, openid: raw_info['openid'], format: 'json' }
@user_info ||= access_token.get('/user/get_user_info', params: params)
param = { oauth_consumer_key: options[:client_id], openid: uid, format: 'json' }
@user_info ||= access_token.get('/user/get_user_info', params: param, parse: :json).parsed
end
end
end

@ -7,4 +7,11 @@ class UserMailer < ApplicationMailer
@code = code
mail(to: mail, subject: '验证你的电子邮件')
end
# 课堂讨论区的邮件通知
def course_message_email(mail, message_id)
@message = Message.find_by(id: message_id)
@course = @message&.board&.course
mail(to: mail, subject: '课堂通知') if @message.present? && @course.present?
end
end

@ -376,7 +376,7 @@ class Course < ApplicationRecord
case type
when 'activity' then '动态'
when 'announcement' then '公告栏'
when 'online_learning' then '在线学习'
when 'online_learning' then '课程学习'
when 'shixun_homework' then '实训作业'
when 'common_homework' then '普通作业'
when 'group_homework' then '分组作业'

@ -70,7 +70,7 @@ class Exercise < ApplicationRecord
if unified_setting
self&.end_time
else
user_course_group = course.course_members.find_by(user_id: user_id)&.course_group_id
user_course_group = course.students.find_by(user_id: user_id)&.course_group_id
exercise_group_settings.find_by(course_group_id:user_course_group)&.end_time
end
end
@ -156,9 +156,9 @@ class Exercise < ApplicationRecord
if unified_setting || teacher #当试卷为统一设置或当前为老师的时候
pb_time = publish_time
en_time = end_time
if (exercise_status != 3) && en_time.present? && (en_time <= Time.now)
update_column("exercise_status",3)
end
# if (exercise_status != 3) && en_time.present? && (en_time <= Time.now)
# update_column("exercise_status",3)
# end
else
# ex_group_setting = exercise_group_settings
user_group = course.students.where(user_id:user_id).select(:course_group_id)

@ -2,4 +2,6 @@ class Partner < ApplicationRecord
belongs_to :school, optional: true
has_many :users
has_many :partner_customers, dependent: :destroy
has_many :customers, through: :partner_customers
end

@ -0,0 +1,24 @@
class Admins::CustomerQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :created_at, default_by: :created_at, default_direction: :desc, default_table: 'customers'
def initialize(params)
@params = params
end
def call
customers = Customer.all
if params[:partner_id].present?
customers = customers.joins(:partner_customers).where(partner_customers: { partner_id: params[:partner_id] })
end
keyword = params[:keyword].to_s.strip
customers = customers.joins(:school).where('schools.name LIKE ?', "%#{keyword}%") if keyword.present?
custom_sort(customers, params[:sort_by], params[:sort_direction])
end
end

@ -0,0 +1,20 @@
class Admins::PartnerQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :created_at, default_by: :created_at, default_direction: :desc
def initialize(params)
@params = params
end
def call
partners = Partner.all
keyword = params[:keyword].to_s.strip
partners = partners.joins(:school).where('schools.name LIKE ?', "%#{keyword}%") if keyword.present?
custom_sort(partners, params[:sort_by], params[:sort_direction])
end
end

@ -77,10 +77,11 @@ class Admins::CheckShixunMirrorsService < ApplicationService
@_bridge_images ||= begin
url = EduSetting.get('cloud_bridge')
res = Faraday.get(url)
res_body = JSON.parse(res.body)
raise Error, '拉取镜像信息异常' if res && res['code'].nonzero?
raise Error, '拉取镜像信息异常' if res_body && res_body['code'].to_i != 0
res
res_body
rescue => e
Rails.logger.error("get response failed ! #{e.message}")
raise Error, '实训云平台繁忙繁忙等级84'

@ -17,7 +17,7 @@ class CreateBindUserService < ApplicationService
bind_user = User.try_to_login(params[:username], params[:password])
raise Error, '用户名或者密码错误' if bind_user.blank?
raise Error, '该账号已被其他微信号绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s)
raise Error, '该账号已被绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s)
ActiveRecord::Base.transaction do
open_user.user_id = bind_user.id

@ -28,7 +28,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService
user.create_user_extension!(gender: gender)
# 下载头像
avatar_path = Util::FileManage.source_disk_filename(user)
Util.download_file(params.dig('info', 'figureurl_qq_1'), avatar_path)
Util.download_file(params.dig('info', 'image'), avatar_path)
end
new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid'], extra: params.dig('extra', 'raw_info'))

@ -41,20 +41,21 @@ class ExercisePublishTask
puts "--------------------------------exercise_publish end"
end
def end
Rails.logger.info("log--------------------------------exercise_end start")
puts "--------------------------------exercise_end start"
# 1。统一设置的试卷
exercises = Exercise.includes(:exercise_users,:exercise_questions).where("exercise_status = 2 AND
unified_setting = true AND end_time <= ?",Time.now + 900)
exercises&.each do |exercise|
ex_type = exercise.exercise_questions.pluck(:question_type).uniq
exercise.update_column('exercise_status', 3)
exercise.exercise_users&.each do |exercise_user|
begin
Rails.logger.info("true: user_id:#{exercise_user.user_id}--commit_status:#{exercise_user.commit_status}")
if (exercise_user&.commit_status == 0) && (exercise_user&.start_at.present?)
s_score = calculate_student_score(exercise, exercise_user.user)[:total_score]
exercises = Exercise.includes(:exercise_questions).where("exercise_status = 2 AND end_time <= ?",Time.now + 900)
exercises.each do |exercise|
Rails.logger.info("end_exercise_id: #{exercise.id}")
exercise.update_attributes!(exercise_status: 3)
if exercise.unified_setting
ex_type = exercise.exercise_questions.pluck(:question_type).uniq
exercise.exercise_users.where("commit_status = 0 and start_at is not null").each do |exercise_user|
begin
Rails.logger.info("true: user_id:#{exercise_user.user_id}--commit_status:#{exercise_user.commit_status}")
s_score = calculate_student_score(exercise, exercise_user.user, exercise.end_time)[:total_score]
if ex_type.include?(4) #是否包含主观题
subjective_score = exercise_user.subjective_score
else
@ -66,72 +67,61 @@ class ExercisePublishTask
Rails.logger.info("true: user_id:#{exercise_user.user_id}--s_score:#{s_score}")
Rails.logger.info("true: user_id:#{exercise_user.user_id}--commit_method:#{exercise_user.commit_method}")
commit_option = {
:status => 1,
:commit_status => 1,
:end_at => Time.now,
:objective_score => s_score,
:score => total_score,
:subjective_score => subjective_score,
:commit_method => exercise_user&.commit_method.to_i > 0 ? exercise_user&.commit_method.to_i : 3
:status => 1,
:commit_status => 1,
:end_at => exercise.end_time,
:objective_score => s_score,
:score => total_score,
:subjective_score => subjective_score,
:commit_method => exercise_user&.commit_method.to_i > 0 ? exercise_user&.commit_method.to_i : 3
}
exercise_user.update_attributes(commit_option)
rescue Exception => e
Rails.logger.info("rescue errors ___________________________#{e}")
next
end
rescue Exception => e
Rails.logger.info("rescue errors ___________________________#{e}")
next
end
end
end
# 2.非统一的试卷
all_exercises = Exercise.includes(:exercise_group_settings,:exercise_users,:exercise_questions).where("unified_setting = false AND exercise_status = 2 AND end_time > ?",Time.now + 900)
exercise_ids = all_exercises.blank? ? "(-1)" : "(" + all_exercises.map(&:id).join(",") + ")"
ex_group_settings = ExerciseGroupSetting.where("end_time <= '#{Time.now}' and exercise_id in #{exercise_ids}")
ex_group_settings&.each do |exercise_setting|
ExerciseGroupSetting.where("end_time < ? and end_time > ?", Time.now + 900, Time.now - 900).each do |exercise_setting|
exercise = exercise_setting.exercise
if exercise.end_time <= Time.now
exercise.update_column('exercise_status', 3)
end
Rails.logger.info("exercise_group_setting: exercise_id:#{exercise.id}--group_settings_id:#{exercise_setting.id}")
users = exercise.course.course_members.where(:course_group_id => exercise_setting.course_group_id)
exercise_users = exercise.exercise_users.where(user_id: users.pluck(:user_id)).where("commit_status = 0 and start_at is not null")
ex_types = exercise.exercise_questions.pluck(:question_type).uniq
users = exercise.course.students.where(:course_group_id => exercise_setting.course_group_id)
exercise_users = exercise.exercise_users.where(:user_id => users.pluck(:user_id))
exercise_users&.each do |exercise_user|
exercise_users.each do |exercise_user|
Rails.logger.info("false: user_id:#{exercise_user.user_id}--commit_status:#{exercise_user.commit_status}")
begin
Rails.logger.info("false: user_id:#{exercise_user.user_id}--commit_status:#{exercise_user.commit_status}")
if exercise_user.commit_status == 0 && !exercise_user.start_at.nil?
if ex_types.include?(4) #是否包含主观题
subjective_score = exercise_user.subjective_score
else
subjective_score = -1.0
end
s_score = calculate_student_score(exercise, exercise_user.user)[:total_score]
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = s_score + total_score_subjective_score
Rails.logger.info("false: user_id:#{exercise_user.user_id}--s_score:#{s_score}")
Rails.logger.info("false: user_id:#{exercise_user.user_id}--subjective_score:#{subjective_score}")
Rails.logger.info("false: user_id:#{exercise_user.user_id}--commit_method:#{exercise_user.commit_method}")
commit_option = {
:status => 1,
:commit_status => 1,
:end_at => Time.now,
:objective_score => s_score,
:score => total_score,
:subjective_score => subjective_score,
:commit_method => exercise_user&.commit_method.to_i > 0 ? exercise_user&.commit_method.to_i : 3
}
exercise_user.update_attributes(commit_option)
if ex_types.include?(4) #是否包含主观题
subjective_score = exercise_user.subjective_score
else
subjective_score = -1.0
end
s_score = calculate_student_score(exercise, exercise_user.user, exercise_setting.end_time)[:total_score]
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = s_score + total_score_subjective_score
Rails.logger.info("false: user_id:#{exercise_user.user_id}--s_score:#{s_score}")
Rails.logger.info("false: user_id:#{exercise_user.user_id}--subjective_score:#{subjective_score}")
Rails.logger.info("false: user_id:#{exercise_user.user_id}--commit_method:#{exercise_user.commit_method}")
commit_option = {
:status => 1,
:commit_status => 1,
:end_at => exercise_setting.end_time,
:objective_score => s_score,
:score => total_score,
:subjective_score => subjective_score,
:commit_method => exercise_user&.commit_method.to_i > 0 ? exercise_user&.commit_method.to_i : 3
}
exercise_user.update_attributes(commit_option)
rescue Exception => e
Rails.logger.info("unified_setting_false_rescue errors ___________________________#{e}")
next
end
end
end
Rails.logger.info("log--------------------------------exercise_end end")
puts "--------------------------------exercise_end end"
end
end

@ -249,6 +249,7 @@
autoRefresh: true,
smartIndent: true,//智能换行
styleActiveLine: true,
lineWrapping: true,
lint: true,
readOnly: "nocursor"
});

@ -16,7 +16,7 @@
<td class="action-container">
<% if prize_user.leader? && prize_user.competition_prize.category == 'bonus' %>
<% bank_content = [prize_user.extra&.[]('bank'), prize_user.extra&.[]('second_bank'), prize_user.extra&.[]('card_no')].compact.join('<br>').presence || '无' %>
<%= javascript_void_link('查看银行账户', data: { toggle: 'popover', title: '银行账号', content: bank_content.html_safe, html: true }) %>
<%= javascript_void_link('查看银行账户', data: { toggle: 'tooltip', title: bank_content.html_safe, html: true, placement: 'left', trigger: 'click' }) %>
<% end %>
<% if prize_user.pending? %>

@ -0,0 +1,19 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('合作伙伴', admins_partners_path) %>
<% add_admin_breadcrumb(current_partner.school&.name || current_partner.name) %>
<% end %>
<div class="box search-form-container customer-list-form">
<%= form_tag(admins_partner_customers_path(current_partner), method: :get, class: 'form-inline search-form', remote: true) do %>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-md-4 ml-3', placeholder: '客户名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
<%= javascript_void_link('添加', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-select-school-modal' }) %>
</div>
<div class="box customer-list-container">
<%= render 'admins/customers/shared/list', customers: @customers %>
</div>
<%= render partial: 'admins/shared/modal/select_school_modal', locals: { title: '添加客户', multiple: true, url: admins_partner_customers_path(current_partner) } %>

@ -0,0 +1 @@
$('.customer-list-container').html("<%= j(render partial: 'admins/customers/shared/list', locals: { customers: @customers }) %>");

@ -0,0 +1,26 @@
<table class="table table-hover text-center customer-list-table">
<thead class="thead-light">
<tr>
<th width="50%" class="text-left">客户名称</th>
<th width="30%"><%= sort_tag('添加时间', name: 'created_at', path: admins_partner_customers_path(current_partner)) %></th>
<th width="20%">操作</th>
</tr>
</thead>
<tbody>
<% if customers.present? %>
<% customers.each do |customer| %>
<tr class="customer-item-<%= customer.id %>">
<td class="text-left"><%= customer.school&.name %></td>
<td><%= customer.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
<td>
<%= delete_link '删除', admins_partner_customer_path(current_partner, customer, element: ".customer-item-#{customer.id}"), class: 'delete-customer-action' %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: customers } %>

@ -0,0 +1,18 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('合作伙伴') %>
<% end %>
<div class="box search-form-container partner-list-form">
<%= form_tag(admins_partners_path, method: :get, class: 'form-inline search-form', remote: true) do %>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-md-4 ml-3', placeholder: '合作伙伴名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
<%= javascript_void_link('添加', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-select-school-modal' }) %>
</div>
<div class="box partner-list-container">
<%= render 'admins/partners/shared/list', partners: @partners %>
</div>
<%= render partial: 'admins/shared/modal/select_school_modal', locals: { title: '添加客户', multiple: true, url: admins_partners_path } %>

@ -0,0 +1 @@
$('.partner-list-container').html("<%= j(render partial: 'admins/partners/shared/list', locals: { partners: @partners }) %>");

@ -0,0 +1,27 @@
<table class="table table-hover text-center partner-list-table">
<thead class="thead-light">
<tr>
<th width="50%" class="text-left">名称</th>
<th width="30%"><%= sort_tag('添加时间', name: 'created_at', path: admins_partners_path) %></th>
<th width="20%">操作</th>
</tr>
</thead>
<tbody>
<% if partners.present? %>
<% partners.each do |partner| %>
<tr class="partner-item-<%= partner.id %>">
<td class="text-left"><%= partner.school&.name || partner.name %></td>
<td><%= partner.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
<td>
<%= link_to '查看', admins_partner_customers_path(partner), class: 'action' %>
<%= delete_link '删除', admins_partner_path(partner, element: ".partner-item-#{partner.id}"), class: 'delete-partner-action' %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: partners } %>

@ -40,6 +40,7 @@
<%= sidebar_item_group('#schools-submenu', '单位管理', icon: 'building') do %>
<li><%= sidebar_item(admins_schools_path, '单位列表', icon: 'university', controller: 'admins-schools') %></li>
<li><%= sidebar_item(admins_departments_path, '部门列表', icon: 'sitemap', controller: 'admins-departments') %></li>
<li><%= sidebar_item(admins_partners_path, '合作伙伴', icon: 'handshake-o', controller: 'admins-partners') %></li>
<% end %>
</li>

@ -0,0 +1,28 @@
<div class="modal fade admin-select-school-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><%= title %></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="admin-select-school-form" data-multiple="<%= multiple || false %>" data-url="<%= url %>">
<div class="form-group d-flex">
<label for="school_ids" class="col-form-label"><%= label ||= '选择单位:' %></label>
<div class="d-flex flex-column-reverse w-75">
<select id="school_ids" name="school_ids" class="form-control school-select" multiple="multiple"></select>
</div>
</div>
<div class="error text-danger"></div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -5,6 +5,7 @@ if @leader
json.bank_account_editable @bank_account_editable
end
json.all_certified current_user.all_certified?
json.personal_certifications do
json.array! @self_prizes do |prize_user|
json.url personal_competition_certificate_path(current_competition.identifier, prize_user)

@ -6,4 +6,5 @@ json.data do
json.boards do
json.array! @boards, :id, :name
end
json.email_notify @course.email_notify
end

@ -10,8 +10,8 @@ json.students do
if @user_course_identity < Course::ASSISTANT_PROFESSOR && !params[:course_group_id].present?
json.member_roles student.user.course_role(@course)
end
json.user_phone student.user.hidden_phone
json.user_mail student.user.hidden_mail
json.user_phone @course.excellent ? "" : student.user.hidden_phone
json.user_mail @course.excellent ? "" : student.user.hidden_mail
end
end
json.students_count @students_count

@ -3,7 +3,7 @@ json.author do
end
json.id message.id
json.content message.contents_show(identity)
json.content content_safe(message.contents_show(identity))
json.time time_from_now(message.created_at)
json.hidden message.hidden
# 主贴与子贴不一致

@ -12,6 +12,7 @@ json.allow_send @user.logged?
json.allow_visit @subject.status > 1 || @is_manager
json.allow_add_member @is_manager
json.is_creator @is_creator
json.cover url_to_avatar(@subject)
if @subject.excellent
json.has_start @subject.has_course_start?

@ -0,0 +1,62 @@
<html>
<head>
<meta charset="utf-8">
<title><%= @course.name %>通知</title>
<style type="text/css">
/* 验证链接页面 */
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;}
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;}
div,img,tr,td,table{ border:0;}
table,tr,td{border:0;}
ol,ul,li{ list-style-type:none}
.new_content{ background:#fff; width: 100%;}
.email-page-link{ }
.email-link-top{ }
.c_white{ color:#fff;}
.email-link-con{ }
.email-link-line{ }
.email-link-footer{ padding:15px; color:#333; line-height: 1.9; }
.c_grey02{ color: #888;}
.fb{ font-weight: normal;}
.f14{ }
</style>
</head>
<body style="background:#fff;">
<div class="new_content">
<div style="width: 598px; background:#fff; margin:20px auto; font-size:14px; ">
<div style="height:50px; width: 578px; background:#46484c; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;">
<a href="https://www.educoder.net">
<img src="https://www.educoder.net/images/educoder/headNavLogo.png" width="36" style="float:left; margin-top: 8px;" >
</a>
<div style="clear:both; overflow:hidden;"></div>
</div>
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:30px 20px; color:#333; line-height: 1.9;">
<p style="color:#333; font-size:16px; margin-bottom:15px;font-weight: bold">
您好!
</p>
<p style="color:#333;">
您正在注册Educoder请在10分钟内在注册页输入此验证码并进行下一步操作。
如非你本人操作,请忽略此邮件。
</p>
<div style="text-align: center;">
<div style="display:block; height: 45px; line-height:45px;padding:0 30px; width:100px; font-size: 20px; font-weight: bold; background:#ffd9d9; color:#e72c37; margin:30px auto;">
<p><%= @code %></p>
</div>
<span style="font-weight: normal;color:#666;">
此邮件为系统所发,请勿直接回复。<br/>
要解决问题或了解您的帐户详情,您可以访问 <a href="https://www.educoder.net/help?index=5" style="font-weight: normal; color:#ff7500;">帮助中心</a>。
</span>
</div>
<p style="color:#666; margin-top:30px;">
如果您并未发过此请求,则可能是因为其他用户在注册时误输了您的邮件地址,而使您收到了这封邮件,那么您可以放心的忽略此邮件,无需进一步采取任何操作。
</p>
</div>
<div style="padding:20px; color:#333; line-height: 1.9;background:#46484c;border:1px solid #ddd; border-top:none; width: 558px;">
<a href="https:///www.educoder.net/" style="font-weight: normal; color:#fff;">www.educoder.net</a>
</div>
</div>
</div>
</body>
</html>

@ -3,4 +3,5 @@ admins-laboratory_settings: 'admins-laboratories'
admins-carousels: 'admins-laboratories'
admins-competition_settings: 'admins-competitions'
admins-enroll_lists: 'admins-competitions'
admins-competition_prize_users: 'admins-competitions'
admins-competition_prize_users: 'admins-competitions'
admins-customers: 'admins-partners'

@ -1,4 +1,8 @@
OmniAuth.config.add_camelization 'qq', 'QQ'
OmniAuth.config.logger = Rails.logger
OmniAuth.config.on_failure = Proc.new { |env|
OmniAuth::FailureEndpoint.new(env).redirect_to_failure
}
oauth_config = {}
begin
@ -13,5 +17,5 @@ rescue => ex
end
Rails.application.config.middleware.use OmniAuth::Builder do
provider :qq, oauth_config['appid'], oauth_config['secret']
provider :qq, oauth_config['appid'], oauth_config['secret'], { provider_ignores_state: true }
end

@ -6,6 +6,8 @@ Rails.application.routes.draw do
get 'attachments/download/:id', to: 'attachments#show'
get 'attachments/download/:id/:filename', to: 'attachments#show'
get 'auth/qq/callback', to: 'oauth/qq#create'
get 'auth/failure', to: 'oauth/base#auth_failure'
resources :edu_settings
scope '/api' do
@ -289,6 +291,7 @@ Rails.application.routes.draw do
post :down_member_position
get :right_banner
post :appointment
post :update_team_title
end
collection do
@ -714,6 +717,7 @@ Rails.application.routes.draw do
collection do
get :school_list
get :for_option
get :search
end
scope module: :ecs do
@ -1077,9 +1081,12 @@ Rails.application.routes.draw do
post :cancel_homepage_show
post :excellent
post :cancel_excellent
post :update_team_title
end
end
resources :partners, only: [:index, :create, :destroy] do
resources :customers, only: [:index, :create, :destroy]
end
end
namespace :cooperative do

@ -0,0 +1,5 @@
class AddEmailNotifyToCourse < ActiveRecord::Migration[5.2]
def change
add_column :courses, :email_notify, :boolean, default: 0
end
end

@ -0,0 +1,60 @@
class Migrate2796ExerciseScore < ActiveRecord::Migration[5.2]
def calculate_student_score(exercise,user)
score1 = 0.0 #实训题
exercise_questions = exercise.exercise_questions.includes(:exercise_standard_answers)
exercise_questions.each do |q|
answers_content = q.exercise_answers.where(user_id: user.id) #学生的答案
if q.question_type <= 2 #为选择题或判断题时
if answers_content.present? #学生有回答时
answer_choice_array = []
answers_content.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
#TODO: 旧版多选题的标准答案是放在一个里面的新版又做成了一个题有多个标准答案exercise_choice_id存放的是标准答案的位置..
if q.question_type == 1 && standard_answer.size == 1
standard_answer = standard_answer.first.to_s.split("").map(&:to_i).sort
end
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
if standard_answer.size > 0
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
else
score1 += 0.0
end
end
end
score1
end
def change
exercise = Exercise.find_by(id: 2796)
if exercise
exercise_users = exercise.exercise_users.where("start_at is not null and commit_status = 0")
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.nil?
exercise_user.update_attributes!(score:total_score,objective_score:calculate_score,end_at:exercise.end_time,commit_status:1,status:1,commit_method:3)
else
exercise_user.update_attributes!(score:total_score,objective_score:calculate_score)
end
puts exercise_user.id
end
end
end
end

@ -110,7 +110,7 @@ namespace :poll_publish do
# # end
# end
PollGroupSetting.where("end_time < ? and end_time > ?", Time.now + 1800, Time.now - 1800).each do |poll_setting|
PollGroupSetting.where("end_time < ? and end_time > ?", Time.now + 900, Time.now - 900).each do |poll_setting|
poll = poll_setting.poll
# poll.update_column('polls_status',3)

File diff suppressed because one or more lines are too long

@ -136185,7 +136185,7 @@ $(document).on('turbolinks:load', function(){
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/for_option.json',
url: '/api/schools/search.json',
dataType: 'json',
data: function(params){
return { keyword: params.term };
@ -138214,6 +138214,96 @@ $(document).on('turbolinks:load', function() {
});
})
});
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-select-school-modal');
if ($modal.length > 0) {
var $link = null;
var $form = $modal.find('form.admin-select-school-form');
var multiple = $form.data('multiple');
$form.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择',
multiple: multiple,
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/search.json',
dataType: 'json',
data: function (params) {
return {keyword: params.term};
},
processResults: function (data) {
return {results: data.schools}
}
},
templateResult: function (item) {
if (!item.id || item.id === '') return item.text;
var html = "<span>" + item.name + "<span class='ml-4 font-12'>";
if(item.province){ html += item.province }
html += "</span></span>";
return $(html);
},
templateSelection: function (item) {
if (item.id) {
}
return item.name || item.text;
}
});
$form.validate({
errorElement: 'span',
errorClass: 'danger text-danger',
rules: {
school_ids: {
required: true
}
},
messages: {
school_ids: {
required: '请选择'
}
}
});
$modal.on('show.bs.modal', function(event){
$link = $(event.relatedTarget);
});
$modal.on('hide.bs.modal', function(){
$form.find('.error').html('');
$form.find('.school-select').select2('val', ' ');
});
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if($form.valid()){
var url = $form.data('url');
var schoolIds = $form.find('#school_ids').val();
$.ajax({
method: 'POST',
dataType: 'json',
url: url,
data: { school_ids: schoolIds },
success: function(){
$.notify({ message: '操作成功' });
$modal.modal('hide');
setTimeout(function(){
window.location.reload();
}, 500);
},
error: function(res){
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
}
});
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-upload-file-modal');
if ($modal.length > 0) {
@ -138636,7 +138726,7 @@ $(document).on('turbolinks:load', function () {
minimumInputLength: 1,
ajax: {
delay: 500,
url: '/api/schools/for_option.json',
url: '/api/schools/search.json',
dataType: 'json',
data: function (params) {
return {keyword: params.term};
@ -138668,12 +138758,18 @@ $(document).on('turbolinks:load', function () {
// 上传图片
$('.modal.admin-upload-file-modal').on('upload:success', function (e, data) {
var $imageElement = $('.subject-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
})
if(data.suffix == '_qrcode'){
var $imageElement = $('.subject-weapp-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
} else {
var $imageElement = $('.subject-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
}
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.subject-list-container').on('click', doElement, function () {

@ -10,8 +10,9 @@
out+=this.renderer.em(this.output(cap[2]||cap[1])) -->
out+=this.renderer.em(this.output(cap[2]||cap[1]), cap.input)
*/
// 0.4.0 /^ *(#{1,6}) ——》/^ *(#{1,6}) 去掉了一个空格 TODO 行内公式带_
// 0.4.0 /^ *(#{1,6}) ——》/^ *(#{1,6}) 去掉了一个空格
/*if("string"!=typeof e)throw new Error("marked(): input parameter is of type "+Object.prototype.toString.call(e)+", string expected");*/
// 说明:左边 --> 右边 左边被替换成了右边的内容
// b(i[1].replace(/^ *| *\| *$/g,"")) --> i[1].replace(/^ *| *\| *$/g, "").split(/ *\| */) table没识别的问题
// header.length===a.align.length --> header.length table没识别的问题
// 2个table b(a.cells[p],a.header.length) -> a.cells[p].replace(/^ *\| *| *\| *$/g, "").split(/ *\| */)

@ -32,7 +32,7 @@ module.exports = {
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s
// devtool: "cheap-module-eval-source-map",
// 开启调试
devtool: "source-map", // 开启调试
// devtool: "source-map", // 开启调试
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.

@ -222,6 +222,12 @@
<div class="code-name">&amp;#xe693;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6c0;</span>
<div class="name">关注</div>
<div class="code-name">&amp;#xe6c0;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe63c;</span>
<div class="name">礼物</div>
@ -324,6 +330,12 @@
<div class="code-name">&amp;#xe678;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6c5;</span>
<div class="name">关注</div>
<div class="code-name">&amp;#xe6c5;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe608;</span>
<div class="name">喇叭</div>
@ -1718,6 +1730,15 @@
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weibiaoti105"></span>
<div class="name">
关注
</div>
<div class="code-name">.icon-weibiaoti105
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-gift"></span>
<div class="name">
@ -1871,6 +1892,15 @@
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-guanzhu"></span>
<div class="name">
关注
</div>
<div class="code-name">.icon-guanzhu
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-laba"></span>
<div class="name">
@ -3740,6 +3770,14 @@
<div class="code-name">#icon-renzhengxinxi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weibiaoti105"></use>
</svg>
<div class="name">关注</div>
<div class="code-name">#icon-weibiaoti105</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-gift"></use>
@ -3876,6 +3914,14 @@
<div class="code-name">#icon-dashujucunchu</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-guanzhu"></use>
</svg>
<div class="name">关注</div>
<div class="code-name">#icon-guanzhu</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-laba"></use>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -229,6 +229,13 @@
"unicode": "e693",
"unicode_decimal": 59027
},
{
"icon_id": "1214792",
"name": "关注",
"font_class": "weibiaoti105",
"unicode": "e6c0",
"unicode_decimal": 59072
},
{
"icon_id": "1221889",
"name": "礼物",
@ -348,6 +355,13 @@
"unicode": "e678",
"unicode_decimal": 59000
},
{
"icon_id": "1901672",
"name": "关注",
"font_class": "guanzhu",
"unicode": "e6c5",
"unicode_decimal": 59077
},
{
"icon_id": "1941293",
"name": "喇叭",

@ -116,6 +116,9 @@ Created by iconfont
<glyph glyph-name="renzhengxinxi" unicode="&#59027;" d="M485.648423-128c-144.376948 0-412.841368 220.864564-412.841368 429.728646L72.807056 717.817567l41.04289 0.68044c0.866014 0 92.50888 1.948532 187.059079 40.331521 96.962668 39.403649 159.532198 84.652894 160.11985 85.054972l24.495832 17.846079 24.712335-17.846079c0.587653-0.433007 63.126253-45.651323 160.11985-85.054972 94.550199-38.382989 186.193065-40.331521 187.151867-40.331521l40.857315-0.68044 0.185574-416.057992C898.582578 92.895494 630.118159-128 485.648423-128L485.648423-128M156.160928 638.051468l0-336.291893c0-161.511659 233.854778-346.374773 329.487495-346.374773 95.632717 0 329.487495 184.863115 329.487495 346.374773L815.135919 638.051468c-40.857315 4.422859-107.200193 15.588257-176.079256 43.548145-70.611091 28.702187-124.242117 59.909629-153.40824 78.498007-29.104265-18.588377-82.76622-49.79582-153.315452-78.498007C263.361121 653.608795 197.018243 642.474326 156.160928 638.051468L156.160928 638.051468M463.56506 145.413072 288.28996 294.738673l53.909387 63.404615 112.458137-95.725504 213.441585 245.886191 63.033466-54.682614L463.56506 145.413072 463.56506 145.413072M463.56506 145.413072 463.56506 145.413072z" horiz-adv-x="1024" />
<glyph glyph-name="weibiaoti105" unicode="&#59072;" d="M936.038 750.874c-109.38 118.519-286.737 118.519-396.083 0l-27.93-30.276-27.947 30.276c-109.363 118.519-286.703 118.519-396.066 0-109.38-118.511-109.38-310.647 0-429.158l27.93-30.251 396.083-365.414 396.066 365.414 27.947 30.251c109.362 118.51 109.362 310.647 0 429.158v0z" horiz-adv-x="1024" />
<glyph glyph-name="gift" unicode="&#58940;" d="M85.931-54.016c0-24.576 7.125-31.317 29.44-31.317h353.365v469.589h-382.805v-438.272zM555.264-85.333h353.365c22.357 0 29.44 6.699 29.44 31.317l-0 438.272h-382.848v-469.589zM938.667 640h-213.333c51.499 11.733 105.899 49.707 112.597 94.293 7.851 50.859-52.565 127.957-125.653 118.187-87.424-12.117-151.509-89.259-196.736-149.077-44.885 58.667-103.381 127.189-187.179 147.115-81.152 19.2-136.747-64.939-135.253-116.992 1.451-44.245 52.608-81.835 105.557-93.525h-213.333c-26.368 0-42.667-14.848-42.667-42.667v-170.581l426.667-0.085v213.333h85.333v-213.333l426.667 0.085v170.581c0 27.819-16.341 42.667-42.667 42.667zM251.648 717.824c-14.763 16.427-4.779 38.741 4.48 55.595 17.024 29.696 40.747 47.744 81.152 30.933 56.32-23.509 97.792-73.216 131.584-117.803-71.552-7.893-178.304-10.965-217.216 31.275zM562.944 687.317c34.816 44.629 75.221 89.941 131.157 117.803 58.581 28.971 113.024-49.323 85.205-86.912-21.419-28.544-89.259-31.232-125.909-32.853-30.080-1.536-60.501-0.811-90.453 1.963z" horiz-adv-x="1024" />
@ -167,6 +170,9 @@ Created by iconfont
<glyph glyph-name="dashujucunchu" unicode="&#59000;" d="M975.644444 233.24444400000004V534.7555560000001c28.444444 14.222222 51.2 42.666667 51.2 76.8 0 48.355556-36.977778 85.333333-85.333333 85.333333-19.911111 0-39.822222-8.533333-54.044444-19.911111L594.488889 830.577778C585.955556 867.555556 551.822222 896 512 896c-42.666667 0-79.644444-31.288889-85.333333-73.955556L145.066667 671.288889C130.844444 688.355556 108.088889 696.8888890000001 85.333333 696.8888890000001c-48.355556 0-85.333333-36.977778-85.333333-85.333333 0-39.822222 28.444444-73.955556 65.422222-82.488889v-290.133334C28.444444 230.39999999999998 0 196.26666699999998 0 156.44444399999998c0-48.355556 36.977778-85.333333 85.333333-85.333333 22.755556 0 45.511111 8.533333 59.733334 25.6l281.6-150.755555c5.688889-42.666667 39.822222-73.955556 85.333333-73.955556 39.822222 0 73.955556 28.444444 82.488889 65.422222l290.133333 153.6c14.222222-11.377778 34.133333-19.911111 54.044445-19.911111 48.355556 0 85.333333 36.977778 85.333333 85.333333 0 34.133333-19.911111 62.577778-48.355556 76.8z m-96.711111-14.222222l-133.688889 65.422222v199.111112l133.688889 65.422222c11.377778-11.377778 22.755556-17.066667 36.977778-19.911111v-290.133334c-14.222222-2.844444-25.6-11.377778-36.977778-19.911111zM853.333333 600.177778l-139.377777-68.266667L540.444444 631.4666669999999V731.022222c19.911111 8.533333 36.977778 22.755556 45.511112 39.822222l267.377777-142.222222v-28.444444zM520.533333 190.57777799999997l-170.666666 96.711111v193.422222l170.666666 96.711111 170.666667-96.711111v-193.422222l-170.666667-96.711111zM483.555556 731.022222v-105.244444l-167.822223-96.711111L170.666667 600.177778V611.555556v8.533333l270.222222 145.066667c8.533333-17.066667 25.6-28.444444 42.666667-34.133334zM145.066667 548.977778l147.911111-73.955556v-184.888889l-147.911111-73.955555c-5.688889 5.688889-14.222222 11.377778-22.755556 17.066666V534.7555560000001c8.533333 2.844444 14.222222 8.533333 22.755556 14.222222zM170.666667 167.822222l145.066666 73.955556 167.822223-96.711111v-105.244445c-17.066667-5.688889-34.133333-17.066667-42.666667-34.133333l-270.222222 142.222222V156.44444399999998v11.377778z m369.777777-130.844444v99.555555l176.355556 99.555556 139.377778-68.266667v-11.377778c0-5.688889 0-11.377778 2.844444-17.066666l-267.377778-142.222222c-14.222222 19.911111-31.288889 34.133333-51.2 39.822222z" horiz-adv-x="1026" />
<glyph glyph-name="guanzhu" unicode="&#59077;" d="M726.109 863.418c-83.782 0-158.255-32.582-214.109-93.091-55.855 60.509-130.327 93.091-214.109 93.091-162.909 0-297.891-144.291-297.891-321.164 0-93.091 37.236-181.527 107.055-246.691l353.745-367.709c13.964-13.964 32.582-23.273 51.2-23.273 18.618 0 37.236 9.309 51.2 23.273l358.4 363.055c65.164 65.164 107.055 158.255 107.055 251.345-4.655 176.873-139.636 321.164-302.545 321.164zM870.4 346.764l-358.4-363.055-358.4 367.709c-51.2 51.2-83.782 116.364-83.782 190.836 0 134.982 102.4 242.036 228.073 242.036 97.745 0 176.873-65.164 214.109-153.6 32.582 88.436 116.364 153.6 214.109 153.6 125.673 0 228.073-107.055 228.073-242.036 0-74.473-32.582-144.291-83.782-195.491z" horiz-adv-x="1028" />
<glyph glyph-name="laba" unicode="&#58888;" d="M858.584615 586.174359c-5.251282 5.251282-10.502564 10.502564-15.753846 13.128205-5.251282 5.251282-10.502564 10.502564-18.379487 13.128205v-10.502564c-21.005128 0-39.384615-18.379487-39.384615-39.384615v-2.625641c0-21.005128 18.379487-39.384615 39.384615-39.384616v-18.379487c26.25641-34.133333 39.384615-73.517949 39.384615-118.153846s-15.753846-86.646154-39.384615-118.153846v-15.753846c-21.005128 0-39.384615-18.379487-39.384615-39.384616v-2.625641c0-21.005128 18.379487-39.384615 39.384615-39.384615v-10.502564c7.876923 5.251282 13.128205 10.502564 21.005128 15.753846 5.251282 2.625641 10.502564 7.876923 13.128205 10.502564 52.512821 49.887179 86.646154 120.779487 86.646154 202.174359 0 78.769231-34.133333 149.661538-86.646154 199.548718z m-189.046153 191.671795h-7.876924c-7.876923 0-13.128205-2.625641-21.005128-7.876923l-330.830769-149.661539H157.538462c-44.635897 0-78.769231-34.133333-78.769231-78.76923v-317.702565c2.625641-42.010256 36.758974-76.14359 78.769231-76.143589h39.384615c21.005128 0 39.384615 18.379487 39.384615 39.384615s-15.753846 36.758974-34.133333 39.384615H236.307692c-65.641026 0-78.769231 13.128205-78.76923 78.769231v-2.625641 170.666667-7.876923c0 60.389744 10.502564 76.14359 65.641025 78.769231H315.076923c5.251282 0 10.502564 2.625641 15.753846 5.251282 2.625641 0 7.876923 2.625641 10.502564 5.251282l288.820513 131.282051v-593.394872L375.466667 213.333333c-18.379487 13.128205-42.010256 7.876923-55.138462-7.876923-13.128205-18.379487-7.876923-42.010256 7.876923-55.138461L638.030769 3.282051c7.876923-5.251282 18.379487-7.876923 26.25641-7.876923h2.625642c21.005128 0 39.384615 18.379487 39.384615 39.384616L708.923077 738.461538c0 23.630769-18.379487 39.384615-39.384615 39.384616z m-506.748718-551.384616H157.538462h5.251282z m-5.251282 315.076924h21.005128H157.538462z" horiz-adv-x="1024" />
@ -659,7 +665,7 @@ Created by iconfont
<glyph glyph-name="xuexizhongxin" unicode="&#59062;" d="M946.907429 889.690634H635.102609c-36.145292 0-68.945093-14.533168-92.91687-38.13605A131.510857 131.510857 0 0 1 449.389714 889.690634H137.591255C64.422957 889.690634 4.916472 830.184149 4.916472 757.015851v-643.472696a39.707031 39.707031 0 0 1 39.751553-39.751553h378.142211c55.149714 0 84.22241-45.348571 85.214609-46.957714 0.496099-0.871354 1.240248-1.367453 1.736348-2.238807 0.623304-0.871354 1.246609-1.615503 1.863552-2.353292 2.111602-2.493217 4.477615-4.725665 6.958112-6.716423l1.494659-1.113043c6.455652-4.35041 14.037068-6.958112 21.987378-6.958112 3.472696 0 7.078957 0.496099 10.558013 1.488298 1.488298 0.375255 2.734907 1.367453 4.096 1.863553 1.990758 0.744149 3.854311 1.615503 5.717863 2.607702 1.615503 0.998559 2.976596 2.111602 4.471255 3.231006a40.19677 40.19677 0 0 1 4.719304 4.471255c0.992199 1.119404 2.111602 2.359652 2.982957 3.606261 0.368894 0.616944 0.992199 1.113043 1.367453 1.736348 1.240248 1.990758 30.306584 47.332969 85.462659 47.332968h378.13585a39.707031 39.707031 0 0 1 39.751553 39.751553V757.015851c0.25441 73.168298-59.252075 132.674783-132.420372 132.674783zM422.931081 121.614311H50.576696V769.736348c0 29.320745 56.154634 69.275826 85.348174 69.275826h311.798459c29.320745 0 72.475031-40.082286 72.475031-69.275826v-667.12646c-21.739329 11.054112-65.841292 19.004422-97.267279 19.004423z m602.582658 0h-363.825292c-31.425988 0-57.884621-7.950311-79.63031-19.004423V769.736348c0 29.320745 27.120099 67.584 56.313639 67.584h330.879205c29.320745 0 56.141913-38.39046 56.141913-67.584v-648.122037h0.127205zM403.055304 644.197764H184.173714c-21.987379 0-39.751553-14.208795-39.751553-31.801242 0-17.586087 17.764174-31.801242 39.751553-31.801242h218.88159c21.987379 0 39.751553 14.215155 39.751553 31.801242 0 17.490683-17.764174 31.801242-39.751553 31.801242z m0-248.049689H184.173714c-21.987379 0-39.751553-14.208795-39.751553-31.801243 0-17.586087 17.764174-31.801242 39.751553-31.801242h218.88159c21.987379 0 39.751553 14.215155 39.751553 31.801242 0 17.490683-17.764174 31.801242-39.751553 31.801243z m497.517715 254.409937H681.564224c-21.987379 0-39.751553-14.208795-39.751553-31.801242 0-17.586087 17.764174-31.801242 39.751553-31.801242h218.88159c21.987379 0 39.751553 14.215155 39.751552 31.801242 0.127205 17.490683-17.636969 31.801242-39.624347 31.801242z m0-254.409937H681.564224c-21.987379 0-39.751553-14.208795-39.751553-31.801243 0-17.586087 17.764174-31.801242 39.751553-31.801242h218.88159c21.987379 0 39.751553 14.215155 39.751552 31.801242 0.127205 17.490683-17.636969 31.801242-39.624347 31.801243z m139.251279-457.638957H52.249441c-21.987379 0-39.751553-14.208795-39.751553-31.801242s17.764174-31.801242 39.751553-31.801242h987.574857c21.987379 0 39.751553 14.208795 39.751553 31.801242 0 17.490683-17.764174 31.801242-39.751553 31.801242z" horiz-adv-x="1081" />
<glyph glyph-name="tongji" unicode="&#59071;" d="M256-32.2h-62.5c-52.9 0-96 43.1-96 96V413.9c0 52.9 43.1 96 96 96H256c52.9 0 96-43.1 96-96v-350.1c0-53-43.1-96-96-96z m-62.5 478.1c-17.6 0-32-14.4-32-32v-350.1c0-17.6 14.4-32 32-32H256c17.6 0 32 14.4 32 32V413.9c0 17.6-14.4 32-32 32h-62.5zM542.2-32.2h-62.5c-52.9 0-96 43.1-96 96V704.2c0 52.9 43.1 96 96 96h62.5c52.9 0 96-43.1 96-96v-640.5c0-52.9-43-95.9-96-95.9z m-62.4 768.4c-17.6 0-32-14.4-32-32v-640.5c0-17.6 14.4-32 32-32h62.5c17.6 0 32 14.4 32 32V704.2c0 17.6-14.4 32-32 32h-62.5zM830.5-32.2H768c-52.9 0-96 43.1-96 96v479c0 52.9 43.1 96 96 96h62.5c52.9 0 96-43.1 96-96v-479c0-53-43.1-96-96-96zM768 574.7c-17.6 0-32-14.4-32-32v-479c0-17.6 14.4-32 32-32h62.5c17.6 0 32 14.4 32 32v479c0 17.6-14.4 32-32 32H768z" horiz-adv-x="1024" />
<glyph glyph-name="tongji" unicode="&#59071;" d="M210.823529 594.823529A90.352941 90.352941 0 0 0 301.176471 504.470588v-542.117647A90.352941 90.352941 0 0 0 210.823529-128h-120.470588A90.352941 90.352941 0 0 0 0-37.64705900000001v542.117647A90.352941 90.352941 0 0 0 90.352941 594.823529h120.470588z m361.411765 301.176471A90.352941 90.352941 0 0 0 662.588235 805.647059v-843.294118A90.352941 90.352941 0 0 0 572.235294-128h-120.470588A90.352941 90.352941 0 0 0 361.411765-37.64705900000001v843.294118A90.352941 90.352941 0 0 0 451.764706 896h120.470588z m361.411765-542.117647a90.352941 90.352941 0 0 0 90.352941-90.352941v-301.176471a90.352941 90.352941 0 0 0-90.352941-90.352941h-120.470588a90.352941 90.352941 0 0 0-90.352942 90.352941v301.176471A90.352941 90.352941 0 0 0 813.176471 353.88235299999997h120.470588z m-722.82353 180.705882h-120.470588a30.117647 30.117647 0 0 1-29.635765-24.69647L60.235294 504.470588v-542.117647a30.117647 30.117647 0 0 1 24.696471-29.635765L90.352941-67.76470600000005h120.470588a30.117647 30.117647 0 0 1 29.635765 24.696471L240.941176-37.64705900000001v542.117647a30.117647 30.117647 0 0 1-30.117647 30.117647z m361.411765 301.176471h-120.470588a30.117647 30.117647 0 0 1-29.635765-24.696471L421.647059 805.647059v-843.294118a30.117647 30.117647 0 0 1 24.69647-29.635765L451.764706-67.76470600000005h120.470588a30.117647 30.117647 0 0 1 29.635765 24.696471L602.352941-37.64705900000001v843.294118a30.117647 30.117647 0 0 1-30.117647 30.117647z m361.411765-542.117647h-120.470588a30.117647 30.117647 0 0 1-29.635765-24.696471L783.058824 263.529412v-301.176471a30.117647 30.117647 0 0 1 24.69647-29.635765l5.421177-0.481882h120.470588a30.117647 30.117647 0 0 1 29.635765 24.696471L963.764706-37.64705900000001v301.176471a30.117647 30.117647 0 0 1-30.117647 30.117647z" horiz-adv-x="1024" />
<glyph glyph-name="menu_voucher" unicode="&#59064;" d="M830.236-64.886H200.924c-63.104 0-114.421 51.316-114.421 114.421V364.191c0 63.104 51.316 114.421 114.421 114.421h629.313c63.104 0 114.421-51.316 114.421-114.421v-314.656c-0.001-63.105-51.317-114.421-114.422-114.421zM200.924 421.401c-31.538 0-57.21-25.672-57.21-57.21v-314.656c0-31.538 25.672-57.21 57.21-57.21h629.313c31.538 0 57.21 25.672 57.21 57.21V364.191c0 31.538-25.672 57.21-57.21 57.21H200.924zM801.631 604.848H229.529c-15.811 0-28.605 12.794-28.605 28.605s12.794 28.605 28.605 28.605h572.103c15.811 0 28.605-12.794 28.605-28.605s-12.795-28.605-28.606-28.605zM630 777.904H401.159c-15.811 0-28.605 12.794-28.605 28.605s12.794 28.605 28.605 28.605H630c15.811 0 28.605-12.794 28.605-28.605S645.812 777.904 630 777.904z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 308 KiB

@ -1 +1,22 @@
需要合并的js确保每个js的结尾都有个;号,不然合并后会报脚本错误。
js_min_all含的js
es6-shim
jQuery v1.8.3
Underscore.js 1.8.2
marked v0.3.3
Raphaël 2.1.3
js sequence diagrams 1.0.4
flowchart, v1.3.4
jQuery.flowchart.js v1.1.0
https://github.com/pandao/editor.md
http://codemirror.net
diff_match_patch
codemirror merge.js
从 edu_tpi.js 挪过来的js
修改过的地方:
Raphaël 2.1.3
Element= -> __Element= Element= 替换成了 __Element=

@ -1,3 +1,8 @@
其他的文档位置:
/educoder/public/react/public/js/readme.txt 关于js_min_all
/educoder/educoder/public/react/scripts/readme-cdn.txt 关于CDN
/educoder/public/react/src/modules/page/readme.txt 关于TPI
1、 安装node v6.9.x此安装包含了node和npm。
2、 安装cnpm命令行 npm install -g cnpm --registry=https://registry.npm.taobao.org

@ -173,7 +173,7 @@ function copyPublicFolder() {
});
}
// 给build脚本增加的方法对其生成的index.html做一些文本替换以及cdn处理
function generateNewIndexJsp() {
// var combinedStream = CombinedStream.create();
var filePath = paths.appBuild + '/index.html';

@ -0,0 +1,16 @@
目前是判断域名的方式动态访问对应的cdn资源
静态资源处理在build.js中如下代码
if (window.location.host == 'pre-newweb.educoder.net') {
_host = 'https://testali-cdn.educoder.net/react/build/'
} else if (window.location.host == 'www.educoder.net') {
_host = 'https://ali-cdn.educoder.net/react/build/'
}
只对预上线和正式版做了处理
动态的chunk资源处理在public-path.js中如下代码
if ( window.location.host == 'pre-newweb.educoder.net') {
__webpack_public_path__ = 'https://testali-cdn.educoder.net/react/build/'
} else if ( window.location.host == 'www.educoder.net') {
__webpack_public_path__ = 'https://ali-cdn.educoder.net/react/build/'
}

@ -75,7 +75,10 @@ const Otherloginstart=Loadable({
loader: () => import('./modules/login/Otherloginstart'),
loading: Loading,
})
const Otherloginsqq=Loadable({
loader: () => import('./modules/login/Otherloginqq'),
loading: Loading,
})
// const TestIndex = Loadable({
// loader: () => import('./modules/test'),
// loading: Loading,
@ -527,6 +530,9 @@ class App extends Component {
<Route
path="/otherloginstart" component={Otherloginstart}
/>
<Route
path={"/otherloginqq"} component={Otherloginsqq}
/>
<Route
path="/otherlogin" component={Otherlogin}
/>

@ -46,6 +46,7 @@ export function initAxiosInterceptors(props) {
//proxy="http://47.96.87.25:48080"
proxy="https://pre-newweb.educoder.net"
proxy="https://test-newweb.educoder.net"
//proxy="http://192.168.2.63:3001"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
// 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制
@ -73,15 +74,22 @@ export function initAxiosInterceptors(props) {
}
requestProxy(config)
var url = `/api${config.url}`;
let url = `/api${config.url}`;
//qq登录去掉api
if(config.params&&config.params.redirect_uri!=undefined){
if(config.params.redirect_uri.indexOf('otherloginqq')!=-1){
url = `${config.url}`;
}
}
if(`${config[0]}`!=`true`){
if (window.location.port === "3007") {
if (url.indexOf('.json') == -1) {
alert('开发提示:请给接口加.json:' + url)
}
// if (url.indexOf('.json') == -1) {
//
// alert('开发提示:请给接口加.json:' + url)
//
// }
config.url = `${proxy}${url}`;
if (config.url.indexOf('?') == -1) {
config.url = `${config.url}?debug=${debugType}`;

@ -59,8 +59,14 @@ const _origin = window.location.origin;
currentPage
comments
buttonText 发送按钮 显示文本
showRewardButton 是否显示奖励按钮
showHiddenButton 是否显示隐藏按钮
onlySuperAdminCouldHide 只有超级管理员才显示隐藏取消隐藏
isChildCommentPagination 是否子回复分页
loadMoreChildComments function 加载所有子回复
接口
deleteComment 删除
@ -402,6 +408,7 @@ class Comments extends Component {
</Tooltip>
</span>
</p>
{/* __useKindEditor暂时没用到了TODO 可以去掉 */}
{ window.__useKindEditor ? <CommentItemKEEditor showReplyEditorFlag={showReplyEditorFlag}
currentReplyComment={currentReplyComment}
item={item}

@ -43,11 +43,34 @@ class CompetitionCommon extends Component{
// })
// }
// }).catch((error) => {
// console.log(error)
// //console.log(error)
// })
}
}
componentDidUpdate = (prevProps) => {
if (prevProps.user != this.props.user) {
//console.log("componentDidUpdatess");
//console.log(this.props.user);
if (this.props.user && this.props.user.login != "") {
const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`;
axios.get((zul)).then((result) => {
if (result) {
if (result.data) {
this.setState({
signupdata: result.data
})
}
}
}).catch((error) => {
////console.log(error);
})
}
}
}
//获取头部信息
getbannerdata=()=>{
let menuid=this.props.location.search.replace('?menu=', '');
let url=`/competitions/${this.props.match.params.identifier}/common_header.json`;
@ -55,7 +78,8 @@ class CompetitionCommon extends Component{
if(response.status===200){
this.setState({
data: response.data,
thiskeys: menuid === undefined || menuid === "" ? response.data.competition_modules[0].id : menuid
thiskeys: menuid === undefined || menuid === "" ? response.data.competition_modules[0].id : menuid,
mode: response.data.mode
})
if(menuid===undefined||menuid===""){
this.getrightdata(
@ -79,9 +103,11 @@ class CompetitionCommon extends Component{
}
}
}).catch((error) => {
console.log(error)
//console.log(error)
})
//this.props.user 有可能为空
if (this.props.user && this.props.user.login != "") {
const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`;
axios.get((zul)).then((result) => {
@ -93,7 +119,7 @@ class CompetitionCommon extends Component{
}
}
}).catch((error) => {
//console.log(error);
////console.log(error);
})
}
@ -135,7 +161,7 @@ class CompetitionCommon extends Component{
}
}).catch((error) => {
console.log(error)
//console.log(error)
})
}
}
@ -166,7 +192,7 @@ class CompetitionCommon extends Component{
}
}).catch((error) => {
console.log(error)
//console.log(error)
})
}else{
if (module_url.substring(0, 7) == 'http://' || module_url.substring(0, 8) == 'https://') {
@ -283,7 +309,7 @@ class CompetitionCommon extends Component{
})
}
}).catch((error) => {
console.log(error)
//console.log(error)
})
}

@ -140,7 +140,10 @@ class CompetitionContentspdfdownload extends Component{
</Row>
<Row className={"mt30"}>
<Col>个人证书{data&&data.personal_certifications.length===0?<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}><span className={"pdfpicture font-14"}></span><a className={"pdfdownloadfont4CACFF"} onClick={()=>this.props.Competitioncallback("2")}></a></span></span>:
<Col>个人证书{data&&data.personal_certifications.length===0&&data&&data.all_certified===false?
<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}><span className={"pdfpicture font-14"}></span><a className={"pdfdownloadfont4CACFF"} onClick={()=>this.props.Competitioncallback("2")}></a></span></span>:
data&&data.personal_certifications.length===0&&data&&data.all_certified===true?
<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}><span className={"pdfpicture font-14"}></span></span></span>:
data&&data.personal_certifications.map((item,key)=>{
return(
<span className={"mr10"} key={key}>

@ -91,6 +91,7 @@ class ListPageIndex extends Component{
this.state={
yslGuideone:undefined,
yslElearning:false,
isexcellent:false
}
}
comyslElearning(bool){
@ -163,6 +164,11 @@ class ListPageIndex extends Component{
});
}
}
ispostexcellenttype=(excellent)=>{
this.setState({
isexcellent:excellent
})
}
render() {
let {yslGuideone} =this.state;
// console.log("98");
@ -175,7 +181,7 @@ class ListPageIndex extends Component{
<div>
<div className="newMain clearfix">
{/*头部banner*/}
<CoursesBanner {...this.props}></CoursesBanner>
<CoursesBanner {...this.props} ispostexcellenttype={(excellent)=>this.ispostexcellenttype(excellent)}></CoursesBanner>
{/*下面是指引哦*/}
{/*{yslGuideone!==undefined?*/}
{/*(*/}

@ -28,7 +28,8 @@ class BoardsNew extends Component{
this.state = {
fileList: [],
boards: [],
title_num: 0
title_num: 0,
email_notify:false
}
}
addSuccess = () => {
@ -44,6 +45,7 @@ class BoardsNew extends Component{
if (response.data.status == 0) {
this.setState({
boards: response.data.data.boards || [],
boardsdata:response.data.data,
course_id: response.data.data.course_id
})
if (!isEdit) {
@ -158,6 +160,7 @@ class BoardsNew extends Component{
axios.post(url, {
...values,
email_notify:this.state.email_notify,
course_id: cid,
attachment_ids,
})
@ -247,6 +250,12 @@ class BoardsNew extends Component{
const boardId = this.props.match.params.boardId
this.props.toListPage(courseId, boardId)
}
setemailchange=(e)=>{
this.setState({
email_notify:e.target.checked
})
}
render() {
let { addGroup, fileList, course_id, title_num } = this.state;
const { getFieldDecorator } = this.props.form;
@ -289,6 +298,7 @@ class BoardsNew extends Component{
const boardId = this.props.match.params.boardId
const isCourseEnd = this.props.isCourseEnd();
document.title=this.props.coursedata&&this.props.coursedata.name;
return(
<div className="newMain ">
<AddDirModal {...this.props}
@ -401,6 +411,10 @@ class BoardsNew extends Component{
</Select>
)}
</Form.Item>
{this.state.boardsdata&&this.state.boardsdata.email_notify===true?this.props.isAdminOrTeacher()===true?this.isEdit ?"":<span className={"setemail"}>
<Checkbox onChange={this.setemailchange} checked={this.state.email_notify}>发送邮件提醒</Checkbox>
</span>:"":""}
{/* { isAdmin && <Form.Item
label=""

@ -35,4 +35,12 @@
.ant-pagination.coursePagination {
text-align: center;
margin-top: 16px;
}
.setemail{
margin-left: 20px;
}
.setemail .ant-checkbox-wrapper{
margin-top: 8px;
}

@ -369,7 +369,9 @@ function buildColumns(that, student_works, studentData) {
</Tooltip> }
{/* toWorkDetailPage */}
{/* /courses/"+courseId+"/common_homeworks/"+workId+ '/' + record.id +"/appraise */}
<a style={{color:'#4CACFF', marginLeft: '4px'}} href={"javascript:void(0)"} onClick={() => that.props.toWorkDetailPage(courseId, workId, record.id)} >{ isAdmin ? '评阅': '查看'}</a>
<a style={{color: '#4CACFF', marginLeft: '4px'}} id={"asdasdasdasd"}
onMouseDown={(e) => that.props.toWorkDetailPage2(e, courseId, workId, record.id)}
onClick={() => that.props.toWorkDetailPage(courseId, workId, record.id)}>{isAdmin ? '评阅' : '查看'}</a>
</div>

@ -12,15 +12,15 @@ export function RouteHOC(options = {}) {
return class Wrapper extends Component {
constructor(props) {
super(props);
this.state = {
}
}
toCreateProject = () => {
let url = '/projects/new'
if (window.location.port == 3007) {
// window.location.href
// window.location.href
url = '/testbdweb.educoder.net/projects/new'
}
window.open(
@ -55,8 +55,8 @@ export function RouteHOC(options = {}) {
} else {
this.props.history.push(`/courses/${_courseId}/boards/${workId}/messages/${topicId}`)
}
}
}
toEditPage = (_courseId, _workId) => {
const secondName = this.getModuleName()
if (typeof _courseId == "object") {
@ -78,6 +78,19 @@ export function RouteHOC(options = {}) {
window.open(`/courses/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`);
}
}
toWorkDetailPage2 = (e, _courseId, _workId, _studentWorkId) => {
console.log("鼠标中键点击了")
console.log(_studentWorkId)
const secondName = this.getModuleName()
if (typeof _courseId == "object") {
const workId = _courseId.workId
const courseId = _courseId.coursesId
const studentWorkId = _courseId.studentWorkId
window.open(`/courses/${courseId}/${secondName}/${_workId || workId}/${_studentWorkId || studentWorkId}/appraise`);
} else {
window.open(`/courses/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`);
}
}
toNewPage = (courseId) => {
const secondName = this.getModuleName()
this.props.history.push(`/courses/${courseId.coursesId}/${secondName}/${courseId.category_id}/new`)
@ -125,8 +138,8 @@ export function RouteHOC(options = {}) {
this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/answer`)
}
}
toWorkQuestionPage = (_courseId, _workId) => {
toWorkQuestionPage = (_courseId, _workId) => {
const secondName = this.getModuleName()
if (typeof _courseId == "object") {
const workId = _workId || _courseId.workId
@ -148,37 +161,36 @@ export function RouteHOC(options = {}) {
}
}
render() {
render() {
const { snackbarOpen} = this.state;
return (
<React.Fragment>
<WrappedComponent {...this.props}
toDetailPage={this.toDetailPage}
toEditPage={this.toEditPage}
toNewPage={this.toNewPage}
toListPage={this.toListPage}
toWorkDetailPage={this.toWorkDetailPage}
toWorkPostPage={this.toWorkPostPage}
toWorkListPage={this.toWorkListPage}
toWorkAnswerPage={this.toWorkAnswerPage}
toWorkQuestionPage={this.toWorkQuestionPage}
toWorkSettingPage={this.toWorkSettingPage}
toCreateProject={this.toCreateProject}
isGroup={this.isGroup}
getModuleName={this.getModuleName}
getModuleType={this.getModuleType}
<WrappedComponent {...this.props}
toDetailPage={this.toDetailPage}
toEditPage={this.toEditPage}
toNewPage={this.toNewPage}
toListPage={this.toListPage}
toWorkDetailPage={this.toWorkDetailPage}
toWorkDetailPage2={this.toWorkDetailPage2}
toWorkPostPage={this.toWorkPostPage}
toWorkListPage={this.toWorkListPage}
toWorkAnswerPage={this.toWorkAnswerPage}
toWorkQuestionPage={this.toWorkQuestionPage}
toWorkSettingPage={this.toWorkSettingPage}
toCreateProject={this.toCreateProject}
isGroup={this.isGroup}
getModuleName={this.getModuleName}
getModuleType={this.getModuleType}
>
</WrappedComponent>
</WrappedComponent>
</React.Fragment>
)
}
}
}
}
}

@ -136,6 +136,7 @@ class CoursesBanner extends Component {
coursedata: data,
excellent:data.excellent,
})
this.props.ispostexcellenttype(data.excellent)
}else{
this.onloadupdatabanner()
}

@ -421,7 +421,7 @@ class Selectresource extends Component{
<Radio style={radioStyle} value={0}>
立即发布
</Radio>
<Radio style={radioStyle} value={1} className={"fl"}>
<Radio style={radioStyle} value={1} className={"fl"} disabled={this.props.isStudent()}>
<span className={"mr5"}>延迟发布</span>
<DatePicker
dropdownClassName="hideDisable"

@ -529,7 +529,7 @@ class Selectsetting extends Component{
<Radio style={radioStyle} value={0}>
立即发布
</Radio>
<Radio style={radioStyle} value={1} className={"fl"}>
<Radio style={radioStyle} value={1} className={"fl"} disabled={this.props.isStudent()}>
<span className={"mr5"}>延迟发布</span>
<DatePicker

@ -263,6 +263,8 @@ class Sendresource extends Component{
height: '30px',
lineHeight: '30px',
};
return(
<div>
{/*提示*/}
@ -396,7 +398,7 @@ class Sendresource extends Component{
<Radio style={radioStyle} value={0}>
立即发布
</Radio>
<Radio style={radioStyle} value={1} className={"fl"}>
<Radio style={radioStyle} value={1} className={"fl"} disabled={this.props.isStudent()}>
<span className={"mr5"}>延迟发布</span>
<DatePicker

@ -16,8 +16,8 @@ const $ = window.$
const { Option } = Select;
const tagArray = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
class SingleEditor extends Component{
@ -92,13 +92,13 @@ class SingleEditor extends Component{
}
const intScore = parseFloat(question_score)
if (intScore == 0) {
this.props.showNotification('分值必须大于0'); return;
} else if(!question_score || intScore == NaN) {
this.props.showNotification('分值:不能为空'); return;
}
}
if(!answerArray || answerArray.length == 0) {
this.props.showNotification('请先点击选择本选择题的正确选项'); return;
}
@ -119,9 +119,9 @@ class SingleEditor extends Component{
"question_type":1,
"question_score":5,
"question_choices":["a答案","b答案","c答案","d答案"],
"standard_answers":[1]
"standard_answers":[1]
}*/
const Id = this.props.match.params.Id
const Id = this.props.match.params.Id
if (question_id) {
const editUrl = this.props.getEditQuestionUrl(question_id);
axios.put(editUrl, {
@ -144,7 +144,7 @@ class SingleEditor extends Component{
});
} else {
const url = this.props.getAddQuestionUrl();
axios.post(url, {
exercise_bank_id: Id,
question_title,
@ -162,16 +162,16 @@ class SingleEditor extends Component{
.catch(function (error) {
console.log(error);
});
}
}
}
onCancel = () => {
this.props.onEditorCancel()
}
componentDidMount = () => {
}
onOptionClick = (index) => {
// if (this.props.exerciseIsPublish) {
@ -186,7 +186,7 @@ class SingleEditor extends Component{
// TODO 新建然后删除CD选项再输入题干会调用到这里且index是3
return;
}
let question_choices = this.state.question_choices.slice(0);
let question_choices = this.state.question_choices.slice(0);
question_choices[index] = value;
this.setState({ question_choices })
}
@ -200,19 +200,19 @@ class SingleEditor extends Component{
mdReactObject.toShowMode()
}
this.mdReactObject = that;
}
toShowMode = () => {
}
render() {
let { question_title, question_score, question_type, question_choices, standard_answers } = this.state;
let { question_id, index, exerciseIsPublish,
// question_title,
// question_type,
// question_title,
// question_type,
// question_score,
isNew } = this.props;
// const { getFieldDecorator } = this.props.form;
const isAdmin = this.props.isAdmin()
@ -221,9 +221,13 @@ class SingleEditor extends Component{
const qNumber = `question_${index}`;
// TODO show模式 isNew为false isEdit为false
// [true, false, true] -> [0, 2]
// [true, false, true] -> [0, 2]
const answerTagArray = standard_answers.map((item, index) => { return item == true ? tagArray[index] : -1 }).filter(item => item != -1);
console.log("xuanzheshijuan");
console.log(answerTagArray);
console.log(!exerciseIsPublish);
return(
<div className="padding20-30 bor-bottom-greyE signleEditor" id={qNumber}>
<style>{`
@ -253,8 +257,8 @@ class SingleEditor extends Component{
ref="titleEditor"
></TPMMDEditor>
{question_choices.map( (item, index) => {
{question_choices.map( (item, index) => {
const bg = standard_answers[index] ? 'check-option-bg' : ''
return <div className="df optionRow " >
{/* 点击设置答案 */}
@ -268,7 +272,7 @@ class SingleEditor extends Component{
</span>
{/* </Tooltip> */}
<div style={{ flex: '0 0 1038px'}}>
<DMDEditor
<DMDEditor
ref={`optionEditor${index}`}
toMDMode={this.toMDMode} toShowMode={this.toShowMode}
height={166} className={'optionMdEditor'} noStorage={true}
@ -292,16 +296,15 @@ class SingleEditor extends Component{
}) }
<div className="mb20">
{/* {!exerciseIsPublish && <ActionBtn style="grey" className="middle mr20" onClick={this.addOption}>新增选项</ActionBtn>} */}
<span style={{color: '#FF6800'}}>{!exerciseIsPublish ? '温馨提示:点击选项标题,可以直接设置答案;选择多个答案即为多选题' : ' '}</span>
<span
style={{color: '#FF6800'}}>{'温馨提示:点击选项输入框可设置答案;选中的选项即为正确答案,选择多个答案即为多选题'}</span>
{ answerTagArray && !!answerTagArray.length ?
<React.Fragment>
<span className="fr color-orange">{answerTagArray.join(' ')}</span>
<span className="fr">标准答案</span>
</React.Fragment>
:
<span className="fr color-orange">请点击正确选项</span>
<React.Fragment>
<span className="fr color-orange">{answerTagArray.join(' ')}</span>
<span className="fr">标准答案</span>
</React.Fragment>
:
<span className="fr color-orange">请点击正确选项</span>
}
</div>
@ -310,18 +313,18 @@ class SingleEditor extends Component{
<InputNumber step={0.1} precision={1} min={0} max={100} style={{width: 100}} value={question_score} onChange={this.on_question_score_change}
disabled={exerciseIsPublish}
></InputNumber>&nbsp;
<span className="fr">
<ActionBtn style="greyBack" className="middle mr20" onClick={this.onCancel}
>取消</ActionBtn>
<ActionBtn style="blue" className="middle" onClick={this.onSave}>保存</ActionBtn>
</span>
</div>
</div>
)
}
}
// RouteHOC()
export default (SingleEditor);
export default (SingleEditor);

@ -697,7 +697,27 @@ class studentsList extends Component{
const isStudentPage = pageType == TYPE_STUDENTS
this.isStudentPage = isStudentPage
const isGroupChildPage = pageType == TYPE_COURSE_GOURP_CHILD
let studentlist=buildColumns(this,isParent);
if(this.props.isexcellent===true){
studentlist.some((item,key)=> {
if (item.title === "手机号") {
studentlist.splice(key, 1)
return true
}
}
)
}
if(this.props.isexcellent===true){
studentlist.some((item,key)=> {
if (item.title === "邮箱") {
studentlist.splice(key, 1)
return true
}
}
)
}
return(
<React.Fragment >
<DownloadMessageysl
@ -866,7 +886,7 @@ class studentsList extends Component{
<Spin size="large" spinning={this.state.isSpin}>
<div className="clearfix stu_table">
{students && !!students.length && <Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}>
<Table columns={buildColumns(this,isParent)} dataSource={students} onChange={this.onTableChange} pagination={false}></Table>
<Table columns={studentlist} dataSource={students} onChange={this.onTableChange} pagination={false}></Table>
</Checkbox.Group> }
</div>
</Spin>

@ -458,6 +458,7 @@ class Listofworksstudentone extends Component {
:
<a style={{textAlign: "center"}}
className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a>
}
@ -810,6 +811,7 @@ class Listofworksstudentone extends Component {
:
<a style={{textAlign: "center"}}
className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a>
}
@ -1175,6 +1177,7 @@ class Listofworksstudentone extends Component {
record.submitstate === "未提交" ? <span style={{color: '#9A9A9A'}}>--</span> :
<span>
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformationt(record)}>查看</a>
</span>
)
@ -1505,6 +1508,7 @@ class Listofworksstudentone extends Component {
record.submitstate === "未提交" ? <span style={{color: '#9A9A9A'}}>--</span> :
<span>
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformationt(record)}>{record.operating}</a>
</span>
)
@ -2779,7 +2783,16 @@ class Listofworksstudentone extends Component {
}
// 调分
Viewstudenttraininginformationtysl2 = (e, data) => {
// console.log("Viewstudenttraininginformationtysl2");
// console.log("shubiao zhongjian ");
// console.log(e);
this.setState({
userids: data.myid,
})
// this.viewtrainingt(e.myid);
window.open(`/courses/${this.state.props.match.params.coursesId}/shixun_homeworks/${data.myid}/shixun_work_report`, '_blank');
}
// 查看学员实训信息
Viewstudenttraininginformationt = (e) => {
// console.log("Viewstudenttraininginformation");

@ -117,12 +117,12 @@ class ShixunHomeworkPage extends Component {
/// 重做的确认
ModalSaves=()=>{
this.setState({
ModalsType:false,
Modalstopval:""
});
this.setState({
ModalsType:false,
Modalstopval:""
});
if(this.state.teacherdatapage){
this.resetshixunCombat(this.state.teacherdatapage.myshixun_identifier);
this.resetshixunCombat(this.state.teacherdatapage.myshixun_identifier);
}
try {
console.log("this.child");
@ -149,29 +149,29 @@ class ShixunHomeworkPage extends Component {
}
//重置按钮
resetshixunCombat=(id)=>{
this.setState({
mylistisSpin:true,
this.setState({
mylistisSpin:true,
})
let zrl=`/myshixuns/${id}/reset_my_game.json`;
axios.get(zrl).then((response) => {
// window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges";
this.setState({
mylistisSpin:false,
})
this.child.Isupdatass();
this.props.showNotification("已清空本实训的学习记录\n" +
"\n" +
"请点击“开启挑战”重做实训作业");
}).catch((error) => {
this.setState({
mylistisSpin:false,
})
let zrl=`/myshixuns/${id}/reset_my_game.json`;
axios.get(zrl).then((response) => {
// window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges";
this.setState({
mylistisSpin:false,
})
this.child.Isupdatass();
this.props.showNotification("已清空本实训的学习记录\n" +
"\n" +
"请点击“开启挑战”重做实训作业");
}).catch((error) => {
this.setState({
mylistisSpin:false,
})
console.log(error)
});
console.log(error)
});
}
bindRef = ref => { this.child = ref }
///////////////教师截止
//编辑作业
//编辑作业
Showupdateinstructionsboolfalse (bool) {
this.setState({
Showupdateinstructions:bool
@ -183,7 +183,7 @@ class ShixunHomeworkPage extends Component {
Showupdateinstructions:true
})
}
gotohome=()=>{
gotohome=()=>{
// console.log(this.props)
let {jobsettingsdatapage}=this.state
@ -194,7 +194,7 @@ class ShixunHomeworkPage extends Component {
const isAdmin = this.props.isAdmin();
// console.log(119)
// console.log(jobsettingsdatapage);
// console.log(jobsettingsdatapage);
document.title=jobsettingsdatapage === undefined ? "" : jobsettingsdatapage.data.course_name;
return (
<div className="newMain clearfix ">
@ -224,34 +224,34 @@ class ShixunHomeworkPage extends Component {
</div>
}
<div className="educontent mb20">
<p className=" fl color-black summaryname" style={{heigth: "33px"}}>
{teacherdatapage === undefined ? "" : teacherdatapage.homework_name}
</p>
<CoursesListType
typelist={teacherdatapage === undefined ? [""] : teacherdatapage.homework_status}
/>
<a className="color-grey-9 fr font-16 summaryname ml20 mr20" onClick={()=>this.gotohome()}>返回</a>
<a className="color-grey-9 fr font-16 mr20"
href={`/shixuns/${teacherdatapage === undefined ? "" : teacherdatapage.shixun_identifier}/challenges`}
target={"_blank"}>实训详情</a>
<div className="educontent mb20">
<p className=" fl color-black summaryname" style={{heigth: "33px"}}>
{teacherdatapage === undefined ? "" : teacherdatapage.homework_name}
</p>
<CoursesListType
typelist={teacherdatapage === undefined ? [""] : teacherdatapage.homework_status}
/>
<a className="color-grey-9 fr font-16 summaryname ml20 mr20" onClick={()=>this.gotohome()}>返回</a>
<a className="color-grey-9 fr font-16 mr20"
href={`/shixuns/${teacherdatapage === undefined ? "" : teacherdatapage.shixun_identifier}/challenges`}
target={"_blank"}>实训详情</a>
</div>
<div className="edu-back-white ">
<div className="stud-class-set bor-bottom-greyE ">
<div className=" clearfix edu-back-white poll_list">
<a className={parseInt(tab) === 0 ? "active" : ""} onClick={(e) => this.ChangeTab(0)}>作品列表</a>
<a className={parseInt(tab) === 1 ? "active" : ""} onClick={(e) => this.ChangeTab(1)}>作业描述</a>
{this.props.isAdmin() ?
this.state.code_review === true || jobsettingsdatapage === undefined ? [""] : jobsettingsdatapage.data.homework_status[0] === "未发布" ? "" :
<a
className={parseInt(tab) === 2 ? "active" : ""}
onClick={(e) => this.ChangeTab(2)}>
代码查重</a> : ""}
{parseInt(tab) === 3?
<style>{this.props.isAdmin()?
`
</div>
<div className="edu-back-white ">
<div className="stud-class-set bor-bottom-greyE ">
<div className=" clearfix edu-back-white poll_list">
<a className={parseInt(tab) === 0 ? "active" : ""} onClick={(e) => this.ChangeTab(0)}>作品列表</a>
<a className={parseInt(tab) === 1 ? "active" : ""} onClick={(e) => this.ChangeTab(1)}>作业描述</a>
{this.props.isAdmin() ?
this.state.code_review === true || jobsettingsdatapage === undefined ? [""] : jobsettingsdatapage.data.homework_status[0] === "未发布" ? "" :
<a
className={parseInt(tab) === 2 ? "active" : ""}
onClick={(e) => this.ChangeTab(2)}>
代码查重</a> : ""}
{parseInt(tab) === 3?
<style>{this.props.isAdmin()?
`
.poll_list a.active:after {
content: '';
width: 57px;
@ -262,17 +262,17 @@ class ShixunHomeworkPage extends Component {
position: absolute;
}
`:""
}</style>
:""}
}</style>
:""}
<a className={parseInt(tab) === 3 ? "active" : ""}
onClick={(e) => this.ChangeTab(3)}
>{this.props.isAdmin()?"设置":"得分规则"}</a>
{/*{this.props.isAdmin() ? <a*/}
{/* className="fr color-blue font-16"*/}
{/* href={`/api/homework_commons/${this.props.match.params.coursesId}/works_list.xlsx`}*/}
{/*>导出</a> : ""}*/}
<style>{`
<a className={parseInt(tab) === 3 ? "active" : ""}
onClick={(e) => this.ChangeTab(3)}
>{this.props.isAdmin()?"设置":"得分规则"}</a>
{/*{this.props.isAdmin() ? <a*/}
{/* className="fr color-blue font-16"*/}
{/* href={`/api/homework_commons/${this.props.match.params.coursesId}/works_list.xlsx`}*/}
{/*>导出</a> : ""}*/}
<style>{`
.drop_down_menu li a {
padding: 0px;
font-size: 14px;
@ -288,74 +288,74 @@ class ShixunHomeworkPage extends Component {
padding-top: 10px;
padding-bottom: 8px;
}
`}</style>
{this.props.isAdmin() ?
<li className="li_line drop_down fr color-blue font-16 mr8 mt20" style={{"padding": "0 20px"}}>
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu" style={{"right": "-0px", "left": "unset", "height": "auto"}}>
{/*<li><a*/}
{/* onClick={(child,i) => this.confirmysl(this.child,1)}>实训报告</a>*/}
{/*</li>*/}
<li><a
onClick={(child,i) => this.confirmysl(this.child,2)}>学生成绩</a>
</li>
{this.props.isAdmin() ?
<li className="li_line drop_down fr color-blue font-16 mr8 mt20" style={{"padding": "0 20px"}}>
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_menu" style={{"right": "-0px", "left": "unset", "height": "auto"}}>
{/*<li><a*/}
{/* onClick={(child,i) => this.confirmysl(this.child,1)}>实训报告</a>*/}
{/*</li>*/}
<li><a
onClick={(child,i) => this.confirmysl(this.child,2)}>学生成绩</a>
</li>
</ul>
</li> : ""}
{this.props.isAdmin() ?
teacherdatapage && teacherdatapage.end_immediately === true ?
<a className="fr color-blue font-16" onClick={(child)=>this.homeworkendss(this.child)}>立即截止</a>
: ""
: ""}
{this.props.isAdmin() ?
teacherdatapage && teacherdatapage.publish_immediately === true ?
<a className="fr color-blue font-16" onClick={(child)=>this.homeworkstarts(this.child)}>立即发布</a>
: ""
: ""}
{this.props.isAdmin() ?
teacherdatapage && teacherdatapage.code_review === true ?
<a className="fr color-blue font-16" onClick={(child)=>this.workshowmodels(this.child)}>代码查重</a>
: "" : ""}
{
parseInt(tab)===1?
this.props.isAdmin() ?
<a className="fr color-blue font-16" onClick={()=>this.edenwork()}>编辑作业</a>
</ul>
</li> : ""}
{this.props.isAdmin() ?
teacherdatapage && teacherdatapage.end_immediately === true ?
<a className="fr color-blue font-16" onClick={(child)=>this.homeworkendss(this.child)}>立即截止</a>
: ""
: ""}
{this.props.isAdmin() ?
teacherdatapage && teacherdatapage.publish_immediately === true ?
<a className="fr color-blue font-16" onClick={(child)=>this.homeworkstarts(this.child)}>立即发布</a>
: ""
: ""}
{this.props.isAdmin() ?
teacherdatapage && teacherdatapage.code_review === true ?
<a className="fr color-blue font-16" onClick={(child)=>this.workshowmodels(this.child)}>代码查重</a>
: "" : ""}
{
parseInt(tab)===1?
this.props.isAdmin() ?
<a className="fr color-blue font-16" onClick={()=>this.edenwork()}>编辑作业</a>
:""
:""
:""
}
}
{this.state.view_report === true ? <Link className="fr color-blue font-16" target={"_blank"}
to={`/courses/${this.props.match.params.coursesId}/${jobsettingsdatapage === undefined ? "" : jobsettingsdatapage.data.category.main === 1 ? "shixun_homeworks" :"shixun_homework"}/${teacherdatapage&&teacherdatapage.work_id}/shixun_work_report`}>
查看实训报告
</Link> : ""}
{
teacherdatapage === undefined ? ""
: teacherdatapage.commit_des === null || teacherdatapage.commit_des === undefined ? "" :
<a className="fr color-blue font-16"
href={`/courses/${this.props.match.params.coursesId}/${jobsettingsdatapage === undefined ? "" : jobsettingsdatapage.data.category.main === 1 ? "shixun_homeworks" :"shixun_homework"}/${teacherdatapage === undefined ? "" : teacherdatapage.id}/commitsummary/${this.props.match.params.homeworkid}`}>{teacherdatapage.commit_des}</a>
}
{teacherdatapage === undefined ? "" : <Startshixuntask
{...this.props}
data={teacherdatapage}
/>}
{this.props.isStudent() ?
(
teacherdatapage&&teacherdatapage.redo_work===true?
<a className="fr color-blue font-16" onClick={()=>this.Modalcancelss()}>重做</a>
:""
)
: "" }
{this.state.view_report === true ? <Link className="fr color-blue font-16" target={"_blank"}
to={`/courses/${this.props.match.params.coursesId}/${jobsettingsdatapage === undefined ? "" : jobsettingsdatapage.data.category.main === 1 ? "shixun_homeworks" :"shixun_homework"}/${teacherdatapage&&teacherdatapage.work_id}/shixun_work_report`}>
查看实训报告
</Link> : ""}
{
teacherdatapage === undefined ? ""
: teacherdatapage.commit_des === null || teacherdatapage.commit_des === undefined ? "" :
<a className="fr color-blue font-16"
href={`/courses/${this.props.match.params.coursesId}/${jobsettingsdatapage === undefined ? "" : jobsettingsdatapage.data.category.main === 1 ? "shixun_homeworks" :"shixun_homework"}/${teacherdatapage === undefined ? "" : teacherdatapage.id}/commitsummary/${this.props.match.params.homeworkid}`}>{teacherdatapage.commit_des}</a>
}
{teacherdatapage === undefined ? "" : <Startshixuntask
{...this.props}
data={teacherdatapage}
/>}
{this.props.isStudent() ?
(
teacherdatapage&&teacherdatapage.redo_work===true?
<a className="fr color-blue font-16" onClick={()=>this.Modalcancelss()}>重做</a>
:""
)
: "" }
</div>
</div>
</div>
</div>
{parseInt(tab) === 0 ?<Listofworksstudentone triggerRef={this.bindRef} {...this.props} {...this.state} Getdataback={(jobsettingsdata, teacherdata) => this.Getdataback(jobsettingsdata, teacherdata)}></Listofworksstudentone>:""}
{parseInt(tab) === 1 ?<Workquestionandanswer triggerRef={this.bindRef} {...this.props} {...this.state} Getdataback={(jobsettingsdata, teacherdata) => this.Getdataback(jobsettingsdata, teacherdata)} Showupdateinstructionsboolfalse={(i)=>this.Showupdateinstructionsboolfalse(i)}></Workquestionandanswer>:""}
{parseInt(tab) === 2 ?<ShixunStudentWork triggerRef={this.bindRef} {...this.props} {...this.state} Getdataback={(jobsettingsdata, teacherdata) => this.Getdataback(jobsettingsdata, teacherdata)}></ShixunStudentWork>:""}
{parseInt(tab) === 3 ?<Trainingjobsetting triggerRef={this.bindRef} {...this.props} {...this.state} Getdataback={(jobsettingsdata, teacherdata) => this.Getdataback(jobsettingsdata, teacherdata)}></Trainingjobsetting>:""}
</Spin>
{parseInt(tab) === 0 ?<Listofworksstudentone triggerRef={this.bindRef} {...this.props} {...this.state} Getdataback={(jobsettingsdata, teacherdata) => this.Getdataback(jobsettingsdata, teacherdata)}></Listofworksstudentone>:""}
{parseInt(tab) === 1 ?<Workquestionandanswer triggerRef={this.bindRef} {...this.props} {...this.state} Getdataback={(jobsettingsdata, teacherdata) => this.Getdataback(jobsettingsdata, teacherdata)} Showupdateinstructionsboolfalse={(i)=>this.Showupdateinstructionsboolfalse(i)}></Workquestionandanswer>:""}
{parseInt(tab) === 2 ?<ShixunStudentWork triggerRef={this.bindRef} {...this.props} {...this.state} Getdataback={(jobsettingsdata, teacherdata) => this.Getdataback(jobsettingsdata, teacherdata)}></ShixunStudentWork>:""}
{parseInt(tab) === 3 ?<Trainingjobsetting triggerRef={this.bindRef} {...this.props} {...this.state} Getdataback={(jobsettingsdata, teacherdata) => this.Getdataback(jobsettingsdata, teacherdata)}></Trainingjobsetting>:""}
</Spin>
</div>
</div>
)

@ -147,7 +147,9 @@ class ShixunsHome extends Component {
nextArrow={<CustomNextArrow />}
prevArrow={<CustomPrevArrow />}
autoplay
animation={false}
autoplaySpeed={5000}
animation={false}
pauseOnHover={true}
style={{width:"100%"}}
arrowPos="outer">
{homedatalist.images_url.map((item, index) => (

@ -136,12 +136,18 @@
.startlogin{
color:#888;
}
.weixinheight390{
height: 390px;
}
.qqheight390{
width: 450px;
height: 390px;
}
#log_reg_content {
padding: 38px 30px 20px !important;
}
.textcenter{
text-align: center;
}
}

@ -7,7 +7,7 @@ import Dialog, {
DialogContentText,
DialogTitle,
} from 'material-ui/Dialog';
import {notification } from 'antd';
import {notification,Modal } from 'antd';
import axios from 'axios';
@ -104,8 +104,8 @@ class LoginDialog extends Component {
MyEduCoderModals:false,
Phonenumberisnotco:undefined,
Phonenumberisnotcobool:false,
weixinlogin:false
weixinlogin:false,
qqlogin:false
};
}
enter=(num) =>{
@ -529,14 +529,30 @@ class LoginDialog extends Component {
weixinlogin:true
})
}
openqqlogin=()=>{
this.setState({
qqlogin:true
})
//window.location.href=`https://graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=101508858&redirect_uri=https%3a%2f%2f${window.location.host}%2otherloginqq&response_type=code`
window.location.href=`https://graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=101508858&redirect_uri=https%3a%2f%2f${window.location.host}%2fotherloginqq&response_type=code`
// window.location.href=`https://graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=101508858&redirect_uri=https%3a%2f%2fwww.educoder.net%2fotherloginstart&tp=qq&response_type=code`
}
openphoneqqlogin=()=>{
window.open(
`https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=716027609&pt_3rd_aid=101508858&daid=383&pt_skey_valid=0&style=35&s_url=http%3A%2F%2Fconnect.qq.com&refer_cgi=authorize&which=&client_id=101508858&response_type=code&scope=get_user_info&redirect_uri=https%3a%2f%2ftest-newweb.educoder.net%2fotherloginqq&response_type=code`
)
}
hideweixinlogin=()=>{
this.setState({
weixinlogin:false
weixinlogin:false,
qqlogin:false
})
}
render() {
let{open,login,speedy,loginValue,regular,isGoing,isGoingValue,disabled,bottonclass,Phonenumberisnotco,
dialogBox,shortcutnum,disabledType,gaincode,authCodeType,authCodeclass, isRender,weixinlogin}=this.state;
let{qqlogin,login,isGoing,isGoingValue,disabled,bottonclass,Phonenumberisnotco,
dialogBox, isRender,weixinlogin}=this.state;
if (isRender === undefined) {
isRender = false
@ -659,8 +675,22 @@ class LoginDialog extends Component {
<a onClick={()=>this.openweixinlogin()}>
<img src={require('./WeChat.png')} alt="微信登录"/>
</a>
<a onClick={()=>this.openqqlogin()} className={"ml10"}>
<img src={require('./qq.png')} alt="qq登录"/>
</a>
</div>
</p>:""}
</p>:<p className="clearfix mt20">
<span className={"startlogin"}> 快速登录 </span>
<div className={"mt10"}>
{/*<a onClick={()=>this.openweixinlogin()}>*/}
{/*<img src={require('./WeChat.png')} alt="微信登录"/>*/}
{/*</a>*/}
<a onClick={()=>this.openphoneqqlogin()} className={"ml10"}>
<img src={require('./qq.png')} alt="qq登录"/>
</a>
</div>
</p>}
</form>}
{weixinlogin===true?<iframe
@ -669,7 +699,9 @@ class LoginDialog extends Component {
sandbox="allow-scripts allow-same-origin allow-top-navigation"
scrolling="no"
src={`https://open.weixin.qq.com/connect/qrconnect?appid=wx6b119e2d829c13fa&redirect_uri=https%3a%2f%2f${window.location.host}%2fotherloginstart&response_type=code&scope=snsapi_login#wechat_redirect`}></iframe>:""}
{weixinlogin===true?<p className="clearfix">
{weixinlogin===true?<p className="clearfix ">
<a className={"startlogin color-blue"} onClick={()=>this.hideweixinlogin()}>返回账号登录</a>
</p>:""}
</div>
@ -690,110 +722,3 @@ class LoginDialog extends Component {
export default LoginDialog ;
// onkeypress="user_login_keypress(event);"
// onkeypress="user_login_keypress(event);"
{/* <div className="pr drag_certi_block width100 mt5">
<div id="quick-drag" className="drag_slider" style={{color: 'rgb(255, 255, 255)'}}></div>
<div className="new-login-error" style={{height: '25px'}}>
<p id="passlogin_error_notice" className="color-orange edu-txt-left none" style={{display: 'block'}}></p>
</div>
</div>}
{/*第三方账号登录*/}
{/* <div className="mt10 edu-txt-center">
<p className="color-grey-9">第三方账号登录</p>
<div className="mt15">
<a href="javascript:void(0)" className="margin15"><img src="/images/educoder/weixin.png" className="radius"/></a>
<a href="javascript:void(0)" className="margin15"><img src="/images/educoder/QQ.png" className="radius"/></a>
<a href="javascript:void(0)" className="margin15"><img src="/images/educoder/weibo.png" className="radius"/></a>
</div>
</div>}
//
// {/*<div className="login-panel none" id="login-panel-2" style={{display:speedy==0?'block':'none'}}>*/}
// {/*<form acceptCharset="UTF-8" action="/login" id="code_login_form" method="post">*/}
// {/*<div style={{"display":"inline","padding":"0","margin":"0"}}>*/}
// {/*<input name="utf8" type="hidden" value="✓"></input>*/}
// {/*<input name="authenticity_token" type="hidden" value="NVLiIlHZfhVBQtO9djnWncJqqdikNQIIxEmOvzK9vNM="></input>*/}
// {/*</div>*/}
// {/*<input name="back_url" type="hidden" value={this.back_url}></input>*/}
// {/*<input*/}
// {/*type="text"*/}
// {/*id="pass_name_input"*/}
// {/*name="username"*/}
// {/*ref="shortcutText"*/}
// {/*onInput={this.shortcutIdChange}*/}
// {/*className="input-100-45 mt20"*/}
// {/*placeholder="手机号/邮箱号">*/}
// {/*</input>*/}
// {/*<div style={{height: '25px'}}>*/}
// {/*<p className="color-orange edu-txt-left none" id="pass_name_error_notice"*/}
// {/*style={{display: shortcutnum==0?'block':'none'}}>请输入有效的手机号/邮箱号*/}
// {/*</p>*/}
// {/*</div>*/}
//
// {/*<div id="wrapper">*/}
// {/*/!*drag*/ }*/}
// {/*<div id="quick-drag" className="drag_slider">*/}
// {/*<div className="drag_bg"></div>*/}
// {/*<div className="drag_text slidetounlock">*/}
// {/*请按住滑块,拖动到最右边*/}
// {/*</div>*/}
// {/*<div className="handler handler_bg"></div>*/}
// {/*</div>*/}
// {/*<div className="new-login-error" style={{height: '25px'}}>*/}
// {/*<p id="passlogin_error_notice" className="color-orange edu-txt-left none">请先拖动滑块完成验证</p>*/}
// {/*</div>*/}
// {/*</div>*/}
//
// {/*<p className="clearfix mt5">*/}
// {/*<input*/}
// {/*type="text"*/}
// {/*name="code"*/}
// {/*id="login_verification_code"*/}
// {/*className="input-48-45 edu-txt-center fl"*/}
// {/*ref="authCodeText"*/}
// {/*onInput={this.authCodeChange}*/}
// {/*placeholder="请输入验证码">*/}
// {/*</input>*/}
// {/*<button className={gaincode} disabled={disabledType}*/}
// {/*onClick={()=>{this.get_login_verification_code()}} id="get_verification_code">获取验证码</button>*/}
// {/*</p>*/}
//
// {/*<div style={{height: '25px'}}>*/}
// {/*<p className="color-orange edu-txt-left none" id="send_code_notice">*/}
// {/*请输入验证码*/}
// {/*</p>*/}
// {/*</div>*/}
//
// {/*<button className={authCodeclass} disabled={authCodeType} id="code_login_btn">登录</button>*/}
//
// {/*<p className="clearfix mt10">*/}
//
// {/*<span className="fl">*/}
// {/*<input type="checkbox"*/}
// {/*className="mr5 magic-checkbox"*/}
// {/*id="autolog"*/}
// {/*checked={isGoing}*/}
// {/*onChange={this.handleInputChange}*/}
// {/*value={isGoingValue}*/}
// {/*name="isGoing"*/}
// {/*></input>*/}
// {/*<label htmlFor="autolog" style={{"top":"0px"}}>下次自动登录</label>*/}
// {/*</span>*/}
//
// {/*<span className="fr">*/}
// {/*<a href="https://www.educoder.net/account/lost_password" className="mr3 color-grey-9">忘记密码</a><em className="vertical-line"></em>*/}
// {/*<a href="https://www.educoder.net/user_join" target="_blank" className="color-grey-9">注册</a>*/}
// {/*</span>*/}
//
// {/*</p>*/}
// {/*</form>*/}
// {/*</div>*/}

@ -132,6 +132,8 @@ class Otherlogin extends Component {
}
postwechatlogin=(type,username,password)=>{
let query=this.props.location.search;
const types = query.split('?type=');
if(type===false){
if(username===undefined||username===""||username===null){
this.setState({
@ -146,9 +148,11 @@ class Otherlogin extends Component {
return
}
}
let url = "/bind_user.json";
axios.post(url, {
type: 'wechat',
type: types[1]==="qq"?"qq":'wechat',
not_bind:type,
username:username,
password:password

@ -0,0 +1,58 @@
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Spin } from 'antd';
import axios from 'axios';
class Otherloginqq extends Component {
componentDidMount() {
let query=this.props.location.search;
const type = query.split('?code=');
const types = type[1].split('&state=');
let codeurl = `/auth/qq/callback`;
axios.get(codeurl,{params:{
code:type[1],
redirect_uri:`https://${window.location.host}/otherloginqq`
}}).then((result)=> {
if(result){
if(result.data.status===0){
if(result.data.new_user===true){
window.location.href="/otherlogin?type=qq"
}else{
// this.getinfo()
if(types[1]==="account"){
window.location.href="/account/binding"
}else{
window.location.href="/"
}
}
}
}
}).catch((error)=>{
})
}
render() {
// Loading
return (
<div className="App" style={{minHeight: '800px',width:"100%"}}>
<style>
{
`
.margintop{
margin-top:20%;
}
`
}
</style>
<Spin size="large" className={"margintop"}/>
</div>
);
}
}
export default Otherloginqq;

@ -8,31 +8,34 @@ class Otherloginstart extends Component {
componentDidMount() {
let query=this.props.location.search;
const type = query.split('?code=');
const types = type[1].split('&state=');
console.log(types)
let codeurl = `/auth/wechat/callback.json`
axios.get(codeurl,{params:{
code:types[0]
}}).then((result)=> {
if(result){
if(result.data.status===0){
if(result.data.new_user===true){
window.location.href="/otherlogin"
}else{
// this.getinfo()
if(types[1]==="account"){
window.location.href="/account/binding"
debugger
if(query!= ""){
const type = query.split('?code=');
const types = type[1].split('&state=');
let codeurl = `/auth/wechat/callback.json`
axios.get(codeurl,{params:{
code:types[0]
}}).then((result)=> {
if(result){
if(result.data.status===0){
if(result.data.new_user===true){
window.location.href="/otherlogin?type=wechat"
}else{
window.location.href="/"
}
// this.getinfo()
if(types[1]==="account"){
window.location.href="/account/binding"
}else{
window.location.href="/"
}
}
}
}
}
}).catch((error)=>{
}).catch((error)=>{
})
}
})
}

@ -226,6 +226,7 @@ class TPIMonaco extends Component {
// https://github.com/Microsoft/monaco-editor/issues/539
window.monaco.editor.setModelLanguage(editor_monaco.getModel(), lang)
} else if (prevProps.isEditablePath != this.props.isEditablePath) {
// 当前文件是否可编辑
if (this.props.isEditablePath || this.props.shixun && this.props.shixun.code_edit_permission == true) {
editor_monaco.updateOptions({readOnly: false})
} else {
@ -250,6 +251,7 @@ class TPIMonaco extends Component {
}
}
componentWillUnmount() {
// 注意销毁不然会出现不能编辑的bug
this.editor_monaco && this.editor_monaco.dispose()
}

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

Loading…
Cancel
Save