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

issues25489
daiao 5 years ago
commit d416224174

@ -63,16 +63,23 @@ $(document).on('turbolinks:load', function() {
theme: 'bootstrap4',
placeholder: '请输入实训名称/创建者检索',
multiple: true,
minimumInputLength: 1,
closeOnSelect: false,
ajax: {
delay: 500,
url: '/admins/laboratories/' + laboratoryId + '/shixuns_for_select',
dataType: 'json',
data: function(params){
return { keyword: params.term };
return { keyword: params.term, page: params.page || 1, per_page: 20 };
},
processResults: function(data){
return { results: data.shixuns }
processResults: function(data, params){
params.page = params.page || 1;
return {
results: data.shixuns,
pagination: {
more: (params.page * 20) < data.count
}
};
}
},
templateResult: function (item) {

@ -7,6 +7,7 @@ $(document).on('turbolinks:load', function() {
$searchForm.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择创建者单位',
allowClear: true,
minimumInputLength: 1,
ajax: {
delay: 500,
@ -85,16 +86,23 @@ $(document).on('turbolinks:load', function() {
theme: 'bootstrap4',
placeholder: '请输入课程名称/创建者检索',
multiple: true,
minimumInputLength: 1,
closeOnSelect: false,
ajax: {
delay: 500,
url: '/admins/laboratories/' + laboratoryId + '/subjects_for_select',
dataType: 'json',
data: function(params){
return { keyword: params.term };
return { keyword: params.term, page: params.page || 1, per_page: 20 }
},
processResults: function(data){
return { results: data.subjects }
processResults: function(data, params){
params.page = params.page || 1;
return {
results: data.subjects,
pagination: {
more: (params.page * 20) < data.count
}
};
}
},
templateResult: function (item) {

@ -0,0 +1,60 @@
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-laboratory-shixuns-index-page').length > 0) {
var $searchForm = $('.laboratory-shixun-list-form .search-form');
$searchForm.find('select#tag_id').select2({
placeholder: "请选择",
allowClear: true
});
// 上传图片
$('.modal.cooperative-upload-file-modal').on('upload:success', function (e, data) {
var $imageElement = $('.shixun-image-' + data.source_id);
if($imageElement.length === 0) return;
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.laboratory-shixun-list-container').on('click', doElement, function () {
var $doAction = $(this);
var $undoAction = $doAction.siblings(undoElement);
var laboratoryShixunId = $doAction.data('id');
customConfirm({
content: '确认进行该操作吗?',
ok: function () {
$.ajax({
url: '/cooperative/laboratory_shixuns/' + laboratoryShixunId + url,
method: 'POST',
dataType: 'json',
success: function () {
show_success_flash();
$doAction.hide();
$undoAction.show();
if (callback && typeof callback === "function") {
callback(laboratoryShixunId, url);
}
}
});
}
});
});
}
// 首页展示与取消首页展示
var homepageShowCallback = function (laboratoryShixunId, url) {
var $laboratoryShixunItem = $('.laboratory-shixun-list-container').find('.laboratory-shixun-item-' + laboratoryShixunId);
if (url === '/homepage') {
$laboratoryShixunItem.find('.homepage-badge').show();
} else {
$laboratoryShixunItem.find('.homepage-badge').hide();
}
}
defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback);
defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback);
}
})

@ -0,0 +1,83 @@
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-laboratory-subjects-index-page').length > 0) {
var $searchForm = $('.laboratory-subject-list-form .search-form');
// ************** 学校选择 *************
$searchForm.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择创建者单位',
allowClear: true,
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;
return item.name;
},
templateSelection: function (item) {
if (item.id) {
}
return item.name || item.text;
}
});
// 上传图片
$('.modal.cooperative-upload-file-modal').on('upload:success', function (e, data) {
var $imageElement = $('.subject-image-' + data.source_id);
if($imageElement.length === 0) return;
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.laboratory-subject-list-container').on('click', doElement, function () {
var $doAction = $(this);
var $undoAction = $doAction.siblings(undoElement);
var laboratorySubjectId = $doAction.data('id');
customConfirm({
content: '确认进行该操作吗?',
ok: function () {
$.ajax({
url: '/cooperative/laboratory_subjects/' + laboratorySubjectId + url,
method: 'POST',
dataType: 'json',
success: function () {
show_success_flash();
$doAction.hide();
$undoAction.show();
if (callback && typeof callback === "function") {
callback(laboratorySubjectId, url);
}
}
});
}
});
});
}
// 首页展示与取消首页展示
var homepageShowCallback = function (laboratoryShixunId, url) {
var $laboratoryShixunItem = $('.laboratory-subject-list-container').find('.laboratory-subject-item-' + laboratoryShixunId);
if (url === '/homepage') {
$laboratoryShixunItem.find('.homepage-badge').show();
} else {
$laboratoryShixunItem.find('.homepage-badge').hide();
}
}
defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback);
defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback);
}
})

@ -0,0 +1,18 @@
$(document).on('turbolinks:load', function () {
$('.cooperative-modal-container').on('show.bs.modal', '.modal.cooperative-edit-subject-modal', function () {
var $modal = $('.modal.cooperative-edit-subject-modal');
var $form = $modal.find('form.cooperative-edit-subject-form');
$modal.on('click', '.submit-btn', function () {
$form.find('.error').html('');
var url = $form.attr('action');
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
});
});
})
});

@ -42,7 +42,7 @@ $(document).on('turbolinks:load', function() {
$.ajax({
method: 'POST',
dataType: 'json',
url: '/cooperatives/files?' + formDataString,
url: '/cooperative/files?' + formDataString,
data: new FormData($form[0]),
processData: false,
contentType: false,

@ -47,6 +47,12 @@
}
}
.image-preview-container {
display: flex;
flex-direction: column;
align-items: center;
}
.action-container {
& > .action {
padding: 0 3px;

@ -47,6 +47,12 @@
}
}
.image-preview-container {
display: flex;
flex-direction: column;
align-items: center;
}
.action-container {
& > .action {
padding: 0 3px;

@ -6,6 +6,7 @@ class Admins::BaseController < ApplicationController
layout 'admin'
skip_before_action :verify_authenticity_token
skip_before_action :setup_laboratory
before_action :require_login, :require_admin!

@ -6,6 +6,16 @@ class Admins::CompetitionPrizeUsersController < Admins::BaseController
include_class = [:competition_team, :competition_prize, :approver,
user: [:process_real_name_apply, :process_professional_apply, user_extension: :school]]
@prize_users = paginate(prize_users.preload(include_class))
respond_to do |format|
format.js
format.html
format.xlsx do
@all_prize_users = prize_users
filename = "#{@competition.name}竞赛获奖人信息列表_#{Time.current.strftime('%Y%m%d%H%M%S')}.xlsx"
render xlsx: 'index', filename: filename
end
end
end
def create

@ -12,10 +12,6 @@ class Admins::EnrollListsController < Admins::BaseController
respond_to do |format|
format.js
format.html
format.xls{
filename = "#{@competition.name}竞赛报名列表_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls"
send_data(shixun_list_xls(shixuns), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename))
}
end
end

@ -1,7 +1,6 @@
class Admins::LaboratoriesController < Admins::BaseController
def index
params[:sort_by] = params[:sort_by].presence || 'id'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
default_sort('id', 'desc')
laboratories = Admins::LaboratoryQuery.call(params)
@laboratories = paginate laboratories.preload(:school, :laboratory_users)
@ -27,10 +26,12 @@ class Admins::LaboratoriesController < Admins::BaseController
keyword = params[:keyword].to_s.strip
if keyword.present?
like_sql = 'shixuns.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword'
shixuns = shixuns.joins(:user).where(like_sql, keyword: "%#{keyword}%")
like_sql = 'shixuns.name LIKE :keyword OR CONCAT(users.lastname, users.firstname) LIKE :keyword '\
'OR mirror_repositories.name LIKE :keyword'
shixuns = shixuns.joins(:user, :mirror_repositories).where(like_sql, keyword: "%#{keyword}%")
end
@count = shixuns.count
@shixuns = paginate(shixuns.includes(:user))
end
@ -45,6 +46,7 @@ class Admins::LaboratoriesController < Admins::BaseController
subjects = subjects.joins(:user).where(like_sql, keyword: "%#{keyword}%")
end
@count = subjects.count
@subjects = paginate(subjects.includes(:user))
end

@ -8,6 +8,7 @@ module Base::RenderHelper
def render_forbidden
render_by_format(html: -> { current_user&.business? ? render('shared/403') : redirect_to('/403') },
js: -> { render_js_error(I18n.t('error.forbidden'), type: :notify) },
json: -> { render status: 403, json: { messages: I18n.t('error.forbidden') } } )
end

@ -1,5 +1,5 @@
class Cooperative::FilesController < Cooperative::BaseController
before_action :convert_file!, only: [:create]
before_action :convert_file!, :check_permission!, only: [:create]
def create
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
@ -29,6 +29,22 @@ class Cooperative::FilesController < Cooperative::BaseController
render_error(ex.message)
end
def check_permission!
permission =
case params[:source_type].to_s
when '' then false
when 'Shixun' then
current_laboratory.laboratory_shixuns.exists?(ownership: true, shixun_id: params[:source_id])
when 'Subject' then
current_laboratory.laboratory_subjects.exists?(ownership: true, subject_id: params[:source_id])
else true
end
return if permission
render_forbidden
end
def file_path
@_file_path ||= begin
case params[:source_type].to_s

@ -0,0 +1,39 @@
class Cooperative::LaboratoryShixunsController < Cooperative::BaseController
before_action :check_shixun_ownership!, only: [:edit, :update]
helper_method :current_laboratory_shixun
def index
laboratory_shixuns = Admins::LaboratoryShixunQuery.call(current_laboratory, params)
@laboratory_shixuns = paginate laboratory_shixuns.includes(shixun: %i[tag_repertoires user])
end
def edit
end
def update
end
def homepage
current_laboratory_shixun.update!(homepage: true)
render_ok
end
def cancel_homepage
current_laboratory_shixun.update!(homepage: false)
render_ok
end
private
def current_laboratory_shixun
@_current_laboratory_shixun ||= current_laboratory.laboratory_shixuns.find(params[:id])
end
def check_shixun_ownership!
return if current_laboratory_shixun.ownership?
render_forbidden
end
end

@ -0,0 +1,46 @@
class Cooperative::LaboratorySubjectsController < Cooperative::BaseController
before_action :check_subject_ownership!, only: [:edit, :update]
helper_method :current_laboratory_subject
def index
laboratory_subjects = Admins::LaboratorySubjectQuery.call(current_laboratory, params)
includes_tables = { subject: [:repertoire, :subject_level_system, user: {user_extension: :school}] }
@laboratory_subjects = paginate(laboratory_subjects.includes(includes_tables))
end
def edit
@laboratory_subject = current_laboratory_subject
end
def update
current_laboratory_subject.subject.update!(update_params)
end
def homepage
current_laboratory_subject.update!(homepage: true)
render_ok
end
def cancel_homepage
current_laboratory_subject.update!(homepage: false)
render_ok
end
private
def current_laboratory_subject
@_current_laboratory_subject ||= current_laboratory.laboratory_subjects.find(params[:id])
end
def check_subject_ownership!
return if current_laboratory_subject.ownership?
render_forbidden
end
def update_params
params.require(:laboratory_subject).permit(:repertoire_id, :subject_level_system_id)
end
end

@ -1141,7 +1141,7 @@ class CoursesController < ApplicationController
# 如果在该课堂已经存在学生身份,且邀请码为分班邀请码,则将其直接加入分班
existing_student.update_attributes(course_group_id: course_group.id) if course_group.present?
else
correspond_teacher_exist = current_user.teacher_of_course? course
correspond_teacher_exist = current_user.none_admin_teacher_of_course? course
new_student = CourseMember.new(user_id: current_user.id, course_id: course.id, role: 4)
new_student.is_active = 0 if correspond_teacher_exist

@ -514,6 +514,9 @@ class ExercisesController < ApplicationController
if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time)
error_count += 1
end
if exercise_group.present? && (exercise_group.first.publish_time < Time.now && exercise_group.first.end_time > Time.now) && (exercise_end_time < Time.now)
error_count += 1
end
if error_count == 0
common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的
new_group_ids = course_id - common_group #新传入的班级id
@ -529,12 +532,12 @@ class ExercisesController < ApplicationController
if the_group_setting_status == 2
ex_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => exercise_end_time
:end_time => exercise_end_time < Time.now ? the_group_setting.end_time : exercise_end_time
}
elsif the_group_setting_status == 3
ex_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => the_group_setting.end_time
:end_time => exercise_end_time
}
end
the_group_setting.update_attributes!(ex_group_params)
@ -558,7 +561,7 @@ class ExercisesController < ApplicationController
if error_count > 0
error_count == 0
normal_status(-1,"已发布/已截止的试卷不允许修改时间")
normal_status(-1,"试卷发布/截止时间不能小于当前时间")
else
# 未发布的分班设置才能删除
if old_exercise_groups.size > 0
@ -609,13 +612,27 @@ class ExercisesController < ApplicationController
def adjust_score
exercise_user = @exercise.exercise_users.find_by!(user_id: params[:user_id])
tip_exception("已提交的作品请去评阅页进行调分") if exercise_user.commit_status == 1
tip_exception("分数不能为空") if params[:score].blank?
tip_exception("分数不能超过0-#{@exercise.question_scores}") if params[:score].to_f < 0 || params[:score].to_f.round(1) > @exercise.question_scores.round(1)
if @exercise.subjective_score > 0
tip_exception("主观题成绩不能为空") if params[:subject_score].blank?
tip_exception("主观题成绩不能小于零") if params[:subject_score].to_f < 0
tip_exception("主观题成绩不能大于总分值:#{@exercise.subjective_score}") if params[:subject_score].to_f.round(1) > @exercise.subjective_score.round(1)
end
if @exercise.objective_score > 0
tip_exception("客观题成绩不能为空") if params[:objective_score].blank?
tip_exception("客观题成绩不能小于零") if params[:objective_score].to_f < 0
tip_exception("客观题成绩不能大于总分值:#{@exercise.objective_score}") if params[:objective_score].to_f.round(1) > @exercise.objective_score.round(1)
end
ActiveRecord::Base.transaction do
start_at_time = exercise_user.start_at || Time.now
exercise_user.update_attributes!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: params[:score].to_f.round(2), commit_method: 5)
ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id, score: params[:score], comment: params[:comment])
subjective_score = @exercise.subjective_score > 0 ? params[:subject_score].to_f.round(2) : 0
objective_score = @exercise.objective_score > 0 ? params[:objective_score].to_f.round(2) : 0
score = subjective_score + objective_score
exercise_user.update_attributes!(start_at: start_at_time, end_at: Time.now, status: 1, commit_status: 1, score: score,
subjective_score: subjective_score, objective_score: objective_score, commit_method: 5)
ExerciseUserScore.create!(exercise_id: @exercise.id, exercise_user_id: exercise_user.id,
subjective_score: subjective_score, objective_score: objective_score)
normal_status("操作成功")
end
end

@ -149,6 +149,7 @@ class GraduationTasksController < ApplicationController
else
respond_to do |format|
format.xlsx{
set_export_cookies
graduation_work_to_xlsx(@work_excel,@task,current_user)
task_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@task.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{task_export_name_.strip}",template: "graduation_tasks/tasks_list.xlsx.axlsx",locals: {table_columns:@head_cells_column, task_users:@task_cells_column}

@ -379,8 +379,9 @@ class GraduationWorksController < ApplicationController
end
def adjust_score
tip_exception("分数不能为空") if params[:score].blank?
tip_exception("分数不能超过0-100") if params[:score].to_f < 0 || params[:score].to_f > 100
tip_exception("成绩不能为空") if params[:score].blank?
tip_exception("成绩不能小于零") if params[:score].to_f < 0
tip_exception("成绩不能大于100") if params[:score].to_f.round(1) > 100
ActiveRecord::Base.transaction do
begin
# 分数不为空的历史评阅都置为失效

@ -26,13 +26,28 @@ class HomeController < ApplicationController
@rep_list << {rep_id: rep.id, rep_name: rep.name, sub_rep_list: sub_rep_list}
end
@shixuns = Shixun.where(homepage_show: 1).includes(:tag_repertoires, :challenges).limit(8)
shixuns = current_laboratory.shixuns
subjects = current_laboratory.subjects
if current_laboratory.main_site?
shixuns = shixuns.where(homepage_show: true)
subjects = subjects.where(homepage_show: true)
else
shixuns = shixuns.where(laboratory_shixuns: { homepage: true })
subjects = subjects.where(laboratory_subjects: { homepage: true })
end
@shixuns = shixuns.includes(:tag_repertoires, :challenges).limit(8)
@subjects = subjects.includes(:repertoire, :shixuns).limit(8)
@subjects = Subject.where(homepage_show: 1).includes(:shixuns, :repertoire).limit(8)
@main_shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(8)
@main_subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(8)
if current_laboratory.main_site?
@tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc")
@stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
end
end
def search
@fuzzy_searchs = params[:keyword].split(" ").join("%")

@ -160,7 +160,7 @@ class HomeworkCommonsController < ApplicationController
# 作品状态 0 未提交, 1 按时提交, 2 延迟提交
if params[:work_status].present?
params_work_status = request.get? ? params[:work_status].split(",") : params[:work_status]
params_work_status = params[:work_status]
work_status = params_work_status.map{|status| status.to_i}
all_student_works = @student_works.left_joins(:myshixun)
@student_works = all_student_works.where(work_status: work_status)
@ -171,7 +171,7 @@ class HomeworkCommonsController < ApplicationController
# 分班情况
unless params[:course_group].blank?
group_ids = request.get? ? params[:course_group].split(",") : params[:course_group]
group_ids = params[:course_group]
group_user_ids = @course.students.where(course_group_id: group_ids).pluck(:user_id)
# 有分组只可能是老师身份查看列表
@student_works = @student_works.where(user_id: group_user_ids)
@ -179,9 +179,9 @@ class HomeworkCommonsController < ApplicationController
if @homework.homework_type == "group" && !params[:member_work].blank?
if params[:member_work].to_i == 1
@student_works = @student_works.where("user_id = commit_user_id")
@student_works = @student_works.where("student_works.user_id = commit_user_id")
elsif params[:member_work].to_i == 0
@student_works = @student_works.where("user_id != commit_user_id")
@student_works = @student_works.where("student_works.user_id != commit_user_id")
end
end

@ -103,14 +103,19 @@ class MessagesController < ApplicationController
return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course)
begin
h = {is_md: true}
board = @message.board&.course&.boards.find_by!(id: params[:select_board_id])
email_notify = @message.email_notify ? 1 : @message.board&.course.email_notify && params[:email_notify]
send_email = !@message.email_notify && email_notify
h = {is_md: true, email_notify: email_notify, board_id: board&.id}
m_params = message_params.merge(h)
@message.update_attributes(m_params)
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
@message.update_content(params[:content])
notify_course_students(@message, @message.board&.course) if send_email
rescue Exception => e
uid_logger_error(e.message)
tip_exception("修改失败")
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@ -123,6 +128,7 @@ class MessagesController < ApplicationController
@message.author = current_user
@message.board_id = params[:select_board_id]
@message.message_detail_attributes = {content: params[:content]}
@message.email_notify = @board.course.email_notify && params[:email_notify] ? 1 : 0
@message.save!
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
if @board.course.email_notify && params[:email_notify]
@ -189,7 +195,7 @@ class MessagesController < ApplicationController
private
def validate_sort_type
normal_status(2, "参数sort_tyope暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
normal_status(2, "参数sort_type暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
end
def find_message
@ -207,7 +213,7 @@ class MessagesController < ApplicationController
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
UserMailer.course_message_email(student&.user&.mail, message.id).deliver_later if student&.user&.mail
end
end
end

@ -35,6 +35,11 @@ class ShixunsController < ApplicationController
Shixun.unhidden
end
## 云上实验室过滤
unless current_laboratory.main_site?
@shixuns = @shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: current_laboratory.id })
end
## 方向
if params[:tag_level].present? && params[:tag_id].present?
@shixuns = @shixuns.filter_tag(params[:tag_level].to_i, params[:tag_id].to_i)

@ -524,19 +524,23 @@ class StudentWorksController < ApplicationController
@echart_data = student_efficiency(@homework, @work)
@myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id }
@myself_consume = @echart_data[:consume_list].find { |item| item.last == @user.id }
filename_ = "#{@use&.student_id}_#{@use&.real_name}_#{@shixun&.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
filename = Base64.urlsafe_encode64(filename_.strip)
stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css)
if params[:export].present? && params[:export]
normal_status(0,"正在下载中")
else
set_export_cookies
render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
end
# render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets, disposition: 'inline', type:"pdf_attachment.content_type",stream:false
end
# 作品调分
def adjust_score
tip_exception("分数不能为空") if params[:score].blank?
tip_exception("分数不能超过0-100") if @homework.homework_type != "practice" && (params[:score].to_f < 0 || params[:score].to_f.round(1) > 100.round(1))
tip_exception("已提交的作品请去评阅页进行调分") if @homework.homework_type == "practice" && @work.work_status > 0
tip_exception("分数不能超过总分值#{@homework.total_score}") if @homework.homework_type == "practice" && (params[:score].to_f < 0 || params[:score].to_f.round(1) > @homework.total_score.round(1))
tip_exception("成绩不能为空") if params[:score].blank?
tip_exception("成绩不能小于零") if params[:score].to_f < 0
tip_exception("成绩不能大于100") if params[:score].to_f.round(1) > 100
ActiveRecord::Base.transaction do
begin
# 分数不为空的历史评阅都置为失效

@ -23,16 +23,17 @@ class SubjectsController < ApplicationController
# 最热排序
if reorder == "myshixun_count"
laboratory_join = current_laboratory.main_site? ? '' : " JOIN laboratory_subjects ls ON ls.subject_id = subjects.id AND ls.laboratory_id = #{current_laboratory.id} "
if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id #{laboratory_join} where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id #{laboratory_join} where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
end
@ -52,6 +53,11 @@ class SubjectsController < ApplicationController
@subjects = Subject.visible.unhidden
end
# 云上实验室过滤
unless current_laboratory.main_site?
@subjects = @subjects.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id })
end
# 类型
if select
@subjects = @subjects.where(repertoire_id: select)

@ -12,6 +12,6 @@ class UserMailer < ApplicationMailer
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?
mail(to: mail, subject: '课堂发布了新的帖子') if @message.present? && @course.present?
end
end

@ -41,6 +41,14 @@ class Exercise < ApplicationRecord
exercise_questions.pluck(:question_score).sum
end
def subjective_score
exercise_questions.where(question_type: [4]).pluck(:question_score).sum
end
def objective_score
exercise_questions.where(question_type: [0, 1, 2, 3, 5]).pluck(:question_score).sum
end
def create_exercise_list
str = ""
# TODO: 一次性为所有学生创建数据是否存在问题?

@ -38,4 +38,17 @@ class Laboratory < ApplicationRecord
def self.current
Thread.current[:current_laboratory] ||= Laboratory.find(1)
end
def shixuns
main_site? ? Shixun.all : Shixun.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: id })
end
def subjects
main_site? ? Subject.all : Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: id })
end
# 是否为主站
def main_site?
id == 1
end
end

@ -1,4 +1,6 @@
class LaboratorySubject < ApplicationRecord
belongs_to :laboratory
belongs_to :subject
delegate :repertoire_id, :subject_level_system_id, :student_count, to: :subject
end

@ -235,6 +235,28 @@ class User < ApplicationRecord
end
end
# 实名认证状态
def auth_status
status = if authentication
"已认证"
elsif process_real_name_apply.present?
"待审核"
else
"未认证"
end
end
# 职业认证状态
def pro_status
status = if professional_certification
"已认证"
elsif process_professional_apply.present?
"待审核"
else
"未认证"
end
end
# 判断当前用户是否通过职业认证
def pro_certification?
professional_certification
@ -265,6 +287,11 @@ class User < ApplicationRecord
course.course_members.exists?(user_id: id, role: [1,2,3], is_active: 1) || admin? || business?
end
# 课堂的老师(创建者、老师、助教),不考虑超管和运营人员
def none_admin_teacher_of_course?(course)
course.course_members.exists?(user_id: id, role: [1,2,3], is_active: 1)
end
# 课堂的老师(创建者、老师、助教),不用考虑当前身份
def teacher_of_course_non_active?(course)
course.course_members.exists?(user_id: id, role: [1,2,3])

@ -94,8 +94,8 @@ class DuplicateCourseService < ApplicationService
exercise = course.exercises.create!(attrs.merge(user_id: user.id))
origin_exercise.exercise_questions.find_each do |origin_question|
question_attrs = origin_question.as_json(only: %i[question_title question_type question_number question_score])
question_attrs[:question_type] ||= 1
question_attrs = origin_question.as_json(only: %i[question_title question_type question_number question_score shixun_name shixun_id is_ordered level])
# question_attrs[:question_type] ||= 1
question = exercise.exercise_questions.create!(question_attrs)
exercise_choice_map = {}
@ -103,15 +103,20 @@ class DuplicateCourseService < ApplicationService
choice_attrs = { choice_position: index + 1, choice_text: origin_choice.choice_text }
choice = question.exercise_choices.create!(choice_attrs)
exercise_choice_map[origin_choice.id] = choice.id
# exercise_choice_map[origin_choice.id] = choice.id 标准答案中存的是choice_position, 直接取原题的exercise_choice_id就行
end
origin_question.exercise_standard_answers.find_each do |origin_answer|
question.exercise_standard_answers.create!(
exercise_choice_id: exercise_choice_map[origin_answer.exercise_choice_id],
exercise_choice_id: origin_answer.exercise_choice_id,
answer_text: origin_answer.answer_text
)
end
origin_question.exercise_shixun_challenges.each_with_index do |sc, index|
question.exercise_shixun_challenges.create!({position: index+1, challenge_id: sc.challenge_id,
shixun_id: sc.shixun_id, question_score: sc.question_score})
end
end
origin_exercise.exercise_bank.increment!(:quotes) if exercise.exercise_bank

@ -50,6 +50,12 @@
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<%= link_to '清除', admins_competition_competition_prize_users_path(@competition), class: "btn btn-default",'data-disable-with': '清除中...' %>
<% end %>
<div class="mt-3 d-flex align-items-end">
<%= link_to '导出', admins_competition_competition_prize_users_path(competition_id: @competition.id, format: :xlsx), class: 'btn btn-primary' %>
<%#= javascript_void_link '导出', class: 'btn btn-primary', 'data-url': admins_competition_competition_prize_users_path(competition_id: @competition.id, format: :xlsx) %>
</div>
</div>
</div>

@ -0,0 +1,33 @@
wb = xlsx_package.workbook
wb.styles do |s|
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center}
wb.add_worksheet(name: "#{@competition.name}证书审批列表") do |sheet|
sheet.add_row %w(序号 排名 奖项 战队ID 战队名称 姓名 职业 学号 学校名称 学院名称 地区 实名认证 职业认证 手机号码 队长 签领/开户行及银行卡号 审批时间 审批人), :height => 25,:style => blue_cell
@all_prize_users.each_with_index do |prize_user, index|
user = prize_user.user
data = [
index + 1,
prize_user.rank,
prize_user.competition_prize.name,
prize_user.competition_team_id,
prize_user.competition_team.name,
user.real_name,
user.identity,
user.student_id,
user.school_name,
user.department_name,
user.location,
user.auth_status,
user.pro_status,
user.phone,
prize_user.leader? ? "是" : "-",
[prize_user.extra&.[]('bank'), prize_user.extra&.[]('second_bank'), prize_user.extra&.[]('card_no')].compact.join('/'),
prize_user.approved_at&.strftime('%Y-%m-%d %H:%M'),
prize_user.approver&.real_name
]
sheet.add_row(data)
end
end
end

@ -1,3 +1,4 @@
json.count @count
json.shixuns do
json.array! @shixuns do |shixun|
json.extract! shixun, :id, :name, :status

@ -1,3 +1,4 @@
json.count @count
json.subjects do
json.array! @subjects do |subject|
json.extract! subject, :id, :name, :status

@ -7,8 +7,8 @@
<th width="10%">封面</th>
<th width="8%">创建者</th>
<th width="8%">状态</th>
<th width="10%">执行时间</th>
<th width="14%">操作</th>
<th width="8%">执行时间</th>
<th width="16%">操作</th>
</tr>
</thead>
<tbody>

@ -1,10 +1,10 @@
<% sidebar_collapse = request.cookies['admin_sidebar_collapse'].to_s == 'true' %>
<nav id="sidebar" class="<%= sidebar_collapse ? 'active' : '' %>" data-current-controller="<%= admin_sidebar_controller %>">
<div class="sidebar-header">
<div class="sidebar-header-logo">
<a href="/" class="sidebar-header-logo" data-toggle="tooltip" data-title="返回主站" >
<img class="rounded-circle" src="/images/<%= url_to_avatar(current_user) %>" />
<span class="logo-label">后台管理</span>
</div>
</a>
<div id="sidebarCollapse" class="navbar-btn <%= sidebar_collapse ? 'active' : '' %>">
<i class="fa fa-chevron-left fold" data-toggle="tooltip" data-placement="right" data-boundary="window" title="收起"></i>
<i class="fa fa-bars unfold" data-toggle="tooltip" data-placement="right" data-boundary="window" title="展开"></i>

@ -0,0 +1,42 @@
<% define_breadcrumbs do %>
<% add_breadcrumb('实训项目') %>
<% end %>
<div class="box search-form-container laboratory-shixun-list-form">
<%= form_tag(cooperative_laboratory_shixuns_path, method: :get, class: 'form-inline search-form', remote: true) do %>
<div class="form-group mr-1">
<label for="status">状态:</label>
<% status_options = [['全部', ''], ['编辑中', 0], ['审核中', 1], ['已发布', 2], ['已关闭', 3]] %>
<%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
</div>
<div class="form-group mr-4">
<label for="status">技术平台:</label>
<%= select_tag(:tag_id, options_for_select(MirrorRepository.pluck(:type_name,:id).unshift(['']), params[:tag_id]), class: 'form-control') %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-12 col-md-2 mr-3', placeholder: '创建者/实训名称检索') %>
<div class="form-check mr-2">
<%= hidden_field_tag(:homepage, false, id:'') %>
<%= check_box_tag(:homepage, true, params[:homepage].to_s == 'true', class: 'form-check-input') %>
<label class="form-check-label" for="homepage">只看首页展示</label>
</div>
<div class="form-check mr-2">
<%= hidden_field_tag(:ownership, false, id:'') %>
<%= check_box_tag(:ownership, true, params[:ownership].to_s == 'true', class: 'form-check-input') %>
<label class="form-check-label" for="ownership">只看自建</label>
</div>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<%= link_to '清空', cooperative_laboratory_shixuns_path, class: 'btn btn-default','data-disable-with': '清空中...' %>
<% end %>
</div>
<div class="box laboratory-shixun-list-container">
<%= render partial: 'cooperative/laboratory_shixuns/shared/list', locals: { laboratory_shixuns: @laboratory_shixuns } %>
</div>
<%= render(partial: 'cooperative/shared/modal/upload_file_modal', locals: { title: '上传封面', accept: 'image/*' }) %>

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

@ -0,0 +1,27 @@
<table class="table text-center laboratory-shixun-list-table">
<thead class="thead-light">
<tr>
<th width="28%" class="text-left">实训名称</th>
<th width="12%">技术平台</th>
<th width="14%" class="text-left">技术体系</th>
<th width="10%">封面</th>
<th width="8%">创建者</th>
<th width="8%">状态</th>
<th width="8%">执行时间</th>
<th width="16%">操作</th>
</tr>
</thead>
<tbody>
<% if laboratory_shixuns.present? %>
<% laboratory_shixuns.each do |laboratory_shixun| %>
<tr class="laboratory-shixun-item-<%= laboratory_shixun.id %>">
<%= render partial: 'cooperative/laboratory_shixuns/shared/td', locals: { laboratory_shixun: laboratory_shixun } %>
</tr>
<% end %>
<% else %>
<%= render 'cooperative/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'cooperative/shared/paginate', locals: { objects: laboratory_shixuns } %>

@ -0,0 +1,32 @@
<%- shixun = laboratory_shixun.shixun -%>
<td class="text-left">
<%= link_to "/shixuns/#{shixun.identifier}", target: '_blank' do %>
<%= shixun.name %>
<span class="badge badge-pill badge-success homepage-badge" style="<%= laboratory_shixun.homepage? ? '' : 'display:none' %>">首页</span>
<span class="badge badge-pill badge-info ownership-badge" style="<%= laboratory_shixun.ownership ? '' : 'display:none' %>">自建</span>
<% end %>
</td>
<td><%= shixun.shixun_main_name %></td>
<td class="text-left">
<% shixun.tag_repertoires.each do |tag| %>
<span class="badge badge-secondary"><%= tag.name %></span>
<% end %>
</td>
<td class="image-preview-container">
<% imageExists = Util::FileManage.exists?(shixun) %>
<%= image_tag(imageExists ? Util::FileManage.source_disk_file_url(shixun) : '', height: 40, class: "preview-image shixun-image-#{shixun.id}", data: { toggle: 'tooltip', title: '点击预览' }, style: imageExists ? '' : 'display:none') %>
<% if laboratory_shixun.ownership? %>
<%= javascript_void_link imageExists ? '重新上传' : '上传图片', class: 'action upload-shixun-image-action', data: { source_id: shixun.id, source_type: 'Shixun', toggle: 'modal', target: '.cooperative-upload-file-modal' } %>
<% end %>
</td>
<td><%= link_to shixun.user&.real_name, "/users/#{shixun.user&.login}", target:'_blank' %></td>
<td><span class="<%= shixun_status_class(shixun) %>"><%= t("shixun.status.#{shixun.status}") %></span></td>
<td><%= shixun.excute_time %></td>
<td class="action-container">
<% if laboratory_shixun.ownership? %>
<%#= link_to('修改', cooperative_laboratory_subjects_path(laboratory_shixun)) %>
<% end %>
<%= javascript_void_link('首页展示', class: 'action homepage-show-action', data: { id: laboratory_shixun.id }, style: laboratory_shixun.homepage? ? 'display:none' : '') %>
<%= javascript_void_link('取消首页展示', class: 'action homepage-hide-action', data: { id: laboratory_shixun.id }, style: laboratory_shixun.homepage? ? '' : 'display:none') %>
</td>

@ -0,0 +1,2 @@
$('.cooperative-modal-container').html("<%= j( render partial: 'cooperative/laboratory_subjects/shared/edit_subject_modal', locals: { laboratory_subject: @laboratory_subject } ) %>");
$('.modal.cooperative-edit-subject-modal').modal('show');

@ -0,0 +1,42 @@
<% define_breadcrumbs do %>
<% add_breadcrumb('实践课程') %>
<% end %>
<div class="box search-form-container laboratory-subject-list-form">
<%= form_tag(cooperative_laboratory_subjects_path, method: :get, class: 'form-inline search-form', remote: true) do %>
<div class="form-group mr-1">
<label for="status">状态:</label>
<% status_options = [['全部', ''], ['编辑中', 0], ['审核中', 1], ['已发布', 2]] %>
<%= select_tag(:status, options_for_select(status_options), class: 'form-control') %>
</div>
<div class="form-group col-12 col-md-3">
<label for="school_name">单位:</label>
<%= select_tag :school_id, options_for_select([''], params[:school_id]), class: 'form-control school-select flex-1' %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-12 col-md-2 mr-3', placeholder: '创建者/课程名称检索') %>
<div class="form-check mr-2">
<%= hidden_field_tag(:homepage, false, id:'') %>
<%= check_box_tag(:homepage, true, params[:homepage].to_s == 'true', class: 'form-check-input') %>
<label class="form-check-label" for="homepage">只看首页展示</label>
</div>
<div class="form-check mr-2">
<%= hidden_field_tag(:ownership, false, id:'') %>
<%= check_box_tag(:ownership, true, params[:ownership].to_s == 'true', class: 'form-check-input') %>
<label class="form-check-label" for="ownership">只看自建</label>
</div>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<%= link_to '清空', cooperative_laboratory_subjects_path(current_laboratory), class: 'btn btn-default','data-disable-with': '清空中...' %>
<% end %>
</div>
<div class="box laboratory-subject-list-container">
<%= render partial: 'cooperative/laboratory_subjects/shared/list', locals: { laboratory_subjects: @laboratory_subjects } %>
</div>
<%= render(partial: 'cooperative/shared/modal/upload_file_modal', locals: { title: '上传封面', accept: 'image/*' }) %>

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

@ -0,0 +1,31 @@
<div class="modal fade cooperative-edit-subject-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">编辑课程信息</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= simple_form_for([:cooperative, laboratory_subject], html: { class: 'cooperative-edit-subject-form' }, defaults: { wrapper_html: { class: 'offset-md-1 col-md-10' } }) do |f| %>
<%= f.input :repertoire_id, label: '技术体系:' do %>
<% repertoire_options = Repertoire.order('CONVERT(name USING gbk) COLLATE gbk_chinese_ci ASC').map{|r| [r.name, r.id]} %>
<%= f.select :repertoire_id, [['请选择', '']] + repertoire_options, {}, class: 'form-control' %>
<% end %>
<%= f.input :subject_level_system_id, label: '等级体系:' do %>
<% level_options = SubjectLevelSystem.all.map{|r| [r.name, r.id]} %>
<%= f.select :subject_level_system_id, [['请选择', '']] + level_options, {}, class: 'form-control' %>
<% end %>
<div class="error text-danger"></div>
<% end %>
</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>

@ -0,0 +1,27 @@
<table class="table text-center laboratory-subject-list-table">
<thead class="thead-light">
<tr>
<th width="28%" class="text-left">课程名称</th>
<th width="12%">技术体系</th>
<th width="10%">等级体系</th>
<th width="10%">封面</th>
<th width="8%">创建者</th>
<th width="10%">单位</th>
<th width="8%">状态</th>
<th width="14%">操作</th>
</tr>
</thead>
<tbody>
<% if laboratory_subjects.present? %>
<% laboratory_subjects.each do |laboratory_subject| %>
<tr class="laboratory-subject-item-<%= laboratory_subject.id %>">
<%= render partial: 'cooperative/laboratory_subjects/shared/td', locals: { laboratory_subject: laboratory_subject } %>
</tr>
<% end %>
<% else %>
<%= render 'cooperative/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'cooperative/shared/paginate', locals: { objects: laboratory_subjects } %>

@ -0,0 +1,28 @@
<%- subject = laboratory_subject.subject -%>
<td class="text-left">
<%= link_to(subject.name, "/paths/#{subject.id}", target: '_blank') %>
<span class="badge badge-pill badge-success homepage-badge" style="<%= laboratory_subject.homepage? ? '' : 'display:none' %>">首页</span>
<span class="badge badge-pill badge-success ownership-badge" style="<%= laboratory_subject.ownership? ? '' : 'display:none' %>">自建</span>
</td>
<td><%= display_text subject.repertoire&.name %></td>
<td><%= display_text subject.subject_level_system&.name %></td>
<td class="image-preview-container">
<% image_exists = Util::FileManage.exists?(subject) %>
<%= image_tag(image_exists ? Util::FileManage.source_disk_file_url(subject) : '', height: 40, class: "w-100 preview-image subject-image-#{subject.id}", style: image_exists ? '' : 'display:none') %>
<% if laboratory_subject.ownership? %>
<%= javascript_void_link image_exists ? '重新上传' : '上传图片', class: 'action upload-subject-image-action', data: { source_id: subject.id, source_type: 'Subject', toggle: 'modal', target: '.cooperative-upload-file-modal' } %>
<% end %>
</td>
<td><%= link_to subject.user&.real_name, "/users/#{subject.user&.login}", target:'_blank' %></td>
<td><%= subject.user.school_name %></td>
<td><%= display_subject_status(subject) %></td>
<td class="action-container">
<% if laboratory_subject.ownership? %>
<%= link_to('修改', edit_cooperative_laboratory_subject_path(laboratory_subject), remote: true) %>
<% end %>
<%= javascript_void_link('首页展示', class: 'action homepage-show-action', data: { id: laboratory_subject.id }, style: laboratory_subject.homepage? ? 'display:none' : '') %>
<%= javascript_void_link('取消首页展示', class: 'action homepage-hide-action', data: { id: laboratory_subject.id }, style: laboratory_subject.homepage? ? '' : 'display:none') %>
</td>

@ -0,0 +1,3 @@
$('.laboratory-subject-list-container .laboratory-subject-item-<%= current_laboratory_subject.id %>').html("<%= j(render partial: 'cooperative/laboratory_subjects/shared/td', locals: { laboratory_subject: current_laboratory_subject }) %>");
$('.cooperative-modal-container .modal.cooperative-edit-subject-modal').modal('hide');
show_success_flash();

@ -17,6 +17,8 @@
<li><%= sidebar_item(edit_cooperative_laboratory_setting_path, '网站设置', icon: 'cogs', controller: 'cooperative-laboratory_settings') %></li>
<li><%= sidebar_item(cooperative_carousels_path, '轮播图设置', icon: 'image', controller: 'cooperative-carousels') %></li>
<li><%= sidebar_item(cooperative_laboratory_users_path, '管理员列表', icon: 'user', controller: 'cooperative-laboratory_users') %></li>
<li><%= sidebar_item(cooperative_laboratory_shixuns_path, '实训项目', icon: 'window-restore', controller: 'cooperative-laboratory_shixuns') %></li>
<li><%= sidebar_item(cooperative_laboratory_subjects_path, '实践课程', icon: 'th-list', controller: 'cooperative-laboratory_subjects') %></li>
<li><%= sidebar_item('/', '返回主页', icon: 'sign-out', controller: 'root') %></li>
</ul>
</nav>

@ -11,12 +11,13 @@
<form class="cooperative-upload-file-form" enctype="multipart/form-data">
<%= hidden_field_tag(:source_type, nil) %>
<%= hidden_field_tag(:source_id, nil) %>
<%= hidden_field_tag(:suffix, nil) %>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">文件</span>
</div>
<div class="custom-file">
<input type="file" name="file" class="upload-file-input" id="upload-file-input">
<input type="file" name="file" class="upload-file-input" accept="<%= accept ||= '*' %>" id="upload-file-input">
<label class="custom-file-label file-names" for="upload-file-input">选择文件</label>
</div>
</div>

@ -16,6 +16,8 @@ json.exercise_types do
json.subjective @subjective_type #是否包含主观题1为包括0为不包括
json.exercise_end_time ((@ex_user_end_time.nil? || @ex_user_end_time < Time.now) ? "--" : how_much_time(@ex_user_end_time))
json.groups_count @c_group_counts
json.subjective_score @exercise.subjective_score
json.objective_score @exercise.objective_score
end
if @exercise_current_user_status == 0 #当为老师的时候

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

@ -3,17 +3,19 @@ json.images_url @images_url
json.reps @rep_list
json.shixuns do
json.partial! 'shixuns/shixun', locals: {shixuns: @shixuns}
json.partial! 'shixuns/shixun', locals: {shixuns: @shixuns.present? ? @shixuns : @main_shixuns}
end
json.subjects do
json.partial! 'subjects/subject', locals: {subjects: @subjects}
json.partial! 'subjects/subject', locals: {subjects: @subjects.present? ? @subjects : @main_subjects}
end
json.teachers do
if current_laboratory.main_site?
json.teachers do
json.partial! 'users/user_small', users: @tea_users
end
end
json.students do
json.students do
json.partial! 'users/user_small', users: @stu_users
end
end

@ -1,2 +1,2 @@
json.extract! message, :id, :parent_id, :subject, :created_on, :total_replies_count, :total_praises_count,
:is_md, :praises_count, :visits, :sticky, :is_hidden, :is_public
:is_md, :praises_count, :visits, :sticky, :is_hidden, :is_public, :email_notify

@ -1,7 +1,7 @@
<html>
<head>
<meta charset="utf-8">
<title><%= @course.name %>通知</title>
<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;}
@ -36,22 +36,16 @@
<p style="color:#333; font-size:16px; margin-bottom:15px;font-weight: bold">
您好!
</p>
<p style="color:#333;">
正在注册Educoder请在10分钟内在注册页输入此验证码并进行下一步操作。
如非你本人操作,请忽略此邮件。
<p style="color:#333; ">
参与的课堂:<%= @course.name %>,有新的帖子发布了:
<a href="https://www.educoder.net/courses/<%= @course.id %>/boards/<%= @message.board_id %>/messages/<%= @message.id %>" style="font-weight: normal; color:#ff7500;"><%= @message.subject %></a>
</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>
<div style="text-align: center; margin-top:40px;">
<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>

@ -2,6 +2,7 @@ admins-mirror_scripts: 'admins-mirror_repositories'
admins-laboratory_settings: 'admins-laboratories'
admins-carousels: 'admins-laboratories'
admins-laboratory_shixuns: 'admins-laboratories'
admins-laboratory_subjects: 'admins-laboratories'
admins-competition_settings: 'admins-competitions'
admins-enroll_lists: 'admins-competitions'
admins-competition_prize_users: 'admins-competitions'

@ -1121,12 +1121,25 @@ Rails.application.routes.draw do
namespace :cooperative do
# get '/', to: 'dashboards#show'
get '/', to: 'laboratory_settings#edit'
resources :files, only: [:create]
resources :users, only: [:index]
resources :laboratory_users, only: [:index, :create, :destroy]
resource :laboratory_setting, only: [:edit, :update]
resources :carousels, only: [:index, :create, :update, :destroy] do
post :drag, on: :collection
end
resources :laboratory_shixuns, only: [:index, :edit, :update] do
member do
post :homepage
post :cancel_homepage
end
end
resources :laboratory_subjects, only: [:index, :edit, :update] do
member do
post :homepage
post :cancel_homepage
end
end
end
resources :colleges, only: [] do

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

@ -0,0 +1,6 @@
class AddColumnToExerciseUserScore < ActiveRecord::Migration[5.2]
def change
add_column :exercise_user_scores, :subjective_score, :float, default: 0
add_column :exercise_user_scores, :objective_score, :float, default: 0
end
end

File diff suppressed because one or more lines are too long

@ -137758,16 +137758,23 @@ $(document).on('turbolinks:load', function() {
theme: 'bootstrap4',
placeholder: '请输入实训名称/创建者检索',
multiple: true,
minimumInputLength: 1,
closeOnSelect: false,
ajax: {
delay: 500,
url: '/admins/laboratories/' + laboratoryId + '/shixuns_for_select',
dataType: 'json',
data: function(params){
return { keyword: params.term };
return { keyword: params.term, page: params.page || 1, per_page: 20 };
},
processResults: function(data){
return { results: data.shixuns }
processResults: function(data, params){
params.page = params.page || 1;
return {
results: data.shixuns,
pagination: {
more: (params.page * 20) < data.count
}
};
}
},
templateResult: function (item) {
@ -137822,6 +137829,7 @@ $(document).on('turbolinks:load', function() {
$searchForm.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择创建者单位',
allowClear: true,
minimumInputLength: 1,
ajax: {
delay: 500,
@ -137900,16 +137908,23 @@ $(document).on('turbolinks:load', function() {
theme: 'bootstrap4',
placeholder: '请输入课程名称/创建者检索',
multiple: true,
minimumInputLength: 1,
closeOnSelect: false,
ajax: {
delay: 500,
url: '/admins/laboratories/' + laboratoryId + '/subjects_for_select',
dataType: 'json',
data: function(params){
return { keyword: params.term };
return { keyword: params.term, page: params.page || 1, per_page: 20 }
},
processResults: function(data){
return { results: data.subjects }
processResults: function(data, params){
params.page = params.page || 1;
return {
results: data.subjects,
pagination: {
more: (params.page * 20) < data.count
}
};
}
},
templateResult: function (item) {

@ -25487,17 +25487,28 @@ input.form-control {
height: 300px;
}
/* line 51, app/assets/stylesheets/admins/common.scss */
/* line 50, app/assets/stylesheets/admins/common.scss */
.admin-body-container .image-preview-container {
display: -webkit-box;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
-webkit-box-align: center;
align-items: center;
}
/* line 57, app/assets/stylesheets/admins/common.scss */
.admin-body-container .action-container > .action {
padding: 0 3px;
}
/* line 56, app/assets/stylesheets/admins/common.scss */
/* line 62, app/assets/stylesheets/admins/common.scss */
.admin-body-container .action-container .more-action-dropdown .dropdown-item {
font-size: 14px;
}
/* line 63, app/assets/stylesheets/admins/common.scss */
/* line 69, app/assets/stylesheets/admins/common.scss */
.admin-body-container .paginate-container {
margin-top: 20px;
display: -webkit-box;
@ -25511,68 +25522,68 @@ input.form-control {
align-items: center;
}
/* line 70, app/assets/stylesheets/admins/common.scss */
/* line 76, app/assets/stylesheets/admins/common.scss */
.admin-body-container .paginate-container .paginate-total {
margin-bottom: 10px;
color: darkgrey;
}
/* line 75, app/assets/stylesheets/admins/common.scss */
/* line 81, app/assets/stylesheets/admins/common.scss */
.admin-body-container .paginate-container .pagination {
margin-bottom: 0px;
}
/* line 81, app/assets/stylesheets/admins/common.scss */
/* line 87, app/assets/stylesheets/admins/common.scss */
.admin-body-container .search-form-container {
display: -webkit-box;
display: flex;
margin-bottom: 20px;
}
/* line 85, app/assets/stylesheets/admins/common.scss */
/* line 91, app/assets/stylesheets/admins/common.scss */
.admin-body-container .search-form-container .search-form {
-webkit-box-flex: 1;
flex: 1;
}
/* line 88, app/assets/stylesheets/admins/common.scss */
/* line 94, app/assets/stylesheets/admins/common.scss */
.admin-body-container .search-form-container .search-form * {
font-size: 14px;
}
/* line 90, app/assets/stylesheets/admins/common.scss */
/* line 96, app/assets/stylesheets/admins/common.scss */
.admin-body-container .search-form-container .search-form select, .admin-body-container .search-form-container .search-form input {
margin-right: 10px;
font-size: 14px;
}
/* line 97, app/assets/stylesheets/admins/common.scss */
/* line 103, app/assets/stylesheets/admins/common.scss */
.admin-body-container .global-error {
color: grey;
min-height: 300px;
}
/* line 101, app/assets/stylesheets/admins/common.scss */
/* line 107, app/assets/stylesheets/admins/common.scss */
.admin-body-container .global-error-code {
font-size: 80px;
}
/* line 105, app/assets/stylesheets/admins/common.scss */
/* line 111, app/assets/stylesheets/admins/common.scss */
.admin-body-container .global-error-text {
font-size: 24px;
}
/* line 111, app/assets/stylesheets/admins/common.scss */
/* line 117, app/assets/stylesheets/admins/common.scss */
.admin-body-container .nav-tabs .nav-link {
padding: 0.5rem 2rem;
}
/* line 116, app/assets/stylesheets/admins/common.scss */
/* line 122, app/assets/stylesheets/admins/common.scss */
.admin-body-container .CodeMirror {
border: 1px solid #ced4da;
}
/* line 120, app/assets/stylesheets/admins/common.scss */
/* line 126, app/assets/stylesheets/admins/common.scss */
.admin-body-container .batch-action-container {
margin-bottom: -15px;
padding: 10px 20px 0;

@ -25047,17 +25047,28 @@ input.form-control {
height: 300px;
}
/* line 51, app/assets/stylesheets/cooperative/common.scss */
/* line 50, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .image-preview-container {
display: -webkit-box;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
-webkit-box-align: center;
align-items: center;
}
/* line 57, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .action-container > .action {
padding: 0 3px;
}
/* line 56, app/assets/stylesheets/cooperative/common.scss */
/* line 62, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .action-container .more-action-dropdown .dropdown-item {
font-size: 14px;
}
/* line 63, app/assets/stylesheets/cooperative/common.scss */
/* line 69, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .paginate-container {
margin-top: 20px;
display: -webkit-box;
@ -25071,68 +25082,68 @@ input.form-control {
align-items: center;
}
/* line 70, app/assets/stylesheets/cooperative/common.scss */
/* line 76, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .paginate-container .paginate-total {
margin-bottom: 10px;
color: darkgrey;
}
/* line 75, app/assets/stylesheets/cooperative/common.scss */
/* line 81, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .paginate-container .pagination {
margin-bottom: 0px;
}
/* line 81, app/assets/stylesheets/cooperative/common.scss */
/* line 87, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .search-form-container {
display: -webkit-box;
display: flex;
margin-bottom: 20px;
}
/* line 85, app/assets/stylesheets/cooperative/common.scss */
/* line 91, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .search-form-container .search-form {
-webkit-box-flex: 1;
flex: 1;
}
/* line 88, app/assets/stylesheets/cooperative/common.scss */
/* line 94, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .search-form-container .search-form * {
font-size: 14px;
}
/* line 90, app/assets/stylesheets/cooperative/common.scss */
/* line 96, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .search-form-container .search-form select, .cooperative-body-container .search-form-container .search-form input {
margin-right: 10px;
font-size: 14px;
}
/* line 97, app/assets/stylesheets/cooperative/common.scss */
/* line 103, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .global-error {
color: grey;
min-height: 300px;
}
/* line 101, app/assets/stylesheets/cooperative/common.scss */
/* line 107, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .global-error-code {
font-size: 80px;
}
/* line 105, app/assets/stylesheets/cooperative/common.scss */
/* line 111, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .global-error-text {
font-size: 24px;
}
/* line 111, app/assets/stylesheets/cooperative/common.scss */
/* line 117, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .nav-tabs .nav-link {
padding: 0.5rem 2rem;
}
/* line 116, app/assets/stylesheets/cooperative/common.scss */
/* line 122, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .CodeMirror {
border: 1px solid #ced4da;
}
/* line 120, app/assets/stylesheets/cooperative/common.scss */
/* line 126, app/assets/stylesheets/cooperative/common.scss */
.cooperative-body-container .batch-action-container {
margin-bottom: -15px;
padding: 10px 20px 0;

@ -136047,6 +136047,151 @@ $(document).on('turbolinks:load', function() {
})
}
});
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-laboratory-shixuns-index-page').length > 0) {
var $searchForm = $('.laboratory-shixun-list-form .search-form');
$searchForm.find('select#tag_id').select2({
placeholder: "请选择",
allowClear: true
});
// 上传图片
$('.modal.cooperative-upload-file-modal').on('upload:success', function (e, data) {
var $imageElement = $('.shixun-image-' + data.source_id);
if($imageElement.length === 0) return;
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.laboratory-shixun-list-container').on('click', doElement, function () {
var $doAction = $(this);
var $undoAction = $doAction.siblings(undoElement);
var laboratoryShixunId = $doAction.data('id');
customConfirm({
content: '确认进行该操作吗?',
ok: function () {
$.ajax({
url: '/cooperative/laboratory_shixuns/' + laboratoryShixunId + url,
method: 'POST',
dataType: 'json',
success: function () {
show_success_flash();
$doAction.hide();
$undoAction.show();
if (callback && typeof callback === "function") {
callback(laboratoryShixunId, url);
}
}
});
}
});
});
}
// 首页展示与取消首页展示
var homepageShowCallback = function (laboratoryShixunId, url) {
var $laboratoryShixunItem = $('.laboratory-shixun-list-container').find('.laboratory-shixun-item-' + laboratoryShixunId);
if (url === '/homepage') {
$laboratoryShixunItem.find('.homepage-badge').show();
} else {
$laboratoryShixunItem.find('.homepage-badge').hide();
}
}
defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback);
defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback);
}
})
;
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-laboratory-subjects-index-page').length > 0) {
var $searchForm = $('.laboratory-subject-list-form .search-form');
// ************** 学校选择 *************
$searchForm.find('.school-select').select2({
theme: 'bootstrap4',
placeholder: '请选择创建者单位',
allowClear: true,
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;
return item.name;
},
templateSelection: function (item) {
if (item.id) {
}
return item.name || item.text;
}
});
// 上传图片
$('.modal.cooperative-upload-file-modal').on('upload:success', function (e, data) {
var $imageElement = $('.subject-image-' + data.source_id);
if($imageElement.length === 0) return;
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
});
// 定义状态切换监听事件
var defineStatusChangeFunc = function (doElement, undoElement, url, callback) {
$('.laboratory-subject-list-container').on('click', doElement, function () {
var $doAction = $(this);
var $undoAction = $doAction.siblings(undoElement);
var laboratorySubjectId = $doAction.data('id');
customConfirm({
content: '确认进行该操作吗?',
ok: function () {
$.ajax({
url: '/cooperative/laboratory_subjects/' + laboratorySubjectId + url,
method: 'POST',
dataType: 'json',
success: function () {
show_success_flash();
$doAction.hide();
$undoAction.show();
if (callback && typeof callback === "function") {
callback(laboratorySubjectId, url);
}
}
});
}
});
});
}
// 首页展示与取消首页展示
var homepageShowCallback = function (laboratoryShixunId, url) {
var $laboratoryShixunItem = $('.laboratory-subject-list-container').find('.laboratory-subject-item-' + laboratoryShixunId);
if (url === '/homepage') {
$laboratoryShixunItem.find('.homepage-badge').show();
} else {
$laboratoryShixunItem.find('.homepage-badge').hide();
}
}
defineStatusChangeFunc('.homepage-show-action', '.homepage-hide-action', '/homepage', homepageShowCallback);
defineStatusChangeFunc('.homepage-hide-action', '.homepage-show-action', '/cancel_homepage', homepageShowCallback);
}
})
;
$(document).on('turbolinks:load', function() {
if ($('body.cooperative-laboratory-users-index-page').length > 0) {
// ============= 添加管理员 ==============
@ -136109,6 +136254,24 @@ $(document).on('turbolinks:load', function() {
});
}
});
$(document).on('turbolinks:load', function () {
$('.cooperative-modal-container').on('show.bs.modal', '.modal.cooperative-edit-subject-modal', function () {
var $modal = $('.modal.cooperative-edit-subject-modal');
var $form = $modal.find('form.cooperative-edit-subject-form');
$modal.on('click', '.submit-btn', function () {
$form.find('.error').html('');
var url = $form.attr('action');
$.ajax({
method: 'PATCH',
dataType: 'script',
url: url,
data: $form.serialize()
});
});
})
});
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.cooperative-upload-file-modal');
if ($modal.length > 0) {
@ -136153,7 +136316,7 @@ $(document).on('turbolinks:load', function() {
$.ajax({
method: 'POST',
dataType: 'json',
url: '/cooperatives/files?' + formDataString,
url: '/cooperative/files?' + formDataString,
data: new FormData($form[0]),
processData: false,
contentType: false,

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

@ -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.

@ -3,7 +3,7 @@ import React,{ Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal, Divider
Row, Col, Select, Modal, Divider,Tooltip
} from 'antd';
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
import axios from 'axios'
@ -29,7 +29,9 @@ class BoardsNew extends Component{
fileList: [],
boards: [],
title_num: 0,
email_notify:false
email_notify:false,
isemail_notify:false,
isemail_notifys:false
}
}
addSuccess = () => {
@ -98,7 +100,7 @@ class BoardsNew extends Component{
}
})
this.setState({ fileList: _fileList, board_name: data.board_name, title_num: parseInt(data.subject.length) })
this.setState({ fileList: _fileList, board_name: data.board_name, title_num: parseInt(data.subject.length) ,isemail_notifys:response.data.data.email_notify})
}
}
})
@ -136,6 +138,7 @@ class BoardsNew extends Component{
select_board_id: values.select_board_id,
content: values.content,
sticky: values.sticky,
email_notify:this.state.isemail_notify,
attachment_ids,
})
.then((response) => {
@ -160,7 +163,7 @@ class BoardsNew extends Component{
axios.post(url, {
...values,
email_notify:this.state.email_notify,
email_notify:this.state.isemail_notify,
course_id: cid,
attachment_ids,
})
@ -253,7 +256,7 @@ class BoardsNew extends Component{
setemailchange=(e)=>{
this.setState({
email_notify:e.target.checked
isemail_notify:e.target.checked
})
}
render() {
@ -299,6 +302,7 @@ class BoardsNew extends Component{
const isCourseEnd = this.props.isCourseEnd();
document.title=this.props.coursedata&&this.props.coursedata.name;
// console.log(this.state)
return(
<div className="newMain ">
<AddDirModal {...this.props}
@ -338,13 +342,17 @@ class BoardsNew extends Component{
{/* notRequired */}
<Form {...formItemLayout} onSubmit={this.handleSubmit}>
<div className="formBlock" style={{paddingBottom: '0px', position: 'relative'}}>
{this.state.boardsdata&&this.state.boardsdata.email_notify===true?this.props.isAdminOrTeacher()===true?<Tooltip placement="bottom" title={this.state.isemail_notifys===true?"邮件只能发送一次":""}><span className={"setemail fr mr70 setemailposition"}>
<Checkbox onChange={this.setemailchange} checked={this.state.isemail_notifys===true?this.state.isemail_notifys:this.state.isemail_notify} disabled={this.state.isemail_notifys}>发送邮件提醒</Checkbox>
</span></Tooltip>:"":""}
{ isAdmin &&
<React.Fragment>
{getFieldDecorator('sticky', {
valuePropName: 'checked',
})(
isAdmin && <Checkbox style={{ right: '22px',
top: '28px',
top: '17px',
position: 'absolute'
}}>置顶</Checkbox>
)}
@ -411,9 +419,7 @@ 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

@ -724,22 +724,28 @@ class CommonWorkSetting extends Component{
let course_id=this.props.match.params.coursesId;
const url = `/homework_commons/${workId}/update_settings.json`
// comments
const temp_publish_time_date = new Date(temp_publish_time)
const temp_end_time_date = new Date(temp_end_time)
const late_time_date = new Date(late_time)
const evaluation_start_date = new Date(evaluation_start)
const evaluation_end_date = new Date(evaluation_end)
const appeal_time_date = new Date(appeal_time)
axios.post(url,{
course_id ,
unified_setting: unified_setting, // 统一设置
group_settings: group_settings_param,
publish_time: temp_end_time ? new Date(temp_publish_time.replace(/-/g, '/')) : temp_end_time, // 发布
end_time: temp_end_time ? new Date(temp_end_time.replace(/-/g, '/')) : temp_end_time, // 截止
publish_time: temp_publish_time ? !isNaN(temp_publish_time_date.getTime()) ? temp_publish_time_date : new Date(temp_publish_time.replace(/-/g, '/')) : temp_publish_time, // 发布
end_time: temp_end_time ? !isNaN(temp_end_time_date.getTime()) ? temp_end_time_date : new Date(temp_end_time.replace(/-/g, '/')) : temp_end_time, // 截止
late_penalty: late_penalty, // 迟交扣分
allow_late: allow_late, // 是否允许补交
late_time: late_time ? new Date(late_time.replace(/-/g, '/')) : late_time, // 补交截止时间
late_time: late_time ? !isNaN(late_time_date.getTime()) ? late_time_date : new Date(late_time.replace(/-/g, '/')) : late_time, // 补交截止时间
anonymous_comment: anonymous_comment, // true: 启用匿评 false:未启用匿评
evaluation_start: evaluation_start ? new Date(evaluation_start.replace(/-/g, '/')) : evaluation_start, //匿评开始时间
evaluation_end: evaluation_end ? new Date(evaluation_end.replace(/-/g, '/')) : evaluation_end,
evaluation_start: evaluation_start ? !isNaN(evaluation_start_date.getTime()) ? evaluation_start_date : new Date(evaluation_start.replace(/-/g, '/')) : evaluation_start, //匿评开始时间
evaluation_end: evaluation_end ? !isNaN(evaluation_end_date.getTime()) ? evaluation_end_date : new Date(evaluation_end.replace(/-/g, '/')) : evaluation_end,
evaluation_num: evaluation_num, // 匿评数
absence_penalty: absence_penalty, // 匿评扣分
anonymous_appeal: anonymous_appeal, // true: 启用匿评申诉, false:未启用
appeal_time: appeal_time ? new Date(appeal_time.replace(/-/g, '/')) : appeal_time, // 申诉结束时间
appeal_time: appeal_time ? !isNaN(appeal_time_date.getTime()) ? appeal_time_date : new Date(appeal_time.replace(/-/g, '/')) : appeal_time, // 申诉结束时间
appeal_penalty: appeal_penalty, // 违规匿评扣分
ta_mode: ta_mode, // 1:普通模式 0:复审模式
final_mode: final_mode, // true: 单项评分优先, false: 多项评分配比

@ -50,3 +50,9 @@
margin-left: 10px;
}
/* errorInline ----------- */
.setemailposition{
position: absolute;
right: 40px;
top: 10px;
}

@ -1,5 +1,5 @@
import React,{ Component } from "react";
import {Modal, Checkbox, Upload, Button, Icon, message, Input, Form} from "antd";
import {Modal, Checkbox, Upload, Button, Icon, message, Input, Form, InputNumber} from "antd";
import { WordNumberTextarea } from 'educoder';
import './Newshixunmodel.css'
@ -17,6 +17,7 @@ class ModulationModal extends Component{
Saves=()=>{
console.log("Saves=()");
let {textareaval,Inputsval}=this.state;
// if(textareaval===""||textareaval===undefined){
// this.setState({
@ -32,7 +33,7 @@ class ModulationModal extends Component{
this.setState({
Inputsval: "",
Inputsvaltype: true,
Inputsvaltest: "请输入分数",
Inputsvaltest: "请填写分数",
})
return
}
@ -40,10 +41,51 @@ class ModulationModal extends Component{
if (this.state.Inputsvaltype === true) {
return;
}
if (Inputsval === undefined || Inputsval === null || Inputsval === "") {
this.setState({
borredszf: "ml10 color-grey-9 bor-reds ",
Inputsval: "",
Inputsvaltype: true,
Inputsvaltest: "成绩不能为空",
})
return
}
var re = /^[0-9]+.?[0-9]*$/; //判断字符串是否为数字 //判断正整数 /^[1-9]+[0-9]*]*$/
var nubmer = Inputsval;
if (!re.test(nubmer)) {
this.setState({
borredszf: "ml10 color-grey-9 bor-reds ",
Inputsval: Inputsval,
Inputsvaltype: true,
Inputsvaltest: "请输入0-100的分数",
})
return;
}
if (0 > parseFloat(Inputsval)) {
this.setState({
borredszf: "ml10 color-grey-9 bor-reds ",
Inputsval: Inputsval,
Inputsvaltype: true,
Inputsvaltest: "成绩不能小于零",
})
return;
} else if (parseFloat(Inputsval) > 100) {
this.setState({
borredszf: "ml10 color-grey-9 bor-reds ",
Inputsval: Inputsval,
Inputsvaltype: true,
Inputsvaltest: "成绩不能大于100",
})
return;
}
this.setState({
Inputsvaltype: false,
Inputsvaltest: "",
})
console.log(Inputsval);
this.props.Saves(textareaval,Inputsval)
}
@ -55,29 +97,11 @@ class ModulationModal extends Component{
}
setInputs=(e)=>{
debugger
var value=parseInt(e.target.value)
console.log("setInputs");
console.log(e);
if(isNaN(value)){
value = 0;
this.setState({
Inputsval: value,
Inputsvaltype: true,
Inputsvaltest: "请输入分数",
})
}else{
if(value<0||value>100){
value = 0;
this.setState({
Inputsval: value,
Inputsvaltype: true,
Inputsvaltest: "请输入0-100的分数",
})
}
}
this.setState({
Inputsval: value,
Inputsval: e,
Inputsvaltype: false,
})
}
@ -100,65 +124,90 @@ class ModulationModal extends Component{
alignItems: "center",
}}>
<div style={{
marginTop: " 27px",
display: "flex",
flexDirection: "initial",
}}>
}}>
<p className=" mt3 font-14 " style={{color: "#666666"}}>该学生的最终成绩将不会按照评分规则进行计算</p>
</div>
<div style={{
marginTop: " 27px",
display: "flex",
flexDirection: "initial",
width: "100%",
}}>
<span style={{
width: "70px",
textAlign: "center",
lineHeight: " 40px",
lineHeight: "40px",
marginLeft: "16px",
}}><span style={{
textAlign: "center",
lineHeight: " 40px",
color: " #f5222d",
}}>*</span></span>
<Input
className={Inputsvaltype === true ? "borerinput" : ""}
}}>*</span></span>
<style>
{
`
.myinputnumbers .ant-input-number-input{
line-height: 40px;
height: 35px;
}
`
}
</style>
{Inputsvaltype === true ?
<style>
{
`
.ant-input:hover {
border: 1px solid #DD1717!important;
}
.ant-input:focus {
border: 1px solid #DD1717!important;
}
}
`
}
</style>
:
""
} <InputNumber
className={Inputsvaltype === true ? "borerinput myinputnumbers bor-reds" : "myinputnumbers"}
style={{
width: "335px",
width: "120px",
height: "40px",
}}
placeholder="请填写分数"
value={Inputsval}
onInput={this.setInputs}
suffix={
onChange={(e) => this.setInputs(e)}
value={Inputsval === undefined || Inputsval === null ? "" : Inputsval}/>
<span
style={{
textAlign: "center",
lineHeight: " 40px",
marginLeft: "10px",
}}
></span>
}
/>
</div>
{
Inputsvaltype === true ?
<p style={{color: "#DD1717", width: "268px"}}>{Inputsvaltest}</p>
<p style={{color: "#DD1717", width: "77%", marginLeft: "1px", marginTop: "10px",}}>{Inputsvaltest}</p>
: ""
}
<div style={{
display: "flex",
flexDirection: "initial",
}}>
<span style={{width: "70px"}}></span>
<p className=" mt3 font-14 " style={{color: "#666666"}}>调分后该学生的最终成绩将不会按照评分规则进行计算</p>
</div>
<div style={{
display: "flex",
flexDirection: "initial",
marginTop: "10px;",
}}>
<span style={{width: "70px", marginTop: "24px"}}>调分原因</span>
<WordNumberTextarea
style={{width: "335px"}}
placeholder={"请输入调分原因(选填)"}
style={{width: "100%"}}
placeholder={"请填写您对作品调分的原因(选填)"}
onInput={(e) => this.settextarea(e)}
value={textareaval}
maxlength={100}
@ -166,15 +215,18 @@ class ModulationModal extends Component{
</div>
<div style={{
marginTop: "27px",
width: " 336px",
marginTop: "15px",
width: "82%",
marginLeft: "70px",
marginBottom: "29px",
display: "flex",
flexDirection: "row-reverse",
}}>
<a className="task-btn color-white mr30" style={{width: "72px",}}
<a className="task-btn task-btn-orange " style={{width: "72px", borderRadius: "5px"}}
onClick={this.Saves}>{this.props.Savesname || '确认'}</a>
<a className="task-btn color-white mr30" style={{width: "72px", borderRadius: "5px"}}
onClick={this.props.Cancel}>{this.props.Cancelname || '取消'}</a>
<a className="task-btn task-btn-orange" style={{width: "72px",}}
onClick={this.Saves}>{this.props.Savesname || '保存'}</a>
</div>
</div>

@ -0,0 +1,176 @@
import React, {Component} from "react";
import {Modal, Checkbox, Upload, Button, Icon, message, Input, Form} from "antd";
import {WordNumberTextarea} from 'educoder';
import './Newshixunmodel.css'
//调分
class ModulationModal_exercise extends Component {
constructor(props) {
super(props);
this.state = {
score: 0,
subjective_questions: 0,
objective_questions: 0,
}
//因为主观题加客观题的和是总分
}
componentDidMount = () => {
}
Saves = () => {
let {textareaval, subjective_questions, objective_questions, score} = this.state;
// this.props.Saves(textareaval, Inputsval)
}
settextarea = (e) => {
this.setState({
textareaval: e.target.value
})
}
setInputs = (e) => {
}
render() {
let {Inputsvaltype, subjective_questions, objective_questions, score} = this.state;
return (
<div>
<Modal
keyboard={false}
className={"HomeworkModal"}
title={this.props.modalname || '评阅'}
visible={this.props.visible}
closable={false}
footer={null}
destroyOnClose={true}
>
<div className="clearfix" style={{
display: "-webkit-flex",
flexDirection: "column",
alignItems: "center",
}}>
<div className="mexertwo">
<p className="mexeheigth2">主观题成绩:</p>
<Input
className={Inputsvaltype === true ? "borerinput myinputnumbers bor-reds" : "myinputnumbers"}
style={{
width: "120px",
height: "40px",
}}
placeholder="请填写主观题成绩"
onChange={(e) => this.setInputs(e)}
value={subjective_questions === undefined || subjective_questions === null ? "" : subjective_questions}/>
<p className="mexeheigth"> ,</p>
<p className="mexeheigth"><span>总分</span><span>45.0 </span><span></span></p>
</div>
<div className="mexertwo">
<p className="mexeheigth2">客观题成绩:</p>
<Input
className={Inputsvaltype === true ? "borerinput myinputnumbers bor-reds" : "myinputnumbers"}
style={{
width: "120px",
height: "40px",
}}
placeholder="请填写客观题成绩"
onChange={(e) => this.setInputs(e)}
value={objective_questions === undefined || objective_questions === null ? "" : objective_questions}/>
<p className="mexeheigth"> ,</p>
<p className="mexeheigth"><span>总分</span><span>45.0 </span><span></span></p>
</div>
<div className="mexertwo">
<p className="mexeheigth2">最终成绩:</p>
<Input
className={Inputsvaltype === true ? "borerinput myinputnumbers bor-reds" : "myinputnumbers"}
style={{
width: "120px",
height: "40px",
}}
placeholder="请填写最终成绩"
onChange={(e) => this.setInputs(e)}
value={score === undefined || score === null ? "" : score}/>
<p className="mexeheigth"> ,</p>
<p className="mexeheigth"><span>总分</span><span>45.0 </span><span></span></p>
</div>
<div className="minbuttionte">
<a className="task-btn color-white mr30" style={{width: "72px",}}
onClick={this.props.Cancel}>{this.props.Cancelname || '取消'}</a>
<a className="task-btn task-btn-orange" style={{width: "72px",}}
onClick={this.Saves}>{this.props.Savesname || '保存'}</a>
</div>
</div>
</Modal>
</div>
)
}
}
export default ModulationModal_exercise;
// <div className="task-popup-content">
// <p className="task-popup-text-center font-16 mb20">
//
// <span className={"color-dark-21"}>该学生的最终成绩将不会按照评分规则进行计算</span>
//
// </p>
//
//
// <div className="clearfix">
// {/*<textarea*/}
// {/*className="winput-100-150"*/}
// {/*placeholder="请填写您对作品调分的原因"*/}
// {/*value={textareaval}*/}
// {/*onInput={this.settextarea}*/}
// {/*></textarea>*/}
//
// <WordNumberTextarea
// placeholder={"请填写您对作品调分的原因"}
// onInput={(e)=>this.settextarea(e)}
// value={textareaval}
// maxlength={100}
// />
//
// {/*<li style={{height:"20px",lineHeight:"20px"}}><span className={textareavaltype===true?"color-red":"none"}>原因不能为空</span></li>*/}
// <div style={{height:"20px",lineHeight:"20px"}}></div>
// </div>
//
// <style>
// {
//
// `
// .pdl10{
// padding-left:10px;
// }
// `
// }
// </style>
//
// <li className={"pdl10"}>
//
// </li>
// <li style={{height:"20px",lineHeight:"20px"}}><span className={Inputsvaltype===true?"color-red":"none"}>分数不能为空</span></li>
// <div className="clearfix edu-txt-center">
// <a className="task-btn color-white mr30" onClick={this.props.Cancel}>{this.props.Cancelname || '取消'}</a>
// <a className="task-btn task-btn-orange" onClick={this.Saves}>{this.props.Savesname || '保存'}</a>
{/* </div>*/
}
{/*</div>*/
}

@ -305,8 +305,27 @@
margin: 10px 10px 0px 10px;
padding: 10px 10px 5px 10px;
backgroud: rgba(234, 234, 234, 1);
width: 335px;
width: 530px;
margin-left: 10px;
margin-top: 25px;
height: 214px !important;
}
.WordNumbernote .WordNumberTextarea {
outline: none;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-color: white;
text-shadow: none;
-webkit-writing-mode: horizontal-tb !important;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
resize: none;
border: none;
width: 100%;
height: 169px !important;
border: none;
display: block;
}
.WordNumberTextarea-count {
@ -325,3 +344,30 @@
border: 1px solid #eee !important;
}
.mexertwo {
display: flex;
flex-direction: initial;
}
.mexeheigth {
line-height: 40px;
}
.mexeheigth2 {
line-height: 40px;
width: 74px;
}
.minbuttionte {
/* display: flex; */
margin-top: 27px;
width: 100%;
/* align-items: center; */
margin-bottom: 17px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex-direction: initial;
}

@ -120,9 +120,9 @@ class ExerciseNewCommon extends Component{
componentDidMount = () => {
this.fetchExercise()
}
handleSubmit = (e) => {
}
// handleSubmit = (e) => {
//
// }
onSaveExercise = () => {
const { exercise_name, exercise_description } = this.state;
const exercise_id = this.props.match.params.Id
@ -472,7 +472,9 @@ class ExerciseNewCommon extends Component{
></div>
</div>}
{this.state.editMode && <Form {...formItemLayout} onSubmit={this.handleSubmit}>
{this.state.editMode && <Form {...formItemLayout}
// onSubmit={this.handleSubmit}
>
<div className="formBlock" style={{paddingBottom: '2px',borderBottom:"none"}}>
<Form.Item
label="试卷标题"

@ -24,6 +24,7 @@ import {getImageUrl, toPath, sortDirections} from 'educoder';
import CheckBoxGroup from "../../page/component/CheckBoxGroup";
import NoneData from '../../../modules/courses/coursesPublic/NoneData'
import ModulationModal from "../coursesPublic/ModulationModal";
import ModulationModal_exercise from "../coursesPublic/ModulationModal_exercise";
const Search = Input.Search;
const RadioGroup = Radio.Group;
const CheckboxGroup = Checkbox.Group;
@ -1030,9 +1031,10 @@ class Studentshavecompletedthelist extends Component {
render: (text, record) => (
<span>
{record.finalscore==="--"?
<span className="color-blue" style={{textAlign: "center", cursor: "pointer"}}
onClick={() => this.Adjustment(record)}
>调分</span>
<span style={{textAlign: "center", color: '#999999'}}
>--</span>
:
<a style={{textAlign: "center"}} className="color-blue"
target="_blank"
@ -1227,9 +1229,8 @@ class Studentshavecompletedthelist extends Component {
render: (text, record) => (
<span>
{record.finalscore==="--"?
<span className="color-blue" style={{textAlign: "center", cursor: "pointer"}}
onClick={() => this.Adjustment(record)}
>调分</span>
<span style={{textAlign: "center", color: '#999999'}}
>--</span>
:
<a style={{textAlign: "center"}} className="color-blue"
target="_blank"
@ -1243,6 +1244,15 @@ class Studentshavecompletedthelist extends Component {
exercise_status:0,
order_type: "desc",
exeuserid: 0,
subjective: 0,
objective_score: 0,
subjective_score: 0,
}
{/*<a style={{textAlign: "center"}} className="color-blue"*/
}
{/* target="_blank"*/
}
{/* onClick={() => this.Adjustment(record.user_id)}>评阅</a>*/
}
// //console.log("Studentshavecompletedthelist");
// //console.log(props.current_status);
@ -1799,6 +1809,9 @@ class Studentshavecompletedthelist extends Component {
course_groups: response.data.course_groups,
mylistansum:response.data.exercise_types.answer_users+response.data.exercise_types.unanswer_users,
loadingstate: false,
subjective: response.data.exercise_types.subjective,
objective_score: response.data.exercise_types.objective_score,
subjective_score: response.data.exercise_types.subjective_score,
columnsys: arr,
})
} else {
@ -1831,6 +1844,9 @@ class Studentshavecompletedthelist extends Component {
exercise_users: response.data.exercise_users,
course_groups: response.data.course_groups,
mylistansum:response.data.exercise_types.answer_users+response.data.exercise_types.unanswer_users,
subjective: response.data.exercise_types.subjective,
objective_score: response.data.exercise_types.objective_score,
subjective_score: response.data.exercise_types.subjective_score,
columnsys: arr,
})
}
@ -1868,6 +1884,9 @@ class Studentshavecompletedthelist extends Component {
course_groups: response.data.course_groups,
mylistansum:response.data.exercise_types.answer_users+response.data.exercise_types.unanswer_users,
loadingstate: false,
subjective: response.data.exercise_types.subjective,
objective_score: response.data.exercise_types.objective_score,
subjective_score: response.data.exercise_types.subjective_score,
columnsys: arr,
})
} else {
@ -1900,6 +1919,9 @@ class Studentshavecompletedthelist extends Component {
course_groups: response.data.course_groups,
mylistansum:response.data.exercise_types.answer_users+response.data.exercise_types.unanswer_users,
loadingstate: false,
subjective: response.data.exercise_types.subjective,
objective_score: response.data.exercise_types.objective_score,
subjective_score: response.data.exercise_types.subjective_score,
columnsys: arr,
})
}
@ -1932,6 +1954,9 @@ class Studentshavecompletedthelist extends Component {
course_groups: response.data.course_groups,
mylistansum:response.data.exercise_types.answer_users+response.data.exercise_types.unanswer_users,
columnsys: arr,
subjective: response.data.exercise_types.subjective,
objective_score: response.data.exercise_types.objective_score,
subjective_score: response.data.exercise_types.subjective_score,
})
} else {
var arr =[];
@ -1957,6 +1982,9 @@ class Studentshavecompletedthelist extends Component {
course_groups: response.data.course_groups,
mylistansum:response.data.exercise_types.answer_users+response.data.exercise_types.unanswer_users,
columnsys:arr,
subjective: response.data.exercise_types.subjective,
objective_score: response.data.exercise_types.objective_score,
subjective_score: response.data.exercise_types.subjective_score,
})
}
} else {
@ -1973,6 +2001,9 @@ class Studentshavecompletedthelist extends Component {
mylistansum:response.data.exercise_types.answer_users+response.data.exercise_types.unanswer_users,
loadingstate: false,
columnsys: this.state.columnsystwo,
subjective: response.data.exercise_types.subjective,
objective_score: response.data.exercise_types.objective_score,
subjective_score: response.data.exercise_types.subjective_score,
})
} else {
var arr =[];
@ -1999,6 +2030,9 @@ class Studentshavecompletedthelist extends Component {
mylistansum:response.data.exercise_types.answer_users+response.data.exercise_types.unanswer_users,
loadingstate: false,
columnsys: arr,
subjective: response.data.exercise_types.subjective,
objective_score: response.data.exercise_types.objective_score,
subjective_score: response.data.exercise_types.subjective_score,
})
}
@ -2586,9 +2620,9 @@ class Studentshavecompletedthelist extends Component {
var exercise_id = this.props.match.params.Id;
let url = `/exercises/${exercise_id}/adjust_score.json`;
axios.post(url, {
score: n,
user_id: this.state.exeuserid,
comment: v,
subjective_score: n,
objective_score: v,
})
.then((response) => {
if (response.data.status == '0') {
@ -2639,6 +2673,13 @@ class Studentshavecompletedthelist extends Component {
Cancel={() => this.Adjustments()}
Saves={(value, num) => this.Testpapergrading(value, num)}
/> : ""}
{/*{*/}
{/* testpapergradingboll === true ? <ModulationModal_exercise*/}
{/* visible={testpapergradingboll}*/}
{/* Cancel={() => this.Adjustments()}*/}
{/* Saves={(value, num) => this.Testpapergrading(value, num)}*/}
{/* /> : ""*/}
{/*}*/}
<div className="edu-back-white" >
<ul className="clearfix" style={{padding: '10px 30px 10px 30px'}}>

@ -292,7 +292,7 @@ class Testpapersettinghomepage extends Component{
const isStudent = this.props.isStudent();
// TODO
// console.log(Commonheadofthetestpaper.exercise_status);
//console.log(Commonheadofthetestpaper.exercise_status);
document.title=this.props.coursedata&&this.props.coursedata.name;
return(
<div className="newMain clearfix ">
@ -411,7 +411,7 @@ class Testpapersettinghomepage extends Component{
</div>
{
isAdmin === true &&Commonheadofthetestpaper && Commonheadofthetestpaper.user_permission.user_commit_counts>0?
isAdmin === true &&Commonheadofthetestpaper && Commonheadofthetestpaper.user_permission.user_commit_counts>0&&Commonheadofthetestpaper.exercise_status===2?
<a className="fr color-blue font-16 mt20 mr20" onClick={this.Ecerciseacallagain}>打回重做</a>:""
}
@ -443,7 +443,7 @@ class Testpapersettinghomepage extends Component{
<a className="fr color-blue font-16 mt20" onClick={()=>this.setgameexercise(`/courses/${this.props.match.params.coursesId}/exercises/${this.props.match.params.Id}/users/${this.props.current_user.login}`)}>开始答题</a>:
<Link className="fr color-blue font-16 mt20"
to={`/courses/${this.props.match.params.coursesId}/exercises/${this.props.match.params.Id}/users/${this.props.current_user.login}`}>
{exercise_status===2?"":exercise_status===3?"":exercise_status===4?"":start_Value[exercise_status]}
{exercise_status===2?start_Value[Commonheadofthetestpaper&&Commonheadofthetestpaper.user_permission.current_status]:exercise_status===3?"":exercise_status===4?"":start_Value[Commonheadofthetestpaper&&Commonheadofthetestpaper.user_permission.current_status]}
</Link>
:""}

@ -211,6 +211,59 @@ class Bullsubdirectory extends Component{
});
}
//上移
Moveupward = (id) => {
let url = `/courses/${this.props.match.params.coursesId}/inform_up.json`;
axios.post(url, {
inform_id: id
}).then((response) => {
if (response) {
if (response.data) {
if (response.data.status === 0) {
this.props.showNotification(`上移成功`);
this.props.getinputdata();
} else {
this.props.showNotification(`上移失败`);
}
} else {
this.props.showNotification(`上移失败`);
}
} else {
this.props.showNotification(`上移失败`);
}
}).catch((error) => {
console.log(error)
});
}
//下移
Movedown = (id) => {
let url = `/courses/${this.props.match.params.coursesId}/inform_down.json`;
axios.post(url, {
inform_id: id
}).then((response) => {
if (response) {
if (response.data) {
if (response.data.status === 0) {
this.props.showNotification(`下移成功`);
this.props.getinputdata();
} else {
this.props.showNotification(`下移失败`);
}
} else {
this.props.showNotification(`下移失败`);
}
} else {
this.props.showNotification(`下移失败`);
}
}).catch((error) => {
console.log(error)
});
}
render(){
let{description,whethertoeditysl,addonAfter,eduintits,informs,isSpinysl} =this.state;
@ -218,7 +271,7 @@ class Bullsubdirectory extends Component{
const {getFieldDecorator} = this.props.form;
// console.log("Bullsubdirectory");
// console.log(this.props.isAdmin());
// console.log(this.props.yslbool);
// console.log(this.props);
return(
<React.Fragment >
<div >
@ -269,12 +322,48 @@ class Bullsubdirectory extends Component{
:""
}
</span>
{
this.props.length - 1 === this.props.index ? "" :
this.props.isAdmin() === true ?
(this.props.yslbool === false ?
<a className="fr yslbianji mr30"
style={{
lineHeight: "31px",
}}
onClick={() => this.Movedown(this.props.id)}
><Tooltip
title="下移"><i
style={{color: "#4CACFF"}}
className=" font-18 iconfont icon-xiangxiayi"></i></Tooltip></a>
:
""
)
: ""
}
{
this.props.index === 0 ? "" :
this.props.isAdmin() === true ?
(this.props.yslbool === false ?
<a className="fr yslbianji mr30"
style={{
lineHeight: "31px",
}}
onClick={() => this.Moveupward(this.props.id)}
><Tooltip
title="上移"><i
style={{color: "#4CACFF"}}
className=" font-18 iconfont icon-xiangshangyi"></i></Tooltip></a>
:
""
)
: ""
}
</div>
<div className="yslclear"></div>
</div>
<div id="MakedownHTML"className="markdown-body fonttext yslmtopcg yslminHeigth markdownysltext" dangerouslySetInnerHTML={{__html: markdownToHTML(mydescription).replace(/▁/g, "▁▁▁")}}/>
</div>
<div className="bor-bottom-greyE mr25 ml25"></div>
{parseInt(this.props&&this.props.informs.length)===parseInt(this.props&&this.props.index+1)?"":<div className="bor-bottom-greyE mr25 ml25"></div>}
</div>
:
<div className="edu-back-white ">

@ -491,9 +491,12 @@ class Eduinforms extends Component{
:
<div className="edu-back-white ">
{/*公告栏底部*/}
{ informs&&informs.map((item, index) => {
return (
<Bullsubdirectory {...this.state} {...this.props} key={index} yslbool={yslbool} id={item.id} myname={item.name} mydescription={item.description}
<Bullsubdirectory {...this.state} {...this.props} key={index} index={index}
length={informs.length} yslbool={yslbool} id={item.id}
myname={item.name} mydescription={item.description}
getyslbooltrue={()=>this.getyslbooltrue()}
getyslboolfalse={()=>this.getyslboolfalse()}
getinputdata={()=>this.getinputdata()} ></Bullsubdirectory>

@ -1,5 +1,5 @@
import React,{ Component } from "react";
import { Pagination} from "antd";
import { Pagination , Spin } from "antd";
import NoneData from "../coursesPublic/NoneData"
import '../css/members.css'
@ -16,10 +16,14 @@ class PollDetailTabSecond extends Component{
page:1,
limit:10,
questions:undefined,
questionsInfo:undefined
questionsInfo:undefined,
isSpin:false
}
}
getInfo=(page)=>{
this.setState({
isSpin:true
})
let pollId=this.props.match.params.pollId;
let url=`/polls/${pollId}/commit_result.json?page=${page}`;
axios.get(url).then((result)=>{
@ -27,7 +31,8 @@ class PollDetailTabSecond extends Component{
this.setState({
page: page,
questions:result.data.questions,
questionsInfo:result.data.question_types
questionsInfo:result.data.question_types,
isSpin:false
})
}
}).catch((error)=>{
@ -56,11 +61,12 @@ class PollDetailTabSecond extends Component{
}
render(){
let {page, limit, questions, questionsInfo} = this.state;
let {page, limit, questions, questionsInfo , isSpin} = this.state;
return(
<Spin size="large" spinning={ isSpin }>
<div>
{
questions && questions.length>0?questions.map((item,key)=>{
questions && questions.length>0 && questions.map((item,key)=>{
return(
<div className="edu-back-white mb10">
<div className="pt20 pl30 pr30 pb10">
@ -90,8 +96,9 @@ class PollDetailTabSecond extends Component{
<p className="countHeader">
{
item.question.question_type==3?
<ul className="clearfix">
<span>文本答案</span>
<ul className="clearfix df">
<span style={{width:"6%"}}>编号</span>
<span style={{width:"50%",textAlign:"left"}}>文本答案</span>
</ul>
:
<ul className="clearfix">
@ -105,19 +112,22 @@ class PollDetailTabSecond extends Component{
{/* 主观题 */}
{
item.question.question_type == 3 && item.question.vote_text &&
<div className="countBody">
<ul className="clearfix">
<span className="color-grey-3 break-word" style={{width:"100%"}}>
<React.Fragment>
{
item.question.vote_text.map((txt,t)=>{
return(
<li>{t+1}.{txt}</li>
)
})
}
<div className="countBody">
<ul className="clearfix df">
<span style={{width:"6%"}} className="pl8">{t+1}</span>
<span className="color-grey-3 break-word edu-txt-left flex1">
<li>{txt}</li>
</span>
</ul>
</div>
)
})
}
</React.Fragment>
}
{/* 单选和多选 */}
{
@ -166,7 +176,10 @@ class PollDetailTabSecond extends Component{
</div>
</div>
)
}):<NoneData></NoneData>
})
}
{
questions && questions.length == 0 && <NoneData></NoneData>
}
{
questionsInfo && questionsInfo.q_counts > limit &&
@ -177,6 +190,7 @@ class PollDetailTabSecond extends Component{
}
</div>
</Spin>
)
}
}

@ -1,5 +1,5 @@
import React,{ Component } from "react";
import { Spin } from 'antd';
import '../css/members.css'
import '../css/busyWork.css'
import './pollStyle.css'
@ -12,10 +12,14 @@ class PollDetailTabThird extends Component{
constructor(props){
super(props);
this.state={
pollDetail:undefined
pollDetail:undefined,
isSpin:false
}
}
getPollInfo=()=>{
this.setState({
isSpin:true
})
let pollId=this.props.match.params.pollId;
let url=`/polls/${pollId}.json`;
axios.get(url).then((result)=>{
@ -23,12 +27,14 @@ class PollDetailTabThird extends Component{
if (result.data.status === 401) {
//未登入
this.setState({
pollDetail: undefined
pollDetail: undefined,
isSpin:false
})
return
}
this.setState({
pollDetail:result.data
pollDetail:result.data,
isSpin:false
})
}
}).catch((error)=>{
@ -39,10 +45,12 @@ class PollDetailTabThird extends Component{
this.getPollInfo();
}
render(){
let {pollDetail}=this.state;
let {pollDetail , isSpin}=this.state;
return(
<div>
<Spin size="large" spinning={isSpin}>
<PollDetailTabThirdInfo {...this.props} {...this.state} pollDetail = {pollDetail}></PollDetailTabThirdInfo>
</Spin>
</div>
)
}

@ -43,6 +43,7 @@ const {Option} = Select;
//GraduationTaskssetting.js
//作品列表(学生)
let allow_lates=false;
class Listofworksstudentone extends Component {
//unifiedsetting 统一设置
//allowreplenishment 允许补交
@ -288,7 +289,11 @@ class Listofworksstudentone extends Component {
),
},
{
title: '实战耗时',
title:<span>实训总耗时<Tooltip placement="top" title={<pre>
计算规则:<br/>
学员离开实训学习界面停止计时<br/>
评测首次通过之后停止计时<br/>
</pre>}><img src={getImageUrl("images/educoder/problem.png")}/></Tooltip></span>,
dataIndex: 'cost_time',
key: 'cost_time',
align: 'center',
@ -383,7 +388,19 @@ class Listofworksstudentone extends Component {
)
},
{
title: '效率分',
title: <span>效率分<Tooltip placement="top" title={allow_lates===true?<pre>
补交结束时系统根据学生在课堂成员中的<br/>
效率表现自动评分计算规则:<br/>
学生工作效率= log(实训总得分/实训总耗时)<br/>
学生效率分 = 学生工作效率 / 课堂学生最高<br/>
工作效率 * 分值<br/>
</pre>:<pre>
作业截止时系统根据学生在课堂成员中的<br/>
效率表现自动评分计算规则:<br/>
学生工作效率= log(实训总得分/实训总耗时)<br/>
学生效率分 = 学生工作效率 / 课堂学生最高<br/>
工作效率 * 分值<br/>
</pre>}><img src={getImageUrl("images/educoder/problem.png")}/></Tooltip></span>,
dataIndex: 'efficiencyscore',
key: 'efficiencyscore',
align: 'center',
@ -645,7 +662,11 @@ class Listofworksstudentone extends Component {
),
},
{
title: '实战耗时',
title:<span>实训总耗时<Tooltip placement="top" title={<pre>
计算规则:<br/>
学员离开实训学习界面停止计时<br/>
评测首次通过之后停止计时<br/>
</pre>}><img src={getImageUrl("images/educoder/problem.png")}/></Tooltip></span>,
dataIndex: 'cost_time',
key: 'cost_time',
align: 'center',
@ -736,7 +757,19 @@ class Listofworksstudentone extends Component {
)
},
{
title: '效率分',
title: <span>效率分<Tooltip placement="top" title={allow_lates===true?<pre>
补交结束时系统根据学生在课堂成员中的<br/>
效率表现自动评分计算规则:<br/>
学生工作效率= log(实训总得分/实训总耗时)<br/>
学生效率分 = 学生工作效率 / 课堂学生最高<br/>
工作效率 * 分值<br/>
</pre>:<pre>
作业截止时系统根据学生在课堂成员中的<br/>
效率表现自动评分计算规则:<br/>
学生工作效率= log(实训总得分/实训总耗时)<br/>
学生效率分 = 学生工作效率 / 课堂学生最高<br/>
工作效率 * 分值<br/>
</pre>}><img src={getImageUrl("images/educoder/problem.png")}/></Tooltip></span>,
dataIndex: 'efficiencyscore',
key: 'efficiencyscore',
align: 'center',
@ -953,7 +986,11 @@ class Listofworksstudentone extends Component {
},
{
title: '实战耗时',
title:<span>实训总耗时<Tooltip placement="top" title={<pre>
计算规则:<br/>
学员离开实训学习界面停止计时<br/>
评测首次通过之后停止计时<br/>
</pre>}><img src={getImageUrl("images/educoder/problem.png")}/></Tooltip></span>,
dataIndex: 'cost_time',
key: 'cost_time',
align: 'center',
@ -1007,17 +1044,10 @@ class Listofworksstudentone extends Component {
className: 'font-14',
render: (text, record) => (
<span>
<Tooltip placement="bottom" title={<div>
<div>已通过{record.completion}{this.state.challenges_count}</div>
<div>完成任务评测之前查看了参考答案{record.view_answer_count}</div>
</div>}>
<span style={{
color: '#07111B',
"text-align": "center"
}}>{record.completion + "/" + this.state.challenges_count} </span>
</Tooltip>
</span>
)
},
@ -1043,7 +1073,19 @@ class Listofworksstudentone extends Component {
)
},
{
title: '效率分',
title: <span>效率分<Tooltip placement="top" title={allow_lates===true?<pre>
补交结束时系统根据学生在课堂成员中的<br/>
效率表现自动评分计算规则:<br/>
学生工作效率= log(实训总得分/实训总耗时)<br/>
学生效率分 = 学生工作效率 / 课堂学生最高<br/>
工作效率 * 分值<br/>
</pre>:<pre>
作业截止时系统根据学生在课堂成员中的<br/>
效率表现自动评分计算规则:<br/>
学生工作效率= log(实训总得分/实训总耗时)<br/>
学生效率分 = 学生工作效率 / 课堂学生最高<br/>
工作效率 * 分值<br/>
</pre>}><img src={getImageUrl("images/educoder/problem.png")}/></Tooltip></span>,
dataIndex: 'efficiencyscore',
key: 'efficiencyscore',
align: 'center',
@ -1053,22 +1095,14 @@ class Listofworksstudentone extends Component {
{
record.efficiencyscore && record.efficiencyscore === "--" ? (
this.state.allow_late && this.state.allow_late === false ?
<Tooltip placement="bottom" title={<div>
<div>作业截止时系统根据学生在课堂成员中的效率表现自动评分</div>
</div>}>
<span style={{color: "#9A9A9A"}}>
--
</span>
</Tooltip>
:
this.state.allow_late && this.state.allow_late === true ?
<Tooltip placement="bottom" title={<div>
<div>补交结束时系统根据学生在课堂成员中的效率表现自动评分</div>
</div>}>
<span style={{color: "#9A9A9A"}}>
--
</span>
</Tooltip>
:
<span style={{color: "#9A9A9A"}}>
--
@ -1104,7 +1138,7 @@ class Listofworksstudentone extends Component {
{
record.ultimate_score === true ?
<Tooltip placement="bottom" title={<div>
<div>{record.user_name}{record.user_login}</div>
{/*<div>{record.user_name}{record.user_login}</div>*/}
<div>{record.finalscore === "--" ? <span>最终调整成绩0</span> :
<span>最终调整成绩{record.finalscore}</span>}</div>
</div>}>
@ -1130,16 +1164,21 @@ class Listofworksstudentone extends Component {
</Tooltip>
:
<Tooltip placement="bottom" title={<div>
<div>{record.user_name}{record.user_login}</div>
<div>完成任务评测之前查看了参考答案{record.view_answer_count}</div>
{/*<div>{record.user_name}{record.user_login}</div>*/}
<div>{record.levelscore === "--" ? <span>关卡得分0</span> :
<span>关卡得分{record.levelscore}</span>}</div>
<div>{record.efficiencyscore === "--" ? <span>效率评分0</span> :
<span>效率评分{record.efficiencyscore}</span>}</div>
<div>{record.late_penalty === "--" ? <span>迟交扣分0</span> :
<span>迟交扣分{record.late_penalty}</span>}</div>
<div>{record.finalscore === "--" ? <span>当前成绩0</span> :
<span>当前成绩{record.finalscore}</span>}</div>
{record.view_answer_count===null?"":<div>查看参考答案{record.view_answer_count}</div>}
<div>{record.finalscore === "--" ? <span>最终成绩0</span> :
<span>最终成绩{record.finalscore}</span>}</div>
</div>}>
{
record.finalscore && record.finalscore === "--" ?
@ -1177,11 +1216,11 @@ class Listofworksstudentone extends Component {
record.submitstate === "未提交" ?
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformationt(record)}>查看</a> :
onClick={() => this.Viewstudenttraininginformationt(record)}>评阅</a> :
<span>
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformationt(record)}>查看</a>
onClick={() => this.Viewstudenttraininginformationt(record)}>评阅</a>
</span>
)
},
@ -1304,7 +1343,11 @@ class Listofworksstudentone extends Component {
// ),
// },
{
title: '实战耗时',
title:<span>实训总耗时<Tooltip placement="top" title={<pre>
计算规则:<br/>
学员离开实训学习界面停止计时<br/>
评测首次通过之后停止计时<br/>
</pre>}><img src={getImageUrl("images/educoder/problem.png")}/></Tooltip></span>,
dataIndex: 'cost_time',
key: 'cost_time',
align: 'center',
@ -1341,17 +1384,10 @@ class Listofworksstudentone extends Component {
className: 'font-14',
render: (text, record) => (
<span>
<Tooltip placement="bottom" title={<div>
<div>已通过{record.completion}{this.state.challenges_count}</div>
<div>完成任务评测之前查看了参考答案{record.view_answer_count}</div>
</div>}>
<span style={{
color: '#07111B',
textAlign: "center"
}}>{record.completion + "/" + this.state.challenges_count} </span>
</Tooltip>
</span>
)
},
@ -1377,7 +1413,19 @@ class Listofworksstudentone extends Component {
)
},
{
title: '效率分',
title: <span>效率分<Tooltip placement="top" title={allow_lates===true?<pre>
补交结束时系统根据学生在课堂成员中的<br/>
效率表现自动评分计算规则:<br/>
学生工作效率= log(实训总得分/实训总耗时)<br/>
学生效率分 = 学生工作效率 / 课堂学生最高<br/>
工作效率 * 分值<br/>
</pre>:<pre>
作业截止时系统根据学生在课堂成员中的<br/>
效率表现自动评分计算规则:<br/>
学生工作效率= log(实训总得分/实训总耗时)<br/>
学生效率分 = 学生工作效率 / 课堂学生最高<br/>
工作效率 * 分值<br/>
</pre>}><img src={getImageUrl("images/educoder/problem.png")}/></Tooltip></span>,
dataIndex: 'efficiencyscore',
key: 'efficiencyscore',
align: 'center',
@ -1387,22 +1435,14 @@ class Listofworksstudentone extends Component {
{
record.efficiencyscore && record.efficiencyscore === "--" ? (
this.state.allow_late && this.state.allow_late === false ?
<Tooltip placement="bottom" title={<div>
<div>作业截止时系统根据学生在课堂成员中的效率表现自动评分</div>
</div>}>
<span style={{color: "#9A9A9A"}}>
--
</span>
</Tooltip>
:
this.state.allow_late && this.state.allow_late === true ?
<Tooltip placement="bottom" title={<div>
<div>补交结束时系统根据学生在课堂成员中的效率表现自动评分</div>
</div>}>
<span style={{color: "#9A9A9A"}}>
--
</span>
</Tooltip>
:
<span style={{color: "#9A9A9A"}}>
--
@ -1438,7 +1478,7 @@ class Listofworksstudentone extends Component {
{
record.ultimate_score === true ?
<Tooltip placement="bottom" title={<div>
<div>{record.user_name}{record.user_login}</div>
{/*<div>{record.user_name}{record.user_login}</div>*/}
<div>{record.finalscore === "--" ? <span>最终调整成绩0</span> :
<span>最终调整成绩{record.finalscore}</span>}</div>
</div>}>
@ -1464,16 +1504,21 @@ class Listofworksstudentone extends Component {
</Tooltip>
:
<Tooltip placement="bottom" title={<div>
<div>{record.user_name}{record.user_login}</div>
<div>完成任务评测之前查看了参考答案{record.view_answer_count}</div>
{/*<div>{record.user_name}{record.user_login}</div>*/}
<div>{record.levelscore === "--" ? <span>关卡得分0</span> :
<span>关卡得分{record.levelscore}</span>}</div>
<div>{record.efficiencyscore === "--" ? <span>效率评分0</span> :
<span>效率评分{record.efficiencyscore}</span>}</div>
<div>{record.late_penalty === "--" ? <span>迟交扣分0</span> :
<span>迟交扣分{record.late_penalty}</span>}</div>
<div>{record.finalscore === "--" ? <span>当前成绩0</span> :
<span>当前成绩{record.finalscore}</span>}</div>
{record.view_answer_count===null?"":<div>查看参考答案{record.view_answer_count}</div>}
<div>{record.finalscore === "--" ? <span>最终成绩0</span> :
<span>最终成绩{record.finalscore}</span>}</div>
</div>}>
{
record.finalscore && record.finalscore === "--" ?
@ -1511,11 +1556,11 @@ class Listofworksstudentone extends Component {
record.submitstate === "未提交" ?
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformationt(record)}>{record.operating}</a> :
onClick={() => this.Viewstudenttraininginformationt(record)}>评阅</a> :
<span>
<a style={{textAlign: "center"}} className="color-blue"
onMouseDown={(e) => this.Viewstudenttraininginformationtysl2(e, record)}
onClick={() => this.Viewstudenttraininginformationt(record)}>{record.operating}</a>
onClick={() => this.Viewstudenttraininginformationt(record)}>评阅</a>
</span>
)
},
@ -1711,6 +1756,7 @@ class Listofworksstudentone extends Component {
homework_status: result.data.homework_status,
update_score: result.data.update_score
});
allow_lates=result.data.allow_late;
this.seacthdatat(result.data, result.data.student_works, result.data.work_efficiency, result.data.course_group_info, 1);
if (result.data.student_works === undefined || result.data.student_works === null || JSON.stringify(result.data.student_works) === "[]") {
@ -2419,6 +2465,7 @@ class Listofworksstudentone extends Component {
challenges_count: result.data.challenges_count,
homework_status: result.data.homework_status,
});
allow_lates=result.data.allow_late
this.seacthdatat(result.data, result.data.student_works, result.data.work_efficiency, result.data.course_group_info, page);
this.props.Getdataback(result, result.data);
// }

@ -72,10 +72,10 @@ class ShixunWorkReport extends Component {
})
}
}else {
this.props.slowDownload(url)
// this.props.slowDownload(url)
// this.props.showNotification(`正在下载中`);
// window.open("/api"+url+'?export=true', '_blank');
this.props.showNotification(`正在下载中`);
window.open("/api"+url+'?export=true', '_blank');
this.setState({ isspinning: false })
}
}).catch((error) => {

@ -394,6 +394,7 @@ class ShixunsHome extends Component {
{/*导师排行榜*/}
{ homedatalist !== undefined && homedatalist.teachers !== undefined && (
<div className="pt60 pb60 mb30 mentor-ranking">
<div className="educontent">
<div className="edu-txt-center">
@ -470,8 +471,10 @@ class ShixunsHome extends Component {
</div>
</div>
)}
{/*程序员排行榜*/}
{ homedatalist !== undefined && homedatalist.students !== undefined && (
<div className="pt60 pb60 mb30 pro-ranking">
<div className="educontent">
<div className="edu-txt-center">
@ -544,6 +547,7 @@ class ShixunsHome extends Component {
</div>
</div>
</div>
)}
</div>
</Spin>
</div>

@ -151,3 +151,11 @@
.textcenter{
text-align: center;
}
.zindextest {
z-index: 1000 !important;
}
.MuiModal-root-15 {
z-index: 1000 !important;
}

@ -476,10 +476,28 @@ class LoginDialog extends Component {
if (response.data.status === 402) {
// window.location.href = response.data.url;
}else if (response.data.status === -2) {
if (response.data.message === "登录密码出错已达上限,账号已被锁定, 请10分钟后重新登录或找回密码") {
const messge = (
<div>
<p>
登录密码出错已达上限账号已被锁定
</p>
<p className="mt10">
请10分钟后重新登录或<a href={'/changepassword'} style={{
textDecoration: "underline",
color: "#4CACFF",
}}>找回密码</a>
</p>
</div>
)
this.openNotifications(messge);
} else {
notification.open({
message: '提示',
description:response.data.message,
description: response.data.message,
duration: 5,
});
}
}else{
@ -529,6 +547,17 @@ class LoginDialog extends Component {
weixinlogin:true
})
}
openNotifications = (btn) => {
// type 1 成功提示绿色 2提醒颜色黄色 3错误提示红色
notification.open({
message: "提示",
description: btn,
duration: 5,
onClick: () => {
},
});
}
openqqlogin=()=>{
this.setState({
qqlogin:true
@ -544,12 +573,16 @@ class LoginDialog extends Component {
)
}
getTContainer = () => {
return document.body;
}
hideweixinlogin=()=>{
this.setState({
weixinlogin:false,
qqlogin:false
})
}
render() {
let{qqlogin,login,isGoing,isGoingValue,disabled,bottonclass,Phonenumberisnotco,
dialogBox, isRender,weixinlogin}=this.state;
@ -560,6 +593,7 @@ class LoginDialog extends Component {
// console.log(this.props)
return (
<Dialog open={true} id="DialogID"
className="zindextest"
style={{ display: isRender==false? 'none' : ''}}
disableEscapeKeyDown={true}
disableBackdropClick={true}
@ -611,6 +645,11 @@ class LoginDialog extends Component {
ref="loginPassText"
onInput={this.loginChange}
onBlur={(e) => this.inputOnBlur(e, 1)}
onPressEnter={disabled === false ?
this.loginEDU : () => {
}
// console.log(1)
}
value={this.state.loginValue}
name="username"
placeholder="请输入有效的手机号/邮箱号" ></input>
@ -625,6 +664,11 @@ class LoginDialog extends Component {
onInput={this.passwordChange}
onKeyDown={this.onKeydowns}
className="input-100-45 mt5"
onPressEnter={disabled === false ?
this.loginEDU : () => {
}
// console.log(1)
}
placeholder="密码" >
</input>
<div style={{height: '25px'}}>
@ -662,7 +706,8 @@ class LoginDialog extends Component {
</span>
<span className="fr">
<a onClick={(url)=>this.getloginurl("/changepassword")} className="mr3 color-grey-9">忘记密码</a><em className="vertical-line"></em>
<a onClick={(url) => this.getloginurl("/changepassword")}
className="mr3 color-grey-9">找回密码</a><em className="vertical-line"></em>
<a onClick={(url)=>this.getloginurl("/register")} className="color-grey-9">注册</a>
</span>

@ -4,10 +4,15 @@
-ms-flex-direction: column;
flex-direction: column;
}
.textright{
text-align: right;
}
.textcenter{
text-align: center;
}
.Osshackathonfont{
width: 80px;
height: 28px;
@ -26,7 +31,7 @@
}
.OsshackathonCard{
width:1200px;
height:150px;
min-height:150px;
background:rgba(248,248,248,1);
border:1px solid rgba(235,235,235,1);
}
@ -37,6 +42,9 @@
font-weight:400;
color:rgba(5,16,26,1);
line-height:24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ant-input::-webkit-input-placeholder{
@ -67,3 +75,84 @@
.Searchant-btn-primary .ant-input-group .ant-input{
height:42px;
}
.Breadcrumbfont{
color:#4CACFF;
}
.ant-breadcrumb-separator{
color:#BCBCBC;
}
.minheight50px{
min-height: 50px;
}
.borderDEDEDE{
border-left:1px solid #DEDEDE;
}
.pl80pt6{
padding-top: 6px;
padding-left: 80px;
}
.OsshackprimaryButton{
width: 100%;
height: 45px;
}
.OsshackprimaryButtonsyle{
background: rgba(255,255,255,1) !important;
border: 1px solid rgba(76,172,255,1);
color: rgba(76,172,255,1);
line-height: 16px;
border-radius: unset;
box-shadow:none;
}
.h45input input{
height:45px;
}
.width14bai{
width: 14%;
}
.Osshackprimaryfonttop{
font-size: 20px;
color: rgba(5,16,26,1);
text-align: center;
}
.Osshackathonmodelinput{
width: 97% !important;
margin-left: 7px;
}
.Osshackathonmodelinput .ant-input::-webkit-input-placeholder{
color: #999;
font-size: 14px;
}
.Osshackathonmodelinput .ant-input::-moz-placeholder{color: #cccccc;font-size:14px;}
.Osshackathonmodelinput .ant-input::-webkit-input-placeholder{color: #cccccc;font-size:14px;}
.Osshackathonmodelinput .ant-input:-ms-input-placeholder{color: #cccccc;font-size:14px;}
.Osshackathonmodelinput .ant-input-group-addon {
color: #adadad !important;
}
.iscursor{
cursor: pointer;
}
.issignup:hover, .issignup:focus {
color: #fff !important;
background-color: #40a9ff;
border-color: #40a9ff;
}
.Osshackathon-btn-primary .ant-btn-primary:hover, .Osshackathon-btn-primary .ant-btn-primary:focus {
color: #fff !important;
background-color: #40a9ff;
border-color: #40a9ff;
}

@ -1,10 +1,12 @@
import React, {Component} from 'react';
import axios from 'axios';
import {SnackbarHOC, WordsBtn,getImageUrl,markdownToHTML} from 'educoder';
import {Row, Col,Input,Divider,Card,Button} from 'antd';
import {Row, Col,Input,Divider,Card,Button,Pagination,Breadcrumb,Icon,Spin} from 'antd';
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
import { CNotificationHOC } from '../courses/common/CNotificationHOC';
import Osshackathonmd from './Osshackathonmd';
import './Osshackathon.css';
import Osshackathonmodel from "./Osshackathonmodel";
const { Search } = Input;
class Osshackathon extends Component {
@ -14,16 +16,22 @@ class Osshackathon extends Component {
page:1,
limit:10,
search:undefined,
data:undefined
data:undefined,
hackathonedit:false,
Osshackathonmodeltype:false,
spinning:false,
}
}
componentDidMount() {
this.getosshackathon();
this.getosshackathonlist();
window.document.title = '竞赛报名';
}
getosshackathon=()=>{
let {page,limit,search}=this.state;
getosshackathon=(page,limit,search)=>{
this.setState({
spinning:true
})
let url=`/osshackathon.json`;
axios.get(url,{params:{
page:page,
@ -31,24 +39,166 @@ class Osshackathon extends Component {
search:search,
}}).then((result)=>{
if(result.status==200){
console.log(result)
this.setState({
data:result.data
data:result.data,
spinning:false
})
}else{
this.setState({
spinning:false
})
}
}).catch((error)=>{
console.log(error);
this.setState({
spinning:true
})
})
}
getosshackathonlist=()=>{
let {page,limit,search}=this.state;
this.setState({
page:1,
search:undefined
})
this.getosshackathon(1,limit,undefined)
}
componentDidUpdate = (prevProps) => {
}
PaginationTask=(pageNumber)=>{
this.setState({
page:pageNumber
})
let {page,limit,search}=this.state;
this.getosshackathon(pageNumber,limit,search)
}
hackathonedit=(id)=>{
//管理员编辑title
this.setState({
hackathonedit:true
})
}
hidehackathonedit=()=>{
this.setState({
hackathonedit:false
})
}
Signupentry=(id)=>{
// 用户报名
if(this.props.checkIfLogin()===false){
this.props.showLoginDialog()
return
}
if(this.props.checkIfProfileCompleted()===false){
this.props.showProfileCompleteDialog()
return
}
this.props.confirm({
content: `是否确认报名?`,
onOk: () => {
this.Signupentrys(id)
}
})
}
Signupentrys=(id)=>{
let url=`/osshackathon/${id}/entry.json`;
axios.post(url
).then((response) => {
if(response.data.status===0){
this.getosshackathonlist()
this.props.showNotification(`报名成功,预祝您夺得桂冠`);
}
}).catch((error) => {
console.log(error)
})
}
editSignupentry=(id,name,description)=>{
// 管理员编辑项目
this.setState({
Osshackathonmodeltype:true
})
if(id===undefined){
this.setState({
modelid:undefined,
modelname:undefined,
modeldescription:undefined
})
}else{
this.setState({
modelid:id,
modelname:name,
modeldescription:description
})
}
}
hideeditSignupentry=(id)=>{
// 管理员取消项目
this.setState({
Osshackathonmodeltype:false
})
}
delSignupentry=(id)=>{
// 管理员删除项目
this.props.confirm({
content: `是否确认删除该项目?`,
onOk: () => {
this.delSignupentrys(id)
}
})
}
delSignupentrys=(id)=>{
let url=`/osshackathon/${id}.json`;
axios.delete(url)
.then((response) => {
if (response.data.status == 0) {
// {"status":1,"message":"删除成功"}
this.getosshackathonlist();
this.props.showNotification(`删除成功`);
}
})
.catch(function (error) {
console.log(error);
});
}
onsearchvalue=(value)=>{
this.setState({
search:value
})
if(value.length>300){
this.props.showNotification(`搜索字数大于300个字`);
}
let {page,limit,search}=this.state;
this.getosshackathon(page,limit,value)
}
onsetsearchvalue=(e)=>{
this.setState({
search:e.target.value
})
}
render() {
let{data}=this.state;
console.log(this.state.data)
let {page,data,hackathonedit}=this.state;
return (
<div className="newMain clearfix newMainybot">
@ -59,6 +209,11 @@ class Osshackathon extends Component {
background: #4CACFF;
border-color: #4CACFF;
}
.ant-btn-primary:hover, .ant-btn-primary:focus {
color: #4CACFF;
background-color: #40a9ff;
border-color: #40a9ff;
}
`
}
</style>
@ -66,18 +221,20 @@ class Osshackathon extends Component {
<div className={"educontent mb20 persmstyle"} style={{width: "1200px", marginTop: "26px"}}>
<div className="registrationback"
style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`,"height":"360px"}}
style={{"background": `url(${getImageUrl(`images/educoder/competitions/heikesong.jpg`)})`,"height":"360px"}}
></div>
<Row className={"mt20"}>
<Spin spinning={this.state.spinning}>
{this.props.user&&this.props.user.admin===true?<Row className={"mt20"}>
<Col span={6}>
<Search
className={"Searchant-btn-primary"}
className={"Osshackathon-btn-primary"}
placeholder="请输入项目名称进行搜索"
enterButton="搜索"
size="large"
onSearch={value => console.log(value)}
value={this.state.search}
onInput={(e)=>this.onsetsearchvalue(e)}
onSearch={value => this.onsearchvalue(value)}
/>
</Col>
@ -87,17 +244,17 @@ class Osshackathon extends Component {
</div>
</Col>
</Row>
</Row>:""}
<Row className={"mt20"}>
{hackathonedit===true?"":<Row className={"mt20"}>
<Col span={6} className={"Osshackathonfont"}>
{data&&data.hackathon.name}
</Col>
<Col span={3} className={"fr textright"}>
<Button type="primary">编辑</Button>
</Col>
</Row>
<style>
{this.props.user&&this.props.user.admin===true?<Col span={3} className={"fr textright"}>
<Button type="primary" className={"OsshackprimaryButtonsyle"} onClick={()=>this.hackathonedit(data&&data.hackathon.id)}>编辑</Button>
</Col>:""}
</Row>}
{hackathonedit===true?"": <style>
{
`
.ant-divider-horizontal{
@ -105,59 +262,126 @@ class Osshackathon extends Component {
}
`
}
</style>
</style>}
<Divider />
{hackathonedit===true?"":<Divider />}
<p className={"Osshackathonfontlist mb30"}>
{hackathonedit===true?"":<p className={"Osshackathonfontlist mb30"}>
{data&&data.hackathon.description===null?"":<div className={"markdown-body"}
dangerouslySetInnerHTML={{__html: markdownToHTML(data&&data.hackathon.description).replace(/▁/g, "▁▁▁")}}></div>}
</p>
</p>}
{hackathonedit===true?<Osshackathonmd
getosshackathon={()=>this.getosshackathonlist()}
hidehackathonedit={()=>this.hidehackathonedit()}
{...this.props}
{...this.state}
/>:""}
{this.state.Osshackathonmodeltype===true?<Osshackathonmodel
getosshackathon={()=>this.getosshackathonlist()}
hideeditSignupentry={()=>this.hideeditSignupentry()}
{...this.props}
{...this.state}
/>:""}
{this.props.user&&this.props.user.admin===true?<Row className={"mb20"}>
<Col span={8}></Col>
<Col span={8}><Button type="primary" className={"OsshackprimaryButton OsshackprimaryButtonsyle"} onClick={()=>this.editSignupentry()}><Icon type="plus" />新建项目</Button></Col>
<Col span={8}></Col>
</Row>:""}
{/*学生身份*/}
{
data&&data.hacks.length==0?"":data&&data.hacks.map((item,key)=>{
this.props.user&&this.props.user.admin===false?data&&data.hacks.length==0?"":data&&data.hacks.map((item,key)=>{
return(
<span></span>
)
})
}
{/*学生身份*/}
<Card className={"OsshackathonCard mb20"}>
<Card className={"OsshackathonCard mb20"} key={key}>
<Row>
<Col span={6} className={"OsshackathonCardtitle"}>
大赛介绍
<Col span={20} className={"OsshackathonCardtitle"}>
{item.name}
</Col>
<Col span={6} className={"fr textright"}>
<Button type="primary fr ">立即报名</Button>
<Button type="primary fr mr20" disabled>
{item.entry_info===true?<Button type="primary fr mr20" disabled>
已报名
</Button>
</Button>:<Button type="primary fr issignup" onClick={()=>this.Signupentry(item.id)}></Button>}
</Col>
</Row>
<p>Card content</p>
<p>Card content</p>
<p className={"mt20"}>{item.description}</p>
</Card>
)
}):""
}
{/*教师身份*/}
<Card className={"OsshackathonCard"}>
{/*教师身份*/}
{this.props.user&&this.props.user.admin===true?<style>
{
`
.ant-col-pull-6 {
right: 17%;
}
.ant-col-18 {
width: 82%;
}
.CompetitionsIndexbottomvalue{
text-align: center;
}
`
}
</style>:""}
{
this.props.user&&this.props.user.admin===true?data&&data.hacks.length==0?"":data&&data.hacks.map((item,key)=>{
return(
<Card className={"OsshackathonCard mb20"}>
<Row>
<Col span={6} className={"OsshackathonCardtitle"}>
大赛介绍
<Col span={20} className={"OsshackathonCardtitle"}>
{item.name}
</Col>
<Col span={6} className={"fr textright"}>
<Button type="primary fr ">立即报名</Button>
<Button type="primary fr mr20" disabled>
已报名
</Button>
<Col span={4} className={"fr textcenter width14bai"}>
<Breadcrumb separator="">
<Breadcrumb.Item className={"Breadcrumbfont iscursor"} onClick={()=>this.editSignupentry(item.id,item.name,item.description)}>编辑</Breadcrumb.Item>
<Breadcrumb.Item className={"Breadcrumbfont iscursor"} onClick={()=>this.delSignupentry(item.id)}>删除</Breadcrumb.Item>
</Breadcrumb>
</Col>
</Row>
<Row className={"mt20"}>
<Col span={4} push={20} className={"minheight50px borderDEDEDE"}>
<div className={"pl80pt6"}>
<Row gutter={16}>
<Col className="gutter-row" span={15}>
<div className="gutter-box Osshackprimaryfonttop">{item.hack_users_count}</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={15}>
<div className="gutter-box CompetitionsIndexbottomvalue">报名数</div>
</Col>
</Row>
<p>Card content</p>
<p>Card content</p>
</div>
</Col>
<Col span={18} pull={6} className={"minheight50px ml5"}>
{item.description}
</Col>
</Row>
</Card>
)}):""
}
{data&&data.hacks_count>10?data&&data.hacks.length===0?"":<div className="mb40 edu-txt-center padding20-30" >
<Pagination
showQuickJumper
defaultCurrent={1}
pageSize={10}
total={data&&data.hacks_count}
current={page}
onChange={this.PaginationTask}
/>
</div>:""}
</Spin>
</div>
</div>

@ -0,0 +1,111 @@
import React, { Component } from 'react';
import {Button, Card, Row, Col ,Upload,Icon,message,Tabs,Form,Input} from 'antd';
import axios from 'axios';
import {getImageUrl,getUrl} from 'educoder';
import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor';
class Osshackathonmd extends Component{
constructor(props) {
super(props)
this.contentMdRef = React.createRef();
this.state={
title_num: 0,
title_value: undefined
}
}
componentDidUpdate =(prevState)=>{
// if(prevState!=this.props){
// let url=`/osshackathon/edit_hackathon.json`;
// axios.get(url).then((result)=>{
// if(result.status==200){
// this.setState({
// title_value:result.data.name
// })
// this.contentMdRef.current.setValue(result.data.description);
// }
// })
// }
}
componentDidMount(){
let url=`/osshackathon/edit_hackathon.json`;
axios.get(url).then((result)=>{
if(result.status==200){
this.setState({
title_value:result.data.name
})
this.contentMdRef.current.setValue(result.data.description);
}
})
}
// 输入title
changeTitle = (e) => {
// title_num: 60 - parseInt(e.target.value.length),
this.setState({
title_num: e.target.value.length,
title_value: e.target.value
})
}
handleSubmit = () => {
let {title_value}=this.state;
const mdContnet = this.contentMdRef.current.getValue().trim();
// if(mdContnet.length>10000){
// this.props.showNotification("内容超过10000个字");
// return
// }
let url=`/osshackathon/update_hackathon.json`;
axios.post(url,{
name:title_value,
description:mdContnet,
}
).then((response) => {
if(response.data.status===0){
this.props.getosshackathon()
this.props.hidehackathonedit()
this.props.showNotification(`提交成功`);
}
}).catch((error) => {
console.log(error)
})
}
render() {
// console.log(this.props.tabkey)
// console.log(chart_rules)
return (
<div className={"mt20"}>
<Form>
<Form.Item label="标题">
<Input placeholder="请输入标题"
value={this.state.title_value}
onInput={this.changeTitle}
className="searchView searchViewAfter h45input" style={{"width": "100%"}} maxLength="60"
addonAfter={String(this.state.title_value===undefined?0:this.state.title_value.length)+"/60"}
/>
</Form.Item>
<Form.Item label="描述">
<TPMMDEditor ref={this.contentMdRef} placeholder="请输入描述" mdID={'courseContentMD'} refreshTimeout={1500}
className="courseMessageMD" initValue={this.state.description}></TPMMDEditor>
</Form.Item>
</Form>
<div className="clearfix mt30 mb30">
<div className={"fr"}>
<Button type="primary" onClick={this.handleSubmit} className="defalutSubmitbtn fl mr20">提交</Button>
<a className="defalutCancelbtn fl" onClick={() => this.props.hidehackathonedit()}>取消</ a>
</div>
</div>
</div>
)
}
}
export default Osshackathonmd;

@ -0,0 +1,217 @@
import React, { Component } from 'react';
import {Button, Card, Row, Col ,Upload,Icon,message,Tabs,Form,Input,Modal} from 'antd';
import axios from 'axios';
import {getImageUrl,getUrl,WordNumberTextarea} from 'educoder';
class Osshackathonmodel extends Component{
constructor(props) {
super(props)
this.state={
title_num: 0,
title_value: undefined,
Textarea_comment:undefined
}
}
componentDidUpdate =(prevState)=>{
// if(prevState!=this.props){
// let name=this.props&&this.props.modelname;
// let mdvalue=this.props&&this.props.modeldescription;
// this.setState({
// title_value:name,
// Textarea_comment:mdvalue
// })
// }
}
componentDidMount(){
if(this.props.modelid===undefined){
this.setState({
title_value:undefined,
Textarea_comment:undefined
})
}else{
let url=`/osshackathon/${this.props.modelid}/edit.json`;
axios.get(url).then((result)=>{
if(result.status==200){
this.setState({
title_value:result.data.name,
Textarea_comment:result.data.description
})
}
})
}
}
handleSubmit = () => {
let {title_value,Textarea_comment}=this.state;
// if(mdContnet.length>10000){
// this.props.showNotification("内容超过10000个字");
// return
// }
//
if(this.props.modelid===undefined){
let url=`/osshackathon.json`;
axios.post(url,{
name:title_value,
description:Textarea_comment,
}
).then((response) => {
if(response.data.status===0){
this.props.getosshackathon()
this.props.hideeditSignupentry()
this.props.showNotification(`提交成功`);
}
}).catch((error) => {
console.log(error)
})
}else{
let url=`/osshackathon/${this.props.modelid}.json`
axios.put(url,{
name:title_value,
description:Textarea_comment,
}
).then((response) => {
if(response.data.status===0){
this.props.getosshackathon()
this.props.hideeditSignupentry()
this.props.showNotification(`提交成功`);
}
}).catch((error) => {
console.log(error)
})
}
}
changeTitle=(e)=>{
this.setState({
title_value:e.target.value,
title_num:e.target.value.length,
})
}
Textarea_comment=(e)=>{
this.setState({
Textarea_comment:e.target.value,
})
}
render() {
let {textareavaltype}=this.state;
// console.log(this.props.tabkey)
// console.log(this.props.Osshackathonmodeltype)
return (
<div>
<style>
{
`
@media (max-width: 2000px) {
.WordNumberTextarea{
height: 130px !important;
}
}
@media (max-width: 1350px) {
.HomeworkModal{
top:10px !important;
}
.WordNumberTextarea{
height: 80px !important;
}
}
@media (max-width: 1250px) {
.HomeworkModal{
top:0px !important;
}
.WordNumberTextarea{
height: 40px !important;
}
}
`
}
</style>
<Modal
keyboard={false}
className={"HomeworkModal"}
title={this.props.modelid===undefined?"新建项目":"编辑项目"}
visible={this.props.Osshackathonmodeltype}
closable={false}
footer={null}
destroyOnClose={true}
>
<div className={"pd015"}>
<style>
{
`
.pd015{
padding: 0px 15px 15px 15px;
}
.font{
font-size: 14px;
font-weight: 400;
color: rgba(5,16,26,1);
}
.newfont{
height: 16px;
font-size: 16px;
font-weight: 400;
color: rgba(5,16,26,1);
line-height: 16px;
margin-bottom: 5px;
}
.Osshackathonmodelinput .ant-input, .ant-input .ant-input-suffix{
background: #fff !important;
}
.Osshackathonmodelinput .ant-input-group-wrapper{
width:510px !important;
margin-left: 10px;
}
`
}
</style>
<div className="clearfix">
<p className={"font mt10 mb10 ml10"}>
名称
</p>
<Input placeholder="请输入项目名称"
value={this.state.title_value}
onInput={(e)=>this.changeTitle(e)}
className={"Osshackathonmodelinput"}
style={{"width": "100%"}} maxLength="60"
addonAfter={String(this.state.title_value===undefined?0:this.state.title_value.length)+"/60"}
/>
<p className={"font mt10 mb10 ml10"}>
描述
</p>
<WordNumberTextarea
placeholder={"请输入项目描述"}
onInput={(e)=>this.Textarea_comment(e)}
value={this.state.Textarea_comment}
maxlength={500}
/>
<li style={{height:"20px",lineHeight:"20px"}} className={textareavaltype===true?"color-red mt20 mb10":"none"}><span>评阅内容至少有一个不为空</span></li>
</div>
<div className={textareavaltype===false?"mt20 clearfix edu-txt-center":"clearfix edu-txt-center mt20"}>
<a className="task-btn color-white mr30" onClick={()=>this.props.hideeditSignupentry()}>取消</a>
<a className="task-btn task-btn-orange" onClick={()=>this.handleSubmit()}>确定</a>
</div>
</div>
</Modal>
</div>
)
}
}
export default Osshackathonmodel;

@ -26,6 +26,7 @@ import './leftView.css'
import CodeEvaluateMultiLevelAnswerUnlock from './CodeEvaluateMultiLevelAnswerUnlock'
import MUIDialogStyleUtil from '../component/MUIDialogStyleUtil'
import moment from 'moment';
// http://danilowoz.com/create-react-content-loader/
const MyLoader = () => (
<ContentLoader
@ -283,7 +284,9 @@ class LeftView extends Component {
}
.multiLevelAnswer .status{
color: #CDCDCD;
flex: 0 0 45px;
}
.multiLevelAnswer .lock-time{
margin-right: 15px;
}
.markdown-body ol, .markdown-body ul {
padding-left: 2.5em;
@ -292,13 +295,17 @@ class LeftView extends Component {
<div className="multiLevelAnswer">
{ unlockedAnswers && unlockedAnswers.map((item, index) => {
const {name, contents, view_time} = item;
return <div className="anwserSection">
<div className="df">
<div className="level">级别{index + 1}</div>
<div className="name">{item.name}</div>
<div className="status">已解锁</div>
<div className="name">{name}</div>
<div className="status">
<span className="lock-time">{view_time ? moment(view_time).format('YYYY-MM-DD HH:mm') : ''}</span>
已解锁
</div>
</div>
<div className="contents markdown-body" dangerouslySetInnerHTML={{__html: markdownToHTML(item.contents)}}>
<div className="contents markdown-body" dangerouslySetInnerHTML={{__html: markdownToHTML(contents)}}>
</div>
</div>
})}

@ -89,4 +89,35 @@
.rateRow .rc-rate-star-half .rc-rate-star-first, .rateRow .rc-rate-star-full .rc-rate-star-second {
color: #FFA800;
}
.tip-info-wrap{
background-color: #111C24;
padding: 20px 0px;
}
.tip-info-wrap .tip-info{
display: flex;
background: rgba(40, 47, 53, 1);
border: 1px solid rgba(112,112,112,1);
border-radius: 100px;
width: 375px;
height: 52px;
font-size: 12px;
align-items: center;
align-items: space-around;
margin: 0 auto;
padding: 0 20px;
}
.finish-wrap{
display: flex;
padding: 0 0px 0 20px;
margin-top: 10px;
}
.finish-wrap .finish-time{
flex: 1;
}
.finish-time .time-title{
color: #747A7F;
margin-right: 5px;
}
/*------------------------------- TaskList End */

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { CircularProgress } from 'material-ui/Progress';
import moment from 'moment';
import Rate from 'rc-rate';
import 'rc-rate/assets/index.css';
@ -21,7 +21,7 @@ class TaskList extends Component {
challenge.experience = challenge.get_experience
challenge.gold = challenge.get_gold
challenge.subject = challenge.name
const {finished_time, view_answer_time} = challenge;
const showExp = (challenge.experience > 0 && challenge.status === 2) ? '+' + challenge.experience : challenge.experience
const showGold = (challenge.gold > 0 && challenge.status === 2) ? '+' + challenge.gold : challenge.gold
return (
@ -70,6 +70,15 @@ class TaskList extends Component {
</span>
</div>
<div className="finish-wrap">
<p class="finish-time font-12">
<span class="time-title">完成时间</span>
{ finished_time ? moment(finished_time).format('YYYY-MM-DD HH:mm') : '--' }
</p>
<p class="finish-time font-12">
<span class="time-title">查看答案时间</span>
{ view_answer_time ? moment(view_answer_time).format('YYYY-MM-DD HH:mm') : '--' } </p>
</div>
{ shixun.status >= 2 && <div className="rateRow">
{/* 已完成、未评分 */}
{challenge.status === 2 && challenge.star === 0?
@ -103,8 +112,15 @@ class TaskList extends Component {
render() {
const { taskListLoading } = this.props;
return (
<div className="page--over">
<div className="col-width-3 -scroll" style={{height: '100%'}} id="all_task_index">
<div className="page--over" style={{ width: '420px'}}>
{/** 增加提示信息 */}
<div className="tip-info-wrap">
<p className="tip-info">
<span><span style={{ color: '#FFBD4C'}}>温馨提示: </span> </span>
</p>
</div>
<div className="col-width-3 -scroll" style={{height: 'calc( 100% - 100px )', width: '420px'}} id="all_task_index">
{ taskListLoading ?
<CircularProgress size={40} thickness={3} style={{ marginLeft: 'auto', marginRight: 'auto', marginTop: '40%', display: 'block' }}/> :
this.renderTasks()

@ -1233,8 +1233,8 @@ submittojoinclass=(value)=>{
{/*<li><Link to={`/interest`}>兴趣页</Link></li>*/}
<li className="bor-top-greyE">
{/*<a href={this.props.Headertop===undefined?"":this.props.Headertop.logout_url}>退出</a>*/}
{/*<a onClick={()=>this.educoderlogin()}>退出</a>*/}
{/*<a onClick={()=>this.educoderlogin()} >登录</a>*/}
<a onClick={()=>this.educoderloginysl()}>退出</a>
</li>

@ -184,7 +184,17 @@ class LoginRegisterComponent extends Component {
message: "提示",
description: messge,
onClick: () => {
console.log('Notification Clicked!');
console.log('Notification Clicked12312313123!');
},
});
}
openNotifications = (btn) => {
// type 1 成功提示绿色 2提醒颜色黄色 3错误提示红色
notification.open({
message: "提示",
description: btn,
onClick: () => {
},
});
}
@ -369,8 +379,23 @@ class LoginRegisterComponent extends Component {
})
return;
}
else {
} else if (response.data.message === "登录密码出错已达上限,账号已被锁定, 请10分钟后重新登录或找回密码") {
const messge = (
<div>
<p>
登录密码出错已达上限账号已被锁定
</p>
<p className="mt10">
请10分钟后重新登录或<a href={'/changepassword'} style={{
textDecoration: "underline",
color: "#4CACFF",
}}>找回密码</a>
</p>
</div>
)
this.openNotifications(messge);
return;
} else {
this.openNotification(response.data.message);
return;
}
@ -1012,7 +1037,9 @@ class LoginRegisterComponent extends Component {
name="username"
className={Phonenumberisnotco && Phonenumberisnotco !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"}
onBlur={(e) => this.inputOnBlur(e, 1)}
style={{marginTop: '30px', height: '38px'}}></Input>
style={{marginTop: '30px', height: '38px'}}
onPressEnter={() => this.postLogin()}
></Input>
{
Phonenumberisnotco && Phonenumberisnotco != "" ?
@ -1024,6 +1051,7 @@ class LoginRegisterComponent extends Component {
<Input type="password" name="password" id="password" value={this.state.password}
onChange={this.passwordonChange}
onPressEnter={() => this.postLogin()}
className={Phonenumberisnotcodmm && Phonenumberisnotcodmm !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"}
placeholder="密码"></Input>
{

@ -200,7 +200,7 @@ class InfosCourse extends Component{
.white-panel li.active {
border-radius: 24px;
border: 0px solid #4CACFF;
border: none !important;
color: #4CACFF;
}

@ -190,7 +190,7 @@ class InfosPackage extends Component{
}
.white-panel li.active {
border-radius: 24px;
border: 0px solid #4CACFF;
border: none !important;
color: #4CACFF;
}

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

Loading…
Cancel
Save