diff --git a/app/assets/javascripts/admins/courses/index.js b/app/assets/javascripts/admins/courses/index.js index 336d8c7c9..0e3473dff 100644 --- a/app/assets/javascripts/admins/courses/index.js +++ b/app/assets/javascripts/admins/courses/index.js @@ -26,6 +26,15 @@ $(document).on('turbolinks:load', function() { }); }); + // 清空 + searchForm.on('click', '.clear-btn', function () { + searchForm.find('select[name="status"]').val(''); + searchForm.find('.school-select').val('').trigger('change'); + searchForm.find('input[name="keyword"]').val(''); + searchForm.find('#homepage_show').attr('checked', false); + searchForm.find('input[type="submit"]').trigger('click'); + }); + // ************** 学校选择 ************* searchForm.find('.school-select').select2({ theme: 'bootstrap4', diff --git a/app/assets/javascripts/admins/laboratories/index.js b/app/assets/javascripts/admins/laboratories/index.js index ec559cb92..f0c557441 100644 --- a/app/assets/javascripts/admins/laboratories/index.js +++ b/app/assets/javascripts/admins/laboratories/index.js @@ -65,7 +65,7 @@ $(document).on('turbolinks:load', function() { }, matcher: matcherFunc }); - } + }; $.ajax({ url: '/api/schools/for_option.json', @@ -171,5 +171,19 @@ $(document).on('turbolinks:load', function() { data: json }) }); + + $(".laboratory-list-container").on("change", '.laboratory-sync-form', function () { + var s_id = $(this).attr("data-id"); + var s_value = $(this).val(); + var s_name = $(this).attr("name"); + var json = {}; + json[s_name] = s_value; + $.ajax({ + url: "/admins/laboratories/" + s_id, + type: "PUT", + dataType:'script', + data: json + }); + }); } }); \ No newline at end of file diff --git a/app/assets/javascripts/admins/laboratory_subjects/index.js b/app/assets/javascripts/admins/laboratory_subjects/index.js index 04e82bb2a..83473994d 100644 --- a/app/assets/javascripts/admins/laboratory_subjects/index.js +++ b/app/assets/javascripts/admins/laboratory_subjects/index.js @@ -107,7 +107,7 @@ $(document).on('turbolinks:load', function() { }, templateResult: function (item) { if(!item.id || item.id === '') return item.text; - var ele = '' + var ele = ''; ele += '' + item.name + ''; ele += ' -- ' + item.creator_name + ''; ele += ' -- ' + item.status_text+ ''; @@ -116,10 +116,9 @@ $(document).on('turbolinks:load', function() { return $(ele); }, templateSelection: function(item){ - if (item.id) { - } - var ele = '' + (item.name || item.text) + ' -- ' + item.creator_name + '' - return $(ele); + if(!item.id || item.id === '') return item.text; + var ele = '' + (item.name || item.text) + ' -- ' + item.creator_name + ''; + return $(ele); } }); diff --git a/app/assets/javascripts/admins/projects/index.js b/app/assets/javascripts/admins/projects/index.js new file mode 100644 index 000000000..534a065ca --- /dev/null +++ b/app/assets/javascripts/admins/projects/index.js @@ -0,0 +1,11 @@ +$(document).on('turbolinks:load', function () { + if ($('body.admins-projects-index-page').length > 0) { + var $form = $('.search-form'); + + // 清空 + $form.on('click', '.clear-btn', function () { + $form.find('input[name="search"]').val(''); + $form.find('input[type="submit"]').trigger('click'); + }); + } +}); diff --git a/app/assets/javascripts/admins/shixun_feedback_messages/index.js b/app/assets/javascripts/admins/shixun_feedback_messages/index.js index c0b32ba32..c25a6b744 100644 --- a/app/assets/javascripts/admins/shixun_feedback_messages/index.js +++ b/app/assets/javascripts/admins/shixun_feedback_messages/index.js @@ -1,12 +1,14 @@ $(document).on('turbolinks:load', function(){ if ($('body.admins-shixun-feedback-messages-index-page').length > 0) { + $(".content-img img").addClass("w-20").addClass("preview-image"); + var baseOptions = { autoclose: true, language: 'zh-CN', format: 'yyyy-mm-dd 00:00:00', startDate: '2017-04-01' - } + }; var defineDateRangeSelect = function(element){ var options = $.extend({inputs: $(element).find('.start-date, .end-date')}, baseOptions); @@ -14,9 +16,9 @@ $(document).on('turbolinks:load', function(){ $(element).find('.start-date').datepicker().on('changeDate', function(e){ $(element).find('.end-date').datepicker('setStartDate', e.date); - }) + }); }; defineDateRangeSelect('.grow-date-input-daterange'); } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/app/assets/javascripts/admins/shixun_modify_records/index.js b/app/assets/javascripts/admins/shixun_modify_records/index.js new file mode 100644 index 000000000..13b348b04 --- /dev/null +++ b/app/assets/javascripts/admins/shixun_modify_records/index.js @@ -0,0 +1,12 @@ +$(document).on('turbolinks:load', function () { + if ($('body.admins-shixun-modify-records-index-page').length > 0) { + var $form = $('.search-form'); + + // 清空 + $form.on('click', '.clear-btn', function () { + $form.find('select[name="date"]').val('weekly'); + $form.find('input[name="user_name"]').val(''); + $form.find('input[type="submit"]').trigger('click'); + }); + } +}); diff --git a/app/assets/stylesheets/admins/diff.scss b/app/assets/stylesheets/admins/diff.scss new file mode 100644 index 000000000..34944ae4c --- /dev/null +++ b/app/assets/stylesheets/admins/diff.scss @@ -0,0 +1,14 @@ +.diff{overflow:auto;} +.diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0 1rem;display:table;width:100%;} +.diff del, .diff ins{display:block;text-decoration:none;} +.diff li{padding:0; display:table-row;margin: 0;height:1em;} +.diff li.ins{background:#dfd; color:#080} +.diff li.del{background:#fee; color:#b00} +.diff li:hover{background:#ffc} + +/* try 'whitespace:pre;' if you don't want lines to wrap */ +.diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;} +.diff del strong{font-weight:normal;background:#fcc;} +.diff ins strong{font-weight:normal;background:#9f9;} +.diff li.diff-comment { display: none; } +.diff li.diff-block-info { background: none repeat scroll 0 0 gray; } \ No newline at end of file diff --git a/app/assets/stylesheets/admins/shixun_feedback_messages.scss b/app/assets/stylesheets/admins/shixun_feedback_messages.scss new file mode 100644 index 000000000..92b92c01c --- /dev/null +++ b/app/assets/stylesheets/admins/shixun_feedback_messages.scss @@ -0,0 +1,7 @@ +.admins-shixun-feedback-messages-index-page { + .content-img { + img { + height: 60px; + } + } +} \ No newline at end of file diff --git a/app/constraint/admin_constraint.rb b/app/constraint/admin_constraint.rb index 3ddf9a11e..2cf5649a7 100644 --- a/app/constraint/admin_constraint.rb +++ b/app/constraint/admin_constraint.rb @@ -1,7 +1,8 @@ class AdminConstraint def matches?(request) - return false unless request.session[:user_id] - user = User.find request.session[:user_id] + laboratory = Laboratory.first + return false unless request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"] + user = User.find request.session[:"#{laboratory.try(:identifier).split('.').first}_user_id"] user && user.admin? end end \ No newline at end of file diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index f03cbdef8..23240fa75 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -38,6 +38,8 @@ class AccountsController < ApplicationController return normal_status(-2, "验证码已失效") if !verifi_code&.effective? end + return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD + code = generate_identifier User, 8, pre login = pre + code @user = User.new(admin: false, login: login, mail: email, phone: phone, type: "User") @@ -114,6 +116,7 @@ class AccountsController < ApplicationController end return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip return normal_status(-2, "验证码已失效") if !verifi_code&.effective? + return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:new_password] =~ CustomRegexp::PASSWORD user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation] ActiveRecord::Base.transaction do @@ -123,7 +126,7 @@ class AccountsController < ApplicationController sucess_status rescue Exception => e uid_logger_error(e.message) - tip_exception("密码重置失败") + tip_exception(e.message) end end diff --git a/app/controllers/admins/courses_controller.rb b/app/controllers/admins/courses_controller.rb index 80f48fab2..518054e12 100644 --- a/app/controllers/admins/courses_controller.rb +++ b/app/controllers/admins/courses_controller.rb @@ -29,9 +29,7 @@ class Admins::CoursesController < Admins::BaseController end def update - if @course.update_attributes(setting_params) - render_ok - else + unless @course.update_attributes!(setting_params) redirect_to admins_courses_path flash[:danger] = "更新失败" end diff --git a/app/controllers/admins/daily_school_statistics_controller.rb b/app/controllers/admins/daily_school_statistics_controller.rb index eb9c75fbc..f0911f239 100644 --- a/app/controllers/admins/daily_school_statistics_controller.rb +++ b/app/controllers/admins/daily_school_statistics_controller.rb @@ -6,6 +6,7 @@ class Admins::DailySchoolStatisticsController < Admins::BaseController total_count, statistics = Admins::SchoolDailyStatisticService.call(params) @statistics = paginate statistics, total_count: total_count + @params_page = params[:page] || 1 respond_to do |format| format.html { load_statistic_total } diff --git a/app/controllers/admins/laboratories_controller.rb b/app/controllers/admins/laboratories_controller.rb index 6bd068a66..9f6d23c9b 100644 --- a/app/controllers/admins/laboratories_controller.rb +++ b/app/controllers/admins/laboratories_controller.rb @@ -61,6 +61,14 @@ class Admins::LaboratoriesController < Admins::BaseController @laboratory = current_laboratory end + def update + @laboratory = current_laboratory + unless @laboratory.update_attributes!(setting_params) + redirect_to admins_laboratories_path + flash[:danger] = "更新失败" + end + end + private def current_laboratory @@ -70,4 +78,8 @@ class Admins::LaboratoriesController < Admins::BaseController def create_params params.permit(:school_id) end + + def setting_params + params.permit(:sync_course, :sync_subject, :sync_shixun) + end end \ No newline at end of file diff --git a/app/controllers/admins/laboratory_settings_controller.rb b/app/controllers/admins/laboratory_settings_controller.rb index a65b13f59..283afc175 100644 --- a/app/controllers/admins/laboratory_settings_controller.rb +++ b/app/controllers/admins/laboratory_settings_controller.rb @@ -16,7 +16,7 @@ class Admins::LaboratorySettingsController < Admins::BaseController def form_params params.permit(:identifier, :name, - :nav_logo, :login_logo, :tab_logo, + :nav_logo, :login_logo, :tab_logo, :oj_banner, :subject_banner, :course_banner, :competition_banner, :moop_cases_banner, :footer, navbar: %i[name link hidden]) end diff --git a/app/controllers/admins/myshixuns_controller.rb b/app/controllers/admins/myshixuns_controller.rb index f70a64554..adc34e95e 100644 --- a/app/controllers/admins/myshixuns_controller.rb +++ b/app/controllers/admins/myshixuns_controller.rb @@ -6,6 +6,7 @@ class Admins::MyshixunsController < Admins::BaseController myshixuns = Admins::MyshixunQuery.call(params) @myshixuns = paginate myshixuns.includes(:last_executable_task, :last_task, shixun: :user, user: { user_extension: :school }) + @params_page = params[:page] || 1 myshixun_ids = @myshixuns.map(&:id) @finish_game_count = Game.where(myshixun_id: myshixun_ids, status: 2).group(:myshixun_id).count diff --git a/app/controllers/admins/school_statistics_controller.rb b/app/controllers/admins/school_statistics_controller.rb index fdd10c70f..5133cc997 100644 --- a/app/controllers/admins/school_statistics_controller.rb +++ b/app/controllers/admins/school_statistics_controller.rb @@ -10,6 +10,7 @@ class Admins::SchoolStatisticsController < Admins::BaseController @grow_summary = service.grow_summary total_count, statistics = service.call + @params_page = params[:page] || 1 @statistics = paginate statistics, total_count: total_count end diff --git a/app/controllers/admins/shixun_modify_records_controller.rb b/app/controllers/admins/shixun_modify_records_controller.rb new file mode 100644 index 000000000..43d9a4a16 --- /dev/null +++ b/app/controllers/admins/shixun_modify_records_controller.rb @@ -0,0 +1,9 @@ +class Admins::ShixunModifyRecordsController < Admins::BaseController + + def index + records = Admins::ShixunModifyRecordQuery.call(params) + + @records = paginate records.includes(:diff_record_content) + end + +end diff --git a/app/controllers/admins/shixun_settings_controller.rb b/app/controllers/admins/shixun_settings_controller.rb index bd54018cd..6dbbc077a 100644 --- a/app/controllers/admins/shixun_settings_controller.rb +++ b/app/controllers/admins/shixun_settings_controller.rb @@ -15,7 +15,8 @@ class Admins::ShixunSettingsController < Admins::BaseController hidden: params[:hidden].present? ? params[:hidden] : false, homepage_show: params[:homepage_show].present? ? params[:homepage_show] : false, task_pass: params[:task_pass].present? ? params[:task_pass] : false, - code_hidden: params[:code_hidden].present? ? params[:code_hidden] : false + code_hidden: params[:code_hidden].present? ? params[:code_hidden] : false, + vip: params[:vip].present? ? params[:vip] : false } @shixuns_type_check = MirrorRepository.pluck(:type_name,:id) @@ -126,6 +127,6 @@ class Admins::ShixunSettingsController < Admins::BaseController end def setting_params - params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,:code_hidden,:page_no, :id,tag_repertoires:[]) + params.permit(:use_scope,:excute_time,:close,:status,:can_copy,:webssh,:hidden,:homepage_show,:task_pass,:code_hidden,:vip,:page_no,:id,tag_repertoires:[]) end end diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index 0c9c49621..f58fe12bf 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -18,9 +18,9 @@ class AttachmentsController < ApplicationController pdf_attachment = params[:disposition] || "attachment" if pdf_attachment == "inline" - send_file absolute_path(local_path(@file)),filename: @file.filename, disposition: 'inline',type: 'application/pdf' + send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf' else - send_file(absolute_path(local_path(@file)), filename: @file.filename,stream:false, type: @file.content_type.presence || 'application/octet-stream') + send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream') end update_downloads(@file) end @@ -68,6 +68,9 @@ class AttachmentsController < ApplicationController @attachment.author_id = current_user.id @attachment.disk_directory = month_folder @attachment.cloud_url = remote_path + @attachment.container_id = conversion_container_id(params[:container_id], params[:container_type]) + @attachment.container_type = params[:container_type] + @attachment.attachtype = params[:attachtype] @attachment.save! else logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}" @@ -91,6 +94,22 @@ class AttachmentsController < ApplicationController end end + # 多文件删除 + def destroy_files + files = Attachment.where(id: params[:id]) + begin + files.each do |file| + file_path = absolute_path(local_path(file)) + file.destroy! + delete_file(file_path) + end + render_ok + rescue => e + uid_logger_error(e.message) + tip_exception(e.message) + end + end + private def find_file @file = @@ -196,4 +215,12 @@ class AttachmentsController < ApplicationController end end end + + def conversion_container_id id, type + if id.is_a?(String) && type == 'Shixun' + Shixun.find_by_identifier(id).id + else + id + end + end end diff --git a/app/controllers/competitions/competitions_controller.rb b/app/controllers/competitions/competitions_controller.rb index 72f53d1e2..5719f8f8b 100644 --- a/app/controllers/competitions/competitions_controller.rb +++ b/app/controllers/competitions/competitions_controller.rb @@ -125,7 +125,7 @@ class Competitions::CompetitionsController < Competitions::BaseController end @all_records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i}) - .select("competition_teams.*, score, cost_time").order("score desc, cost_time desc") + .select("competition_teams.*, score, cost_time").order("score desc, cost_time asc") current_team_ids = @competition.team_members.where(user_id: current_user.id).pluck(:competition_team_id).uniq @user_ranks = @all_records.select{|com_team| current_team_ids.include?(com_team.id)} @@ -213,7 +213,7 @@ class Competitions::CompetitionsController < Competitions::BaseController if personal row_cells_column << record_user.real_name row_cells_column << record_user.school_name - row_cells_column << record_user.student_id.present? ? (record_user.student_id.to_s + "\t") : "--" + row_cells_column << (record_user.student_id.present? ? (record_user.student_id.to_s + "\t") : "--") else row_cells_column << record.name row_cells_column << record.teachers_name diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index de24f7a8e..b08ba2dbd 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -1299,8 +1299,10 @@ class CoursesController < ApplicationController begin @all_members = @course.students search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索 - group_id = params[:group_id] #分班的班级id - @all_members = @all_members.where(course_group_id: group_id.map(&:to_i)) unless group_id.blank? + if params[:group_id].present? + group_ids = params[:group_id].is_a?(String) ? [params[:group_id].to_i] : params[:group_id].map(&:to_i) + @all_members = @all_members.where(course_group_id: group_ids) + end unless search.blank? @all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{search}%","%#{search}%") end diff --git a/app/controllers/exercise_answers_controller.rb b/app/controllers/exercise_answers_controller.rb index 4b94676e5..238aaca17 100644 --- a/app/controllers/exercise_answers_controller.rb +++ b/app/controllers/exercise_answers_controller.rb @@ -4,85 +4,83 @@ class ExerciseAnswersController < ApplicationController include ExercisesHelper def create #每一次答案的点击,请求一次,实训题不在这里回答 - ActiveRecord::Base.transaction do - begin - q_type = @exercise_question.question_type #试卷的类型 - choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : "" - answer_text = params[:answer_text].present? ? params[:answer_text].strip : "" #为字符串 - if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank? - normal_status(-1,"请选择序号") - else - ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案 - if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题 - if ea.exists? - ea.first.update_attribute(:exercise_choice_id,choice_id ) - else - answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => choice_id, - :answer_text => "" - } - ex_a = ExerciseAnswer.new(answer_option) - ex_a.save! - end - elsif q_type == Exercise::MULTIPLE #多选题的 - choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : [] - - ea_ids = ea.pluck(:exercise_choice_id) - common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id - new_ids = choice_ids - common_answer_ids # 新增的id - old_ids = ea_ids - common_answer_ids #没有选择的,则删掉 - if new_ids.size > 0 - new_ids.each do |e| - answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => e, - :answer_text => "" - } - ex_a = ExerciseAnswer.new(answer_option) - ex_a.save! - end - end - if old_ids.size > 0 - ea_answer = ea.search_answer_users("exercise_choice_id",old_ids) - ea_answer.destroy_all - end - elsif q_type == Exercise::COMPLETION #填空题 - answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => choice_id, - :answer_text => answer_text - } - ea_answer = ea.search_answer_users("exercise_choice_id",choice_id) - if ea.present? && ea_answer.present? - ea_answer.update(answer_option) - else - ex_new = ExerciseAnswer.new(answer_option) - ex_new.save! - end - elsif q_type == Exercise::SUBJECTIVE #简答题 + begin + q_type = @exercise_question.question_type #试卷的类型 + choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : "" + answer_text = params[:answer_text].present? ? params[:answer_text].strip : "" #为字符串 + if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank? + normal_status(-1,"请选择序号") + else + ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案 + if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题 + if ea.exists? + ea.first.update_attribute(:exercise_choice_id,choice_id ) + else answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id + :user_id => current_user.id, + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => choice_id, + :answer_text => "" } - if ea.present? #已经回答了的, - ea.first.update_attribute("answer_text",answer_text) - else - answer_option.merge!(answer_text:answer_text) + ex_a = ExerciseAnswer.new(answer_option) + ex_a.save! + end + elsif q_type == Exercise::MULTIPLE #多选题的 + choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : [] + + ea_ids = ea.pluck(:exercise_choice_id) + common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id + new_ids = (choice_ids - common_answer_ids).uniq # 新增的id + old_ids = (ea_ids - common_answer_ids).uniq #没有选择的,则删掉 + if new_ids.size > 0 + new_ids.each do |e| + answer_option = { + :user_id => current_user.id, + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => e, + :answer_text => "" + } ex_a = ExerciseAnswer.new(answer_option) ex_a.save! end end - normal_status(0,"回答成功") + if old_ids.size > 0 + ea_answer = ea.search_answer_users("exercise_choice_id",old_ids) + ea_answer.destroy_all + end + elsif q_type == Exercise::COMPLETION #填空题 + answer_option = { + :user_id => current_user.id, + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => choice_id, + :answer_text => answer_text + } + ea_answer = ea.search_answer_users("exercise_choice_id",choice_id) + if ea.present? && ea_answer.present? + ea_answer.update(answer_option) + else + ex_new = ExerciseAnswer.new(answer_option) + ex_new.save! + end + elsif q_type == Exercise::SUBJECTIVE #简答题 + answer_option = { + :user_id => current_user.id, + :exercise_question_id => @exercise_question.id + } + if ea.present? #已经回答了的, + ea.first.update_attribute("answer_text",answer_text) + else + answer_option.merge!(answer_text:answer_text) + ex_a = ExerciseAnswer.new(answer_option) + ex_a.save! + end end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("页面调用失败!") - raise ActiveRecord::Rollback + normal_status(0,"回答成功") end + rescue Exception => e + uid_logger_error(e.message) + tip_exception("页面调用失败!") + raise ActiveRecord::Rollback end end diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index 0299fdf7d..25e0de44a 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -47,26 +47,26 @@ class FilesController < ApplicationController def bulk_publish return normal_status(403, "您没有权限进行操作") if current_user.course_identity(@course) >= 5 - tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0 + # tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0 attachments = @course.attachments.by_ids(@attachment_ids) ActiveRecord::Base.transaction do # 有分班设置时 - if @course.course_group_module? && @course.course_groups_count != 0 && params[:group_ids] - group_ids = params[:group_ids]&.reject(&:blank?) - charge_group_ids = @course.charge_group_ids(current_user) - publish_groups = charge_group_ids & group_ids if group_ids - - attachments.each do |atta| - if atta.published? && !atta.unified_setting || !atta.published? - create_atta_group_settings atta - atta.update_all(unified_setting: 0) if atta.unified_setting - none_publish_settings = atta.attachment_group_settings.where(course_group_id: publish_groups).none_published - none_publish_settings.update_all(publish_time: Time.now) - end - end - end + # if @course.course_group_module? && @course.course_groups_count != 0 && params[:group_ids] + # group_ids = params[:group_ids]&.reject(&:blank?) + # charge_group_ids = @course.charge_group_ids(current_user) + # publish_groups = charge_group_ids & group_ids if group_ids + # + # attachments.each do |atta| + # if atta.published? && !atta.unified_setting || !atta.published? + # create_atta_group_settings atta + # atta.update_attributes!(unified_setting: 0) if atta.unified_setting + # none_publish_settings = atta.attachment_group_settings.where(course_group_id: publish_groups).none_published + # none_publish_settings.update_all(publish_time: Time.now) + # end + # end + # end # 未发布的资源更新状态 attachments.where(is_publish: 0).update_all(is_publish: 1, publish_time: Time.now) @@ -140,7 +140,7 @@ class FilesController < ApplicationController def public_with_course_and_project @attachments = Attachment.publiced.simple_columns .contains_course_and_project - .includes(:author => :user_extension) + .includes(:container, author: :user_extension) .by_filename_or_user_name(params[:search]) .ordered(sort: 0, sort_type: 'created_on') @@ -361,15 +361,16 @@ class FilesController < ApplicationController def publish_params tip_exception("缺少发布参数") if params[:delay_publish].blank? @unified_setting = 1 - if params[:delay_publish].to_i == 1 && @course.course_group_module? && @course.course_groups_count != 0 - tip_exception("分班发布设置不能为空") if params[:group_settings].blank? - min_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).min - max_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).max - tip_exception("分班发布设置不能为空") if min_publish_time.blank? - - # 分班设置中的时间一样且包含所有分班 则按统一设置处理,否则是非统一设置 - @unified_setting = 0 unless min_publish_time == max_publish_time && params[:group_settings].pluck(:group_id).flatten.sort == @course.course_groups.pluck(:id).sort - elsif params[:delay_publish].to_i == 1 + # if params[:delay_publish].to_i == 1 && @course.course_group_module? && @course.course_groups_count != 0 + # tip_exception("分班发布设置不能为空") if params[:group_settings].blank? + # min_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).min + # max_publish_time = params[:group_settings].pluck(:publish_time).reject(&:blank?).max + # tip_exception("分班发布设置不能为空") if min_publish_time.blank? + # + # # 分班设置中的时间一样且包含所有分班 则按统一设置处理,否则是非统一设置 + # @unified_setting = 0 unless min_publish_time == max_publish_time && params[:group_settings].pluck(:group_id).flatten.sort == @course.course_groups.pluck(:id).sort + # els + if params[:delay_publish].to_i == 1 tip_exception("缺少延期发布的时间参数") if params[:publish_time].blank? min_publish_time = params[:publish_time] end diff --git a/app/controllers/hack_user_lastest_codes_controller.rb b/app/controllers/hack_user_lastest_codes_controller.rb index 37102a166..b7ec6fb8e 100644 --- a/app/controllers/hack_user_lastest_codes_controller.rb +++ b/app/controllers/hack_user_lastest_codes_controller.rb @@ -1,13 +1,14 @@ class HackUserLastestCodesController < ApplicationController before_action :require_login, except: [:listen_result] - before_action :find_my_hack, only: [:show, :code_debug, :code_submit, :update_code, + before_action :find_my_hack, only: [:show, :code_debug, :code_submit, :update_code, :sync_code, :listen_result, :result, :submit_records, :restore_initial_code] before_action :update_user_hack_status, only: [:code_debug, :code_submit] - before_action :require_auth_identity, only: [:update_code, :restore_initial_code] + before_action :require_auth_identity, only: [:update_code, :restore_initial_code, :sync_code] before_action :require_manager_identity, only: [:update_code] def show @my_hack.update_attribute(:submit_status, 0) if @my_hack.submit_status == 1 + @modify = @my_hack.modify_time.to_i < @hack.hack_codes.first.modify_time.to_i end def update_code @@ -15,10 +16,14 @@ class HackUserLastestCodesController < ApplicationController render_ok end - # 回复初始代码 + # 恢复初始代码 def restore_initial_code @my_hack.update_attribute(:code, @hack.code) - render_ok + end + + # 同步代码 + def sync_code + @my_hack.update_attributes(code: @hack.code, modify_time: @hack.modify_time) end # 调试代码 @@ -55,12 +60,15 @@ class HackUserLastestCodesController < ApplicationController end # 提交记录 - def submit_records;end + def submit_records + @records = @my_hack.hack_user_codes.created_order + end # 提交记录详情 def record_detail @hack_user = HackUserCode.find params[:id] + @my_hack = @hack_user.hack_user_lastest_code end # 接收中间件返回结果接口 diff --git a/app/controllers/hacks_controller.rb b/app/controllers/hacks_controller.rb index 993cba4e6..657ad0f2a 100644 --- a/app/controllers/hacks_controller.rb +++ b/app/controllers/hacks_controller.rb @@ -1,8 +1,8 @@ class HacksController < ApplicationController before_action :require_login, except: [:index] - before_action :find_hack, only: [:edit, :update, :publish, :start, :update_set, :delete_set] - before_action :require_teacher_identity, only: [:create, :update_set] - before_action :require_auth_identity, only: [:update, :edit, :publish, :update_set, :delete_set] + before_action :find_hack, only: [:edit, :update, :publish, :start, :update_set, :delete_set, :destroy] + before_action :require_teacher_identity, only: [:create] + before_action :require_auth_identity, only: [:update, :edit, :publish, :update_set, :delete_set, :destroy] # 开启编程,如果第一次开启,创建一条记录,如果已经开启过的话,直接返回标识即可 @@ -15,7 +15,7 @@ class HacksController < ApplicationController user_hack.identifier else user_identifier = generate_identifier HackUserLastestCode, 12 - user_code = {user_id: current_user.id, code: @hack.code, + user_code = {user_id: current_user.id, code: @hack.code, modify_time: Time.now, identifier: user_identifier, language: @hack.language} @hack.hack_user_lastest_codes.create!(user_code) user_identifier @@ -47,10 +47,10 @@ class HacksController < ApplicationController hack.identifier = generate_identifier Hack, 8 hack.save! # 创建测试集与代码 - logger.info("hack_sets_params:#{hack_sets_params}") - logger.info("hack_code_params:#{hack_code_params}") hack.hack_sets.create!(hack_sets_params) - hack.hack_codes.create!(hack_code_params) + hack_codes = hack.hack_codes.new(hack_code_params) + hack_codes.modify_time = Time.now + hack_codes.save! end render_ok({identifier: hack.identifier}) rescue Exception => e @@ -69,7 +69,8 @@ class HacksController < ApplicationController # 新建 @hack.hack_sets.create!(hack_sets_params) # 更新代码 - @hack.hack_codes.create!(hack_code_params) + code_params = params[:hack_codes][:code] != @hack.code ? hack_code_params.merge(modify_time: Time.now) : hack_code_params + @hack.hack_codes.first.update_attributes!(code_params) end render_ok rescue Exception => e @@ -109,6 +110,13 @@ class HacksController < ApplicationController def edit;end + def new;end + + def destroy + @hack.destroy + render_ok + end + private # 实名认证老师,管理员与运营人员权限 def require_teacher_identity @@ -199,7 +207,7 @@ class HacksController < ApplicationController end def start_hack_auth - return true if @hack == 1 + return true if @hack.status == 1 require_auth_identity end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index e31c77499..d0b8d67d9 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -20,8 +20,8 @@ class HomeController < ApplicationController 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 }) + shixuns = shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { homepage: true, laboratory_id: current_laboratory.id}) + subjects = subjects.joins(:laboratory_subjects).where(laboratory_subjects: { homepage: true, laboratory_id: current_laboratory.id}) end @shixuns = shixuns.includes(:tag_repertoires, :challenges).limit(8) diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb index a94eed83f..e11fefea1 100644 --- a/app/controllers/homework_commons_controller.rb +++ b/app/controllers/homework_commons_controller.rb @@ -294,7 +294,7 @@ class HomeworkCommonsController < ApplicationController HomeworksService.new.update_myshixun_work_score work, myshixun, games, @homework, challenge_settings normal_status("更新成功") else - normal_status("还开启挑战,暂不能更新成绩") + normal_status("还未开启挑战,暂不能更新成绩") end rescue Exception => e uid_logger(e.message) @@ -453,7 +453,9 @@ class HomeworkCommonsController < ApplicationController # 课堂结束后不能再更新 unless @course.is_end + UpdateHomeworkPublishSettingService.call(@homework, publish_params) # 作业未发布时,unified_setting参数不能为空 +=begin if @homework.publish_time.nil? || @homework.publish_time > Time.now tip_exception("缺少统一设置的参数") if params[:unified_setting].nil? if params[:unified_setting] || @course.course_groups_count == 0 @@ -549,6 +551,7 @@ class HomeworkCommonsController < ApplicationController @homework.end_time = @homework.max_group_end_time end end +=end # 补交设置 tip_exception("缺少allow_late参数") if params[:allow_late].nil? @@ -582,8 +585,8 @@ class HomeworkCommonsController < ApplicationController tip_exception("缺少answer_open_evaluation参数") if params[:answer_open_evaluation].nil? tip_exception("缺少work_efficiency参数") if params[:work_efficiency].nil? tip_exception("缺少eff_score参数") if params[:work_efficiency] && params[:eff_score].blank? - tip_exception("效率分不能小于等于0") if params[:eff_score] && params[:eff_score].to_f <= 0 - tip_exception("效率分不能大于总分值") if params[:eff_score] && params[:eff_score].to_f.round(2) > params[:total_score].to_f.round(2) + tip_exception("效率分不能小于等于0") if params[:work_efficiency] && params[:eff_score] && params[:eff_score].to_f <= 0 + tip_exception("效率分不能大于总分值") if params[:work_efficiency] && params[:eff_score] && params[:eff_score].to_f.round(2) > params[:total_score].to_f.round(2) tip_exception("缺少shixun_evaluation参数") if params[:shixun_evaluation].blank? tip_exception("缺少challenge_settings参数") if params[:challenge_settings].blank? # tip_exception("缺少challenge_id参数") if params[:challenge_settings][:challenge_id].blank? @@ -591,6 +594,10 @@ class HomeworkCommonsController < ApplicationController # tip_exception("challenge_id参数的长度与challenge_score参数的长度不匹配") if # params[:challenge_settings][:challenge_score].length != params[:challenge_settings][:challenge_id].length + sum_challenge_score = params[:challenge_settings].pluck(:challenge_score).reject(&:blank?).map{|score| score.to_f}.sum + total_score = params[:work_efficiency] ? (params[:eff_score].to_f + sum_challenge_score) : sum_challenge_score + tip_exception("分值之和必须等于总分值:#{params[:total_score]}分") if params[:total_score].to_f.round(2) != total_score.to_f.round(2) + current_eff_score = @homework.eff_score.to_f.round(2) @homework.total_score = params[:total_score] @homework.work_efficiency = params[:work_efficiency] @@ -631,7 +638,7 @@ class HomeworkCommonsController < ApplicationController @homework.save! if score_change && @homework.end_or_late_none_group - UpdateShixunWorkScoreJob.perform_now(@homework.id) + UpdateShixunWorkScoreJob.perform_later(@homework.id) elsif update_eff_score && (@homework.end_or_late_none_group || @homework.max_efficiency > 0) # 更新所有学生的效率分(作业允许补交且补交已截止 或者 作业不允许补交且提交已截止 或者作业已计算过效率分) HomeworksService.new.update_student_eff_score HomeworkCommon.find_by(id: @homework.id) @@ -822,12 +829,16 @@ class HomeworkCommonsController < ApplicationController end end - - HomeworkCommonPushNotifyJob.perform_later(@homework.id, publish_group_ids) if send_tiding normal_status(0, "更新成功") else tip_exception("课堂已结束不能再更新") end + # rescue ActiveRecord::RecordInvalid + # render_error("保存失败") + # rescue ApplicationService::Error => ex + # uid_logger(ex.message) + # render_error(ex.message) + # raise ActiveRecord::Rollback rescue Exception => e uid_logger(e.backtrace) tip_exception(e.message) @@ -1097,7 +1108,7 @@ class HomeworkCommonsController < ApplicationController else homework.unified_setting = false # 创建作业分班设置:homework_group_setting - create_homework_group_settings(homework) + homework.create_homework_group_settings # 选中的分班设置的发布时间改为当前时间,截止时间改为传的截止时间参数 if params[:detail] @@ -1133,7 +1144,7 @@ class HomeworkCommonsController < ApplicationController # 发消息 HomeworkCommonPushNotifyJob.perform_later(homework.id, tiding_group_ids) else - create_homework_group_settings(homework) + homework.create_homework_group_settings none_publish_settings = homework.homework_group_settings.where(course_group_id: publish_groups).none_published if params[:detail] @@ -1207,7 +1218,7 @@ class HomeworkCommonsController < ApplicationController # 分组设置 if !params[:group_ids].blank? # 确保之前是统一设置或者有新创建的分班的数据一致性 - create_homework_group_settings(homework) + homework.create_homework_group_settings homework.unified_setting = false if homework.unified_setting && end_groups.length != @course.course_groups_count @@ -1578,15 +1589,6 @@ class HomeworkCommonsController < ApplicationController end - def create_homework_group_settings homework - if homework.homework_group_settings.size != @course.course_groups.size - @course.course_groups.where.not(id: homework.homework_group_settings.pluck(:course_group_id)).each do |group| - homework.homework_group_settings << HomeworkGroupSetting.new(course_group_id: group.id, course_id: @course.id, - publish_time: homework.publish_time, end_time: homework.end_time) - end - end - end - def get_new_code_reviews_result homework if homework.code_reviews_new_results? # 获取最新的查询id @@ -1649,4 +1651,8 @@ class HomeworkCommonsController < ApplicationController homework_bank end + def publish_params + params.permit(:unified_setting, :publish_time, :end_time, group_settings: [:publish_time, :end_time, group_id: []]) + end + end diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb index 4b2e3f54f..b5c8af1f3 100644 --- a/app/controllers/myshixuns_controller.rb +++ b/app/controllers/myshixuns_controller.rb @@ -216,7 +216,8 @@ class MyshixunsController < ApplicationController begin shixun_tomcat = edu_setting('tomcat_webssh') uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo" - params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), + # 由于中间层采用混合云的方式,因为local参数表示在有文件生成的实训是在本地生成,还是在其他云端生成评测文件 + params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), local: @myshixun.shixun.show_type != -1, containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))} res = uri_post uri, params if res && res['code'].to_i != 0 diff --git a/app/controllers/poll_votes_controller.rb b/app/controllers/poll_votes_controller.rb index 4a15ae301..17223a955 100644 --- a/app/controllers/poll_votes_controller.rb +++ b/app/controllers/poll_votes_controller.rb @@ -6,119 +6,117 @@ class PollVotesController < ApplicationController def create #每一次答案的点击,请求一次 - ActiveRecord::Base.transaction do - begin - question_votes = @poll_question.poll_votes - question_type = @poll_question.question_type - question_answer_id = params[:poll_answer_id] ? params[:poll_answer_id] : nil #该答案的id - question_answer_text = params[:vote_text].present? ? params[:vote_text] : nil #其他选项的内容 - user_votes = question_votes.find_current_vote("user_id",current_user.id) #当前用户的答案,可能有多个 - # 当前用户的当前答案,如果已存在,当再次点击的时候,取消答案,即删除该答案 - current_vote_text = nil + begin + question_votes = @poll_question.poll_votes + question_type = @poll_question.question_type + question_answer_id = params[:poll_answer_id] ? params[:poll_answer_id] : -1 #该答案的id + question_answer_text = params[:vote_text].present? ? params[:vote_text] : nil #其他选项的内容 + user_votes = question_votes.find_current_vote("user_id",current_user.id) #当前用户的答案,可能有多个 + # 当前用户的当前答案,如果已存在,当再次点击的时候,取消答案,即删除该答案 + current_vote_text = nil - # if user_votes.find_vote_text.present? - # current_vote_text = user_votes.find_vote_text.first - # end + # if user_votes.find_vote_text.present? + # current_vote_text = user_votes.find_vote_text.first + # end - vote_answer_params = { - :user_id => current_user.id, - :poll_question_id => @poll_question.id, - :poll_answer_id => question_answer_id, - :vote_text => question_answer_text - } - #begin - if question_type == 1 - if user_votes.present? #用户曾经回答过的,答案选择不一样,否则新建 - current_user_answer = user_votes.first - if current_user_answer&.poll_answer_id != question_answer_id #如果说更换了答案,则以前的答案删除,并新建记录 - current_user_answer.destroy - PollVote.create(vote_answer_params) - else + vote_answer_params = { + :user_id => current_user.id, + :poll_question_id => @poll_question.id, + :poll_answer_id => question_answer_id, + :vote_text => question_answer_text + } + #begin + if question_type == 1 + if user_votes.present? #用户曾经回答过的,答案选择不一样,否则新建 + current_user_answer = user_votes.first + if current_user_answer&.poll_answer_id != question_answer_id #如果说更换了答案,则以前的答案删除,并新建记录 + current_user_answer.destroy + PollVote.create(vote_answer_params) + else - if question_answer_text.present? - current_user_answer.update_attribute("vote_text", question_answer_text) - end + if question_answer_text.present? + current_user_answer.update_attribute("vote_text", question_answer_text) end - else - PollVote.create(vote_answer_params) end - elsif question_type == 2 #多选题的话,答案应该是1个以上 - question_answer_ids = params[:poll_answer_id] ? params[:poll_answer_id] : [] #该答案的id - if question_answer_ids.present? - if question_answer_text.present? #有文字输入,但是不存在其他选项的 - ques_vote_id = question_answer_ids.map(&:to_i).max - if user_votes.find_vote_text.present? - current_vote_text = user_votes.find_vote_text.first - current_vote_text.update_attribute("vote_text", question_answer_text) - else - answer_option = { - :user_id => current_user.id, - :poll_question_id => @poll_question.id, - :poll_answer_id => ques_vote_id, - :vote_text => question_answer_text - } - PollVote.create(answer_option) - end - # if current_vote_text.present? #已有其他输入文字的选项 - # current_vote_text.update_attribute("vote_text", question_answer_text) - # else - # - # end + else + PollVote.create(vote_answer_params) + end + elsif question_type == 2 #多选题的话,答案应该是1个以上 + question_answer_ids = params[:poll_answer_id] ? params[:poll_answer_id] : [] #该答案的id + if question_answer_ids.present? + if question_answer_text.present? #有文字输入,但是不存在其他选项的 + ques_vote_id = question_answer_ids.map(&:to_i).max + if user_votes.find_vote_text.present? + current_vote_text = user_votes.find_vote_text.first + current_vote_text.update_attribute("vote_text", question_answer_text) + else + answer_option = { + :user_id => current_user.id, + :poll_question_id => @poll_question.id, + :poll_answer_id => ques_vote_id, + :vote_text => question_answer_text + } + PollVote.create(answer_option) end + # if current_vote_text.present? #已有其他输入文字的选项 + # current_vote_text.update_attribute("vote_text", question_answer_text) + # else + # + # end + end - ea_ids = user_votes.pluck(:poll_answer_id) - common_answer_ids = question_answer_ids & ea_ids #已经存在的试卷选项id - new_ids = question_answer_ids - common_answer_ids # 新增的id - old_ids = ea_ids - common_answer_ids #没有选择的,则删掉 - if new_ids.size > 0 - new_ids.each do |e| - answer_option = { - :user_id => current_user.id, - :poll_question_id => @poll_question.id, - :poll_answer_id => e, - :vote_text => nil - } - ex_a = PollVote.new(answer_option) - ex_a.save! - end - end - if old_ids.size > 0 - ea_answer = user_votes.find_current_vote("poll_answer_id",old_ids) - ea_answer.destroy_all + ea_ids = user_votes.pluck(:poll_answer_id) + common_answer_ids = question_answer_ids & ea_ids #已经存在的试卷选项id + new_ids = question_answer_ids - common_answer_ids # 新增的id + old_ids = ea_ids - common_answer_ids #没有选择的,则删掉 + if new_ids.size > 0 + new_ids.each do |e| + answer_option = { + :user_id => current_user.id, + :poll_question_id => @poll_question.id, + :poll_answer_id => e, + :vote_text => nil + } + ex_a = PollVote.new(answer_option) + ex_a.save! end - else - user_votes.destroy_all end - else #主观题的输入 - # current_vote_text = user_votes.find_vote_text - if user_votes.present? - user_votes.first.update_attribute("vote_text", question_answer_text) - # if question_answer_text.present? - # user_votes.first.update_attribute("vote_text", question_answer_text) - # else - # user_votes.destroy_all - # end - else - PollVote.create(vote_answer_params) + if old_ids.size > 0 + ea_answer = user_votes.find_current_vote("poll_answer_id",old_ids) + ea_answer.destroy_all end + else + user_votes.destroy_all end - @current_question_number = @poll_question.question_number - @current_question_necessary = @poll_question.is_necessary - #问答记录存在,且有值,才会有返回值。 - @current_question_status = 0 - new_user_votes = question_votes.where(user_id: current_user.id) - if new_user_votes.present? - vote_answer_id = new_user_votes.pluck(:poll_answer_id).reject(&:blank?).size - vote_text_count = new_user_votes.pluck(:vote_text).reject(&:blank?).size - if vote_text_count > 0 || vote_answer_id > 0 - @current_question_status = 1 - end + else #主观题的输入 + # current_vote_text = user_votes.find_vote_text + if user_votes.present? + user_votes.first.update_attribute("vote_text", question_answer_text) + # if question_answer_text.present? + # user_votes.first.update_attribute("vote_text", question_answer_text) + # else + # user_votes.destroy_all + # end + else + PollVote.create(vote_answer_params) + end + end + @current_question_number = @poll_question.question_number + @current_question_necessary = @poll_question.is_necessary + #问答记录存在,且有值,才会有返回值。 + @current_question_status = 0 + new_user_votes = question_votes.where(user_id: current_user.id) + if new_user_votes.present? + vote_answer_id = new_user_votes.pluck(:poll_answer_id).reject(&:blank?).size + vote_text_count = new_user_votes.pluck(:vote_text).reject(&:blank?).size + if vote_text_count > 0 || vote_answer_id > 0 + @current_question_status = 1 end - rescue Exception => e - uid_logger_error(e.message) - tip_exception("页面调用失败!") - raise ActiveRecord::Rollback end + rescue Exception => e + uid_logger_error(e.message) + tip_exception("页面调用失败!") + raise ActiveRecord::Rollback end end diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 068a0dafd..0c442a613 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -1409,23 +1409,29 @@ class PollsController < ApplicationController poll_questions.each do |q| user_poll_votes = u_user.poll_votes.find_current_vote("poll_question_id",q.id) if user_poll_votes.present? - user_poll_answer_ids = user_poll_votes.pluck(:poll_answer_id).reject(&:blank?) - user_poll_vote_texts = user_poll_votes.pluck(:vote_text).reject(&:blank?) - if user_poll_answer_ids.count > 0 - answer_content = q.poll_answers.find_answer_by_custom("id",user_poll_answer_ids) - if user_poll_answer_ids.count >1 - u_answer = answer_content.pluck(:answer_text).join(";") + if q.question_type < 3 + user_poll_answer_ids = user_poll_votes.pluck(:poll_answer_id).reject(&:blank?) + if user_poll_answer_ids.count > 0 + answer_content = q.poll_answers.find_answer_by_custom("id",user_poll_answer_ids) + if user_poll_answer_ids.count >1 + u_answer = answer_content.pluck(:answer_text).join(";") + else + u_answer = answer_content.first&.answer_text + end else - u_answer = answer_content.first.answer_text + u_answer = "--" end - elsif user_poll_vote_texts.count > 0 - if user_poll_vote_texts.count > 1 - u_answer = user_poll_vote_texts.join(";") + else + user_poll_vote_texts = user_poll_votes.pluck(:vote_text).reject(&:blank?) + if user_poll_vote_texts.count > 0 + if user_poll_vote_texts.count > 1 + u_answer = user_poll_vote_texts.join(";") + else + u_answer = user_poll_vote_texts.first + end else - u_answer = user_poll_vote_texts.first + u_answer = "--" end - else - u_answer = "--" end else u_answer = "--" diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb index a321beb25..a3030001c 100644 --- a/app/controllers/shixuns_controller.rb +++ b/app/controllers/shixuns_controller.rb @@ -26,22 +26,7 @@ class ShixunsController < ApplicationController ## 获取课程列表 def index - ## 我的实训 - @shixuns = - if params[:order_by] == 'mine' - tip_exception(401, "..") unless current_user.logged? - current_user.my_shixuns - else - Shixun.unhidden - end - - ## 云上实验室过滤 - unless current_laboratory.main_site? - @shixuns = @shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: current_laboratory.id }) - else - not_shixun_ids = Shixun.joins(:laboratory_shixuns).where("laboratory_shixuns.laboratory_id != #{current_laboratory.id}") - @shixuns = @shixuns.where.not(id: not_shixun_ids) - end + @shixuns = current_laboratory.shixuns.unhidden ## 方向 if params[:tag_level].present? && params[:tag_id].present? @@ -379,76 +364,107 @@ class ShixunsController < ApplicationController end def create - # 评测脚本的一些操作 - main_type, sub_type = params[:main_type], params[:small_type] - mirror = MirrorScript.where(:mirror_repository_id => main_type) - - identifier = generate_identifier Shixun, 8 - @shixun = Shixun.new(shixun_params) - @shixun.identifier = identifier - @shixun.user_id = current_user.id - @shixun.reset_time, @shixun.modify_time = Time.now, Time.now - - if sub_type.blank? - shixun_script = mirror.first.try(:script) - else - main_mirror = MirrorRepository.find(main_type).type_name - sub_mirror = MirrorRepository.where(id: sub_type).pluck(:type_name) - if main_mirror == "Java" && sub_mirror.include?("Mysql") - shixun_script = mirror.last.try(:script) - else - shixun_script = mirror.first.try(:script) - shixun_script = modify_shixun_script @shixun, shixun_script - end + begin + @shixun = CreateShixunService.call(current_user, shixun_params, params) + rescue => e + logger_error("shixun_create_error: #{e.message}") + tip_exception("创建实训失败!") end + end - ActiveRecord::Base.transaction do - begin - @shixun.save! - # shixun_info关联ß - ShixunInfo.create!(shixun_id: @shixun.id, evaluate_script: shixun_script, description: params[:description]) - # 实训的公开范围 - if params[:scope_partment].present? - arr = [] - ids = School.where(:name => params[:scope_partment]).pluck(:id).uniq - ids.each do |id| - arr << { :school_id => id, :shixun_id => @shixun.id } - end - ShixunSchool.create!(arr) + def update + # 镜像方面 + mirror_ids = MirrorRepository.where(id: params[:main_type]) + .or( MirrorRepository.where(id: params[:sub_type])).pluck(:id).uniq + old_mirror_ids = @shixun.shixun_mirror_repositories + .where(mirror_repository_id: params[:main_type]) + .or(@shixun.shixun_mirror_repositories.where(mirror_repository_id: params[:sub_type])) + .pluck(:mirror_repository_id).uniq + new_mirror_id = (mirror_ids - old_mirror_ids).map{|id| {mirror_repository_id: id}} # 转换成数组hash方便操作 + logger.info("##########new_mirror_id: #{new_mirror_id}") + logger.info("##########old_mirror_ids: #{old_mirror_ids}") + logger.info("##########mirror_ids: #{mirror_ids}") + # 服务配置方面 + service_create_params = service_config_params[:shixun_service_configs] + .select{|config| !old_mirror_ids.include?(config[:mirror_repository_id]) && + MirrorRepository.find(config[:mirror_repository_id]).name.present?} + service_update_params = service_config_params[:shixun_service_configs] + .select{|config| old_mirror_ids.include?(config[:mirror_repository_id])} + logger.info("#########service_create_params: #{service_create_params}") + logger.info("#########service_update_params: #{service_update_params}") + begin + ActiveRecord::Base.transaction do + @shixun.update_attributes(shixun_params) + @shixun.shixun_info.update_attributes(shixun_info_params) + # 镜像变动 + @shixun.shixun_mirror_repositories.where.not(mirror_repository_id: old_mirror_ids).destroy_all + @shixun.shixun_mirror_repositories.create!(new_mirror_id) + # 镜像变动要更换服务配置 + @shixun.shixun_service_configs.where.not(mirror_repository_id: old_mirror_ids).destroy_all + @shixun.shixun_service_configs.create!(service_create_params) + service_update_params&.map do |service| + smr = @shixun.shixun_service_configs.find_by(mirror_repository_id: service[:mirror_repository_id]) + smr.update_attributes(service) end - - # 实训合作者 - @shixun.shixun_members.create!(user_id: current_user.id, role: 1) - - # 镜像-实训关联表 - ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if main_type.present? - # 实训主镜像服务配置 - ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) - if sub_type.present? - sub_type.each do |mirror| - ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) - # 实训子镜像服务配置 - name = MirrorRepository.find_by(id: mirror).try(:name) #查看镜像是否有名称,如果没有名称就不用服务配置 - ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) if name.present? + # 添加第二仓库(管理员权限) + if current_user.admin_or_business? + if params[:is_secret_repository] + add_secret_repository if @shixun.shixun_secret_repository.blank? + else + # 如果有仓库,就要删 + if @shixun.shixun_secret_repository&.repo_name + @shixun.shixun_secret_repository.lock! + GitService.delete_repository(repo_path: @shixun.shixun_secret_repository.repo_path) + @shixun.shixun_secret_repository.destroy + end end end + end + rescue => e + uid_logger_error(e.message) + tip_exception("基本信息更新失败:#{e.message}") + end + end - # 创建版本库 - repo_path = repo_namespace(User.current.login, @shixun.identifier) - GitService.add_repository(repo_path: repo_path) - # todo: 为什么保存的时候要去除后面的.git呢?? - @shixun.update_column(:repo_name, repo_path.split(".")[0]) + # 实训权限设置 + def update_permission_setting + # 查找需要增删的高校id + school_id = School.where(:name => params[:scope_partment]).pluck(:id) + old_school_ids = @shixun.shixun_schools.pluck(:school_id) + school_params = (school_id - old_school_ids).map{|id| {school_id: id}} + begin + ActiveRecord::Base.transaction do + @shixun.update_attributes!(shixun_params) + @shixun.shixun_schools.where.not(school_id: school_id).destroy_all if school_id.present? + @shixun.shixun_schools.create!(school_params) + end + rescue => e + uid_logger_error("实训权限设置失败--------#{e.message}") + tip_exception("实训权限设置失败") + end + end - # 将实训标志为该云上实验室建立 - Laboratory.current.laboratory_shixuns.create!(shixun: @shixun, ownership: true) - rescue Exception => e - uid_logger_error(e.message) - tip_exception("实训创建失败") - raise ActiveRecord::Rollback + # 实训学习页面设置 + def update_learn_setting + begin + ActiveRecord::Base.transaction do + @shixun.update_attributes!(shixun_params) end + rescue => e + uid_logger_error("实训学习页面设置失败--------#{e.message}") + tip_exception("实训学习页面设置失败") end end + # Jupyter数据集 + def jupyter_data_sets + page = params[:page] || 1 + limit = params[:limit] || 10 + data_sets = @shixun.jupyter_data_sets + @data_count = data_sets.count + @data_sets= data_sets.page(page).per(limit) + end + def apply_shixun_mirror form_params = params.permit(*%i[language runtime run_method attachment_id]) form = ApplyShixunMirrorForm.new(form_params) @@ -477,61 +493,6 @@ class ShixunsController < ApplicationController tip_exception("申请失败") end - def update - ActiveRecord::Base.transaction do - begin - @shixun.shixun_mirror_repositories.destroy_all - if params[:main_type].present? - ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => params[:main_type].to_i) - end - if params[:small_type].present? - params[:small_type].each do |mirror| - ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror) - end - end - @shixun.update_attributes(shixun_params) - @shixun.shixun_info.update_attributes(shixun_info_params) - @shixun.shixun_schools.delete_all - # scope_partment: 高校的名称 - if params[:scope_partment].present? - arr = [] - ids = School.where(:name => params[:scope_partment]).pluck(:id).uniq - ids.each do |id| - arr << { :school_id => id, :shixun_id => @shixun.id } - end - ShixunSchool.create!(arr) - end - # 超级管理员和运营人员才能保存 中间层服务器pod信息的配置 - # 如果镜像改动了,则也需要更改 - mirror = @shixun.shixun_service_configs.map(&:mirror_repository_id).sort - new_mirror = params[:shixun_service_configs].map{|c| c[:mirror_repository_id]}.sort - if current_user.admin? || current_user.business? || (mirror != new_mirror) - @shixun.shixun_service_configs.destroy_all - service_config_params[:shixun_service_configs].each do |config| - name = MirrorRepository.find_by_id(config[:mirror_repository_id])&.name - # 不保存没有镜像的配置 - @shixun.shixun_service_configs.create!(config) if name.present? - end - end - # 添加第二仓库 - if params[:is_secret_repository] - add_secret_repository if @shixun.shixun_secret_repository.blank? - else - # 如果有仓库,就要删 - if @shixun.shixun_secret_repository&.repo_name - @shixun.shixun_secret_repository.lock! - GitService.delete_repository(repo_path: @shixun.shixun_secret_repository.repo_path) - @shixun.shixun_secret_repository.destroy - end - end - - rescue Exception => e - uid_logger_error("实训保存失败--------#{e.message}") - tip_exception("实训保存失败") - raise ActiveRecord::Rollback - end - end - end # 永久关闭实训 def close @@ -1036,10 +997,9 @@ class ShixunsController < ApplicationController private def shixun_params - raise("实训名称不能为空") if params[:shixun][:name].blank? params.require(:shixun).permit(:name, :trainee, :webssh, :can_copy, :use_scope, :vnc, :test_set_permission, :task_pass, :multi_webssh, :opening_time, :mirror_script_id, :code_hidden, - :hide_code, :forbid_copy, :vnc_evaluate, :code_edit_permission) + :hide_code, :forbid_copy, :vnc_evaluate, :code_edit_permission, :is_jupyter) end def validate_review_shixun_params @@ -1048,8 +1008,6 @@ private end def shixun_info_params - raise("实训描述不能为空") if params[:shixun_info][:description].blank? - raise("评测脚本不能为空") if params[:shixun_info][:evaluate_script].blank? params.require(:shixun_info).permit(:description, :evaluate_script) end diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb index 096a0fe52..6a9438a79 100644 --- a/app/controllers/subjects_controller.rb +++ b/app/controllers/subjects_controller.rb @@ -25,15 +25,9 @@ class SubjectsController < ApplicationController # 最热排序 if reorder == "myshixun_count" - if current_laboratory.main_site? - not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{current_laboratory.id}").pluck(:id) - not_subject_ids = not_subject_ids.length > 0 ? "(" + not_subject_ids.join(",") + ")" : "(-1)" - laboratory_join = " AND subjects.id not in #{not_subject_ids} " - else - subject_ids = Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id }).pluck(:id) - subject_ids = subject_ids.length > 0 ? "(" + subject_ids.join(",") + ")" : "(-1)" - laboratory_join = " AND subjects.id in #{subject_ids} " - end + subject_ids = current_laboratory.subjects.pluck(:id) + subject_ids = subject_ids.length > 0 ? "(" + subject_ids.join(",") + ")" : "(-1)" + laboratory_join = " AND subjects.id in #{subject_ids} " if select @subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status, @@ -49,6 +43,7 @@ class SubjectsController < ApplicationController GROUP BY subjects.id ORDER BY myshixun_member_count DESC") end else + @subjects = current_laboratory.subjects # 我的路径 if reorder == "mine" tip_exception(401, "..") unless current_user.logged? @@ -57,19 +52,11 @@ class SubjectsController < ApplicationController (select distinct(shixun_id) from myshixuns where user_id=#{current_user.id})").map(&:subject_id) manage_subject_id = SubjectMember.where(user_id: current_user.id).pluck(:subject_id) total_subject_id = (mine_subject_id + manage_subject_id).uniq - @subjects = Subject.where(id: total_subject_id) + @subjects = @subjects.where(id: total_subject_id) elsif reorder == "publish_time" - @subjects = Subject.unhidden - else - @subjects = Subject.visible.unhidden - end - - # 云上实验室过滤 - unless current_laboratory.main_site? - @subjects = @subjects.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id }) + @subjects = @subjects.unhidden else - not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{current_laboratory.id}") - @subjects = @subjects.where.not(id: not_subject_ids) + @subjects = @subjects.visible.unhidden end # 类型 @@ -217,7 +204,7 @@ class SubjectsController < ApplicationController def add_shixun_to_stage identifier = generate_identifier Shixun, 8 ActiveRecord::Base.transaction do - @shixun = Shixun.create!(name: params[:name], user_id: current_user.id, identifier: identifier) + @shixun = Shixun.create!(name: params[:name], user_id: current_user.id, identifier: identifier, is_jupyter: params[:is_jupyter]) # 添加合作者 @shixun.shixun_members.create!(user_id: current_user.id, role: 1) # 创建长字段 diff --git a/app/controllers/users/authentication_applies_controller.rb b/app/controllers/users/authentication_applies_controller.rb index 3c43be553..bf5aa0d40 100644 --- a/app/controllers/users/authentication_applies_controller.rb +++ b/app/controllers/users/authentication_applies_controller.rb @@ -1,5 +1,6 @@ class Users::AuthenticationAppliesController < Users::BaseAccountController before_action :private_user_resources! + before_action :check_account, only: [:create] def create Users::ApplyAuthenticationService.call(observed_user, create_params) diff --git a/app/controllers/users/professional_auth_applies_controller.rb b/app/controllers/users/professional_auth_applies_controller.rb index d1ee70953..9fc8e73db 100644 --- a/app/controllers/users/professional_auth_applies_controller.rb +++ b/app/controllers/users/professional_auth_applies_controller.rb @@ -1,5 +1,6 @@ class Users::ProfessionalAuthAppliesController < Users::BaseAccountController before_action :private_user_resources! + before_action :check_account, only: [:create] def create Users::ApplyProfessionalAuthService.call(observed_user, create_params) diff --git a/app/controllers/users/shixuns_controller.rb b/app/controllers/users/shixuns_controller.rb index fcf9e3618..978a2e8e7 100644 --- a/app/controllers/users/shixuns_controller.rb +++ b/app/controllers/users/shixuns_controller.rb @@ -1,14 +1,6 @@ class Users::ShixunsController < Users::BaseController def index - shixuns = Users::ShixunService.new(observed_user, query_params).call - - ## 云上实验室过滤 - if current_laboratory.main_site? - not_shixun_ids = Shixun.joins(:laboratory_shixuns).where("laboratory_shixuns.laboratory_id != #{current_laboratory.id}") - shixuns = shixuns.where.not(id: not_shixun_ids) - else - shixuns = shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: current_laboratory.id }) - end + shixuns = Users::ShixunService.new(observed_user, query_params, current_laboratory).call @count = shixuns.count @shixuns = paginate(shixuns.includes(:first_tag_repertoire), special: observed_user.is_teacher?) diff --git a/app/controllers/users/subjects_controller.rb b/app/controllers/users/subjects_controller.rb index 8c1e35425..e3a43a023 100644 --- a/app/controllers/users/subjects_controller.rb +++ b/app/controllers/users/subjects_controller.rb @@ -2,13 +2,7 @@ class Users::SubjectsController < Users::BaseController def index subjects = Users::SubjectService.new(observed_user, query_params).call - ## 云上实验室过滤 - if current_laboratory.main_site? - not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{current_laboratory.id}") - subjects = subjects.where.not(id: not_subject_ids) - else - subjects = subjects.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id }) - end + subjects = subjects.where(id: current_laboratory.subjects) @count = subjects.count @subjects = paginate(subjects.includes(:user, :repertoire), special: observed_user.is_teacher?) diff --git a/app/controllers/weapps/code_sessions_controller.rb b/app/controllers/weapps/code_sessions_controller.rb index 2dbd08e82..350fa4978 100644 --- a/app/controllers/weapps/code_sessions_controller.rb +++ b/app/controllers/weapps/code_sessions_controller.rb @@ -6,7 +6,9 @@ class Weapps::CodeSessionsController < Weapps::BaseController logged = false result = Wechat::Weapp.jscode2session(params[:code]) - + Rails.logger.info("###########result: #{result}") + Rails.logger.info("###########result: #{result['session_key']}") + Rails.logger.info("###########result: #{result['unionid']}") # 能根据 code 拿到 unionid open_user = OpenUsers::Wechat.find_by(uid: result['unionid']) if open_user.present? && open_user.user diff --git a/app/controllers/weapps/courses_controller.rb b/app/controllers/weapps/courses_controller.rb index c2335998e..a30fdfa4c 100644 --- a/app/controllers/weapps/courses_controller.rb +++ b/app/controllers/weapps/courses_controller.rb @@ -1,11 +1,12 @@ class Weapps::CoursesController < Weapps::BaseController before_action :require_login before_action :set_course, :user_course_identity, except: [:create] + before_action :check_account, only: [:create] before_action :teacher_allowed, only: [:edit, :update] before_action :teacher_or_admin_allowed, only: [:change_member_roles, :delete_course_teachers] def create - return render_error("只有老师身份才能创建课堂") unless current_user.is_teacher? + # return render_error("只有老师身份才能创建课堂") unless current_user.is_teacher? course = Course.new(tea_id: current_user.id) Weapps::CreateCourseService.call(course, course_params) render_ok @@ -106,7 +107,7 @@ class Weapps::CoursesController < Weapps::BaseController # 批量修改角色 def change_member_roles @course = current_course - tip_exception("请至少选择一个角色") if params[:roles].blank? + tip_exception("请至少选择一个角色") if params[:roles].reject(&:blank?).blank? tip_exception("不能具有老师、助教两种角色") if params[:roles].include?("PROFESSOR") && params[:roles].include?("ASSISTANT_PROFESSOR") params[:user_ids].each do |user_id| @@ -149,13 +150,13 @@ class Weapps::CoursesController < Weapps::BaseController new_student.is_active = 0 if correspond_teacher_exist new_student.save! - CourseAddStudentCreateWorksJob.perform_later(@course.id, user_id) + CourseAddStudentCreateWorksJob.perform_later(@course.id, [user_id]) # StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id) elsif !params[:roles].include?("STUDENT") && student_member.present? # 删除学生身份时激活老师身份 teacher_member.update_attributes!(is_active: 1) if student_member.is_active && teacher_member.present? student_member.destroy! - CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, user_id) + CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [user_id]) # CourseDeleteStudentNotifyJob.perform_later(@course.id, [params[:user_id]], current_user.id) elsif params[:roles].include?("STUDENT") && student_member.present? && !params[:roles].include?("PROFESSOR") && !params[:roles].include?("ASSISTANT_PROFESSOR") # 学生身份存在且学生没有教师身份时更新is_active diff --git a/app/controllers/weapps/homework_commons_controller.rb b/app/controllers/weapps/homework_commons_controller.rb new file mode 100644 index 000000000..ebadd00b0 --- /dev/null +++ b/app/controllers/weapps/homework_commons_controller.rb @@ -0,0 +1,38 @@ +class Weapps::HomeworkCommonsController < Weapps::BaseController + before_action :require_login + before_action :find_homework, :user_course_identity + before_action :teacher_allowed + + def update_settings + begin + # 课堂结束后不能再更新 + unless @course.is_end + UpdateHomeworkPublishSettingService.call(@homework, publish_params) + render_ok + else + tip_exception("课堂已结束不能再更新") + end + rescue Exception => e + uid_logger(e.backtrace) + tip_exception(e.message) + raise ActiveRecord::Rollback + end + end + + private + + def teacher_allowed + return render_forbidden unless @user_course_identity < Course::STUDENT + end + + def find_homework + @homework = HomeworkCommon.find_by!(id: params[:id]) + @course = @homework.course + @homework_detail_manual = @homework.homework_detail_manual + end + + def publish_params + params.permit(:unified_setting, :publish_time, :end_time, group_settings: [:publish_time, :end_time, group_id: []]) + end + +end \ No newline at end of file diff --git a/app/forms/users/apply_authentication_form.rb b/app/forms/users/apply_authentication_form.rb index e0e7931b1..c7c171e31 100644 --- a/app/forms/users/apply_authentication_form.rb +++ b/app/forms/users/apply_authentication_form.rb @@ -3,7 +3,7 @@ class Users::ApplyAuthenticationForm attr_accessor :name, :show_realname, :id_number, :gender, :upload_image, :attachment_ids - validates :name, presence: true + validates :name, presence: true, length: { minimum: 2, maximum: 10 }, format: { with: CustomRegexp::LASTNAME, message: "2-10位中英文、数字" } validate :validate_ID_number validate :validate_attachment_ids diff --git a/app/forms/users/update_account_form.rb b/app/forms/users/update_account_form.rb index 16c3c8013..0eae399d8 100644 --- a/app/forms/users/update_account_form.rb +++ b/app/forms/users/update_account_form.rb @@ -5,8 +5,8 @@ class Users::UpdateAccountForm attr_accessor :nickname, :name, :show_realname, :gender, :location, :location_city, :identity, :student_id, :technical_title, :school_id, :department_id - validates :nickname, presence: true, length: { maximum: 20 } - validates :name, presence: true, length: { maximum: 10 } + validates :nickname, presence: true, length: { minimum: 2, maximum: 20 }, format: { with: CustomRegexp::NICKNAME, message: "2-20位中英文、数字及下划线" } + validates :name, presence: true, length: { minimum: 2, maximum: 10 }, format: { with: CustomRegexp::LASTNAME, message: "2-10位中英文、数字" } validates :gender, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1] } validates :location, presence: true validates :location_city, presence: true diff --git a/app/forms/users/update_password_form.rb b/app/forms/users/update_password_form.rb index 4da341839..db674384c 100644 --- a/app/forms/users/update_password_form.rb +++ b/app/forms/users/update_password_form.rb @@ -3,5 +3,5 @@ class Users::UpdatePasswordForm attr_accessor :password, :old_password - validates :password, presence: true + validates :password, presence: true, length: { minimum: 8, maximum: 16 }, format: { with: CustomRegexp::PASSWORD, message: "8~16位密码,支持字母数字和符号" } end \ No newline at end of file diff --git a/app/libs/custom_regexp.rb b/app/libs/custom_regexp.rb index d7afc61ed..2980f2ed2 100644 --- a/app/libs/custom_regexp.rb +++ b/app/libs/custom_regexp.rb @@ -1,4 +1,7 @@ module CustomRegexp PHONE = /1\d{10}/ - EMAIL = /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ + EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/ + LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/ + NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/ + PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/ end \ No newline at end of file diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 37884e40b..f18d9cd2a 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -21,18 +21,27 @@ class Attachment < ApplicationRecord scope :contains_only_project, -> { where(container_type: 'Project') } scope :contains_course_and_project, -> { contains_only_course.or(contains_only_project) } scope :mine, -> (author_id) { where(author_id: author_id) } - scope :simple_columns, -> { select(:id, :filename, :filesize, :created_on, :cloud_url, :author_id, :content_type) } + scope :simple_columns, -> { select(:id, :filename, :filesize, :created_on, :cloud_url, :author_id, :content_type, :container_type, :container_id) } scope :search_by_container, -> (ids) {where(container_id: ids)} scope :unified_setting, -> {where("unified_setting = ? ", 1)} validates_length_of :description, maximum: 100 + DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z) + def diskfile File.join(File.join(Rails.root, "files"), disk_directory.to_s, disk_filename.to_s) end def title - filename + title = filename + if container && container.is_a?(StudentWork) && author_id != User.current.id + course = container&.homework_common&.course + unless User.current.teacher_of_course?(course) + title = "#{Time.now.strftime('%Y%m%d%H%M%S')}_#{DCODES.sample(8).join}" + File.extname(filename) + end + end + title end def downloads_count diff --git a/app/models/competition.rb b/app/models/competition.rb index 23fa268ec..96fd14c1c 100644 --- a/app/models/competition.rb +++ b/app/models/competition.rb @@ -165,7 +165,7 @@ class Competition < ApplicationRecord def get_module_name type case type - when 'home' then '首页' + when 'home' then '赛制介绍' when 'enroll' then '报名' when 'inform' then '通知公告' when 'chart' then '排行榜' diff --git a/app/models/hack.rb b/app/models/hack.rb index 80724d3d4..506cd4942 100644 --- a/app/models/hack.rb +++ b/app/models/hack.rb @@ -3,6 +3,8 @@ class Hack < ApplicationRecord # diffcult: 难度 1:简单;2:中等; 3:困难 # 编程题 validates_length_of :name, maximum: 60 + validates :description, presence: { message: "描述不能为空" } + validates :name, presence: { message: "名称不能为空" } # 测试集 has_many :hack_sets, ->{order("position asc")}, :dependent => :destroy # 代码 @@ -39,4 +41,9 @@ class Hack < ApplicationRecord hack_sets.first&.input end + # 管理员 + def manager?(user) + user_id == user.id || user.admin_or_business? + end + end diff --git a/app/models/hack_set.rb b/app/models/hack_set.rb index 5dab862b5..6afe05663 100644 --- a/app/models/hack_set.rb +++ b/app/models/hack_set.rb @@ -1,6 +1,7 @@ class HackSet < ApplicationRecord - validates :input, presence: { message: "测试集输入不能为空" } + #validates :input, presence: { message: "测试集输入不能为空" } validates :output, presence: { message: "测试集输出不能为空" } + validates_uniqueness_of :input, scope: [:hack_id, :input], message: "多个测试集的输入不能相同" # 编程题测试集 belongs_to :hack end diff --git a/app/models/hack_user_code.rb b/app/models/hack_user_code.rb index d9d2dff77..eee394e39 100644 --- a/app/models/hack_user_code.rb +++ b/app/models/hack_user_code.rb @@ -1,4 +1,7 @@ class HackUserCode < ApplicationRecord # 用户编程题的信息 belongs_to :hack + belongs_to :hack_user_lastest_code + + scope :created_order, ->{ order("created_at desc")} end diff --git a/app/models/homework_common.rb b/app/models/homework_common.rb index def3b6b0d..d37650c37 100644 --- a/app/models/homework_common.rb +++ b/app/models/homework_common.rb @@ -285,6 +285,15 @@ class HomeworkCommon < ApplicationRecord homework_challenge_settings.find_by(challenge_id: challenge_id)&.score.to_f end + def create_homework_group_settings + if homework_group_settings.size != course.course_groups.size + course.course_groups.where.not(id: homework_group_settings.pluck(:course_group_id)).each do |group| + homework_group_settings << HomeworkGroupSetting.new(course_group_id: group.id, course_id: course.id, + publish_time: publish_time, end_time: end_time) + end + end + end + def update_homework_work_score if unified_setting works = student_works diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb index 102e964b1..2ba86ed90 100644 --- a/app/models/laboratory.rb +++ b/app/models/laboratory.rb @@ -47,11 +47,31 @@ class Laboratory < ApplicationRecord end def shixuns - main_site? ? Shixun.all : Shixun.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: id }) + if main_site? + not_shixun_ids = Shixun.joins(:laboratory_shixuns).where("laboratory_shixuns.laboratory_id != #{Laboratory.current.id}") + Shixun.where.not(id: not_shixun_ids.pluck(:shixun_id)) + elsif sync_shixun + laboratory_shixun_ids = laboratory_shixuns.pluck(:shixun_id) + school_shixun_ids = Shixun.joins("join user_extensions on shixuns.user_id=user_extensions.user_id").where(user_extensions: { school_id: school_id }).pluck(:id) + shixun_ids = laboratory_shixun_ids + school_shixun_ids + Shixun.where(id: shixun_ids.uniq) + else + Shixun.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: id }) + end end def subjects - main_site? ? Subject.all : Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: id }) + if main_site? + not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{Laboratory.current.id}") + Subject.where.not(id: not_subject_ids.pluck(:subject_id)) + elsif sync_subject + laboratory_subject_ids = laboratory_subjects.pluck(:subject_id) + school_subject_ids = Subject.joins("join user_extensions on subjects.user_id=user_extensions.user_id").where(user_extensions: { school_id: school_id }).pluck(:id) + subject_ids = laboratory_subject_ids + school_subject_ids + Subject.where(id: subject_ids.uniq) + else + Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: id }) + end end def all_courses diff --git a/app/models/laboratory_setting.rb b/app/models/laboratory_setting.rb index 416020836..4eacaf460 100644 --- a/app/models/laboratory_setting.rb +++ b/app/models/laboratory_setting.rb @@ -42,6 +42,10 @@ class LaboratorySetting < ApplicationRecord image_url('_moop_cases_banner') end + def oj_banner_url + image_url('_oj_banner') + end + def default_navbar self.class.default_config[:navbar] end diff --git a/app/models/shixun.rb b/app/models/shixun.rb index 0f9842739..770dd81f7 100644 --- a/app/models/shixun.rb +++ b/app/models/shixun.rb @@ -9,6 +9,7 @@ class Shixun < ApplicationRecord # webssh 0:不开启webssh;1:开启练习模式; 2:开启评测模式 # trainee 实训的难度 # vnc: VCN实训是否用于评测 + validates_presence_of :name, message: "实训名称不能为空" has_many :challenges, -> {order("challenges.position asc")}, dependent: :destroy has_many :challenge_tags, through: :challenges has_many :myshixuns, :dependent => :destroy @@ -54,6 +55,8 @@ class Shixun < ApplicationRecord has_many :laboratory_shixuns, dependent: :destroy belongs_to :laboratory, optional: true + # Jupyter数据集,附件 + has_many :jupyter_data_sets, ->{where(attachtype: 2)}, class_name: 'Attachment', as: :container, dependent: :destroy scope :search_by_name, ->(keyword) { where("name like ? or description like ? ", "%#{keyword}%", "%#{keyword}%") } diff --git a/app/models/shixun_info.rb b/app/models/shixun_info.rb index 74a49412e..e16f16537 100644 --- a/app/models/shixun_info.rb +++ b/app/models/shixun_info.rb @@ -1,7 +1,7 @@ class ShixunInfo < ApplicationRecord belongs_to :shixun validates_uniqueness_of :shixun_id - validates_presence_of :shixun_id + validates_presence_of :shixun_id, :description after_commit :create_diff_record diff --git a/app/models/shixun_mirror_repository.rb b/app/models/shixun_mirror_repository.rb index 9376aac0b..841be6bb2 100644 --- a/app/models/shixun_mirror_repository.rb +++ b/app/models/shixun_mirror_repository.rb @@ -2,4 +2,5 @@ class ShixunMirrorRepository < ApplicationRecord belongs_to :shixun belongs_to :mirror_repository validates_uniqueness_of :shixun_id, :scope => :mirror_repository_id + validates_presence_of :shixun_id, :mirror_repository_id end diff --git a/app/models/shixun_service_config.rb b/app/models/shixun_service_config.rb index 6d106fc07..4dda75a25 100644 --- a/app/models/shixun_service_config.rb +++ b/app/models/shixun_service_config.rb @@ -1,4 +1,6 @@ class ShixunServiceConfig < ApplicationRecord belongs_to :shixun belongs_to :mirror_repository + + validates_presence_of :shixun_id, :mirror_repository_id end diff --git a/app/models/user.rb b/app/models/user.rb index 27c9e03ae..eb3ece0a4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -21,7 +21,7 @@ class User < ApplicationRecord VALID_EMAIL_REGEX = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/i VALID_PHONE_REGEX = /^1\d{10}$/ # 身份证 - VALID_NUMBER_REGEX = /^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/ + VALID_NUMBER_REGEX = /(^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^([A-Z]\d{6,10}(\(\w{1}\))?)$)/ LOGIN_LENGTH_LIMIT = 30 MAIL_LENGTH_LMIT = 60 diff --git a/app/queries/admins/shixun_modify_record_query.rb b/app/queries/admins/shixun_modify_record_query.rb new file mode 100644 index 000000000..227e2f4c2 --- /dev/null +++ b/app/queries/admins/shixun_modify_record_query.rb @@ -0,0 +1,33 @@ +class Admins::ShixunModifyRecordQuery < ApplicationQuery + attr_reader :params + + def initialize(params) + @params = params + end + + def call + if params[:user_name].blank? || params[:date].blank? + records = DiffRecord.none + else + records = DiffRecord.joins(:user).where("concat(users.lastname, users.firstname) like ?", "%#{params[:user_name].strip}%") + if time_range.present? + records = records.where(created_at: time_range) + end + end + records.order("diff_records.created_at desc") + end + + private + + def time_range + @_time_range ||= begin + case params[:date] + when 'weekly' then 1.weeks.ago..Time.now + when 'monthly' then 1.months.ago..Time.now + when 'quarterly' then 3.months.ago..Time.now + when 'yearly' then 1.years.ago..Time.now + else '' + end + end + end +end diff --git a/app/queries/admins/shixun_settings_query.rb b/app/queries/admins/shixun_settings_query.rb index ab871b58e..377e7bf60 100644 --- a/app/queries/admins/shixun_settings_query.rb +++ b/app/queries/admins/shixun_settings_query.rb @@ -51,6 +51,7 @@ class Admins::ShixunSettingsQuery < ApplicationQuery all_shixuns = all_shixuns.where(homepage_show: params[:homepage_show]) if params[:homepage_show] all_shixuns = all_shixuns.where(task_pass: params[:task_pass]) if params[:task_pass] all_shixuns = all_shixuns.where(code_hidden: params[:code_hidden]) if params[:code_hidden] + all_shixuns = all_shixuns.where(vip: params[:vip]) if params[:vip] custom_sort(all_shixuns, params[:sort_by], params[:sort_direction]) end diff --git a/app/services/admins/check_shixun_mirrors_service.rb b/app/services/admins/check_shixun_mirrors_service.rb index 8334df485..4aa0af4cf 100644 --- a/app/services/admins/check_shixun_mirrors_service.rb +++ b/app/services/admins/check_shixun_mirrors_service.rb @@ -75,13 +75,12 @@ class Admins::CheckShixunMirrorsService < ApplicationService def bridge_images @_bridge_images ||= begin - url = EduSetting.get('cloud_bridge') + url = "#{EduSetting.get('cloud_bridge')}/bridge/docker/images" res = Faraday.get(url) - res_body = JSON.parse(res.body) + res = JSON.parse(res.body) + raise Error, '拉取镜像信息异常' if res && res['code'] != 0 - raise Error, '拉取镜像信息异常' if res_body && res_body['code'].to_i != 0 - - res_body + res rescue => e Rails.logger.error("get response failed ! #{e.message}") raise Error, '实训云平台繁忙(繁忙等级:84)' diff --git a/app/services/admins/save_laboratory_setting_service.rb b/app/services/admins/save_laboratory_setting_service.rb index b35323608..c29e374bd 100644 --- a/app/services/admins/save_laboratory_setting_service.rb +++ b/app/services/admins/save_laboratory_setting_service.rb @@ -43,6 +43,7 @@ class Admins::SaveLaboratorySettingService < ApplicationService save_image_file(params[:course_banner], '_course_banner') save_image_file(params[:competition_banner], '_competition_banner') save_image_file(params[:moop_cases_banner], '_moop_cases_banner') + save_image_file(params[:oj_banner], '_oj_banner') end def save_image_file(file, type) diff --git a/app/services/application_service.rb b/app/services/application_service.rb index 1be6896eb..81c48de95 100644 --- a/app/services/application_service.rb +++ b/app/services/application_service.rb @@ -3,6 +3,12 @@ class ApplicationService Error = Class.new(StandardError) + def regix_emoji content + " " if content.blank? + regex = /[^a-zA-Z0-9\u4E00-\u9FFF]/ + content.gsub(regex, '') + end + private def strip(str) diff --git a/app/services/create_diff_record_service.rb b/app/services/create_diff_record_service.rb index 8365404e2..3943af1ae 100644 --- a/app/services/create_diff_record_service.rb +++ b/app/services/create_diff_record_service.rb @@ -25,21 +25,23 @@ class CreateDiffRecordService < ApplicationService index = 0 fragment_size = 1 Diffy::Diff.new(before, after).each do |line| - unless line =~ /^[\+-]/ - if arr.empty? && index < fragment_size - content += line - index += 1 - else - index = 0 - arr << line - arr.shift if arr.size > fragment_size + unless line.include?("\\ 文件尾没有 newline 字符") + unless line =~ /^[\+-]/ + if arr.empty? && index < fragment_size + content += line + index += 1 + else + index = 0 + arr << line + arr.shift if arr.size > fragment_size + end + next end - next - end - content += arr.join('') if arr.present? - content += line - arr.clear + content += arr.join('') if arr.present? + content += line + arr.clear + end end content end diff --git a/app/services/oauth/create_or_find_qq_account_service.rb b/app/services/oauth/create_or_find_qq_account_service.rb index 007de595e..dafcc3f88 100644 --- a/app/services/oauth/create_or_find_qq_account_service.rb +++ b/app/services/oauth/create_or_find_qq_account_service.rb @@ -17,7 +17,8 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService new_user = true # 新用户 login = User.generate_login('Q') - @user = User.new(login: login, nickname: params.dig('info', 'nickname').force_encoding('UTF-8'), type: 'User', status: User::STATUS_ACTIVE) + #nickname = regix_emoji params.dig('info', 'nickname') + @user = User.new(login: login, type: 'User', status: User::STATUS_ACTIVE) end ActiveRecord::Base.transaction do @@ -31,7 +32,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService Util.download_file(params.dig('info', 'image'), avatar_path) end - new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid'], extra: params.dig('extra', 'raw_info')) + new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid']) Rails.cache.write(new_open_user.can_bind_cache_key, 1, expires_in: 1.hours) if new_user # 方便后面进行账号绑定 end diff --git a/app/services/oauth/create_or_find_wechat_account_service.rb b/app/services/oauth/create_or_find_wechat_account_service.rb index a5f23b4c8..75091a5c3 100644 --- a/app/services/oauth/create_or_find_wechat_account_service.rb +++ b/app/services/oauth/create_or_find_wechat_account_service.rb @@ -24,15 +24,10 @@ class Oauth::CreateOrFindWechatAccountService < ApplicationService new_user = true # 新用户 login = User.generate_login('w') - cd = CharDet.detect(result['nickname']) - Rails.logger.info "encoding: #{cd['encoding']} confidence: #{cd['confidence']}" - decode_content = - if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8 - result['nickname'].encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '}) - else - result['nickname'].force_encoding('UTF-8') - end - @user = User.new(login: login, nickname: decode_content, type: 'User', status: User::STATUS_ACTIVE) + # result['nickname'] = regix_emoji(result['nickname']) + @user = User.new(login: login, type: 'User', status: User::STATUS_ACTIVE) + #@user = User.new(login: login, nickname: result['nickname'], type: 'User', status: User::STATUS_ACTIVE) + end ActiveRecord::Base.transaction do @@ -47,7 +42,7 @@ class Oauth::CreateOrFindWechatAccountService < ApplicationService Util.download_file(result['headimgurl'], avatar_path) end - new_open_user= OpenUsers::Wechat.create!(user: user, uid: result['unionid'], extra: result) + new_open_user= OpenUsers::Wechat.create!(user: user, uid: result['unionid']) Rails.cache.write(new_open_user.can_bind_cache_key, 1, expires_in: 1.hours) if new_user # 方便后面进行账号绑定 end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 350048c2e..5eb11f398 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -40,23 +40,11 @@ class SearchService < ApplicationService def extra_options case params[:type].to_s.strip when 'shixun' then - if Laboratory.current.main_site? - not_shixun_ids = Shixun.joins(:laboratory_shixuns).where("laboratory_shixuns.laboratory_id != #{Laboratory.current.id}") - shixun_ids = Shixun.where.not(id: not_shixun_ids).pluck(:id) - else - shixun_ids = Laboratory.current.shixuns.pluck(:id) - end - { where: { id: shixun_ids } } + { where: { id: Laboratory.current.shixuns.pluck(:id) } } when 'subject' then - if Laboratory.current.main_site? - not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{Laboratory.current.id}") - subject_ids = Subject.where.not(id: not_subject_ids).pluck(:id) - else - subject_ids = Laboratory.current.subjects.pluck(:id) - end - { where: { id: subject_ids } } + { where: { id: Laboratory.current.subjects.pluck(:id) } } when 'course' then - { where: { laboratory_id: Laboratory.current.id } } + { where: { id: Laboratory.current.all_courses.pluck(:id) } } else {} end diff --git a/app/services/shixun_search_service.rb b/app/services/shixun_search_service.rb index 63e10d6b0..580208dfe 100644 --- a/app/services/shixun_search_service.rb +++ b/app/services/shixun_search_service.rb @@ -14,16 +14,18 @@ class ShixunSearchService < ApplicationService # 状态:已发布/未发布 status = params[:status] || "all" + @shixuns = laboratory.shixuns.none_closed + # 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭) if type == "mine" - @shixuns = User.current.shixuns.none_closed + @shixuns = @shixuns.where(id: User.current.shixuns) else - if User.current.admin? || User.current.business? - @shixuns = Shixun.none_closed.where(hidden: 0) + if User.current.admin? || User.current.business? || !User.current.school_id + @shixuns = @shixuns.where(hidden: 0) else none_shixun_ids = ShixunSchool.where("school_id != #{User.current.school_id}").pluck(:shixun_id) - @shixuns = Shixun.where.not(id: none_shixun_ids).none_closed.where(hidden: 0) + @shixuns = @shixuns.where.not(id: none_shixun_ids).where(hidden: 0) end end @@ -36,17 +38,6 @@ class ShixunSearchService < ApplicationService @shixuns = @shixuns.where(trainee: params[:diff]) end - ## 云上实验室过滤 - if laboratory.main_site? - not_shixun_ids = Shixun.joins(:laboratory_shixuns).where("laboratory_shixuns.laboratory_id != #{laboratory.id}") - @shixuns = @shixuns.where.not(id: not_shixun_ids) - else - @shixuns = @shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: laboratory.id }) - end - - # laboratory = Laboratory.find_by_subdomain(subdomain) - # @shixuns = @shixuns.where(id: laboratory.shixuns) if laboratory - Shixun.search(keyword, search_options) end diff --git a/app/services/shixuns/create_shixun_service.rb b/app/services/shixuns/create_shixun_service.rb new file mode 100644 index 000000000..aa9968f5b --- /dev/null +++ b/app/services/shixuns/create_shixun_service.rb @@ -0,0 +1,104 @@ +class CreateShixunService < ApplicationService + attr_reader :user, :params, :permit_params + + def initialize(user, permit_params, params) + @user = user + @params = params + @permit_params = permit_params + end + + def call + shixun = Shixun.new(permit_params) + identifier = Util::UUID.generate_identifier(Shixun, 8) + shixun.identifier= identifier + shixun.user_id = user.id + main_mirror = MirrorRepository.find params[:main_type] + sub_mirrors = MirrorRepository.where(id: params[:sub_type]) + ActiveRecord::Base.transaction do + shixun.save! + # 获取脚本内容 + shixun_script = get_shixun_script(shixun, main_mirror, sub_mirrors) + # 创建额外信息 + ShixunInfo.create!(shixun_id: shixun.id, evaluate_script: shixun_script, description: params[:description]) + # 创建合作者 + shixun.shixun_members.create!(user_id: user.id, role: 1) + # 创建镜像 + ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => main_mirror.id) + # 创建主服务配置 + ShixunServiceConfig.create!(:shixun_id => shixun.id, :mirror_repository_id => main_mirror.id) + # 创建子镜像相关数据(实训镜像关联表,子镜像服务配置) + sub_mirrors.each do |sub| + ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => sub.id) + # 实训子镜像服务配置 + name = sub.name #查看镜像是否有名称,如果没有名称就不用服务配置 + ShixunServiceConfig.create!(:shixun_id => shixun.id, :mirror_repository_id => sub.id) if name.present? + end + # 创建版本库 + repo_path = repo_namespace(user.login, shixun.identifier) + GitService.add_repository(repo_path: repo_path) + shixun.update_column(:repo_name, repo_path.split(".")[0]) + # 如果是云上实验室,创建相关记录 + if !Laboratory.current.main_site? + Laboratory.current.laboratory_shixuns.create!(shixun: shixun, ownership: true) + end + return shixun + end + end + + private + + def get_shixun_script shixun, main_mirror, sub_mirrors + if !shixun.is_jupyter? + mirror = main_mirror.mirror_scripts + if main_mirror.blank? + modify_shixun_script shixun, mirror.first&.(:script) + else + sub_name = sub_mirrors.pluck(:type_name) + if main_mirror.type_name == "Java" && sub_name.include?("Mysql") + mirror.last.try(:script) + else + shixun_script = mirror.first&.script + modify_shixun_script shixun, shixun_script + end + end + end + end + + def modify_shixun_script shixun, script + if script.present? + source_class_name = [] + challenge_program_name = [] + shixun.challenges.map(&:exec_path).each do |exec_path| + challenge_program_name << "\"#{exec_path}\"" + if shixun.main_mirror_name == "Java" + if exec_path.nil? || exec_path.split("src/")[1].nil? + source = "\"\"" + else + source = "\"#{exec_path.split("src/")[1].split(".java")[0]}\"" + end + logger.info("----source: #{source}") + source_class_name << source.gsub("/", ".") if source.present? + elsif shixun.main_mirror_name.try(:first) == "C#" + if exec_path.nil? || exec_path.split(".")[1].nil? + source = "\"\"" + else + source = "\"#{exec_path.split(".")[0]}.exe\"" + end + source_class_name << source if source.present? + end + end + script = if script.include?("sourceClassName") && script.include?("challengeProgramName") + script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{source_class_name.reject(&:blank?).join(" ")}\)") + else + script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)") + end + end + return script + end + + # 版本库目录空间 + def repo_namespace(user, shixun_identifier) + "#{user}/#{shixun_identifier}.git" + end + +end diff --git a/app/services/subject_search_service.rb b/app/services/subject_search_service.rb index 101a31085..9c2776beb 100644 --- a/app/services/subject_search_service.rb +++ b/app/services/subject_search_service.rb @@ -12,21 +12,12 @@ class SubjectSearchService < ApplicationService # 全部实训/我的实训 type = params[:type] || "all" - if type == "mine" - @subjects = User.current.subjects.visible.unhidden - else - @subjects = Subject.visible.unhidden - end + @subjects = laboratory.subjects - # laboratory = Laboratory.find_by_subdomain(subdomain) - # @subjects = @subjects.where(id: laboratory.subjects) if laboratory - - ## 云上实验室过滤 - if laboratory.main_site? - not_subject_ids = Subject.joins(:laboratory_subjects).where("laboratory_subjects.laboratory_id != #{laboratory.id}") - @subjects = @subjects.where.not(id: not_subject_ids) + if type == "mine" + @subjects = @subjects.where(id: User.current.subjects).visible.unhidden else - @subjects = @subjects.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: laboratory.id }) + @subjects = @subjects.visible.unhidden end Subject.search(keyword, search_options) diff --git a/app/services/update_homework_publish_setting_service.rb b/app/services/update_homework_publish_setting_service.rb new file mode 100644 index 000000000..69a68b613 --- /dev/null +++ b/app/services/update_homework_publish_setting_service.rb @@ -0,0 +1,116 @@ +class UpdateHomeworkPublishSettingService < ApplicationService + attr_reader :homework, :params + + def initialize(homework, params) + @params = params + @homework = homework + end + + def call + puts params + course = homework.course + # 作业未发布时,unified_setting参数不能为空 + if homework.publish_time.nil? || homework.publish_time > Time.now + tip_exception("缺少统一设置的参数") if params[:unified_setting].nil? + if params[:unified_setting] || course.course_groups_count == 0 + tip_exception("发布时间不能为空") if params[:publish_time].blank? + tip_exception("截止时间不能为空") if params[:end_time].blank? + tip_exception("发布时间不能早于当前时间") if params[:publish_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S") + tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S") + tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_time] + tip_exception("截止时间不能晚于课堂结束时间(#{course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if + course.end_date.present? && params[:end_time] > course.end_date.end_of_day + + homework.unified_setting = 1 + homework.homework_group_settings.destroy_all + homework.publish_time = params[:publish_time] + # 截止时间为空时取发布时间后一个月 + homework.end_time = params[:end_time] + + else + tip_exception("分班发布设置不能为空") if params[:group_settings].blank? + # 创建作业的分班设置 + homework.create_homework_group_settings + + setting_group_ids = [] + + params[:group_settings].each do |setting| + tip_exception("分班id不能为空") if setting[:group_id].length == 0 + tip_exception("发布时间不能为空") if setting[:publish_time].blank? + tip_exception("截止时间不能为空") if setting[:end_time].blank? + tip_exception("发布时间不能早于当前时间") if setting[:publish_time].to_time <= Time.now + tip_exception("截止时间不能早于当前时间") if setting[:end_time].to_time <= Time.now + tip_exception("截止时间不能早于发布时间") if setting[:publish_time].to_time > setting[:end_time].to_time + tip_exception("截止时间不能晚于课堂结束时间(#{course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if + course.end_date.present? && setting[:end_time] > course.end_date.end_of_day + + + publish_time = setting[:publish_time] == "" ? Time.now : setting[:publish_time] + # 截止时间为空时取发布时间后一个月 + end_time = setting[:end_time] + HomeworkGroupSetting.where(homework_common_id: homework.id, course_group_id: setting[:group_id]). + update_all(publish_time: publish_time, end_time: end_time) + setting_group_ids << setting[:group_id] + end + + # 未设置的分班:发布时间和截止时间都为nil + HomeworkGroupSetting.where.not(course_group_id: setting_group_ids).where(homework_common_id: homework.id). + update_all(publish_time: nil, end_time: nil) + + # 记录已发布需要发消息的分班 + publish_group_ids = HomeworkGroupSetting.where(homework_common_id: homework.id).group_published.pluck(:course_group_id) + + homework.unified_setting = 0 + homework.publish_time = homework.min_group_publish_time + homework.end_time = homework.max_group_end_time + end + + # 如果作业立即发布则更新状态、发消息 + if homework.publish_time <= Time.now and homework_detail_manual.comment_status == 0 + homework_detail_manual.comment_status = 1 + send_tiding = true + end + + # 作业在"提交中"状态时 + else + if homework.end_time > Time.now && homework.unified_setting + tip_exception("截止时间不能为空") if params[:end_time].blank? + tip_exception("截止时间不能早于当前时间") if params[:end_time].to_time <= Time.now + tip_exception("截止时间不能晚于课堂结束时间(#{course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if + course.end_date.present? && params[:end_time].to_time > course.end_date.end_of_day + + homework.end_time = params[:end_time] + + elsif !homework.unified_setting + homework.create_homework_group_settings + tip_exception("分班发布设置不能为空") if params[:group_settings].reject(&:blank?).blank? + params[:group_settings].each do |setting| + group_settings = HomeworkGroupSetting.where(homework_common_id: homework.id, course_group_id: setting[:group_id]) + + tip_exception("分班id不能为空") if setting[:group_id].length == 0 + tip_exception("发布时间不能为空") if setting[:publish_time].blank? + tip_exception("截止时间不能为空") if setting[:end_time].blank? + # 如果该发布规则 没有已发布的分班则需判断发布时间 + tip_exception("发布时间不能早于等于当前时间") if setting[:publish_time].to_time <= Time.now && group_settings.group_published.count == 0 + + tip_exception("截止时间不能早于等于当前时间") if setting[:end_time].to_time <= Time.now && group_settings.none_end.count > 0 + tip_exception("截止时间不能早于发布时间") if setting[:publish_time].to_time > setting[:end_time].to_time + tip_exception("截止时间不能晚于课堂结束时间(#{course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")})") if + course.end_date.present? && setting[:end_time].to_time > course.end_date.end_of_day + + group_settings.none_published.update_all(publish_time: setting[:publish_time]) + group_settings.none_end.update_all(end_time: setting[:end_time]) + end + + homework.end_time = homework.max_group_end_time + end + end + homework.save! + HomeworkCommonPushNotifyJob.perform_later(homework.id, publish_group_ids) if send_tiding + end + + private + def tip_exception(status = -1, message) + raise Educoder::TipException.new(status, message) + end +end \ No newline at end of file diff --git a/app/services/users/shixun_service.rb b/app/services/users/shixun_service.rb index aeaac6a2c..ef399ce8c 100644 --- a/app/services/users/shixun_service.rb +++ b/app/services/users/shixun_service.rb @@ -1,12 +1,14 @@ class Users::ShixunService - attr_reader :user, :params + attr_reader :user, :params, :laboratory - def initialize(user, params) + def initialize(user, params, laboratory) @user = user @params = params + @laboratory = laboratory end def call + shixuns = category_scope_shixuns shixuns = user_policy_filter(shixuns) @@ -19,12 +21,12 @@ class Users::ShixunService def category_scope_shixuns case params[:category] when 'study' then - user.study_shixuns + user.study_shixuns.where(shixuns: {id: laboratory.shixuns}) when 'manage' then - user.shixuns + laboratory.shixuns.where(id: user.shixuns) else ids = user.study_shixuns.pluck(:id) + user.shixuns.pluck(:id) - Shixun.where(id: ids) + laboratory.shixuns.where(id: ids) end end diff --git a/app/views/admins/courses/shared/_list.html.erb b/app/views/admins/courses/shared/_list.html.erb index 31661d8c5..4105c8153 100644 --- a/app/views/admins/courses/shared/_list.html.erb +++ b/app/views/admins/courses/shared/_list.html.erb @@ -1,56 +1,31 @@ + - + - + - - + + <% if courses.present? %> - <% courses.each do |course| %> + <% courses.each_with_index do |course, index| %> - - - - - - - - - - - - - - - - - + <%= render partial: 'admins/courses/shared/td', locals: {course: course, no: index} %> <% end %> <% else %> diff --git a/app/views/admins/courses/shared/_td.html.erb b/app/views/admins/courses/shared/_td.html.erb new file mode 100644 index 000000000..51cc4b199 --- /dev/null +++ b/app/views/admins/courses/shared/_td.html.erb @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/views/admins/courses/update.js.erb b/app/views/admins/courses/update.js.erb new file mode 100644 index 000000000..983ac22f0 --- /dev/null +++ b/app/views/admins/courses/update.js.erb @@ -0,0 +1,3 @@ +var index = $("#course-item-<%= @course.id %>").children(":first").html(); +$("#course-item-<%= @course.id %>").html("<%= j render partial: "admins/courses/shared/td",locals: {course: @course, no: 1} %>"); +$("#course-item-<%= @course.id %>").children(":first").html(index); \ No newline at end of file diff --git a/app/views/admins/customers/shared/_list.html.erb b/app/views/admins/customers/shared/_list.html.erb index 0ba5638cb..6f84db4e5 100644 --- a/app/views/admins/customers/shared/_list.html.erb +++ b/app/views/admins/customers/shared/_list.html.erb @@ -1,15 +1,17 @@
序号 ID 课堂名称成员成员 资源 普通作业 分组作业 实训作业 试卷评测次数评测次数 私有 状态 单位 创建者 <%= sort_tag('创建时间', name: 'created_at', path: admins_courses_path) %> 首页邮件通知操作邮件通知操作
<%= course.id %> - <%= link_to(course.name, "/courses/#{course.id}", target: '_blank') %> - <%= course.course_members_count %><%= get_attachment_count(course, 0) %><%= course.course_homework_count(1) %><%= course.course_homework_count(3) %><%= course.course_homework_count(4) %><%= course.exercises_count %><%= course.evaluate_count %><%= course.is_public == 1 ? "--" : "√" %><%= course.is_end ? "已结束" : "正在进行" %><%= course.school&.name %><%= course.teacher&.real_name %><%= course.created_at&.strftime('%Y-%m-%d %H:%M') %> - <%= check_box_tag :homepage_show,!course.homepage_show,course.homepage_show,remote:true,data:{id:course.id},class:"course-setting-form" %> - - <%= check_box_tag :email_notify,!course.email_notify,course.email_notify,remote:true,data:{id:course.id},class:"course-setting-form" %> - - <% if course.is_delete == 0 %> - <%= delete_link '删除', admins_course_path(course, element: ".course-item-#{course.id}"), class: 'delete-course-action' %> - <% end %> -
<%= list_index_no((params[:page] || 1).to_i, no) %><%= course.id %> + <%= link_to(course.name, "/courses/#{course.id}", target: '_blank') %> +<%= course.course_members_count %><%= get_attachment_count(course, 0) %><%= course.course_homework_count(1) %><%= course.course_homework_count(3) %><%= course.course_homework_count(4) %><%= course.exercises_count %><%= course.evaluate_count %><%= course.is_public == 1 ? "--" : "√" %><%= course.is_end ? "已结束" : "正在进行" %><%= course.school&.name %><%= course.teacher&.real_name %><%= course.created_at&.strftime('%Y-%m-%d %H:%M') %> + <%= check_box_tag :homepage_show,!course.homepage_show,course.homepage_show,remote:true,data:{id:course.id},class:"course-setting-form" %> + + <%= check_box_tag :email_notify,!course.email_notify,course.email_notify,remote:true,data:{id:course.id},class:"course-setting-form" %> + + <% if course.is_delete == 0 %> + <%= delete_link '删除', admins_course_path(course, element: ".course-item-#{course.id}"), class: 'delete-course-action' %> + <% end %> +
- + + <% if customers.present? %> - <% customers.each do |customer| %> + <% customers.each_with_index do |customer, index| %> +
客户名称序号客户名称 <%= sort_tag('添加时间', name: 'created_at', path: admins_partner_customers_path(current_partner)) %> 操作
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= customer.school&.name %> <%= customer.created_at&.strftime('%Y-%m-%d %H:%M') %> diff --git a/app/views/admins/daily_school_statistics/shared/_list.html.erb b/app/views/admins/daily_school_statistics/shared/_list.html.erb index 611acdd2a..6982891ee 100644 --- a/app/views/admins/daily_school_statistics/shared/_list.html.erb +++ b/app/views/admins/daily_school_statistics/shared/_list.html.erb @@ -1,8 +1,8 @@ + - @@ -16,13 +16,14 @@ - + <% if statistics.present? %> - <% statistics.each do |statistic| %> + <% statistics.each_with_index do |statistic, index| %> +
序号 单位名称<%= sort_tag('教师总数', name: 'teacher_count', path: admins_daily_school_statistics_path) %> <%= sort_tag('学生总数', name: 'student_count', path: admins_daily_school_statistics_path) %> <%= sort_tag('课堂总数', name: 'course_count', path: admins_daily_school_statistics_path) %> <%= sort_tag('实训作业总数', name: 'homework_count', path: admins_daily_school_statistics_path) %> <%= sort_tag('其它作业总数', name: 'other_homework_count', path: admins_daily_school_statistics_path) %><%= sort_tag('动态时间', name: 'nearly_course_time', path: admins_daily_school_statistics_path) %><%= sort_tag('动态时间', name: 'nearly_course_time', path: admins_daily_school_statistics_path) %>
<%= list_index_no(@params_page.to_i, index) %> <%= link_to statistic[:name], "/colleges/#{statistic[:id]}/statistics", target: '_blank', data: { toggle: 'tooltip', title: '点击查看学校统计概况' } %> diff --git a/app/views/admins/department_applies/shared/_list.html.erb b/app/views/admins/department_applies/shared/_list.html.erb index 0a1d803be..87d5ab66f 100644 --- a/app/views/admins/department_applies/shared/_list.html.erb +++ b/app/views/admins/department_applies/shared/_list.html.erb @@ -1,18 +1,20 @@ + - + <% if applies.present? %> - <% applies.each do |apply| %> + <% applies.each_with_index do |apply, index| %> + diff --git a/app/views/admins/department_members/create.js.erb b/app/views/admins/department_members/create.js.erb index 4355c7432..6bf0a6ac3 100644 --- a/app/views/admins/department_members/create.js.erb +++ b/app/views/admins/department_members/create.js.erb @@ -1,4 +1,6 @@ $('.modal.admin-add-department-member-modal').modal('hide'); $.notify({ message: '操作成功' }); -$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: { department: current_department }) %>") \ No newline at end of file +var index = $(".department-item-<%= current_department.id %>").children(":first").html(); +$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: { department: current_department, index: 1 }) %>"); +$(".department-item-<%= current_department.id %>").children(":first").html(index); \ No newline at end of file diff --git a/app/views/admins/departments/shared/_department_item.html.erb b/app/views/admins/departments/shared/_department_item.html.erb index 64b4ee70b..62f3a81ac 100644 --- a/app/views/admins/departments/shared/_department_item.html.erb +++ b/app/views/admins/departments/shared/_department_item.html.erb @@ -1,3 +1,4 @@ + <% not_list = defined?(:users_count) %> diff --git a/app/views/admins/departments/shared/_list.html.erb b/app/views/admins/departments/shared/_list.html.erb index 6af63d6f4..09ba2a65f 100644 --- a/app/views/admins/departments/shared/_list.html.erb +++ b/app/views/admins/departments/shared/_list.html.erb @@ -1,10 +1,11 @@
序号 ID 部门名称 单位名称创建者创建者 <%= sort_tag('创建于', name: 'created_at', path: admins_department_applies_path) %> 操作
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= apply.id %> <%= apply.name %> <%= apply.school.try(:name) %><%= list_index_no((params[:page] || 1).to_i, index) %><%= overflow_hidden_span department.name, width: 150 %>
+ - + @@ -14,9 +15,9 @@ <% if departments.present? %> - <% departments.each do |department| %> + <% departments.each_with_index do |department, index| %> - <%= render 'admins/departments/shared/department_item', department: department %> + <%= render partial: 'admins/departments/shared/department_item', locals: {department: department, index: index} %> <% end %> <% else %> diff --git a/app/views/admins/departments/update.js.erb b/app/views/admins/departments/update.js.erb index 359bac59c..d20ca9524 100644 --- a/app/views/admins/departments/update.js.erb +++ b/app/views/admins/departments/update.js.erb @@ -1,4 +1,6 @@ $('.modal.admin-edit-department-modal').modal('hide'); $.notify({ message: '操作成功' }); -$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: { department: current_department }) %>") \ No newline at end of file +var index = $(".department-item-<%= current_department.id %>").children(":first").html(); +$('.department-list-table .department-item-<%= current_department.id %>').html("<%= j(render partial: 'admins/departments/shared/department_item', locals: {department: current_department, index: 1}) %>"); +$(".department-item-<%= current_department.id %>").children(":first").html(index); \ No newline at end of file diff --git a/app/views/admins/identity_authentications/shared/_list.html.erb b/app/views/admins/identity_authentications/shared/_list.html.erb index 607feb93a..6e12d1c54 100644 --- a/app/views/admins/identity_authentications/shared/_list.html.erb +++ b/app/views/admins/identity_authentications/shared/_list.html.erb @@ -3,6 +3,7 @@
序号 部门名称 单位名称 用户数已职业认证已职业认证 部门管理员 统计链接 云主机数
+ <% unless is_processed %> - + <% unless is_processed %> <% if applies.present? %> - <% applies.each do |apply| %> + <% applies.each_with_index do |apply, index| %> <% user = apply.user %> + <% unless is_processed %> <% end %> diff --git a/app/views/admins/laboratories/shared/_laboratory_item.html.erb b/app/views/admins/laboratories/shared/_laboratory_item.html.erb index be9a228b1..765616926 100644 --- a/app/views/admins/laboratories/shared/_laboratory_item.html.erb +++ b/app/views/admins/laboratories/shared/_laboratory_item.html.erb @@ -1,4 +1,5 @@ <% school = laboratory.school %> + + +
序号 <%= check_box_tag('all-check', 1, false, id: nil, class: 'batch-all-check-box', @@ -13,7 +14,7 @@ 姓名 身份证号 学校/单位职称职称 照片 @@ -33,9 +34,10 @@
<%= list_index_no((params[:page] || 1).to_i, index) %><%= check_box_tag('ids[]', apply.id, false, id: nil, class: 'batch-check-box') %><%= list_index_no((params[:page] || 1).to_i, index) %> <%= school&.name || 'EduCoder主站' %> <% if laboratory.identifier %> @@ -31,7 +32,17 @@ <%= laboratory.created_at.strftime('%Y-%m-%d %H:%M') %> <% if school.present? && laboratory.id != 1 %> - <%= check_box_tag :sync_course,!laboratory.sync_course,laboratory.sync_course,remote:true,data:{id:laboratory.id},class:"laboratory-sync-course" %> + <%= check_box_tag :sync_course,!laboratory.sync_course,laboratory.sync_course,remote:true,data:{id:laboratory.id},class:"laboratory-sync-form" %> + <% end %> + + <% if school.present? && laboratory.id != 1 %> + <%= check_box_tag :sync_subject,!laboratory.sync_subject,laboratory.sync_subject,remote:true,data:{id:laboratory.id},class:"laboratory-sync-form" %> + <% end %> + + <% if school.present? && laboratory.id != 1 %> + <%= check_box_tag :sync_shixun,!laboratory.sync_shixun,laboratory.sync_shixun,remote:true,data:{id:laboratory.id},class:"laboratory-sync-form" %> <% end %> diff --git a/app/views/admins/laboratories/shared/_list.html.erb b/app/views/admins/laboratories/shared/_list.html.erb index 90b4bdb7a..a731be44a 100644 --- a/app/views/admins/laboratories/shared/_list.html.erb +++ b/app/views/admins/laboratories/shared/_list.html.erb @@ -1,20 +1,23 @@ + - + - - - + + + + + <% if laboratories.present? %> - <% laboratories.each do |laboratory| %> + <% laboratories.each_with_index do |laboratory, index| %> - <%= render 'admins/laboratories/shared/laboratory_item', laboratory: laboratory %> + <%= render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: laboratory, index: index} %> <% end %> <% else %> diff --git a/app/views/admins/laboratories/update.js.erb b/app/views/admins/laboratories/update.js.erb new file mode 100644 index 000000000..149539ad6 --- /dev/null +++ b/app/views/admins/laboratories/update.js.erb @@ -0,0 +1,3 @@ +var index = $(".laboratory-item-<%= @laboratory.id %>").children(":first").html(); +$(".laboratory-item-<%= @laboratory.id %>").html("<%= j render partial: "admins/laboratories/shared/laboratory_item",locals: {laboratory: @laboratory, index: 1} %>"); +$(".laboratory-item-<%= @laboratory.id %>").children(":first").html(index); \ No newline at end of file diff --git a/app/views/admins/laboratories/update_sync_course.js.erb b/app/views/admins/laboratories/update_sync_course.js.erb index 5ae68f673..663f56ee1 100644 --- a/app/views/admins/laboratories/update_sync_course.js.erb +++ b/app/views/admins/laboratories/update_sync_course.js.erb @@ -1 +1,3 @@ -$("#laboratory-item-<%= @laboratory.id %>").html("<%= j render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: @laboratory} %>") \ No newline at end of file +var index = $(".laboratory-item-<%= @laboratory.id %>").children(":first").html(); +$("#laboratory-item-<%= @laboratory.id %>").html("<%= j render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: @laboratory, index: 1} %>"); +$(".laboratory-item-<%= @laboratory.id %>").children(":first").html(index); \ No newline at end of file diff --git a/app/views/admins/laboratory_settings/show.html.erb b/app/views/admins/laboratory_settings/show.html.erb index b99d6f022..ee9880fbb 100644 --- a/app/views/admins/laboratory_settings/show.html.erb +++ b/app/views/admins/laboratory_settings/show.html.erb @@ -129,6 +129,16 @@ + + diff --git a/app/views/admins/laboratory_shixuns/shared/_list.html.erb b/app/views/admins/laboratory_shixuns/shared/_list.html.erb index e1244c472..462486f4b 100644 --- a/app/views/admins/laboratory_shixuns/shared/_list.html.erb +++ b/app/views/admins/laboratory_shixuns/shared/_list.html.erb @@ -1,21 +1,22 @@
序号 单位名称 域名统计链接统计链接 管理员<%= sort_tag('创建时间', name: 'id', path: admins_laboratories_path) %>同步课堂操作<%= sort_tag('创建时间', name: 'id', path: admins_laboratories_path) %>同步课堂同步实践课程同步实训操作
- + + - + <% if laboratory_shixuns.present? %> - <% laboratory_shixuns.each do |laboratory_shixun| %> + <% laboratory_shixuns.each_with_index do |laboratory_shixun, index| %> - <%= render partial: 'admins/laboratory_shixuns/shared/td', locals: { laboratory_shixun: laboratory_shixun } %> + <%= render partial: 'admins/laboratory_shixuns/shared/td', locals: { laboratory_shixun: laboratory_shixun, index: index } %> <% end %> <% else %> diff --git a/app/views/admins/laboratory_shixuns/shared/_td.html.erb b/app/views/admins/laboratory_shixuns/shared/_td.html.erb index dbdf0df75..d987b53b4 100644 --- a/app/views/admins/laboratory_shixuns/shared/_td.html.erb +++ b/app/views/admins/laboratory_shixuns/shared/_td.html.erb @@ -1,5 +1,6 @@ <%- shixun = laboratory_shixun.shixun -%> +
实训名称序号实训名称 技术平台 技术体系 封面 创建者状态状态 执行时间 操作
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= link_to "/shixuns/#{shixun.identifier}", target: '_blank' do %> <%= shixun.name %> diff --git a/app/views/admins/laboratory_subjects/shared/_list.html.erb b/app/views/admins/laboratory_subjects/shared/_list.html.erb index 55f67dea8..c40d02260 100644 --- a/app/views/admins/laboratory_subjects/shared/_list.html.erb +++ b/app/views/admins/laboratory_subjects/shared/_list.html.erb @@ -1,7 +1,8 @@ - + + @@ -13,10 +14,11 @@ <% if laboratory_subjects.present? %> - <% laboratory_subjects.each do |laboratory_subject| %> + <% laboratory_subjects.each_with_index do |laboratory_subject, index| %> <%- subject = laboratory_subject.subject -%> +
课程名称序号课程名称 技术体系 等级体系 封面
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= link_to(subject.name, "/paths/#{subject.id}", target: '_blank') %> 首页 diff --git a/app/views/admins/laboratory_users/create.js.erb b/app/views/admins/laboratory_users/create.js.erb index f43fd7887..604e62943 100644 --- a/app/views/admins/laboratory_users/create.js.erb +++ b/app/views/admins/laboratory_users/create.js.erb @@ -1,4 +1,6 @@ $('.modal.admin-add-laboratory-user-modal').modal('hide'); $.notify({ message: '操作成功' }); -$('.laboratory-list-table .laboratory-item-<%= current_laboratory.id %>').html("<%= j(render partial: 'admins/laboratories/shared/laboratory_item', locals: { laboratory: current_laboratory }) %>") \ No newline at end of file +var index = $(".laboratory-item-<%= current_laboratory.id %>").children(":first").html(); +$('.laboratory-list-table .laboratory-item-<%= current_laboratory.id %>').html("<%= j(render partial: 'admins/laboratories/shared/laboratory_item', locals: {laboratory: current_laboratory, index: 1}) %>"); +$(".laboratory-item-<%= current_laboratory.id %>").children(":first").html(index); \ No newline at end of file diff --git a/app/views/admins/library_applies/shared/_list.html.erb b/app/views/admins/library_applies/shared/_list.html.erb index 783d0db30..fde3d1d1a 100644 --- a/app/views/admins/library_applies/shared/_list.html.erb +++ b/app/views/admins/library_applies/shared/_list.html.erb @@ -3,11 +3,12 @@ + - + <% if is_processed %> @@ -18,10 +19,11 @@ <% if applies.present? %> - <% applies.each do |apply| %> + <% applies.each_with_index do |apply, index| %> <% user = apply.library.user %> <% library = apply.library %> +
序号 头像 姓名 教学案例 案例描述时间时间拒绝原因 状态
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= link_to "/users/#{user.login}", class: 'professional-authentication-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %> diff --git a/app/views/admins/myshixuns/shared/_list.html.erb b/app/views/admins/myshixuns/shared/_list.html.erb index 440437320..a80a4ef23 100644 --- a/app/views/admins/myshixuns/shared/_list.html.erb +++ b/app/views/admins/myshixuns/shared/_list.html.erb @@ -1,9 +1,10 @@ + - + @@ -14,8 +15,9 @@ <% if myshixuns.present? %> - <% myshixuns.each do |myshixun| %> + <% myshixuns.each_with_index do |myshixun, index| %> +
序号 ID 标识实训名称实训名称 实训老师 完成 经验值
<%= list_index_no(@params_page.to_i, index) %> <%= myshixun.id %> <%= myshixun.identifier %> diff --git a/app/views/admins/partners/shared/_list.html.erb b/app/views/admins/partners/shared/_list.html.erb index 0bebc2a4b..71153c175 100644 --- a/app/views/admins/partners/shared/_list.html.erb +++ b/app/views/admins/partners/shared/_list.html.erb @@ -1,15 +1,17 @@ - + + <% if partners.present? %> - <% partners.each do |partner| %> + <% partners.each_with_index do |partner, index| %> + diff --git a/app/views/admins/professional_authentications/shared/_list.html.erb b/app/views/admins/professional_authentications/shared/_list.html.erb index 6ec6355ba..7ffa5837e 100644 --- a/app/views/admins/professional_authentications/shared/_list.html.erb +++ b/app/views/admins/professional_authentications/shared/_list.html.erb @@ -3,6 +3,7 @@
名称序号名称 <%= sort_tag('添加时间', name: 'created_at', path: admins_partners_path) %> 操作
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= link_to partner.school&.name || partner.name, customers_partner_path(partner), target: '_blank' %>
+ <% unless is_processed %> - + <% unless is_processed %> <% if applies.present? %> - <% applies.each do |apply| %> + <% applies.each_with_index do |apply, index| %> <% user = apply.user %> + <% unless is_processed %> <% end %> diff --git a/app/views/admins/project_package_applies/shared/_list.html.erb b/app/views/admins/project_package_applies/shared/_list.html.erb index d94c96184..bec0912ca 100644 --- a/app/views/admins/project_package_applies/shared/_list.html.erb +++ b/app/views/admins/project_package_applies/shared/_list.html.erb @@ -3,11 +3,12 @@
序号 <%= check_box_tag('all-check', 1, false, id: nil, class: 'batch-all-check-box', @@ -12,7 +13,7 @@ 头像 姓名 学校/单位职称职称 照片 @@ -31,9 +32,10 @@
<%= list_index_no((params[:page] || 1).to_i, index) %><%= check_box_tag('ids[]', apply.id, false, id: nil, class: 'batch-check-box') %>
+ - + <% if is_processed %> @@ -18,10 +19,11 @@ <% if applies.present? %> - <% applies.each do |apply| %> + <% applies.each_with_index do |apply, index| %> <% package = apply.project_package %> <% user = package.creator %> +
序号 头像 姓名 众包需求 需求描述时间时间拒绝原因 状态
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= link_to "/users/#{user.login}", class: 'professional-authentication-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %> diff --git a/app/views/admins/projects/shared/_list.html.erb b/app/views/admins/projects/shared/_list.html.erb index 8a84a72d0..e2a6307ad 100644 --- a/app/views/admins/projects/shared/_list.html.erb +++ b/app/views/admins/projects/shared/_list.html.erb @@ -1,6 +1,7 @@ + @@ -11,14 +12,15 @@ - + <% if projects.present? %> - <% projects.each do |project| %> + <% projects.each_with_index do |project, index| %> +
序号 ID 项目名称 公开里程碑 成员 管理员<%= sort_tag('创建时间', name: 'created_at', path: admins_projects_path) %><%= sort_tag('创建时间', name: 'created_at', path: admins_projects_path) %> 操作
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= project.id %> <%= link_to(project.name, "/projects/#{project.id}", target: '_blank') %> diff --git a/app/views/admins/school_statistics/shared/_list.html.erb b/app/views/admins/school_statistics/shared/_list.html.erb index aa043f097..9d2a1c209 100644 --- a/app/views/admins/school_statistics/shared/_list.html.erb +++ b/app/views/admins/school_statistics/shared/_list.html.erb @@ -20,7 +20,8 @@ - + + @@ -32,8 +33,9 @@ <% if statistics.present? %> - <% statistics.each do |statistic| %> + <% statistics.each_with_index do |statistic, index| %> +
单位名称序号单位名称 <%= sort_tag('新增教师', name: 'teacher_increase_count', path: admins_school_statistics_path) %> <%= sort_tag('新增学生', name: 'student_increase_count', path: admins_school_statistics_path) %> <%= sort_tag('新增课堂', name: 'course_increase_count', path: admins_school_statistics_path) %>
<%= list_index_no(@params_page.to_i, index) %> <%= link_to statistic.school_name, "/colleges/#{statistic.school_id}/statistics", target: '_blank', data: { toggle: 'tooltip', title: '点击查看学校统计概况' } %> diff --git a/app/views/admins/schools/index.html.erb b/app/views/admins/schools/index.html.erb index 9c41067ee..56cbadd9d 100644 --- a/app/views/admins/schools/index.html.erb +++ b/app/views/admins/schools/index.html.erb @@ -4,7 +4,7 @@
<%= form_tag(admins_schools_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> - <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '部门名称检索') %> + <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '单位名称检索') %> <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> diff --git a/app/views/admins/schools/shared/_list.html.erb b/app/views/admins/schools/shared/_list.html.erb index ec7475028..ff0b17992 100644 --- a/app/views/admins/schools/shared/_list.html.erb +++ b/app/views/admins/schools/shared/_list.html.erb @@ -1,6 +1,7 @@ + @@ -11,13 +12,14 @@ - + <% if schools.present? %> - <% schools.each do |school| %> + <% schools.each_with_index do |school, index| %> +
序号 ID LOGO 标识码<%= sort_tag('用户数', name: 'users_count', path: admins_schools_path) %> 部门数 <%= sort_tag('创建时间', name: 'created_at', path: admins_schools_path) %>操作操作
<%= list_index_no((params[:page] || 1).to_i, index) %> <%= school.id %> <% if Util::FileManage.exists?(school) %> diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb index df344fd1a..4b84068e7 100644 --- a/app/views/admins/shared/_sidebar.html.erb +++ b/app/views/admins/shared/_sidebar.html.erb @@ -27,8 +27,9 @@
  • <%= sidebar_item(admins_shixun_settings_path, '实训配置', icon: 'cog', controller: 'admins-shixun_settings') %>
  • <%= sidebar_item(admins_mirror_repositories_path, '镜像管理', icon: 'cubes', controller: 'admins-mirror_repositories') %>
  • <%= sidebar_item(admins_myshixuns_path, '学员实训列表', icon: 'server', controller: 'admins-myshixuns') %>
  • -
  • <%= sidebar_item(admins_shixun_recycles_path, '实训回收站', icon: 'recycle', controller: 'admins-myshixuns') %>
  • - <% end %> +
  • <%= sidebar_item(admins_shixun_modify_records_path, '实训修改记录', icon: 'eraser', controller: 'admins-shixun_modify_records') %>
  • +
  • <%= sidebar_item(admins_shixun_recycles_path, '实训回收站', icon: 'recycle', controller: 'admins-shixun_recycles') %>
  • + <% end %>
  • diff --git a/app/views/admins/shixun_authorizations/shared/_list.html.erb b/app/views/admins/shixun_authorizations/shared/_list.html.erb index c1dec5f45..c3828ec86 100644 --- a/app/views/admins/shixun_authorizations/shared/_list.html.erb +++ b/app/views/admins/shixun_authorizations/shared/_list.html.erb @@ -3,11 +3,12 @@ + - + <% if is_processed %> @@ -19,12 +20,13 @@ <% if applies.present? %> - <% applies.each do |apply| %> + <% applies.each_with_index do |apply, index| %> <% user = apply.user %> <% shixun = shixun_map[apply.container_id] %> <% content_review = shixun.shixun_reviews.select{|sr| sr.review_type == 'Content'}.first %> <% perference_review = shixun.shixun_reviews.select{|sr| sr.review_type == 'Performance'}.first %> + <% identifier = Game.find_by(challenge_id: discuss.challenge_id, user_id: discuss.user_id)&.identifier %> - + diff --git a/app/views/admins/shixun_modify_records/index.html.erb b/app/views/admins/shixun_modify_records/index.html.erb new file mode 100644 index 000000000..cecba30cb --- /dev/null +++ b/app/views/admins/shixun_modify_records/index.html.erb @@ -0,0 +1,25 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('实训修改记录') %> +<% end %> + +
    + <%= form_tag(admins_shixun_modify_records_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> +
    + + <%= text_field_tag :user_name, params[:user_name], class: 'form-control flex-1', placeholder: '真实姓名搜索' %> +
    + +
    + + <% data_arrs = [['最近一周', 'weekly'], ['最近一个月', 'monthly']] %> + <%= select_tag(:date, options_for_select(data_arrs, params[:date]), class: 'form-control') %> +
    + + <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> + + <% end %> +
    + +
    + <%= render partial: 'admins/shixun_modify_records/shared/list', locals: { records: @records } %> +
    \ No newline at end of file diff --git a/app/views/admins/shixun_modify_records/index.js.erb b/app/views/admins/shixun_modify_records/index.js.erb new file mode 100644 index 000000000..fc9dc033b --- /dev/null +++ b/app/views/admins/shixun_modify_records/index.js.erb @@ -0,0 +1 @@ +$('.shixun-modify-record-list-container').html("<%= j( render partial: 'admins/shixun_modify_records/shared/list', locals: { records: @records } ) %>"); \ No newline at end of file diff --git a/app/views/admins/shixun_modify_records/shared/_list.html.erb b/app/views/admins/shixun_modify_records/shared/_list.html.erb new file mode 100644 index 000000000..525583d8e --- /dev/null +++ b/app/views/admins/shixun_modify_records/shared/_list.html.erb @@ -0,0 +1,36 @@ +<% if records.present? %> + <% records.each do |record| %> +
    +
    + <%= record.user.real_name %> + <%= format_time record.created_at %> +
    + +
    + 实训名称:<%= record.container&.shixun&.name %> + <% if record.container_type == "Challenge" %> + / + 关卡名:<%= record.container&.subject %> + <% end %> +
    + +
    +
      + <% record.diff_record_content&.content&.split("\n").each do |line| %> + <% if line =~ /^[\+]/ %> +
    • <%= line %>
    • + <% elsif line =~ /^[\-]/ %> +
    • <%= line %>
    • + <% else %> +
    • <%= line %>
    • + <% end %> + <% end %> +
    +
    +
    + <% end %> +<% else %> + <%= render 'admins/shared/no_data_for_table' %> +<% end %> + +<%= render partial: 'admins/shared/paginate', locals: { objects: records } %> \ No newline at end of file diff --git a/app/views/admins/shixun_recycles/shared/_list.html.erb b/app/views/admins/shixun_recycles/shared/_list.html.erb index 60d2742e9..5518fc753 100644 --- a/app/views/admins/shixun_recycles/shared/_list.html.erb +++ b/app/views/admins/shixun_recycles/shared/_list.html.erb @@ -1,16 +1,18 @@
    序号 头像 创建者 实训名称 审核情况任务数任务数 时间拒绝原因
    <%= list_index_no((params[:page] || 1).to_i, index) %> <%= link_to "/users/#{user.login}", class: 'shixun-authorization-avatar', target: '_blank', data: { toggle: 'tooltip', title: '个人主页' } do %> diff --git a/app/views/admins/shixun_feedback_messages/shared/_list.html.erb b/app/views/admins/shixun_feedback_messages/shared/_list.html.erb index af81f9e58..dfe140428 100644 --- a/app/views/admins/shixun_feedback_messages/shared/_list.html.erb +++ b/app/views/admins/shixun_feedback_messages/shared/_list.html.erb @@ -15,7 +15,7 @@ <%= (@params_page.to_i - 1) * 20 + index + 1 %><%= link_to discuss.dis.name, "/tasks/#{identifier}", target: '_blank'%><%= content_safe discuss.content %><%= content_safe discuss.content %> <%= discuss.user.show_real_name %> <%= format_time discuss.created_at %>
    + - + <% if shixuns.present? %> - <% shixuns.each do |shixun| %> + <% shixuns.each_with_index do |shixun, index| %> + diff --git a/app/views/admins/shixun_settings/index.html.erb b/app/views/admins/shixun_settings/index.html.erb index 7aab73f64..66286926a 100644 --- a/app/views/admins/shixun_settings/index.html.erb +++ b/app/views/admins/shixun_settings/index.html.erb @@ -65,6 +65,12 @@ 只看已隐藏文件目录 +
    + +
    <% end %> diff --git a/app/views/admins/shixun_settings/shared/_list.html.erb b/app/views/admins/shixun_settings/shared/_list.html.erb index 7591fe323..549c7edf4 100644 --- a/app/views/admins/shixun_settings/shared/_list.html.erb +++ b/app/views/admins/shixun_settings/shared/_list.html.erb @@ -1,12 +1,13 @@
    序号 ID 实训名称子站源子站源 创建者 <%= sort_tag('创建于', name: 'created_at', path: admins_shixun_recycles_path) %> 操作
    <%= list_index_no((params[:page] || 1).to_i, index) %> <%= shixun.identifier %> <%= link_to overflow_hidden_span(shixun.name), "/shixuns/#{shixun.identifier}", :target => "_blank", :title => shixun.name %> <%= shixun.laboratory&.school&.name %>
    - + + - - - + + + @@ -14,7 +15,7 @@ diff --git a/app/views/admins/shixun_settings/shared/_td.html.erb b/app/views/admins/shixun_settings/shared/_td.html.erb index f4a05f178..fc5af645a 100644 --- a/app/views/admins/shixun_settings/shared/_td.html.erb +++ b/app/views/admins/shixun_settings/shared/_td.html.erb @@ -1,3 +1,4 @@ + diff --git a/public/react/public/js/applications.js b/public/react/public/js/applications.js new file mode 100644 index 000000000..ad46a5aa0 --- /dev/null +++ b/public/react/public/js/applications.js @@ -0,0 +1,19833 @@ +/* +Unobtrusive JavaScript +https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts +Released under the MIT license + */ + + +(function() { + var context = this; + + (function() { + (function() { + this.Rails = { + linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]', + buttonClickSelector: { + selector: 'button[data-remote]:not([form]), button[data-confirm]:not([form])', + exclude: 'form button' + }, + inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]', + formSubmitSelector: 'form', + formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])', + formDisableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled', + formEnableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled', + fileInputSelector: 'input[name][type=file]:not([disabled])', + linkDisableSelector: 'a[data-disable-with], a[data-disable]', + buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]' + }; + + }).call(this); + }).call(context); + + var Rails = context.Rails; + + (function() { + (function() { + var nonce; + + nonce = null; + + Rails.loadCSPNonce = function() { + var ref; + return nonce = (ref = document.querySelector("meta[name=csp-nonce]")) != null ? ref.content : void 0; + }; + + Rails.cspNonce = function() { + return nonce != null ? nonce : Rails.loadCSPNonce(); + }; + + }).call(this); + (function() { + var expando, m; + + m = Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector; + + Rails.matches = function(element, selector) { + if (selector.exclude != null) { + return m.call(element, selector.selector) && !m.call(element, selector.exclude); + } else { + return m.call(element, selector); + } + }; + + expando = '_ujsData'; + + Rails.getData = function(element, key) { + var ref; + return (ref = element[expando]) != null ? ref[key] : void 0; + }; + + Rails.setData = function(element, key, value) { + if (element[expando] == null) { + element[expando] = {}; + } + return element[expando][key] = value; + }; + + Rails.$ = function(selector) { + return Array.prototype.slice.call(document.querySelectorAll(selector)); + }; + + }).call(this); + (function() { + var $, csrfParam, csrfToken; + + $ = Rails.$; + + csrfToken = Rails.csrfToken = function() { + var meta; + meta = document.querySelector('meta[name=csrf-token]'); + return meta && meta.content; + }; + + csrfParam = Rails.csrfParam = function() { + var meta; + meta = document.querySelector('meta[name=csrf-param]'); + return meta && meta.content; + }; + + Rails.CSRFProtection = function(xhr) { + var token; + token = csrfToken(); + if (token != null) { + return xhr.setRequestHeader('X-CSRF-Token', token); + } + }; + + Rails.refreshCSRFTokens = function() { + var param, token; + token = csrfToken(); + param = csrfParam(); + if ((token != null) && (param != null)) { + return $('form input[name="' + param + '"]').forEach(function(input) { + return input.value = token; + }); + } + }; + + }).call(this); + (function() { + var CustomEvent, fire, matches, preventDefault; + + matches = Rails.matches; + + CustomEvent = window.CustomEvent; + + if (typeof CustomEvent !== 'function') { + CustomEvent = function(event, params) { + var evt; + evt = document.createEvent('CustomEvent'); + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); + return evt; + }; + CustomEvent.prototype = window.Event.prototype; + preventDefault = CustomEvent.prototype.preventDefault; + CustomEvent.prototype.preventDefault = function() { + var result; + result = preventDefault.call(this); + if (this.cancelable && !this.defaultPrevented) { + Object.defineProperty(this, 'defaultPrevented', { + get: function() { + return true; + } + }); + } + return result; + }; + } + + fire = Rails.fire = function(obj, name, data) { + var event; + event = new CustomEvent(name, { + bubbles: true, + cancelable: true, + detail: data + }); + obj.dispatchEvent(event); + return !event.defaultPrevented; + }; + + Rails.stopEverything = function(e) { + fire(e.target, 'ujs:everythingStopped'); + e.preventDefault(); + e.stopPropagation(); + return e.stopImmediatePropagation(); + }; + + Rails.delegate = function(element, selector, eventType, handler) { + return element.addEventListener(eventType, function(e) { + var target; + target = e.target; + while (!(!(target instanceof Element) || matches(target, selector))) { + target = target.parentNode; + } + if (target instanceof Element && handler.call(target, e) === false) { + e.preventDefault(); + return e.stopPropagation(); + } + }); + }; + + }).call(this); + (function() { + var AcceptHeaders, CSRFProtection, createXHR, cspNonce, fire, prepareOptions, processResponse; + + cspNonce = Rails.cspNonce, CSRFProtection = Rails.CSRFProtection, fire = Rails.fire; + + AcceptHeaders = { + '*': '*/*', + text: 'text/plain', + html: 'text/html', + xml: 'application/xml, text/xml', + json: 'application/json, text/javascript', + script: 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript' + }; + + Rails.ajax = function(options) { + var xhr; + options = prepareOptions(options); + xhr = createXHR(options, function() { + var ref, response; + response = processResponse((ref = xhr.response) != null ? ref : xhr.responseText, xhr.getResponseHeader('Content-Type')); + if (Math.floor(xhr.status / 100) === 2) { + if (typeof options.success === "function") { + options.success(response, xhr.statusText, xhr); + } + } else { + if (typeof options.error === "function") { + options.error(response, xhr.statusText, xhr); + } + } + return typeof options.complete === "function" ? options.complete(xhr, xhr.statusText) : void 0; + }); + if ((options.beforeSend != null) && !options.beforeSend(xhr, options)) { + return false; + } + if (xhr.readyState === XMLHttpRequest.OPENED) { + return xhr.send(options.data); + } + }; + + prepareOptions = function(options) { + options.url = options.url || location.href; + options.type = options.type.toUpperCase(); + if (options.type === 'GET' && options.data) { + if (options.url.indexOf('?') < 0) { + options.url += '?' + options.data; + } else { + options.url += '&' + options.data; + } + } + if (AcceptHeaders[options.dataType] == null) { + options.dataType = '*'; + } + options.accept = AcceptHeaders[options.dataType]; + if (options.dataType !== '*') { + options.accept += ', */*; q=0.01'; + } + return options; + }; + + createXHR = function(options, done) { + var xhr; + xhr = new XMLHttpRequest(); + xhr.open(options.type, options.url, true); + xhr.setRequestHeader('Accept', options.accept); + if (typeof options.data === 'string') { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); + } + if (!options.crossDomain) { + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + } + CSRFProtection(xhr); + xhr.withCredentials = !!options.withCredentials; + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.DONE) { + return done(xhr); + } + }; + return xhr; + }; + + processResponse = function(response, type) { + var parser, script; + if (typeof response === 'string' && typeof type === 'string') { + if (type.match(/\bjson\b/)) { + try { + response = JSON.parse(response); + } catch (error) {} + } else if (type.match(/\b(?:java|ecma)script\b/)) { + script = document.createElement('script'); + script.setAttribute('nonce', cspNonce()); + script.text = response; + document.head.appendChild(script).parentNode.removeChild(script); + } else if (type.match(/\b(xml|html|svg)\b/)) { + parser = new DOMParser(); + type = type.replace(/;.+/, ''); + try { + response = parser.parseFromString(response, type); + } catch (error) {} + } + } + return response; + }; + + Rails.href = function(element) { + return element.href; + }; + + Rails.isCrossDomain = function(url) { + var e, originAnchor, urlAnchor; + originAnchor = document.createElement('a'); + originAnchor.href = location.href; + urlAnchor = document.createElement('a'); + try { + urlAnchor.href = url; + return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) || (originAnchor.protocol + '//' + originAnchor.host === urlAnchor.protocol + '//' + urlAnchor.host)); + } catch (error) { + e = error; + return true; + } + }; + + }).call(this); + (function() { + var matches, toArray; + + matches = Rails.matches; + + toArray = function(e) { + return Array.prototype.slice.call(e); + }; + + Rails.serializeElement = function(element, additionalParam) { + var inputs, params; + inputs = [element]; + if (matches(element, 'form')) { + inputs = toArray(element.elements); + } + params = []; + inputs.forEach(function(input) { + if (!input.name || input.disabled) { + return; + } + if (matches(input, 'select')) { + return toArray(input.options).forEach(function(option) { + if (option.selected) { + return params.push({ + name: input.name, + value: option.value + }); + } + }); + } else if (input.checked || ['radio', 'checkbox', 'submit'].indexOf(input.type) === -1) { + return params.push({ + name: input.name, + value: input.value + }); + } + }); + if (additionalParam) { + params.push(additionalParam); + } + return params.map(function(param) { + if (param.name != null) { + return (encodeURIComponent(param.name)) + "=" + (encodeURIComponent(param.value)); + } else { + return param; + } + }).join('&'); + }; + + Rails.formElements = function(form, selector) { + if (matches(form, 'form')) { + return toArray(form.elements).filter(function(el) { + return matches(el, selector); + }); + } else { + return toArray(form.querySelectorAll(selector)); + } + }; + + }).call(this); + (function() { + var allowAction, fire, stopEverything; + + fire = Rails.fire, stopEverything = Rails.stopEverything; + + Rails.handleConfirm = function(e) { + if (!allowAction(this)) { + return stopEverything(e); + } + }; + + allowAction = function(element) { + var answer, callback, message; + message = element.getAttribute('data-confirm'); + if (!message) { + return true; + } + answer = false; + if (fire(element, 'confirm')) { + try { + answer = confirm(message); + } catch (error) {} + callback = fire(element, 'confirm:complete', [answer]); + } + return answer && callback; + }; + + }).call(this); + (function() { + var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, matches, setData, stopEverything; + + matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, stopEverything = Rails.stopEverything, formElements = Rails.formElements; + + Rails.handleDisabledElement = function(e) { + var element; + element = this; + if (element.disabled) { + return stopEverything(e); + } + }; + + Rails.enableElement = function(e) { + var element; + element = e instanceof Event ? e.target : e; + if (matches(element, Rails.linkDisableSelector)) { + return enableLinkElement(element); + } else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formEnableSelector)) { + return enableFormElement(element); + } else if (matches(element, Rails.formSubmitSelector)) { + return enableFormElements(element); + } + }; + + Rails.disableElement = function(e) { + var element; + element = e instanceof Event ? e.target : e; + if (matches(element, Rails.linkDisableSelector)) { + return disableLinkElement(element); + } else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formDisableSelector)) { + return disableFormElement(element); + } else if (matches(element, Rails.formSubmitSelector)) { + return disableFormElements(element); + } + }; + + disableLinkElement = function(element) { + var replacement; + replacement = element.getAttribute('data-disable-with'); + if (replacement != null) { + setData(element, 'ujs:enable-with', element.innerHTML); + element.innerHTML = replacement; + } + element.addEventListener('click', stopEverything); + return setData(element, 'ujs:disabled', true); + }; + + enableLinkElement = function(element) { + var originalText; + originalText = getData(element, 'ujs:enable-with'); + if (originalText != null) { + element.innerHTML = originalText; + setData(element, 'ujs:enable-with', null); + } + element.removeEventListener('click', stopEverything); + return setData(element, 'ujs:disabled', null); + }; + + disableFormElements = function(form) { + return formElements(form, Rails.formDisableSelector).forEach(disableFormElement); + }; + + disableFormElement = function(element) { + var replacement; + replacement = element.getAttribute('data-disable-with'); + if (replacement != null) { + if (matches(element, 'button')) { + setData(element, 'ujs:enable-with', element.innerHTML); + element.innerHTML = replacement; + } else { + setData(element, 'ujs:enable-with', element.value); + element.value = replacement; + } + } + element.disabled = true; + return setData(element, 'ujs:disabled', true); + }; + + enableFormElements = function(form) { + return formElements(form, Rails.formEnableSelector).forEach(enableFormElement); + }; + + enableFormElement = function(element) { + var originalText; + originalText = getData(element, 'ujs:enable-with'); + if (originalText != null) { + if (matches(element, 'button')) { + element.innerHTML = originalText; + } else { + element.value = originalText; + } + setData(element, 'ujs:enable-with', null); + } + element.disabled = false; + return setData(element, 'ujs:disabled', null); + }; + + }).call(this); + (function() { + var stopEverything; + + stopEverything = Rails.stopEverything; + + Rails.handleMethod = function(e) { + var csrfParam, csrfToken, form, formContent, href, link, method; + link = this; + method = link.getAttribute('data-method'); + if (!method) { + return; + } + href = Rails.href(link); + csrfToken = Rails.csrfToken(); + csrfParam = Rails.csrfParam(); + form = document.createElement('form'); + formContent = ""; + if ((csrfParam != null) && (csrfToken != null) && !Rails.isCrossDomain(href)) { + formContent += ""; + } + formContent += ''; + form.method = 'post'; + form.action = href; + form.target = link.target; + form.innerHTML = formContent; + form.style.display = 'none'; + document.body.appendChild(form); + form.querySelector('[type="submit"]').click(); + return stopEverything(e); + }; + + }).call(this); + (function() { + var ajax, fire, getData, isCrossDomain, isRemote, matches, serializeElement, setData, stopEverything, + slice = [].slice; + + matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, fire = Rails.fire, stopEverything = Rails.stopEverything, ajax = Rails.ajax, isCrossDomain = Rails.isCrossDomain, serializeElement = Rails.serializeElement; + + isRemote = function(element) { + var value; + value = element.getAttribute('data-remote'); + return (value != null) && value !== 'false'; + }; + + Rails.handleRemote = function(e) { + var button, data, dataType, element, method, url, withCredentials; + element = this; + if (!isRemote(element)) { + return true; + } + if (!fire(element, 'ajax:before')) { + fire(element, 'ajax:stopped'); + return false; + } + withCredentials = element.getAttribute('data-with-credentials'); + dataType = element.getAttribute('data-type') || 'script'; + if (matches(element, Rails.formSubmitSelector)) { + button = getData(element, 'ujs:submit-button'); + method = getData(element, 'ujs:submit-button-formmethod') || element.method; + url = getData(element, 'ujs:submit-button-formaction') || element.getAttribute('action') || location.href; + if (method.toUpperCase() === 'GET') { + url = url.replace(/\?.*$/, ''); + } + if (element.enctype === 'multipart/form-data') { + data = new FormData(element); + if (button != null) { + data.append(button.name, button.value); + } + } else { + data = serializeElement(element, button); + } + setData(element, 'ujs:submit-button', null); + setData(element, 'ujs:submit-button-formmethod', null); + setData(element, 'ujs:submit-button-formaction', null); + } else if (matches(element, Rails.buttonClickSelector) || matches(element, Rails.inputChangeSelector)) { + method = element.getAttribute('data-method'); + url = element.getAttribute('data-url'); + data = serializeElement(element, element.getAttribute('data-params')); + } else { + method = element.getAttribute('data-method'); + url = Rails.href(element); + data = element.getAttribute('data-params'); + } + ajax({ + type: method || 'GET', + url: url, + data: data, + dataType: dataType, + beforeSend: function(xhr, options) { + if (fire(element, 'ajax:beforeSend', [xhr, options])) { + return fire(element, 'ajax:send', [xhr]); + } else { + fire(element, 'ajax:stopped'); + return false; + } + }, + success: function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return fire(element, 'ajax:success', args); + }, + error: function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return fire(element, 'ajax:error', args); + }, + complete: function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return fire(element, 'ajax:complete', args); + }, + crossDomain: isCrossDomain(url), + withCredentials: (withCredentials != null) && withCredentials !== 'false' + }); + return stopEverything(e); + }; + + Rails.formSubmitButtonClick = function(e) { + var button, form; + button = this; + form = button.form; + if (!form) { + return; + } + if (button.name) { + setData(form, 'ujs:submit-button', { + name: button.name, + value: button.value + }); + } + setData(form, 'ujs:formnovalidate-button', button.formNoValidate); + setData(form, 'ujs:submit-button-formaction', button.getAttribute('formaction')); + return setData(form, 'ujs:submit-button-formmethod', button.getAttribute('formmethod')); + }; + + Rails.preventInsignificantClick = function(e) { + var data, insignificantMetaClick, link, metaClick, method, primaryMouseKey; + link = this; + method = (link.getAttribute('data-method') || 'GET').toUpperCase(); + data = link.getAttribute('data-params'); + metaClick = e.metaKey || e.ctrlKey; + insignificantMetaClick = metaClick && method === 'GET' && !data; + primaryMouseKey = e.button === 0; + if (!primaryMouseKey || insignificantMetaClick) { + return e.stopImmediatePropagation(); + } + }; + + }).call(this); + (function() { + var $, CSRFProtection, delegate, disableElement, enableElement, fire, formSubmitButtonClick, getData, handleConfirm, handleDisabledElement, handleMethod, handleRemote, loadCSPNonce, preventInsignificantClick, refreshCSRFTokens; + + fire = Rails.fire, delegate = Rails.delegate, getData = Rails.getData, $ = Rails.$, refreshCSRFTokens = Rails.refreshCSRFTokens, CSRFProtection = Rails.CSRFProtection, loadCSPNonce = Rails.loadCSPNonce, enableElement = Rails.enableElement, disableElement = Rails.disableElement, handleDisabledElement = Rails.handleDisabledElement, handleConfirm = Rails.handleConfirm, preventInsignificantClick = Rails.preventInsignificantClick, handleRemote = Rails.handleRemote, formSubmitButtonClick = Rails.formSubmitButtonClick, handleMethod = Rails.handleMethod; + + if ((typeof jQuery !== "undefined" && jQuery !== null) && (jQuery.ajax != null)) { + if (jQuery.rails) { + throw new Error('If you load both jquery_ujs and rails-ujs, use rails-ujs only.'); + } + jQuery.rails = Rails; + jQuery.ajaxPrefilter(function(options, originalOptions, xhr) { + if (!options.crossDomain) { + return CSRFProtection(xhr); + } + }); + } + + Rails.start = function() { + if (window._rails_loaded) { + throw new Error('rails-ujs has already been loaded!'); + } + window.addEventListener('pageshow', function() { + $(Rails.formEnableSelector).forEach(function(el) { + if (getData(el, 'ujs:disabled')) { + return enableElement(el); + } + }); + return $(Rails.linkDisableSelector).forEach(function(el) { + if (getData(el, 'ujs:disabled')) { + return enableElement(el); + } + }); + }); + delegate(document, Rails.linkDisableSelector, 'ajax:complete', enableElement); + delegate(document, Rails.linkDisableSelector, 'ajax:stopped', enableElement); + delegate(document, Rails.buttonDisableSelector, 'ajax:complete', enableElement); + delegate(document, Rails.buttonDisableSelector, 'ajax:stopped', enableElement); + delegate(document, Rails.linkClickSelector, 'click', preventInsignificantClick); + delegate(document, Rails.linkClickSelector, 'click', handleDisabledElement); + delegate(document, Rails.linkClickSelector, 'click', handleConfirm); + delegate(document, Rails.linkClickSelector, 'click', disableElement); + delegate(document, Rails.linkClickSelector, 'click', handleRemote); + delegate(document, Rails.linkClickSelector, 'click', handleMethod); + delegate(document, Rails.buttonClickSelector, 'click', preventInsignificantClick); + delegate(document, Rails.buttonClickSelector, 'click', handleDisabledElement); + delegate(document, Rails.buttonClickSelector, 'click', handleConfirm); + delegate(document, Rails.buttonClickSelector, 'click', disableElement); + delegate(document, Rails.buttonClickSelector, 'click', handleRemote); + delegate(document, Rails.inputChangeSelector, 'change', handleDisabledElement); + delegate(document, Rails.inputChangeSelector, 'change', handleConfirm); + delegate(document, Rails.inputChangeSelector, 'change', handleRemote); + delegate(document, Rails.formSubmitSelector, 'submit', handleDisabledElement); + delegate(document, Rails.formSubmitSelector, 'submit', handleConfirm); + delegate(document, Rails.formSubmitSelector, 'submit', handleRemote); + delegate(document, Rails.formSubmitSelector, 'submit', function(e) { + return setTimeout((function() { + return disableElement(e); + }), 13); + }); + delegate(document, Rails.formSubmitSelector, 'ajax:send', disableElement); + delegate(document, Rails.formSubmitSelector, 'ajax:complete', enableElement); + delegate(document, Rails.formInputClickSelector, 'click', preventInsignificantClick); + delegate(document, Rails.formInputClickSelector, 'click', handleDisabledElement); + delegate(document, Rails.formInputClickSelector, 'click', handleConfirm); + delegate(document, Rails.formInputClickSelector, 'click', formSubmitButtonClick); + document.addEventListener('DOMContentLoaded', refreshCSRFTokens); + document.addEventListener('DOMContentLoaded', loadCSPNonce); + return window._rails_loaded = true; + }; + + if (window.Rails === Rails && fire(document, 'rails:attachBindings')) { + Rails.start(); + } + + }).call(this); + }).call(this); + + if (typeof module === "object" && module.exports) { + module.exports = Rails; + } else if (typeof define === "function" && define.amd) { + define(Rails); + } +}).call(this); +(function(global, factory) { + typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : factory(global.ActiveStorage = {}); +})(this, function(exports) { + "use strict"; + function createCommonjsModule(fn, module) { + return module = { + exports: {} + }, fn(module, module.exports), module.exports; + } + var sparkMd5 = createCommonjsModule(function(module, exports) { + (function(factory) { + { + module.exports = factory(); + } + })(function(undefined) { + var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ]; + function md5cycle(x, k) { + var a = x[0], b = x[1], c = x[2], d = x[3]; + a += (b & c | ~b & d) + k[0] - 680876936 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[1] - 389564586 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[2] + 606105819 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[3] - 1044525330 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[4] - 176418897 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[5] + 1200080426 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[6] - 1473231341 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[7] - 45705983 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[8] + 1770035416 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[9] - 1958414417 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[10] - 42063 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[11] - 1990404162 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & c | ~b & d) + k[12] + 1804603682 | 0; + a = (a << 7 | a >>> 25) + b | 0; + d += (a & b | ~a & c) + k[13] - 40341101 | 0; + d = (d << 12 | d >>> 20) + a | 0; + c += (d & a | ~d & b) + k[14] - 1502002290 | 0; + c = (c << 17 | c >>> 15) + d | 0; + b += (c & d | ~c & a) + k[15] + 1236535329 | 0; + b = (b << 22 | b >>> 10) + c | 0; + a += (b & d | c & ~d) + k[1] - 165796510 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[6] - 1069501632 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[11] + 643717713 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[0] - 373897302 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[5] - 701558691 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[10] + 38016083 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[15] - 660478335 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[4] - 405537848 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[9] + 568446438 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[14] - 1019803690 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[3] - 187363961 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[8] + 1163531501 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b & d | c & ~d) + k[13] - 1444681467 | 0; + a = (a << 5 | a >>> 27) + b | 0; + d += (a & c | b & ~c) + k[2] - 51403784 | 0; + d = (d << 9 | d >>> 23) + a | 0; + c += (d & b | a & ~b) + k[7] + 1735328473 | 0; + c = (c << 14 | c >>> 18) + d | 0; + b += (c & a | d & ~a) + k[12] - 1926607734 | 0; + b = (b << 20 | b >>> 12) + c | 0; + a += (b ^ c ^ d) + k[5] - 378558 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[8] - 2022574463 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[11] + 1839030562 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[14] - 35309556 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[1] - 1530992060 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[4] + 1272893353 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[7] - 155497632 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[10] - 1094730640 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[13] + 681279174 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[0] - 358537222 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[3] - 722521979 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[6] + 76029189 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (b ^ c ^ d) + k[9] - 640364487 | 0; + a = (a << 4 | a >>> 28) + b | 0; + d += (a ^ b ^ c) + k[12] - 421815835 | 0; + d = (d << 11 | d >>> 21) + a | 0; + c += (d ^ a ^ b) + k[15] + 530742520 | 0; + c = (c << 16 | c >>> 16) + d | 0; + b += (c ^ d ^ a) + k[2] - 995338651 | 0; + b = (b << 23 | b >>> 9) + c | 0; + a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; + b = (b << 21 | b >>> 11) + c | 0; + a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; + a = (a << 6 | a >>> 26) + b | 0; + d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; + d = (d << 10 | d >>> 22) + a | 0; + c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; + c = (c << 15 | c >>> 17) + d | 0; + b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; + b = (b << 21 | b >>> 11) + c | 0; + x[0] = a + x[0] | 0; + x[1] = b + x[1] | 0; + x[2] = c + x[2] | 0; + x[3] = d + x[3] | 0; + } + function md5blk(s) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; + } + function md5blk_array(a) { + var md5blks = [], i; + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); + } + return md5blks; + } + function md51(s) { + var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + length = s.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function md51_array(a) { + var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; + for (i = 64; i <= n; i += 64) { + md5cycle(state, md5blk_array(a.subarray(i - 64, i))); + } + a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0); + length = a.length; + tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= a[i] << (i % 4 << 3); + } + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = n * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(state, tail); + return state; + } + function rhex(n) { + var s = "", j; + for (j = 0; j < 4; j += 1) { + s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15]; + } + return s; + } + function hex(x) { + var i; + for (i = 0; i < x.length; i += 1) { + x[i] = rhex(x[i]); + } + return x.join(""); + } + if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ; + if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) { + (function() { + function clamp(val, length) { + val = val | 0 || 0; + if (val < 0) { + return Math.max(val + length, 0); + } + return Math.min(val, length); + } + ArrayBuffer.prototype.slice = function(from, to) { + var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray; + if (to !== undefined) { + end = clamp(to, length); + } + if (begin > end) { + return new ArrayBuffer(0); + } + num = end - begin; + target = new ArrayBuffer(num); + targetArray = new Uint8Array(target); + sourceArray = new Uint8Array(this, begin, num); + targetArray.set(sourceArray); + return target; + }; + })(); + } + function toUtf8(str) { + if (/[\u0080-\uFFFF]/.test(str)) { + str = unescape(encodeURIComponent(str)); + } + return str; + } + function utf8Str2ArrayBuffer(str, returnUInt8Array) { + var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i; + for (i = 0; i < length; i += 1) { + arr[i] = str.charCodeAt(i); + } + return returnUInt8Array ? arr : buff; + } + function arrayBuffer2Utf8Str(buff) { + return String.fromCharCode.apply(null, new Uint8Array(buff)); + } + function concatenateArrayBuffers(first, second, returnUInt8Array) { + var result = new Uint8Array(first.byteLength + second.byteLength); + result.set(new Uint8Array(first)); + result.set(new Uint8Array(second), first.byteLength); + return returnUInt8Array ? result : result.buffer; + } + function hexToBinaryString(hex) { + var bytes = [], length = hex.length, x; + for (x = 0; x < length - 1; x += 2) { + bytes.push(parseInt(hex.substr(x, 2), 16)); + } + return String.fromCharCode.apply(String, bytes); + } + function SparkMD5() { + this.reset(); + } + SparkMD5.prototype.append = function(str) { + this.appendBinary(toUtf8(str)); + return this; + }; + SparkMD5.prototype.appendBinary = function(contents) { + this._buff += contents; + this._length += contents.length; + var length = this._buff.length, i; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i))); + } + this._buff = this._buff.substring(i - 64); + return this; + }; + SparkMD5.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.prototype.reset = function() { + this._buff = ""; + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.prototype.getState = function() { + return { + buff: this._buff, + length: this._length, + hash: this._hash + }; + }; + SparkMD5.prototype.setState = function(state) { + this._buff = state.buff; + this._length = state.length; + this._hash = state.hash; + return this; + }; + SparkMD5.prototype.destroy = function() { + delete this._hash; + delete this._buff; + delete this._length; + }; + SparkMD5.prototype._finish = function(tail, length) { + var i = length, tmp, lo, hi; + tail[i >> 2] |= 128 << (i % 4 << 3); + if (i > 55) { + md5cycle(this._hash, tail); + for (i = 0; i < 16; i += 1) { + tail[i] = 0; + } + } + tmp = this._length * 8; + tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); + lo = parseInt(tmp[2], 16); + hi = parseInt(tmp[1], 16) || 0; + tail[14] = lo; + tail[15] = hi; + md5cycle(this._hash, tail); + }; + SparkMD5.hash = function(str, raw) { + return SparkMD5.hashBinary(toUtf8(str), raw); + }; + SparkMD5.hashBinary = function(content, raw) { + var hash = md51(content), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + SparkMD5.ArrayBuffer = function() { + this.reset(); + }; + SparkMD5.ArrayBuffer.prototype.append = function(arr) { + var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i; + this._length += arr.byteLength; + for (i = 64; i <= length; i += 64) { + md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i))); + } + this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0); + return this; + }; + SparkMD5.ArrayBuffer.prototype.end = function(raw) { + var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret; + for (i = 0; i < length; i += 1) { + tail[i >> 2] |= buff[i] << (i % 4 << 3); + } + this._finish(tail, length); + ret = hex(this._hash); + if (raw) { + ret = hexToBinaryString(ret); + } + this.reset(); + return ret; + }; + SparkMD5.ArrayBuffer.prototype.reset = function() { + this._buff = new Uint8Array(0); + this._length = 0; + this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; + return this; + }; + SparkMD5.ArrayBuffer.prototype.getState = function() { + var state = SparkMD5.prototype.getState.call(this); + state.buff = arrayBuffer2Utf8Str(state.buff); + return state; + }; + SparkMD5.ArrayBuffer.prototype.setState = function(state) { + state.buff = utf8Str2ArrayBuffer(state.buff, true); + return SparkMD5.prototype.setState.call(this, state); + }; + SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; + SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; + SparkMD5.ArrayBuffer.hash = function(arr, raw) { + var hash = md51_array(new Uint8Array(arr)), ret = hex(hash); + return raw ? hexToBinaryString(ret) : ret; + }; + return SparkMD5; + }); + }); + var classCallCheck = function(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + var createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; + var FileChecksum = function() { + createClass(FileChecksum, null, [ { + key: "create", + value: function create(file, callback) { + var instance = new FileChecksum(file); + instance.create(callback); + } + } ]); + function FileChecksum(file) { + classCallCheck(this, FileChecksum); + this.file = file; + this.chunkSize = 2097152; + this.chunkCount = Math.ceil(this.file.size / this.chunkSize); + this.chunkIndex = 0; + } + createClass(FileChecksum, [ { + key: "create", + value: function create(callback) { + var _this = this; + this.callback = callback; + this.md5Buffer = new sparkMd5.ArrayBuffer(); + this.fileReader = new FileReader(); + this.fileReader.addEventListener("load", function(event) { + return _this.fileReaderDidLoad(event); + }); + this.fileReader.addEventListener("error", function(event) { + return _this.fileReaderDidError(event); + }); + this.readNextChunk(); + } + }, { + key: "fileReaderDidLoad", + value: function fileReaderDidLoad(event) { + this.md5Buffer.append(event.target.result); + if (!this.readNextChunk()) { + var binaryDigest = this.md5Buffer.end(true); + var base64digest = btoa(binaryDigest); + this.callback(null, base64digest); + } + } + }, { + key: "fileReaderDidError", + value: function fileReaderDidError(event) { + this.callback("Error reading " + this.file.name); + } + }, { + key: "readNextChunk", + value: function readNextChunk() { + if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) { + var start = this.chunkIndex * this.chunkSize; + var end = Math.min(start + this.chunkSize, this.file.size); + var bytes = fileSlice.call(this.file, start, end); + this.fileReader.readAsArrayBuffer(bytes); + this.chunkIndex++; + return true; + } else { + return false; + } + } + } ]); + return FileChecksum; + }(); + function getMetaValue(name) { + var element = findElement(document.head, 'meta[name="' + name + '"]'); + if (element) { + return element.getAttribute("content"); + } + } + function findElements(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + var elements = root.querySelectorAll(selector); + return toArray$1(elements); + } + function findElement(root, selector) { + if (typeof root == "string") { + selector = root; + root = document; + } + return root.querySelector(selector); + } + function dispatchEvent(element, type) { + var eventInit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var disabled = element.disabled; + var bubbles = eventInit.bubbles, cancelable = eventInit.cancelable, detail = eventInit.detail; + var event = document.createEvent("Event"); + event.initEvent(type, bubbles || true, cancelable || true); + event.detail = detail || {}; + try { + element.disabled = false; + element.dispatchEvent(event); + } finally { + element.disabled = disabled; + } + return event; + } + function toArray$1(value) { + if (Array.isArray(value)) { + return value; + } else if (Array.from) { + return Array.from(value); + } else { + return [].slice.call(value); + } + } + var BlobRecord = function() { + function BlobRecord(file, checksum, url) { + var _this = this; + classCallCheck(this, BlobRecord); + this.file = file; + this.attributes = { + filename: file.name, + content_type: file.type, + byte_size: file.size, + checksum: checksum + }; + this.xhr = new XMLHttpRequest(); + this.xhr.open("POST", url, true); + this.xhr.responseType = "json"; + this.xhr.setRequestHeader("Content-Type", "application/json"); + this.xhr.setRequestHeader("Accept", "application/json"); + this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + this.xhr.setRequestHeader("X-CSRF-Token", getMetaValue("csrf-token")); + this.xhr.addEventListener("load", function(event) { + return _this.requestDidLoad(event); + }); + this.xhr.addEventListener("error", function(event) { + return _this.requestDidError(event); + }); + } + createClass(BlobRecord, [ { + key: "create", + value: function create(callback) { + this.callback = callback; + this.xhr.send(JSON.stringify({ + blob: this.attributes + })); + } + }, { + key: "requestDidLoad", + value: function requestDidLoad(event) { + if (this.status >= 200 && this.status < 300) { + var response = this.response; + var direct_upload = response.direct_upload; + delete response.direct_upload; + this.attributes = response; + this.directUploadData = direct_upload; + this.callback(null, this.toJSON()); + } else { + this.requestDidError(event); + } + } + }, { + key: "requestDidError", + value: function requestDidError(event) { + this.callback('Error creating Blob for "' + this.file.name + '". Status: ' + this.status); + } + }, { + key: "toJSON", + value: function toJSON() { + var result = {}; + for (var key in this.attributes) { + result[key] = this.attributes[key]; + } + return result; + } + }, { + key: "status", + get: function get$$1() { + return this.xhr.status; + } + }, { + key: "response", + get: function get$$1() { + var _xhr = this.xhr, responseType = _xhr.responseType, response = _xhr.response; + if (responseType == "json") { + return response; + } else { + return JSON.parse(response); + } + } + } ]); + return BlobRecord; + }(); + var BlobUpload = function() { + function BlobUpload(blob) { + var _this = this; + classCallCheck(this, BlobUpload); + this.blob = blob; + this.file = blob.file; + var _blob$directUploadDat = blob.directUploadData, url = _blob$directUploadDat.url, headers = _blob$directUploadDat.headers; + this.xhr = new XMLHttpRequest(); + this.xhr.open("PUT", url, true); + this.xhr.responseType = "text"; + for (var key in headers) { + this.xhr.setRequestHeader(key, headers[key]); + } + this.xhr.addEventListener("load", function(event) { + return _this.requestDidLoad(event); + }); + this.xhr.addEventListener("error", function(event) { + return _this.requestDidError(event); + }); + } + createClass(BlobUpload, [ { + key: "create", + value: function create(callback) { + this.callback = callback; + this.xhr.send(this.file.slice()); + } + }, { + key: "requestDidLoad", + value: function requestDidLoad(event) { + var _xhr = this.xhr, status = _xhr.status, response = _xhr.response; + if (status >= 200 && status < 300) { + this.callback(null, response); + } else { + this.requestDidError(event); + } + } + }, { + key: "requestDidError", + value: function requestDidError(event) { + this.callback('Error storing "' + this.file.name + '". Status: ' + this.xhr.status); + } + } ]); + return BlobUpload; + }(); + var id = 0; + var DirectUpload = function() { + function DirectUpload(file, url, delegate) { + classCallCheck(this, DirectUpload); + this.id = ++id; + this.file = file; + this.url = url; + this.delegate = delegate; + } + createClass(DirectUpload, [ { + key: "create", + value: function create(callback) { + var _this = this; + FileChecksum.create(this.file, function(error, checksum) { + if (error) { + callback(error); + return; + } + var blob = new BlobRecord(_this.file, checksum, _this.url); + notify(_this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr); + blob.create(function(error) { + if (error) { + callback(error); + } else { + var upload = new BlobUpload(blob); + notify(_this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr); + upload.create(function(error) { + if (error) { + callback(error); + } else { + callback(null, blob.toJSON()); + } + }); + } + }); + }); + } + } ]); + return DirectUpload; + }(); + function notify(object, methodName) { + if (object && typeof object[methodName] == "function") { + for (var _len = arguments.length, messages = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { + messages[_key - 2] = arguments[_key]; + } + return object[methodName].apply(object, messages); + } + } + var DirectUploadController = function() { + function DirectUploadController(input, file) { + classCallCheck(this, DirectUploadController); + this.input = input; + this.file = file; + this.directUpload = new DirectUpload(this.file, this.url, this); + this.dispatch("initialize"); + } + createClass(DirectUploadController, [ { + key: "start", + value: function start(callback) { + var _this = this; + var hiddenInput = document.createElement("input"); + hiddenInput.type = "hidden"; + hiddenInput.name = this.input.name; + this.input.insertAdjacentElement("beforebegin", hiddenInput); + this.dispatch("start"); + this.directUpload.create(function(error, attributes) { + if (error) { + hiddenInput.parentNode.removeChild(hiddenInput); + _this.dispatchError(error); + } else { + hiddenInput.value = attributes.signed_id; + } + _this.dispatch("end"); + callback(error); + }); + } + }, { + key: "uploadRequestDidProgress", + value: function uploadRequestDidProgress(event) { + var progress = event.loaded / event.total * 100; + if (progress) { + this.dispatch("progress", { + progress: progress + }); + } + } + }, { + key: "dispatch", + value: function dispatch(name) { + var detail = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + detail.file = this.file; + detail.id = this.directUpload.id; + return dispatchEvent(this.input, "direct-upload:" + name, { + detail: detail + }); + } + }, { + key: "dispatchError", + value: function dispatchError(error) { + var event = this.dispatch("error", { + error: error + }); + if (!event.defaultPrevented) { + alert(error); + } + } + }, { + key: "directUploadWillCreateBlobWithXHR", + value: function directUploadWillCreateBlobWithXHR(xhr) { + this.dispatch("before-blob-request", { + xhr: xhr + }); + } + }, { + key: "directUploadWillStoreFileWithXHR", + value: function directUploadWillStoreFileWithXHR(xhr) { + var _this2 = this; + this.dispatch("before-storage-request", { + xhr: xhr + }); + xhr.upload.addEventListener("progress", function(event) { + return _this2.uploadRequestDidProgress(event); + }); + } + }, { + key: "url", + get: function get$$1() { + return this.input.getAttribute("data-direct-upload-url"); + } + } ]); + return DirectUploadController; + }(); + var inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])"; + var DirectUploadsController = function() { + function DirectUploadsController(form) { + classCallCheck(this, DirectUploadsController); + this.form = form; + this.inputs = findElements(form, inputSelector).filter(function(input) { + return input.files.length; + }); + } + createClass(DirectUploadsController, [ { + key: "start", + value: function start(callback) { + var _this = this; + var controllers = this.createDirectUploadControllers(); + var startNextController = function startNextController() { + var controller = controllers.shift(); + if (controller) { + controller.start(function(error) { + if (error) { + callback(error); + _this.dispatch("end"); + } else { + startNextController(); + } + }); + } else { + callback(); + _this.dispatch("end"); + } + }; + this.dispatch("start"); + startNextController(); + } + }, { + key: "createDirectUploadControllers", + value: function createDirectUploadControllers() { + var controllers = []; + this.inputs.forEach(function(input) { + toArray$1(input.files).forEach(function(file) { + var controller = new DirectUploadController(input, file); + controllers.push(controller); + }); + }); + return controllers; + } + }, { + key: "dispatch", + value: function dispatch(name) { + var detail = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return dispatchEvent(this.form, "direct-uploads:" + name, { + detail: detail + }); + } + } ]); + return DirectUploadsController; + }(); + var processingAttribute = "data-direct-uploads-processing"; + var submitButtonsByForm = new WeakMap(); + var started = false; + function start() { + if (!started) { + started = true; + document.addEventListener("click", didClick, true); + document.addEventListener("submit", didSubmitForm); + document.addEventListener("ajax:before", didSubmitRemoteElement); + } + } + function didClick(event) { + var target = event.target; + if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) { + submitButtonsByForm.set(target.form, target); + } + } + function didSubmitForm(event) { + handleFormSubmissionEvent(event); + } + function didSubmitRemoteElement(event) { + if (event.target.tagName == "FORM") { + handleFormSubmissionEvent(event); + } + } + function handleFormSubmissionEvent(event) { + var form = event.target; + if (form.hasAttribute(processingAttribute)) { + event.preventDefault(); + return; + } + var controller = new DirectUploadsController(form); + var inputs = controller.inputs; + if (inputs.length) { + event.preventDefault(); + form.setAttribute(processingAttribute, ""); + inputs.forEach(disable); + controller.start(function(error) { + form.removeAttribute(processingAttribute); + if (error) { + inputs.forEach(enable); + } else { + submitForm(form); + } + }); + } + } + function submitForm(form) { + var button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]"); + if (button) { + var _button = button, disabled = _button.disabled; + button.disabled = false; + button.focus(); + button.click(); + button.disabled = disabled; + } else { + button = document.createElement("input"); + button.type = "submit"; + button.style.display = "none"; + form.appendChild(button); + button.click(); + form.removeChild(button); + } + submitButtonsByForm.delete(form); + } + function disable(input) { + input.disabled = true; + } + function enable(input) { + input.disabled = false; + } + function autostart() { + if (window.ActiveStorage) { + start(); + } + } + setTimeout(autostart, 1); + exports.start = start; + exports.DirectUpload = DirectUpload; + Object.defineProperty(exports, "__esModule", { + value: true + }); +}); +/* +Turbolinks 5.2.0 +Copyright © 2018 Basecamp, LLC + */ + +(function(){var t=this;(function(){(function(){this.Turbolinks={supported:function(){return null!=window.history.pushState&&null!=window.requestAnimationFrame&&null!=window.addEventListener}(),visit:function(t,r){return e.controller.visit(t,r)},clearCache:function(){return e.controller.clearCache()},setProgressBarDelay:function(t){return e.controller.setProgressBarDelay(t)}}}).call(this)}).call(t);var e=t.Turbolinks;(function(){(function(){var t,r,n,o=[].slice;e.copyObject=function(t){var e,r,n;r={};for(e in t)n=t[e],r[e]=n;return r},e.closest=function(e,r){return t.call(e,r)},t=function(){var t,e;return t=document.documentElement,null!=(e=t.closest)?e:function(t){var e;for(e=this;e;){if(e.nodeType===Node.ELEMENT_NODE&&r.call(e,t))return e;e=e.parentNode}}}(),e.defer=function(t){return setTimeout(t,1)},e.throttle=function(t){var e;return e=null,function(){var r;return r=1<=arguments.length?o.call(arguments,0):[],null!=e?e:e=requestAnimationFrame(function(n){return function(){return e=null,t.apply(n,r)}}(this))}},e.dispatch=function(t,e){var r,o,i,s,a,u;return a=null!=e?e:{},u=a.target,r=a.cancelable,o=a.data,i=document.createEvent("Events"),i.initEvent(t,!0,r===!0),i.data=null!=o?o:{},i.cancelable&&!n&&(s=i.preventDefault,i.preventDefault=function(){return this.defaultPrevented||Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}}),s.call(this)}),(null!=u?u:document).dispatchEvent(i),i},n=function(){var t;return t=document.createEvent("Events"),t.initEvent("test",!0,!0),t.preventDefault(),t.defaultPrevented}(),e.match=function(t,e){return r.call(t,e)},r=function(){var t,e,r,n;return t=document.documentElement,null!=(e=null!=(r=null!=(n=t.matchesSelector)?n:t.webkitMatchesSelector)?r:t.msMatchesSelector)?e:t.mozMatchesSelector}(),e.uuid=function(){var t,e,r;for(r="",t=e=1;36>=e;t=++e)r+=9===t||14===t||19===t||24===t?"-":15===t?"4":20===t?(Math.floor(4*Math.random())+8).toString(16):Math.floor(15*Math.random()).toString(16);return r}}).call(this),function(){e.Location=function(){function t(t){var e,r;null==t&&(t=""),r=document.createElement("a"),r.href=t.toString(),this.absoluteURL=r.href,e=r.hash.length,2>e?this.requestURL=this.absoluteURL:(this.requestURL=this.absoluteURL.slice(0,-e),this.anchor=r.hash.slice(1))}var e,r,n,o;return t.wrap=function(t){return t instanceof this?t:new this(t)},t.prototype.getOrigin=function(){return this.absoluteURL.split("/",3).join("/")},t.prototype.getPath=function(){var t,e;return null!=(t=null!=(e=this.requestURL.match(/\/\/[^\/]*(\/[^?;]*)/))?e[1]:void 0)?t:"/"},t.prototype.getPathComponents=function(){return this.getPath().split("/").slice(1)},t.prototype.getLastPathComponent=function(){return this.getPathComponents().slice(-1)[0]},t.prototype.getExtension=function(){var t,e;return null!=(t=null!=(e=this.getLastPathComponent().match(/\.[^.]*$/))?e[0]:void 0)?t:""},t.prototype.isHTML=function(){return this.getExtension().match(/^(?:|\.(?:htm|html|xhtml))$/)},t.prototype.isPrefixedBy=function(t){var e;return e=r(t),this.isEqualTo(t)||o(this.absoluteURL,e)},t.prototype.isEqualTo=function(t){return this.absoluteURL===(null!=t?t.absoluteURL:void 0)},t.prototype.toCacheKey=function(){return this.requestURL},t.prototype.toJSON=function(){return this.absoluteURL},t.prototype.toString=function(){return this.absoluteURL},t.prototype.valueOf=function(){return this.absoluteURL},r=function(t){return e(t.getOrigin()+t.getPath())},e=function(t){return n(t,"/")?t:t+"/"},o=function(t,e){return t.slice(0,e.length)===e},n=function(t,e){return t.slice(-e.length)===e},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.HttpRequest=function(){function r(r,n,o){this.delegate=r,this.requestCanceled=t(this.requestCanceled,this),this.requestTimedOut=t(this.requestTimedOut,this),this.requestFailed=t(this.requestFailed,this),this.requestLoaded=t(this.requestLoaded,this),this.requestProgressed=t(this.requestProgressed,this),this.url=e.Location.wrap(n).requestURL,this.referrer=e.Location.wrap(o).absoluteURL,this.createXHR()}return r.NETWORK_FAILURE=0,r.TIMEOUT_FAILURE=-1,r.timeout=60,r.prototype.send=function(){var t;return this.xhr&&!this.sent?(this.notifyApplicationBeforeRequestStart(),this.setProgress(0),this.xhr.send(),this.sent=!0,"function"==typeof(t=this.delegate).requestStarted?t.requestStarted():void 0):void 0},r.prototype.cancel=function(){return this.xhr&&this.sent?this.xhr.abort():void 0},r.prototype.requestProgressed=function(t){return t.lengthComputable?this.setProgress(t.loaded/t.total):void 0},r.prototype.requestLoaded=function(){return this.endRequest(function(t){return function(){var e;return 200<=(e=t.xhr.status)&&300>e?t.delegate.requestCompletedWithResponse(t.xhr.responseText,t.xhr.getResponseHeader("Turbolinks-Location")):(t.failed=!0,t.delegate.requestFailedWithStatusCode(t.xhr.status,t.xhr.responseText))}}(this))},r.prototype.requestFailed=function(){return this.endRequest(function(t){return function(){return t.failed=!0,t.delegate.requestFailedWithStatusCode(t.constructor.NETWORK_FAILURE)}}(this))},r.prototype.requestTimedOut=function(){return this.endRequest(function(t){return function(){return t.failed=!0,t.delegate.requestFailedWithStatusCode(t.constructor.TIMEOUT_FAILURE)}}(this))},r.prototype.requestCanceled=function(){return this.endRequest()},r.prototype.notifyApplicationBeforeRequestStart=function(){return e.dispatch("turbolinks:request-start",{data:{url:this.url,xhr:this.xhr}})},r.prototype.notifyApplicationAfterRequestEnd=function(){return e.dispatch("turbolinks:request-end",{data:{url:this.url,xhr:this.xhr}})},r.prototype.createXHR=function(){return this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url,!0),this.xhr.timeout=1e3*this.constructor.timeout,this.xhr.setRequestHeader("Accept","text/html, application/xhtml+xml"),this.xhr.setRequestHeader("Turbolinks-Referrer",this.referrer),this.xhr.onprogress=this.requestProgressed,this.xhr.onload=this.requestLoaded,this.xhr.onerror=this.requestFailed,this.xhr.ontimeout=this.requestTimedOut,this.xhr.onabort=this.requestCanceled},r.prototype.endRequest=function(t){return this.xhr?(this.notifyApplicationAfterRequestEnd(),null!=t&&t.call(this),this.destroy()):void 0},r.prototype.setProgress=function(t){var e;return this.progress=t,"function"==typeof(e=this.delegate).requestProgressed?e.requestProgressed(this.progress):void 0},r.prototype.destroy=function(){var t;return this.setProgress(1),"function"==typeof(t=this.delegate).requestFinished&&t.requestFinished(),this.delegate=null,this.xhr=null},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.ProgressBar=function(){function e(){this.trickle=t(this.trickle,this),this.stylesheetElement=this.createStylesheetElement(),this.progressElement=this.createProgressElement()}var r;return r=300,e.defaultCSS=".turbolinks-progress-bar {\n position: fixed;\n display: block;\n top: 0;\n left: 0;\n height: 3px;\n background: #0076ff;\n z-index: 9999;\n transition: width "+r+"ms ease-out, opacity "+r/2+"ms "+r/2+"ms ease-in;\n transform: translate3d(0, 0, 0);\n}",e.prototype.show=function(){return this.visible?void 0:(this.visible=!0,this.installStylesheetElement(),this.installProgressElement(),this.startTrickling())},e.prototype.hide=function(){return this.visible&&!this.hiding?(this.hiding=!0,this.fadeProgressElement(function(t){return function(){return t.uninstallProgressElement(),t.stopTrickling(),t.visible=!1,t.hiding=!1}}(this))):void 0},e.prototype.setValue=function(t){return this.value=t,this.refresh()},e.prototype.installStylesheetElement=function(){return document.head.insertBefore(this.stylesheetElement,document.head.firstChild)},e.prototype.installProgressElement=function(){return this.progressElement.style.width=0,this.progressElement.style.opacity=1,document.documentElement.insertBefore(this.progressElement,document.body),this.refresh()},e.prototype.fadeProgressElement=function(t){return this.progressElement.style.opacity=0,setTimeout(t,1.5*r)},e.prototype.uninstallProgressElement=function(){return this.progressElement.parentNode?document.documentElement.removeChild(this.progressElement):void 0},e.prototype.startTrickling=function(){return null!=this.trickleInterval?this.trickleInterval:this.trickleInterval=setInterval(this.trickle,r)},e.prototype.stopTrickling=function(){return clearInterval(this.trickleInterval),this.trickleInterval=null},e.prototype.trickle=function(){return this.setValue(this.value+Math.random()/100)},e.prototype.refresh=function(){return requestAnimationFrame(function(t){return function(){return t.progressElement.style.width=10+90*t.value+"%"}}(this))},e.prototype.createStylesheetElement=function(){var t;return t=document.createElement("style"),t.type="text/css",t.textContent=this.constructor.defaultCSS,t},e.prototype.createProgressElement=function(){var t;return t=document.createElement("div"),t.className="turbolinks-progress-bar",t},e}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.BrowserAdapter=function(){function r(r){this.controller=r,this.showProgressBar=t(this.showProgressBar,this),this.progressBar=new e.ProgressBar}var n,o,i;return i=e.HttpRequest,n=i.NETWORK_FAILURE,o=i.TIMEOUT_FAILURE,r.prototype.visitProposedToLocationWithAction=function(t,e){return this.controller.startVisitToLocationWithAction(t,e)},r.prototype.visitStarted=function(t){return t.issueRequest(),t.changeHistory(),t.loadCachedSnapshot()},r.prototype.visitRequestStarted=function(t){return this.progressBar.setValue(0),t.hasCachedSnapshot()||"restore"!==t.action?this.showProgressBarAfterDelay():this.showProgressBar()},r.prototype.visitRequestProgressed=function(t){return this.progressBar.setValue(t.progress)},r.prototype.visitRequestCompleted=function(t){return t.loadResponse()},r.prototype.visitRequestFailedWithStatusCode=function(t,e){switch(e){case n:case o:return this.reload();default:return t.loadResponse()}},r.prototype.visitRequestFinished=function(t){return this.hideProgressBar()},r.prototype.visitCompleted=function(t){return t.followRedirect()},r.prototype.pageInvalidated=function(){return this.reload()},r.prototype.showProgressBarAfterDelay=function(){return this.progressBarTimeout=setTimeout(this.showProgressBar,this.controller.progressBarDelay)},r.prototype.showProgressBar=function(){return this.progressBar.show()},r.prototype.hideProgressBar=function(){return this.progressBar.hide(),clearTimeout(this.progressBarTimeout)},r.prototype.reload=function(){return window.location.reload()},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.History=function(){function r(e){this.delegate=e,this.onPageLoad=t(this.onPageLoad,this),this.onPopState=t(this.onPopState,this)}return r.prototype.start=function(){return this.started?void 0:(addEventListener("popstate",this.onPopState,!1),addEventListener("load",this.onPageLoad,!1),this.started=!0)},r.prototype.stop=function(){return this.started?(removeEventListener("popstate",this.onPopState,!1),removeEventListener("load",this.onPageLoad,!1),this.started=!1):void 0},r.prototype.push=function(t,r){return t=e.Location.wrap(t),this.update("push",t,r)},r.prototype.replace=function(t,r){return t=e.Location.wrap(t),this.update("replace",t,r)},r.prototype.onPopState=function(t){var r,n,o,i;return this.shouldHandlePopState()&&(i=null!=(n=t.state)?n.turbolinks:void 0)?(r=e.Location.wrap(window.location),o=i.restorationIdentifier,this.delegate.historyPoppedToLocationWithRestorationIdentifier(r,o)):void 0},r.prototype.onPageLoad=function(t){return e.defer(function(t){return function(){return t.pageLoaded=!0}}(this))},r.prototype.shouldHandlePopState=function(){return this.pageIsLoaded()},r.prototype.pageIsLoaded=function(){return this.pageLoaded||"complete"===document.readyState},r.prototype.update=function(t,e,r){var n;return n={turbolinks:{restorationIdentifier:r}},history[t+"State"](n,null,e)},r}()}.call(this),function(){e.HeadDetails=function(){function t(t){var e,r,n,s,a,u;for(this.elements={},n=0,a=t.length;a>n;n++)u=t[n],u.nodeType===Node.ELEMENT_NODE&&(s=u.outerHTML,r=null!=(e=this.elements)[s]?e[s]:e[s]={type:i(u),tracked:o(u),elements:[]},r.elements.push(u))}var e,r,n,o,i;return t.fromHeadElement=function(t){var e;return new this(null!=(e=null!=t?t.childNodes:void 0)?e:[])},t.prototype.hasElementWithKey=function(t){return t in this.elements},t.prototype.getTrackedElementSignature=function(){var t,e;return function(){var r,n;r=this.elements,n=[];for(t in r)e=r[t].tracked,e&&n.push(t);return n}.call(this).join("")},t.prototype.getScriptElementsNotInDetails=function(t){return this.getElementsMatchingTypeNotInDetails("script",t)},t.prototype.getStylesheetElementsNotInDetails=function(t){return this.getElementsMatchingTypeNotInDetails("stylesheet",t)},t.prototype.getElementsMatchingTypeNotInDetails=function(t,e){var r,n,o,i,s,a;o=this.elements,s=[];for(n in o)i=o[n],a=i.type,r=i.elements,a!==t||e.hasElementWithKey(n)||s.push(r[0]);return s},t.prototype.getProvisionalElements=function(){var t,e,r,n,o,i,s;r=[],n=this.elements;for(e in n)o=n[e],s=o.type,i=o.tracked,t=o.elements,null!=s||i?t.length>1&&r.push.apply(r,t.slice(1)):r.push.apply(r,t);return r},t.prototype.getMetaValue=function(t){var e;return null!=(e=this.findMetaElementByName(t))?e.getAttribute("content"):void 0},t.prototype.findMetaElementByName=function(t){var r,n,o,i;r=void 0,i=this.elements;for(o in i)n=i[o].elements,e(n[0],t)&&(r=n[0]);return r},i=function(t){return r(t)?"script":n(t)?"stylesheet":void 0},o=function(t){return"reload"===t.getAttribute("data-turbolinks-track")},r=function(t){var e;return e=t.tagName.toLowerCase(),"script"===e},n=function(t){var e;return e=t.tagName.toLowerCase(),"style"===e||"link"===e&&"stylesheet"===t.getAttribute("rel")},e=function(t,e){var r;return r=t.tagName.toLowerCase(),"meta"===r&&t.getAttribute("name")===e},t}()}.call(this),function(){e.Snapshot=function(){function t(t,e){this.headDetails=t,this.bodyElement=e}return t.wrap=function(t){return t instanceof this?t:"string"==typeof t?this.fromHTMLString(t):this.fromHTMLElement(t)},t.fromHTMLString=function(t){var e;return e=document.createElement("html"),e.innerHTML=t,this.fromHTMLElement(e)},t.fromHTMLElement=function(t){var r,n,o,i;return o=t.querySelector("head"),r=null!=(i=t.querySelector("body"))?i:document.createElement("body"),n=e.HeadDetails.fromHeadElement(o),new this(n,r)},t.prototype.clone=function(){return new this.constructor(this.headDetails,this.bodyElement.cloneNode(!0))},t.prototype.getRootLocation=function(){var t,r;return r=null!=(t=this.getSetting("root"))?t:"/",new e.Location(r)},t.prototype.getCacheControlValue=function(){return this.getSetting("cache-control")},t.prototype.getElementForAnchor=function(t){try{return this.bodyElement.querySelector("[id='"+t+"'], a[name='"+t+"']")}catch(e){}},t.prototype.getPermanentElements=function(){return this.bodyElement.querySelectorAll("[id][data-turbolinks-permanent]")},t.prototype.getPermanentElementById=function(t){return this.bodyElement.querySelector("#"+t+"[data-turbolinks-permanent]")},t.prototype.getPermanentElementsPresentInSnapshot=function(t){var e,r,n,o,i;for(o=this.getPermanentElements(),i=[],r=0,n=o.length;n>r;r++)e=o[r],t.getPermanentElementById(e.id)&&i.push(e);return i},t.prototype.findFirstAutofocusableElement=function(){return this.bodyElement.querySelector("[autofocus]")},t.prototype.hasAnchor=function(t){return null!=this.getElementForAnchor(t)},t.prototype.isPreviewable=function(){return"no-preview"!==this.getCacheControlValue()},t.prototype.isCacheable=function(){return"no-cache"!==this.getCacheControlValue()},t.prototype.isVisitable=function(){return"reload"!==this.getSetting("visit-control")},t.prototype.getSetting=function(t){return this.headDetails.getMetaValue("turbolinks-"+t)},t}()}.call(this),function(){var t=[].slice;e.Renderer=function(){function e(){}var r;return e.render=function(){var e,r,n,o;return n=arguments[0],r=arguments[1],e=3<=arguments.length?t.call(arguments,2):[],o=function(t,e,r){r.prototype=t.prototype;var n=new r,o=t.apply(n,e);return Object(o)===o?o:n}(this,e,function(){}),o.delegate=n,o.render(r),o},e.prototype.renderView=function(t){return this.delegate.viewWillRender(this.newBody),t(),this.delegate.viewRendered(this.newBody)},e.prototype.invalidateView=function(){return this.delegate.viewInvalidated()},e.prototype.createScriptElement=function(t){var e;return"false"===t.getAttribute("data-turbolinks-eval")?t:(e=document.createElement("script"),e.textContent=t.textContent,e.async=!1,r(e,t),e)},r=function(t,e){var r,n,o,i,s,a,u;for(i=e.attributes,a=[],r=0,n=i.length;n>r;r++)s=i[r],o=s.name,u=s.value,a.push(t.setAttribute(o,u));return a},e}()}.call(this),function(){var t,r,n=function(t,e){function r(){this.constructor=t}for(var n in e)o.call(e,n)&&(t[n]=e[n]);return r.prototype=e.prototype,t.prototype=new r,t.__super__=e.prototype,t},o={}.hasOwnProperty;e.SnapshotRenderer=function(e){function o(t,e,r){this.currentSnapshot=t,this.newSnapshot=e,this.isPreview=r,this.currentHeadDetails=this.currentSnapshot.headDetails,this.newHeadDetails=this.newSnapshot.headDetails,this.currentBody=this.currentSnapshot.bodyElement,this.newBody=this.newSnapshot.bodyElement}return n(o,e),o.prototype.render=function(t){return this.shouldRender()?(this.mergeHead(),this.renderView(function(e){return function(){return e.replaceBody(),e.isPreview||e.focusFirstAutofocusableElement(),t()}}(this))):this.invalidateView()},o.prototype.mergeHead=function(){return this.copyNewHeadStylesheetElements(),this.copyNewHeadScriptElements(),this.removeCurrentHeadProvisionalElements(),this.copyNewHeadProvisionalElements()},o.prototype.replaceBody=function(){var t;return t=this.relocateCurrentBodyPermanentElements(),this.activateNewBodyScriptElements(),this.assignNewBody(),this.replacePlaceholderElementsWithClonedPermanentElements(t)},o.prototype.shouldRender=function(){return this.newSnapshot.isVisitable()&&this.trackedElementsAreIdentical()},o.prototype.trackedElementsAreIdentical=function(){return this.currentHeadDetails.getTrackedElementSignature()===this.newHeadDetails.getTrackedElementSignature()},o.prototype.copyNewHeadStylesheetElements=function(){var t,e,r,n,o;for(n=this.getNewHeadStylesheetElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(t));return o},o.prototype.copyNewHeadScriptElements=function(){var t,e,r,n,o;for(n=this.getNewHeadScriptElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(this.createScriptElement(t)));return o},o.prototype.removeCurrentHeadProvisionalElements=function(){var t,e,r,n,o;for(n=this.getCurrentHeadProvisionalElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.removeChild(t));return o},o.prototype.copyNewHeadProvisionalElements=function(){var t,e,r,n,o;for(n=this.getNewHeadProvisionalElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(t));return o},o.prototype.relocateCurrentBodyPermanentElements=function(){var e,n,o,i,s,a,u;for(a=this.getCurrentBodyPermanentElements(),u=[],e=0,n=a.length;n>e;e++)i=a[e],s=t(i),o=this.newSnapshot.getPermanentElementById(i.id),r(i,s.element),r(o,i),u.push(s);return u},o.prototype.replacePlaceholderElementsWithClonedPermanentElements=function(t){var e,n,o,i,s,a,u;for(u=[],o=0,i=t.length;i>o;o++)a=t[o],n=a.element,s=a.permanentElement,e=s.cloneNode(!0),u.push(r(n,e));return u},o.prototype.activateNewBodyScriptElements=function(){var t,e,n,o,i,s;for(i=this.getNewBodyScriptElements(),s=[],e=0,o=i.length;o>e;e++)n=i[e],t=this.createScriptElement(n),s.push(r(n,t));return s},o.prototype.assignNewBody=function(){return document.body=this.newBody},o.prototype.focusFirstAutofocusableElement=function(){var t;return null!=(t=this.newSnapshot.findFirstAutofocusableElement())?t.focus():void 0},o.prototype.getNewHeadStylesheetElements=function(){return this.newHeadDetails.getStylesheetElementsNotInDetails(this.currentHeadDetails)},o.prototype.getNewHeadScriptElements=function(){return this.newHeadDetails.getScriptElementsNotInDetails(this.currentHeadDetails)},o.prototype.getCurrentHeadProvisionalElements=function(){return this.currentHeadDetails.getProvisionalElements()},o.prototype.getNewHeadProvisionalElements=function(){return this.newHeadDetails.getProvisionalElements()},o.prototype.getCurrentBodyPermanentElements=function(){return this.currentSnapshot.getPermanentElementsPresentInSnapshot(this.newSnapshot)},o.prototype.getNewBodyScriptElements=function(){return this.newBody.querySelectorAll("script")},o}(e.Renderer),t=function(t){var e;return e=document.createElement("meta"),e.setAttribute("name","turbolinks-permanent-placeholder"),e.setAttribute("content",t.id),{element:e,permanentElement:t}},r=function(t,e){var r;return(r=t.parentNode)?r.replaceChild(e,t):void 0}}.call(this),function(){var t=function(t,e){function n(){this.constructor=t}for(var o in e)r.call(e,o)&&(t[o]=e[o]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t},r={}.hasOwnProperty;e.ErrorRenderer=function(e){function r(t){var e;e=document.createElement("html"),e.innerHTML=t,this.newHead=e.querySelector("head"),this.newBody=e.querySelector("body")}return t(r,e),r.prototype.render=function(t){return this.renderView(function(e){return function(){return e.replaceHeadAndBody(),e.activateBodyScriptElements(),t()}}(this))},r.prototype.replaceHeadAndBody=function(){var t,e;return e=document.head,t=document.body,e.parentNode.replaceChild(this.newHead,e),t.parentNode.replaceChild(this.newBody,t)},r.prototype.activateBodyScriptElements=function(){var t,e,r,n,o,i;for(n=this.getScriptElements(),i=[],e=0,r=n.length;r>e;e++)o=n[e],t=this.createScriptElement(o),i.push(o.parentNode.replaceChild(t,o));return i},r.prototype.getScriptElements=function(){return document.documentElement.querySelectorAll("script")},r}(e.Renderer)}.call(this),function(){e.View=function(){function t(t){this.delegate=t,this.htmlElement=document.documentElement}return t.prototype.getRootLocation=function(){return this.getSnapshot().getRootLocation()},t.prototype.getElementForAnchor=function(t){return this.getSnapshot().getElementForAnchor(t)},t.prototype.getSnapshot=function(){return e.Snapshot.fromHTMLElement(this.htmlElement)},t.prototype.render=function(t,e){var r,n,o;return o=t.snapshot,r=t.error,n=t.isPreview,this.markAsPreview(n),null!=o?this.renderSnapshot(o,n,e):this.renderError(r,e)},t.prototype.markAsPreview=function(t){return t?this.htmlElement.setAttribute("data-turbolinks-preview",""):this.htmlElement.removeAttribute("data-turbolinks-preview")},t.prototype.renderSnapshot=function(t,r,n){return e.SnapshotRenderer.render(this.delegate,n,this.getSnapshot(),e.Snapshot.wrap(t),r)},t.prototype.renderError=function(t,r){return e.ErrorRenderer.render(this.delegate,r,t)},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.ScrollManager=function(){function r(r){this.delegate=r,this.onScroll=t(this.onScroll,this),this.onScroll=e.throttle(this.onScroll)}return r.prototype.start=function(){return this.started?void 0:(addEventListener("scroll",this.onScroll,!1),this.onScroll(),this.started=!0)},r.prototype.stop=function(){return this.started?(removeEventListener("scroll",this.onScroll,!1),this.started=!1):void 0},r.prototype.scrollToElement=function(t){return t.scrollIntoView()},r.prototype.scrollToPosition=function(t){var e,r;return e=t.x,r=t.y,window.scrollTo(e,r)},r.prototype.onScroll=function(t){return this.updatePosition({x:window.pageXOffset,y:window.pageYOffset})},r.prototype.updatePosition=function(t){var e;return this.position=t,null!=(e=this.delegate)?e.scrollPositionChanged(this.position):void 0},r}()}.call(this),function(){e.SnapshotCache=function(){function t(t){this.size=t,this.keys=[],this.snapshots={}}var r;return t.prototype.has=function(t){var e;return e=r(t),e in this.snapshots},t.prototype.get=function(t){var e;if(this.has(t))return e=this.read(t),this.touch(t),e},t.prototype.put=function(t,e){return this.write(t,e),this.touch(t),e},t.prototype.read=function(t){var e;return e=r(t),this.snapshots[e]},t.prototype.write=function(t,e){var n;return n=r(t),this.snapshots[n]=e},t.prototype.touch=function(t){var e,n;return n=r(t),e=this.keys.indexOf(n),e>-1&&this.keys.splice(e,1),this.keys.unshift(n),this.trim()},t.prototype.trim=function(){var t,e,r,n,o;for(n=this.keys.splice(this.size),o=[],t=0,r=n.length;r>t;t++)e=n[t],o.push(delete this.snapshots[e]);return o},r=function(t){return e.Location.wrap(t).toCacheKey()},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.Visit=function(){function r(r,n,o){this.controller=r,this.action=o,this.performScroll=t(this.performScroll,this),this.identifier=e.uuid(),this.location=e.Location.wrap(n),this.adapter=this.controller.adapter,this.state="initialized",this.timingMetrics={}}var n;return r.prototype.start=function(){return"initialized"===this.state?(this.recordTimingMetric("visitStart"),this.state="started",this.adapter.visitStarted(this)):void 0},r.prototype.cancel=function(){var t;return"started"===this.state?(null!=(t=this.request)&&t.cancel(),this.cancelRender(),this.state="canceled"):void 0},r.prototype.complete=function(){var t;return"started"===this.state?(this.recordTimingMetric("visitEnd"),this.state="completed","function"==typeof(t=this.adapter).visitCompleted&&t.visitCompleted(this),this.controller.visitCompleted(this)):void 0},r.prototype.fail=function(){var t;return"started"===this.state?(this.state="failed","function"==typeof(t=this.adapter).visitFailed?t.visitFailed(this):void 0):void 0},r.prototype.changeHistory=function(){var t,e;return this.historyChanged?void 0:(t=this.location.isEqualTo(this.referrer)?"replace":this.action,e=n(t),this.controller[e](this.location,this.restorationIdentifier),this.historyChanged=!0)},r.prototype.issueRequest=function(){return this.shouldIssueRequest()&&null==this.request?(this.progress=0,this.request=new e.HttpRequest(this,this.location,this.referrer),this.request.send()):void 0},r.prototype.getCachedSnapshot=function(){var t;return!(t=this.controller.getCachedSnapshotForLocation(this.location))||null!=this.location.anchor&&!t.hasAnchor(this.location.anchor)||"restore"!==this.action&&!t.isPreviewable()?void 0:t},r.prototype.hasCachedSnapshot=function(){return null!=this.getCachedSnapshot()},r.prototype.loadCachedSnapshot=function(){var t,e;return(e=this.getCachedSnapshot())?(t=this.shouldIssueRequest(),this.render(function(){var r;return this.cacheSnapshot(),this.controller.render({snapshot:e,isPreview:t},this.performScroll),"function"==typeof(r=this.adapter).visitRendered&&r.visitRendered(this),t?void 0:this.complete()})):void 0},r.prototype.loadResponse=function(){return null!=this.response?this.render(function(){var t,e;return this.cacheSnapshot(),this.request.failed?(this.controller.render({error:this.response},this.performScroll),"function"==typeof(t=this.adapter).visitRendered&&t.visitRendered(this),this.fail()):(this.controller.render({snapshot:this.response},this.performScroll),"function"==typeof(e=this.adapter).visitRendered&&e.visitRendered(this),this.complete())}):void 0},r.prototype.followRedirect=function(){return this.redirectedToLocation&&!this.followedRedirect?(this.location=this.redirectedToLocation,this.controller.replaceHistoryWithLocationAndRestorationIdentifier(this.redirectedToLocation,this.restorationIdentifier),this.followedRedirect=!0):void 0},r.prototype.requestStarted=function(){var t;return this.recordTimingMetric("requestStart"),"function"==typeof(t=this.adapter).visitRequestStarted?t.visitRequestStarted(this):void 0},r.prototype.requestProgressed=function(t){var e;return this.progress=t,"function"==typeof(e=this.adapter).visitRequestProgressed?e.visitRequestProgressed(this):void 0},r.prototype.requestCompletedWithResponse=function(t,r){return this.response=t,null!=r&&(this.redirectedToLocation=e.Location.wrap(r)),this.adapter.visitRequestCompleted(this)},r.prototype.requestFailedWithStatusCode=function(t,e){return this.response=e,this.adapter.visitRequestFailedWithStatusCode(this,t)},r.prototype.requestFinished=function(){var t;return this.recordTimingMetric("requestEnd"),"function"==typeof(t=this.adapter).visitRequestFinished?t.visitRequestFinished(this):void 0},r.prototype.performScroll=function(){return this.scrolled?void 0:("restore"===this.action?this.scrollToRestoredPosition()||this.scrollToTop():this.scrollToAnchor()||this.scrollToTop(),this.scrolled=!0)},r.prototype.scrollToRestoredPosition=function(){var t,e;return t=null!=(e=this.restorationData)?e.scrollPosition:void 0,null!=t?(this.controller.scrollToPosition(t),!0):void 0},r.prototype.scrollToAnchor=function(){return null!=this.location.anchor?(this.controller.scrollToAnchor(this.location.anchor),!0):void 0},r.prototype.scrollToTop=function(){return this.controller.scrollToPosition({x:0,y:0})},r.prototype.recordTimingMetric=function(t){var e;return null!=(e=this.timingMetrics)[t]?e[t]:e[t]=(new Date).getTime()},r.prototype.getTimingMetrics=function(){return e.copyObject(this.timingMetrics)},n=function(t){switch(t){case"replace":return"replaceHistoryWithLocationAndRestorationIdentifier";case"advance":case"restore":return"pushHistoryWithLocationAndRestorationIdentifier"}},r.prototype.shouldIssueRequest=function(){return"restore"===this.action?!this.hasCachedSnapshot():!0},r.prototype.cacheSnapshot=function(){return this.snapshotCached?void 0:(this.controller.cacheSnapshot(),this.snapshotCached=!0)},r.prototype.render=function(t){return this.cancelRender(),this.frame=requestAnimationFrame(function(e){return function(){return e.frame=null,t.call(e)}}(this))},r.prototype.cancelRender=function(){return this.frame?cancelAnimationFrame(this.frame):void 0},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.Controller=function(){function r(){this.clickBubbled=t(this.clickBubbled,this),this.clickCaptured=t(this.clickCaptured,this),this.pageLoaded=t(this.pageLoaded,this),this.history=new e.History(this),this.view=new e.View(this),this.scrollManager=new e.ScrollManager(this),this.restorationData={},this.clearCache(),this.setProgressBarDelay(500)}return r.prototype.start=function(){return e.supported&&!this.started?(addEventListener("click",this.clickCaptured,!0),addEventListener("DOMContentLoaded",this.pageLoaded,!1),this.scrollManager.start(),this.startHistory(),this.started=!0,this.enabled=!0):void 0},r.prototype.disable=function(){return this.enabled=!1},r.prototype.stop=function(){return this.started?(removeEventListener("click",this.clickCaptured,!0),removeEventListener("DOMContentLoaded",this.pageLoaded,!1),this.scrollManager.stop(),this.stopHistory(),this.started=!1):void 0},r.prototype.clearCache=function(){return this.cache=new e.SnapshotCache(10)},r.prototype.visit=function(t,r){var n,o;return null==r&&(r={}),t=e.Location.wrap(t),this.applicationAllowsVisitingLocation(t)?this.locationIsVisitable(t)?(n=null!=(o=r.action)?o:"advance",this.adapter.visitProposedToLocationWithAction(t,n)):window.location=t:void 0},r.prototype.startVisitToLocationWithAction=function(t,r,n){var o;return e.supported?(o=this.getRestorationDataForIdentifier(n),this.startVisit(t,r,{restorationData:o})):window.location=t},r.prototype.setProgressBarDelay=function(t){return this.progressBarDelay=t},r.prototype.startHistory=function(){return this.location=e.Location.wrap(window.location),this.restorationIdentifier=e.uuid(),this.history.start(),this.history.replace(this.location,this.restorationIdentifier)},r.prototype.stopHistory=function(){return this.history.stop()},r.prototype.pushHistoryWithLocationAndRestorationIdentifier=function(t,r){return this.restorationIdentifier=r,this.location=e.Location.wrap(t),this.history.push(this.location,this.restorationIdentifier)},r.prototype.replaceHistoryWithLocationAndRestorationIdentifier=function(t,r){return this.restorationIdentifier=r,this.location=e.Location.wrap(t),this.history.replace(this.location,this.restorationIdentifier)},r.prototype.historyPoppedToLocationWithRestorationIdentifier=function(t,r){var n;return this.restorationIdentifier=r,this.enabled?(n=this.getRestorationDataForIdentifier(this.restorationIdentifier),this.startVisit(t,"restore",{restorationIdentifier:this.restorationIdentifier,restorationData:n,historyChanged:!0}),this.location=e.Location.wrap(t)):this.adapter.pageInvalidated()},r.prototype.getCachedSnapshotForLocation=function(t){var e;return null!=(e=this.cache.get(t))?e.clone():void 0},r.prototype.shouldCacheSnapshot=function(){return this.view.getSnapshot().isCacheable(); +},r.prototype.cacheSnapshot=function(){var t,r;return this.shouldCacheSnapshot()?(this.notifyApplicationBeforeCachingSnapshot(),r=this.view.getSnapshot(),t=this.lastRenderedLocation,e.defer(function(e){return function(){return e.cache.put(t,r.clone())}}(this))):void 0},r.prototype.scrollToAnchor=function(t){var e;return(e=this.view.getElementForAnchor(t))?this.scrollToElement(e):this.scrollToPosition({x:0,y:0})},r.prototype.scrollToElement=function(t){return this.scrollManager.scrollToElement(t)},r.prototype.scrollToPosition=function(t){return this.scrollManager.scrollToPosition(t)},r.prototype.scrollPositionChanged=function(t){var e;return e=this.getCurrentRestorationData(),e.scrollPosition=t},r.prototype.render=function(t,e){return this.view.render(t,e)},r.prototype.viewInvalidated=function(){return this.adapter.pageInvalidated()},r.prototype.viewWillRender=function(t){return this.notifyApplicationBeforeRender(t)},r.prototype.viewRendered=function(){return this.lastRenderedLocation=this.currentVisit.location,this.notifyApplicationAfterRender()},r.prototype.pageLoaded=function(){return this.lastRenderedLocation=this.location,this.notifyApplicationAfterPageLoad()},r.prototype.clickCaptured=function(){return removeEventListener("click",this.clickBubbled,!1),addEventListener("click",this.clickBubbled,!1)},r.prototype.clickBubbled=function(t){var e,r,n;return this.enabled&&this.clickEventIsSignificant(t)&&(r=this.getVisitableLinkForNode(t.target))&&(n=this.getVisitableLocationForLink(r))&&this.applicationAllowsFollowingLinkToLocation(r,n)?(t.preventDefault(),e=this.getActionForLink(r),this.visit(n,{action:e})):void 0},r.prototype.applicationAllowsFollowingLinkToLocation=function(t,e){var r;return r=this.notifyApplicationAfterClickingLinkToLocation(t,e),!r.defaultPrevented},r.prototype.applicationAllowsVisitingLocation=function(t){var e;return e=this.notifyApplicationBeforeVisitingLocation(t),!e.defaultPrevented},r.prototype.notifyApplicationAfterClickingLinkToLocation=function(t,r){return e.dispatch("turbolinks:click",{target:t,data:{url:r.absoluteURL},cancelable:!0})},r.prototype.notifyApplicationBeforeVisitingLocation=function(t){return e.dispatch("turbolinks:before-visit",{data:{url:t.absoluteURL},cancelable:!0})},r.prototype.notifyApplicationAfterVisitingLocation=function(t){return e.dispatch("turbolinks:visit",{data:{url:t.absoluteURL}})},r.prototype.notifyApplicationBeforeCachingSnapshot=function(){return e.dispatch("turbolinks:before-cache")},r.prototype.notifyApplicationBeforeRender=function(t){return e.dispatch("turbolinks:before-render",{data:{newBody:t}})},r.prototype.notifyApplicationAfterRender=function(){return e.dispatch("turbolinks:render")},r.prototype.notifyApplicationAfterPageLoad=function(t){return null==t&&(t={}),e.dispatch("turbolinks:load",{data:{url:this.location.absoluteURL,timing:t}})},r.prototype.startVisit=function(t,e,r){var n;return null!=(n=this.currentVisit)&&n.cancel(),this.currentVisit=this.createVisit(t,e,r),this.currentVisit.start(),this.notifyApplicationAfterVisitingLocation(t)},r.prototype.createVisit=function(t,r,n){var o,i,s,a,u;return i=null!=n?n:{},a=i.restorationIdentifier,s=i.restorationData,o=i.historyChanged,u=new e.Visit(this,t,r),u.restorationIdentifier=null!=a?a:e.uuid(),u.restorationData=e.copyObject(s),u.historyChanged=o,u.referrer=this.location,u},r.prototype.visitCompleted=function(t){return this.notifyApplicationAfterPageLoad(t.getTimingMetrics())},r.prototype.clickEventIsSignificant=function(t){return!(t.defaultPrevented||t.target.isContentEditable||t.which>1||t.altKey||t.ctrlKey||t.metaKey||t.shiftKey)},r.prototype.getVisitableLinkForNode=function(t){return this.nodeIsVisitable(t)?e.closest(t,"a[href]:not([target]):not([download])"):void 0},r.prototype.getVisitableLocationForLink=function(t){var r;return r=new e.Location(t.getAttribute("href")),this.locationIsVisitable(r)?r:void 0},r.prototype.getActionForLink=function(t){var e;return null!=(e=t.getAttribute("data-turbolinks-action"))?e:"advance"},r.prototype.nodeIsVisitable=function(t){var r;return(r=e.closest(t,"[data-turbolinks]"))?"false"!==r.getAttribute("data-turbolinks"):!0},r.prototype.locationIsVisitable=function(t){return t.isPrefixedBy(this.view.getRootLocation())&&t.isHTML()},r.prototype.getCurrentRestorationData=function(){return this.getRestorationDataForIdentifier(this.restorationIdentifier)},r.prototype.getRestorationDataForIdentifier=function(t){var e;return null!=(e=this.restorationData)[t]?e[t]:e[t]={}},r}()}.call(this),function(){!function(){var t,e;if((t=e=document.currentScript)&&!e.hasAttribute("data-turbolinks-suppress-warning"))for(;t=t.parentNode;)if(t===document.body)return console.warn("You are loading Turbolinks from a ') - .attr('src', `${_url_origin}/javascripts/jquery-1.8.3-ui-1.9.2-ujs-2.0.3.js?_t=${versionNum}`); - -} - // `${_url_origin}/javascripts/jquery-1.8.3-ui-1.9.2-ujs-2.0.3.js?_t=${versionNum}` -// TODO css加载完成后再打开页面,行为和tpm其他页面一致 -export function TPMIndexHOC(WrappedComponent) { - // 这里如果extends WrappedComponent 会出现 WrappedComponent mount twice的问题 - return class II extends React.Component { - constructor(props) { - super(props) - window.$('#root').css('position', 'relative') - - this.state = { - tpmLoading: true, - resLoading: true, - Headertop:undefined, - Footerdown:undefined, - coursedata: {}, - - isRender: false, - AccountProfiletype: false, - - globalLoading: false, - dataquerys:{}, - isloginCancel:undefined, - mygetHelmetapi: null, - } - } - - // header里面需要有user - initCommonState(user) { - // 更新头像后,需要改变参数,不然会被图片缓存影响到 --> 后台已加 ?t=${new Date().getTime() - const newUser = Object.assign({}, {...user}, { image_url: `${user.image_url}`}); - this.setState({ - user: newUser, - current_user: newUser - }) - } - showShixun = () => { - const { shixunId } = this.props.match.params - const url = `/api/v1/shixuns/${shixunId}/show_shixun` - - this.setState({ tpmLoading: true }) - axios.get(url, - { - withCredentials: true - } - ).then((response) => { - if (response.data && response.data.shixun) { - this.initCommonState(response.data.current_user) - response.data.tpmLoading = false; - this.setState(response.data); - } - - }).catch((error) => { - console.log(error) - }) - } - aboutFocus = () => { - const { creator, watched } = this.state - /*http://localhost:3000/api/v1/users/155/watch?object_id=156&object_type=user*/ - - const focusUrl = `/api/v1/users/${creator.owner_id}/${watched ? 'unwatch' : 'watch'}?object_id=${creator.owner_id}&object_type=user` - - axios.get(focusUrl,{ - }) - .then((response) => { - const status = response.data.status; - if(status == 1){ - const new_author_info = Object.assign({}, creator) - this.setState({ - watched: !watched - }) - } - }).catch((error) => { - console.log(error) - }) - } - - keyupListener = (e) => { - if (e.key === "Escape") { - this.setState({ globalLoading: false }) - } - } - componentWillUnmount() { - window.removeEventListener('keyup', this.keyupListener) - } - - componentDidMount() { - // console.log("TPMIndexHOC========"); - // console.log(this.props); - window.addEventListener('keyup', this.keyupListener) - - if(this.props.match.path==="/"){ - // document.title="创新源于实践"; - }else if(this.props.match.path==="/403"){ - document.title="你没有权限访问"; - }else if(this.props.match.path==="/nopage"){ - document.title="没有找到该页面"; - }else if(this.props.match.path==="/shixuns"){ - document.title="实训项目"; - }else if(this.props.match.path==="/paths"){ - document.title="实践课程"; - }else if(this.props.match.path==="/courses"){ - document.title="翻转课堂"; - } - - - $.ajaxSetup({ - cache: true - }); - - //帮助后台传参数 - const query = this.props.location.search; - // const type = query.split('?chinaoocTimestamp='); - // console.log("Eduinforms12345"); - // console.log(this.foo(query)); - // console.log(JSON.stringify(this.foo(query))); - var dataqueryss={} - try { - var foqus=this.foo(query); - if(JSON.stringify(foqus) ==="{}"){ - this.setState({ - dataquerys:{}, - }); - }else{ - this.setState({ - dataquerys:foqus, - }); - dataqueryss=foqus; - } - }catch (e) { - this.setState({ - dataquerys:{}, - }) - } - this.fetchUsers(dataqueryss); - - let url=`/users/get_navigation_info.json`; - axios.get(url, { - - }).then((response) => { - // console.log("开始请求/get_navigation_info.json"); - // console.log(response); - if(response!=undefined){ - if(response.status===200){ - this.setState({ - Headertop:response.data.top, - Footerdown:response.data.down - }) - } - } - }); - ///请求定制化的信息 - this.getAppdata(); - } - /** - 课堂权限相关方法,暂时写这里了 ----------------------------------------START - ADMIN = 0 # 超级管理员 - CREATOR = 1 # 课程创建者 - PROFESSOR = 2 # 课程老师 - ASSISTANT_PROFESSOR = 3 # 课程助教 - STUDENT = 4 # 学生 - NORMAL = 5 # 普通用户 - - v2 - # 课程权限判断 - ADMIN = 0 # 超级管理员 - BUSINESS = 1 # 运营人员 - CREATOR = 2 # 课程创建者 课堂管理员 - PROFESSOR = 3 # 课程老师 - ASSISTANT_PROFESSOR = 4 # 课程助教 - STUDENT = 5 # 学生 - NORMAL = 6 # 普通用户 - Anonymous = 7 # 普未登录 - */ - //超管0 - isSuperAdmin = () => { - // return false - return this.state.coursedata&&this.state.coursedata.course_identity === 0 - } - isCourseAdmin = () => { - return this.state.coursedata&&this.state.coursedata.course_identity === 2 - } - //超管、运维0-1 - isClassManagement = () => { - return this.state.coursedata&&this.state.coursedata.course_identity < 2 - } - //超管、运维、课堂管理0-2 - isAdminOrCreator = () => { - return this.state.coursedata&&this.state.coursedata.course_identity < 3 - } - //超管、运维、课堂管理、老师0-3 - isAdminOrTeacher = () => { - return this.state.coursedata&&this.state.coursedata.course_identity < 4 - } - // 超管、运维、课堂管理、老师、助教0-4 - isAdmin = () => { - return this.state.coursedata&&this.state.coursedata.course_identity < 5 - } - // 学生5 - isStudent = () => { - return this.state.coursedata&&this.state.coursedata.course_identity === 5 - } - // 超管、运维、课堂管理、老师、助教、学生0-5 - isAdminOrStudent = () => { - return this.state.coursedata&&this.state.coursedata.course_identity <= 5 - } - // 游客未登录/非课堂成员6> - isNotMember = () => { - return this.state.coursedata&&this.state.coursedata.course_identity >= 6 - } - //课堂是否已结束 - isCourseEnd = () => { - return this.state.current_user ? this.state.current_user.course_is_end : false - } - - // setTrialapplication = ()=>{ - // this.setState({ - // isRenders:true - // }) - // - // } - - //获取数据为空的时候 - gettablogourlnull = () => { - this.setState({ - mygetHelmetapi: undefined - }); - document.title = "EduCoder"; - var link = document.createElement('link'), - oldLink = document.getElementById('dynamic-favicon'); - link.id = 'dynamic-favicon'; - link.rel = 'shortcut icon'; - link.href = "/react/build/./favicon.ico"; - if (oldLink) { - document.head.removeChild(oldLink); - } - document.head.appendChild(link); - }; - - //获取数据的时候 - gettablogourldata = (response) => { - document.title = response.data.setting.name; - var link = document.createElement('link'), - oldLink = document.getElementById('dynamic-favicon'); - link.id = 'dynamic-favicon'; - link.rel = 'shortcut icon'; - link.href = '/' + response.data.setting.tab_logo_url; - if (oldLink) { - document.head.removeChild(oldLink); - } - document.head.appendChild(link); - } - //获取当前定制信息 - getAppdata = () => { - let url = "/setting.json"; - axios.get(url).then((response) => { - // console.log("app.js开始请求/setting.json"); - // console.log("获取当前定制信息"); - if (response) { - if (response.data) { - this.setState({ - mygetHelmetapi: response.data.setting - }); - try { - if (response.data.setting.tab_logo_url) { - this.gettablogourldata(response); - } else { - this.gettablogourlnull(); - } - } catch (e) { - this.gettablogourlnull(); - } - - - } else { - - this.gettablogourlnull(); - - } - - } else { - this.gettablogourlnull(); - - } - - }).catch((error) => { - this.gettablogourlnull(); - - }); - }; - /** - 课堂权限相关方法,暂时写这里了 ----------------------------------------END - */ - fetchUser = () => { - let url = `/users/get_user_info.json` - let courseId; - let query = this.props.location.pathname; - const type = query.split('/'); - if (type[1] == 'courses' && type[2]) { - courseId = parseInt(type[2]) - // url += `?course_id=${courseId}` - } - var datay={}; - if(JSON.stringify(this.state.dataquerys) ==="{}"){ - datay={ - course_id:isNaN(courseId)?undefined:courseId, - school:1 - } - }else{ - datay={ - course_id:isNaN(courseId)?undefined:courseId, - school:1, - chinaoocTimestamp:this.state.dataquerys.chinaoocTimestamp, - websiteName:this.state.dataquerys.websiteName, - chinaoocKey:this.state.dataquerys.chinaoocKey, - } - } - axios.get(url,{params: - datay - }, - { - // withCredentials: true - } - ).then((response) => { - /* - { - "username": "黄井泉", - "login": "Hjqreturn", - "user_id": 12, - "image_url": "avatar/User/12", - "admin": true, - "is_teacher": false, - "tidding_count": 0 - } - */ - if(response=== undefined){ - return - } - if (response.data) { - this.initCommonState(response.data) - this.setState({ - tpmLoading: false, - coursedata: { - course_identity: response.data.course_identity >= 0 ? response.data.course_identity : undefined, - course_public: response.data.course_public, - name: response.data.course_name, - userid:response.data.user_id - }, - - }) - - } - - }).catch((error) => { - console.log(error) - }) - }; - fetchUsers = (yslurlobject) => { - let url = `/users/get_user_info.json` - let courseId; - let query = this.props.location.pathname; - const type = query.split('/'); - if (type[1] == 'courses' && type[2]) { - courseId = parseInt(type[2]) - // url += `?course_id=${courseId}` - } - var datay={}; - if(JSON.stringify(yslurlobject) ==="{}"){ - datay={ - course_id:isNaN(courseId)?undefined:courseId, - school:1 - } - }else{ - datay={ - course_id:isNaN(courseId)?undefined:courseId, - school:1, - chinaoocTimestamp:yslurlobject.chinaoocTimestamp, - websiteName:yslurlobject.websiteName, - chinaoocKey:yslurlobject.chinaoocKey, - } - } - axios.get(url,{params: - datay - }, - { - // withCredentials: true - } - ).then((response) => { - /* - { - "username": "黄井泉", - "login": "Hjqreturn", - "user_id": 12, - "image_url": "avatar/User/12", - "admin": true, - "is_teacher": false, - "tidding_count": 0 - } - */ - if(response=== undefined){ - return - } - if (response.data) { - this.initCommonState(response.data) - this.setState({ - tpmLoading: false, - coursedata: { - course_identity: response.data.course_identity >= 0 ? response.data.course_identity : undefined, - course_public: response.data.course_public, - name: response.data.course_name, - userid:response.data.user_id - }, - - }) - - } - - }).catch((error) => { - console.log(error) - }) - }; - //截取url 数据的 - foo=(url)=> { - var json = {}; - var regExp = /[\?\&](\w+)(=?)(\w*)/g; - var arr; - do { - arr = regExp.exec(url); - // console.log(arr); // arr = [完整的字符串, key, 等号或'', value或''] - - if (arr) { - var key = arr[1]; - var value = arr[3]; - // arr[2] === ''时, value = undefined - if (!arr[2]) - value = undefined; - - json[key] = value; - } - } while (arr); - - return json; - }; - hideLoginDialog = () => { - this.setState({ - isRender: false, - isloginCancel:undefined - }) - } - showLoginDialog = () => { - this.setState({ - isRender: true, - isloginCancel:"iscancel" - }) - } - //验证登录是否成功方法 - checkIfLogin = () => { - return this.state.current_user && this.state.current_user.login != '' - } - - hideAccountProfile = () => { - this.setState({ - AccountProfiletype: false - }) - } - showProfileCompleteDialog = () => { - this.dialogObj = {} - this.setState({ - AccountProfiletype: true - }) - } - //验证是否完善资料 - checkIfProfileCompleted = () => { - return this.state.current_user && this.state.current_user.profile_completed - } - showProfessionalCertificationDialog = () => { - this.dialogObj = { - content: '您需要去完成您的职业认证,才能使用此功能', - okText: '立即完成', - okHref: '/account/certification' - } - this.setState({ - AccountProfiletype: true, - }) - } - checkIfProfessionalCertification = () => { - return this.state.current_user && this.state.current_user.professional_certification - } - - - ShowOnlinePdf = (url) => { - return axios({ - method:'get', - url:url, - responseType: 'arraybuffer', - }).then((result)=>{ - var binaryData = []; - binaryData.push(result.data); - this.url =window.URL.createObjectURL(new Blob(binaryData, {type:"application/pdf"})); - window.open(this.url); - }) - } - DownloadFileA=(title,url)=>{ - let link = document.createElement('a'); - document.body.appendChild(link); - link.href =url; - link.download = title; - //兼容火狐浏览器 - let evt = document.createEvent("MouseEvents"); - evt.initEvent("click", false, false); - link.dispatchEvent(evt); - document.body.removeChild(link); - } - - DownloadOpenPdf=(type,url)=>{ - type===true?window.open(url):window.location.href=url; - } - slowDownload = (url, tip) => { - this._gLoadingTip = tip || '正在生成文件,请稍后...'; - this.setState({ globalLoading: true }) - const fileUrl = url; - downloadFile({ - url: fileUrl, - successCallback: (url) => { - this.setState({ globalLoading: false }) - console.log('successCallback') - }, - failCallback: (responseHtml, url) => { - this.setState({ globalLoading: false }) - console.log('failCallback') - } - }) - } - yslslowCheckresults =(tip) =>{ - this._gLoadingTip = tip || '成绩计算中,请稍候...'; - this.setState({ globalLoading: true }) - } - yslslowCheckresultsNo =() =>{ - this.setState({ globalLoading: false }) - } - - showGlobalLoading = (tip) => { - this._gLoadingTip = tip || '加载中,请稍后...'; - this.setState({ globalLoading: true }) - } - hideGlobalLoading = () => { - this.setState({ globalLoading: false }) - } - - MdifHasAnchorJustScorll=()=>{ - //mdhash滚动 - let anchor = decodeURI(this.props.location.hash).replace('#', ''); - // 对应id的话, 滚动到相应位置 - if (!!anchor) { - let anchorElement = document.getElementsByName(anchor); - if (anchorElement) { - if (anchorElement.length>0){ - anchorElement[anchorElement.length-1].scrollIntoView(); - } - } - } - } - - render() { - let{Headertop,Footerdown, isRender, AccountProfiletype,mygetHelmetapi}=this.state; - const common = { - isSuperAdmin:this.isSuperAdmin, - isAdminOrCreator:this.isAdminOrCreator, - isClassManagement:this.isClassManagement, - isCourseAdmin:this.isCourseAdmin, - - isAdmin: this.isAdmin, - isAdminOrTeacher: this.isAdminOrTeacher, - isStudent: this.isStudent, - isAdminOrStudent: this.isAdminOrStudent, - isNotMember: this.isNotMember, - isCourseEnd: this.isCourseEnd, - - isUserid:this.state.coursedata&&this.state.coursedata.userid, - fetchUser: this.fetchUser, - - showLoginDialog: this.showLoginDialog, - checkIfLogin: this.checkIfLogin, - showProfileCompleteDialog: this.showProfileCompleteDialog, - checkIfProfileCompleted: this.checkIfProfileCompleted, - checkIfProfessionalCertification: this.checkIfProfessionalCertification, - showProfessionalCertificationDialog: this.showProfessionalCertificationDialog, - - ShowOnlinePdf:(url)=>this.ShowOnlinePdf(url), - DownloadFileA:(title,url)=>this.DownloadFileA(title,url), - DownloadOpenPdf:(type,url)=>this.DownloadOpenPdf(type,url), - - slowDownload: this.slowDownload, - showGlobalLoading: this.showGlobalLoading, - hideGlobalLoading: this.hideGlobalLoading, - yslslowCheckresults:this.yslslowCheckresults, - yslslowCheckresultsNo:this.yslslowCheckresultsNo, - MdifHasAnchorJustScorll:this.MdifHasAnchorJustScorll - - }; - // console.log("this.props.mygetHelmetapi"); - // console.log(this.props.mygetHelmetapi); - return ( -
    - {isRender===true ? this.hideLoginDialog()} - {...this.props} - {...this.state} - /> : ""} - {/* AccountProfile 也用作职业认证 */} - {AccountProfiletype===true ? this.hideAccountProfile()} - {...this.props} - {...this.state} - {...this.dialogObj} - />:""} - - {/* 注释掉了1440 影响到了手机屏幕的展示 */} - - - - - -
    - this.initCommonState(user)} - {...this.props} {...this.state} - showShixun={this.showShixun} aboutFocus={this.aboutFocus} - {...common} - > - - -
    - -
    - - - -
    - ); - } - } -} \ No newline at end of file diff --git a/public/react/src/tpm/TPMPropaedeutics.js b/public/react/src/tpm/TPMPropaedeutics.js deleted file mode 100644 index 88a05fde7..000000000 --- a/public/react/src/tpm/TPMPropaedeutics.js +++ /dev/null @@ -1,74 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import PropTypes from 'prop-types'; - -import { CircularProgress } from 'material-ui/Progress'; - -import './TPMShixunDiscuss.css' - -import Propaedeutics from './shixunchild/Propaedeutics/Propaedeu_tics' - -import TPMRightSection from './component/TPMRightSection' - -import TPMNav from './component/TPMNav' - -import axios from 'axios'; - -class TPMPropaedeutics extends Component { - constructor(props) { - super(props) - this.state = { - shixunId: undefined - } - } - - componentWillReceiveProps(newProps, newContext) { - } - - componentDidMount() { - - - } - - - render() { - const { loadingContent, creator, shixun, myshixun, recommend_shixuns, current_user, watched, - aboutFocus, user, match - } = this.props; - // - return ( - -
    - -
    - - - - -
    - -
    - -
    -
    -
    - - ); - } -} - -export default TPMPropaedeutics; diff --git a/public/react/src/tpm/TPMPropaedeuticsComponent.js b/public/react/src/tpm/TPMPropaedeuticsComponent.js deleted file mode 100644 index 7c3eadb89..000000000 --- a/public/react/src/tpm/TPMPropaedeuticsComponent.js +++ /dev/null @@ -1,39 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import PropTypes from 'prop-types'; - -import TPMPropaedeutics from './TPMPropaedeutics' - -import axios from 'axios'; - -class TPMPropaedeuticsComponent extends Component { - constructor(props) { - super(props) - this.state = { - // tpmLoading: true, - // creator: { - // owner_id: '' - // } - } - } - - render() { - const { tpmLoading } = this.props; - - return ( - - { tpmLoading ?
    : - - - } -
    - - - ); - } -} - -export default TPMPropaedeuticsComponent ; diff --git a/public/react/src/tpm/TPMRanking_list.js b/public/react/src/tpm/TPMRanking_list.js deleted file mode 100644 index 7171692a7..000000000 --- a/public/react/src/tpm/TPMRanking_list.js +++ /dev/null @@ -1,59 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import PropTypes from 'prop-types'; - -import { CircularProgress } from 'material-ui/Progress'; - -import './TPMShixunDiscuss.css' - -import Ranking_list from './shixunchild/Ranking_list/Ranking_list' -import TPMRightSection from './component/TPMRightSection' -import TPMNav from './component/TPMNav' - -class TPMRanking_list extends Component { - constructor(props) { - super(props) - - } - - render() { - const { loadingContent, creator, shixun, myshixun, recommend_shixuns, current_user, watched, - aboutFocus, user, match - } = this.props; - - // - return ( - -
    - -
    - - - - - -
    - -
    - -
    -
    -
    - - ); - } -} - -export default TPMRanking_list; diff --git a/public/react/src/tpm/TPMRanking_listContainer.js b/public/react/src/tpm/TPMRanking_listContainer.js deleted file mode 100644 index 98841b1ab..000000000 --- a/public/react/src/tpm/TPMRanking_listContainer.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import PropTypes from 'prop-types'; - -import TPMRanking_list from './TPMRanking_list' - -import axios from 'axios'; - -class TPMRanking_listContainer extends Component { - constructor(props) { - super(props) - this.state = { - } - } - - render() { - const { tpmLoading } = this.props; - const user = this.props.current_user; - - return ( - - { tpmLoading ?
    : - - - } -
    - ); - } -} - -export default TPMRanking_listContainer; diff --git a/public/react/src/tpm/TPMRepository.js b/public/react/src/tpm/TPMRepository.js deleted file mode 100644 index 0f8e31258..000000000 --- a/public/react/src/tpm/TPMRepository.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import PropTypes from 'prop-types'; - -import { CircularProgress } from 'material-ui/Progress'; - -import './TPMShixunDiscuss.css' - -import Repository from './shixunchild/Repository/Repository' -import TPMRightSection from './component/TPMRightSection' -import TPMNav from './component/TPMNav' - -// import RepositoryChooseModal from './component/modal/RepositoryChooseModal' - -class TPMRepository extends Component { - constructor(props) { - super(props) - } - - - render() { - const { loadingContent, creator, shixun, myshixun, recommend_shixuns, current_user, watched, - aboutFocus, user, match, isContentWidth100 - } = this.props; - - return ( - -
    - {/* 可能会影响到其他页面的样式,需要测试、协商 */} -
    - - {/* */} - { loadingContent ? - : - - } -
    - - { !isContentWidth100 &&
    - -
    } -
    -
    - - ); - } -} - -export default TPMRepository; diff --git a/public/react/src/tpm/TPMRepositoryComponent.js b/public/react/src/tpm/TPMRepositoryComponent.js deleted file mode 100644 index 027f3f705..000000000 --- a/public/react/src/tpm/TPMRepositoryComponent.js +++ /dev/null @@ -1,229 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import PropTypes from 'prop-types'; - -import TPMRepository from './TPMRepository' - -import axios from 'axios'; - -import { trace_collapse, info } from 'educoder' - -import RepositoryCodeEditor from './shixunchild/Repository/RepositoryCodeEditor' - - -class TPMRepositoryComponent extends Component { - constructor(props) { - super(props) - this.nameTypeMap = {} - let pathArray = [] - var splitArray = window.location.pathname.split('shixun_show/'); - if (splitArray[1]) { - pathArray = splitArray[1].split('/') - if (pathArray[pathArray.length - 1] == '') { - // 有可能是这么访问的: http://localhost:3007/shixuns/3ozvy5f8/repository/fsu7tkaw/master/shixun_show/src/ - pathArray.length = pathArray.length - 1; - } - } - this.state = { - repositoryLoading: true, - pathArray: pathArray, - isContentWidth100: this._isFileInPathArray(pathArray) - } - } - componentDidUpdate(prevProps, prevState) { - if (this.props.secret_repository_tab != prevProps.secret_repository_tab) { - this.fetchRepo() - } - } - - - componentDidMount = () => { - - this.fetchRepo() - } - setContentWidth100 = (flag) => { - const newFileContent = flag === false ? '' : this.state.fileContent - this.setState({ - // isCodeFile - isContentWidth100: flag, - fileContent: newFileContent - }) - } - saveCode = (content) => { - const path = this.state.pathArray.join('/') - let id = this.props.match.params.shixunId; - let url = `/shixuns/${id}/update_file.json`; - axios.post(url, { - path: path, - content - }).then((response) => { - if(response.status === 200){ - this.setState({ - fileContent: response.data.content, - repositoryLoading: false - }); - } - trace_collapse('tpm save code res: ', response) - this.props.showSnackbar('文件保存成功') - - }).catch((error)=>{ - console.log(error) - }); - } - fetchCode = (newPathArray) => { - const path = newPathArray.join('/') - - // https://testeduplus2.educoder.net/shixuns/3ozvy5f8/file_content.json - this.setContentWidth100(true) - this.setState({ repositoryLoading: true, pathArray: newPathArray }) - let id = this.props.match.params.shixunId; - let url = `/shixuns/${id}/file_content.json`; - axios.post(url, { - path: path, - secret_repository: this.props.secret_repository_tab - }).then((response) => { - trace_collapse('repository res: ', response) - - if (response.data.status == -1) { - this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!') - return; - } - if(response.status === 200){ - this.setState({ - fileContent: response.data.content, - repositoryLoading: false - }); - this.props.history - .replace(`${this.props.match.url}/master/shixun_show/${newPathArray.join('/')}`) - } - - }).catch((error)=>{ - this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!') - console.log(error) - }); - } - _isFileName = (name) => { - return name.indexOf('.') !== -1 - } - _isFileInPathArray = (array) => { - if (!array || array.length === 0) { - return false - } - return this.nameTypeMap[array[array.length - 1]] !== 'tree' && this._isFileName( array[array.length - 1] ) - } - // listItem 如果是num,则是通过面包屑点击过来的,取pathArray的子集 - fetchRepo = (listItem) => { - const { pathArray } = this.state; - let newPathArray = pathArray.slice(0) - - if (listItem === 0 || listItem) { - this.setContentWidth100(false) - this.nameTypeMap[listItem.name] = listItem.type - if (typeof listItem == 'number') { // 参数是数字的话,做截取 - // if (this._isFileName(newPathArray[listItem])) { // 面包屑中的文件不让点击了 - // listItem--; - // } - newPathArray = newPathArray.slice(0, listItem) - } else if (listItem.type === 'tree') { - newPathArray.push(listItem.name) - } else if (listItem.type === 'blob') { - newPathArray.push(listItem.name) - this.setState({ pathArray: newPathArray }) - this.fetchCode(newPathArray) - return; - } - } - // https://testeduplus2.educoder.net/shixuns/3ozvy5f8/repository.json - this.setState({ repositoryLoading: true, pathArray: newPathArray }) - let urlNewPathArray = newPathArray; - let fileInPathArray = false; - if (newPathArray.length) { - fileInPathArray = this.nameTypeMap[newPathArray[newPathArray.length - 1]] ? this.nameTypeMap[newPathArray[newPathArray.length - 1]] !== 'tree' - : (listItem ? listItem.type !== 'tree' : this._isFileName( newPathArray[newPathArray.length - 1] )) - if ( fileInPathArray ) { - urlNewPathArray = newPathArray.slice(0, newPathArray.length - 1) - } - } - const path = urlNewPathArray.join('/') - - let id = this.props.match.params.shixunId; - let url = `/shixuns/${id}/${this.props.secret_repository_tab ? 'secret_repository' : 'repository'}.json`; - // this.props.setLoadingContent(true) - axios.post(url, { - path: path ? path : '' - }).then((response) => { - // this.props.setLoadingContent(false) - - const trees = response.data.trees - const treeIsFileMap = {} - if (!trees || !Array.isArray(trees)) { - // this.props.showSnackbar('无法找到对应的资源,请变更地址或联系管理员!') - // return; - } else { - trees.forEach(item => { - treeIsFileMap[item.name] = item.type == 'blob' - }) - } - if(response.status === 200){ - this.setState({ - treeIsFileMap, - ...response.data, - repositoryLoading: false - }); - this.props.history - .replace(`${this.props.match.url}` + - (newPathArray.length ? `/master/shixun_show/${newPathArray.join('/')}` : '')) - } - - // 初始化时,repo接口完毕后需要看是否需要fetchCode - if (fileInPathArray) { - this.fetchCode(newPathArray) - } - // info(response) - trace_collapse('repository res: ', response) - - }).catch((error)=>{ - console.log(error) - }); - } - - - render() { - const { isContentWidth100 } = this.state; - - // 需要重构 - return ( - - { !isContentWidth100 ? - - : -
    - {/* 可能会影响到其他页面的样式,需要测试、协商 */} -
    - -
    -
    - } - -
    - - - ); - } -} - -export default TPMRepositoryComponent ; diff --git a/public/react/src/tpm/TPMShixunDiscuss.css b/public/react/src/tpm/TPMShixunDiscuss.css deleted file mode 100644 index 3af4ec269..000000000 --- a/public/react/src/tpm/TPMShixunDiscuss.css +++ /dev/null @@ -1,47 +0,0 @@ -.tpmComment .-fit { - position: inherit; -} -.tpmComment .rc-pagination { - margin-left: auto; - margin-right: auto; - margin-top: 12px; - margin-bottom: 20px; -} -.tpmComment .paginationSection { - background: #FAFAFA; -} -.tpmComment .comment_item_cont.df.clearfix:nth-last-child(1) { - border-bottom: none; -} - -/*.tpmComment .fl.edu-back-white {*/ -/*min-height: 600px;*/ -/*}*/ - - -.user_watch_btn { - cursor: pointer; -} - - -/*md编辑器*/ -.tpmComment .commentItemMDEditor a.task-btn { - background: #4cacff!important; - margin-right: 16px; - margin-top: 16px; -} -/* md编辑器 resizeBar*/ - .tpmComment .commentItemMDEditor .editor__resize { - transform: translateX(-176%) -} - -#ratePanel > div > div > div.fr div.rateYo.fl.mt3 { - height: 20px; - line-height: 20px; - cursor: default; - width: 110px; -} - -.tpmComment .icon-jiangli { - /* margin-top: 2px; */ -} \ No newline at end of file diff --git a/public/react/src/tpm/TPMShixunDiscuss.js b/public/react/src/tpm/TPMShixunDiscuss.js deleted file mode 100644 index 9350060cc..000000000 --- a/public/react/src/tpm/TPMShixunDiscuss.js +++ /dev/null @@ -1,72 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import PropTypes from 'prop-types'; - -import { CircularProgress } from 'material-ui/Progress'; - -import './TPMShixunDiscuss.css' - -import ShixunDiscuss from './shixunchild/ShixunDiscuss/ShixunDiscuss' -import TPMRightSection from './component/TPMRightSection' -import TPMNav from './component/TPMNav' - -import Comments from '../comment/Comments' -import { commentHOC } from '../comment/CommentsHOC' - -class TPMShixunDiscuss extends Component { - constructor(props) { - super(props) - - } - - componentWillReceiveProps(newProps, newContext) { - } - - componentDidMount() { - // TODO 加了HOC后 mount了两次 - this.props.fetchCommentIfNotFetched && - this.props.fetchCommentIfNotFetched(); - } - - render() { - const { loadingContent, creator, shixun, myshixun, recommend_shixuns, current_user, watched, - aboutFocus, user, match - } = this.props; - - return ( - -
    - -
    - - { loadingContent ? - : - - // onPaginationChange={this.onPaginationChange} - // - } -
    - -
    - -
    -
    -
    - - ); - } -} - -export default commentHOC ( TPMShixunDiscuss ); diff --git a/public/react/src/tpm/TPMShixunDiscussContainer.js b/public/react/src/tpm/TPMShixunDiscussContainer.js deleted file mode 100644 index 535840772..000000000 --- a/public/react/src/tpm/TPMShixunDiscussContainer.js +++ /dev/null @@ -1,45 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import PropTypes from 'prop-types'; - -import TPMShixunDiscuss from './TPMShixunDiscuss' - -import axios from 'axios'; - -class TPMShixunDiscussContainer extends Component { - constructor(props) { - super(props) - this.state = { - } - } - - componentWillReceiveProps(newProps, newContext) { - - } - - componentDidMount() { - - } - - render() { - const { tpmLoading } = this.props; - const user = this.props.current_user; - return ( - - { tpmLoading ?
    : - - - } -
    - ); - } -} - -export default TPMShixunDiscussContainer; diff --git a/public/react/src/tpm/TPMUpdatepropaede/TPMUpdatepropaede.js b/public/react/src/tpm/TPMUpdatepropaede/TPMUpdatepropaede.js deleted file mode 100644 index 63872b133..000000000 --- a/public/react/src/tpm/TPMUpdatepropaede/TPMUpdatepropaede.js +++ /dev/null @@ -1,100 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -import axios from 'axios'; - -import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; - -import {getUrl} from 'educoder'; - - - -export default class TPMUpdatepropaede extends Component { - constructor(props) { - super(props) - this.neweditanswerRef=React.createRef(); - this.state = { - shixunId:undefined, - } - } - - componentDidMount() { - let id = this.props.match.params.shixunId; - let url="/shixuns/"+id+"/propaedeutics.json"; - axios.get(url).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - this.setState({ - shixunId:id, - }) - if(response.data.content[0]!=null){ - this.setState({ - editanswersRefval:response.data.content, - }) - this.neweditanswerRef.current.setValue(response.data.content) - }else{ - this.setState({ - editanswersRefval:"", - }) - this.neweditanswerRef.current.setValue('') - } - } - }).catch((error) => { - console.log(error) - }); - - } - - updatepropaedeuticsvalue=()=>{ - let id = this.props.match.params.shixunId; - let url="/shixuns/"+id+"/update_propaedeutics.json"; - const update_propaedeuticsvalue = this.neweditanswerRef.current.getValue().trim(); - axios.post(url,{ - content:update_propaedeuticsvalue - } - ).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - this.props.showSnackbar(response.data.message); - } - }).catch((error) => { - console.log(error) - }); - } - render() { - let {shixunId} = this.state; - return ( - -
    - -
    -
    - 背景知识 - 返回 -
    - -
    - -
    -
    - -
    - 保存 - 取消 -
    - -
    -
    - ) - } -} - - diff --git a/public/react/src/tpm/TPMsettings/TPMsettings.js b/public/react/src/tpm/TPMsettings/TPMsettings.js deleted file mode 100644 index 7acaf98d6..000000000 --- a/public/react/src/tpm/TPMsettings/TPMsettings.js +++ /dev/null @@ -1,2437 +0,0 @@ -import React, { Component } from 'react'; - -import MonacoEditor from 'react-monaco-editor'; - -//MonacoDiffEditor 对比模式 -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal,Icon,DatePicker,Breadcrumb,Upload,Button,notification, Tooltip} from 'antd'; - -// import "antd/dist/antd.css"; - -import locale from 'antd/lib/date-picker/locale/zh_CN'; - -import moment from 'moment'; - -import axios from 'axios'; - -import './css/TPMsettings.css'; - -import { getImageUrl, toPath, getUrl ,appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder'; - -let origin = getUrl(); - -let path = getUrl("/editormd/lib/") - -const $ = window.$; - -let timeout; - -let currentValue; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; -const confirm = Modal.confirm; -// 处理整点 半点 -// 取传入时间往后的第一个半点 -export function handleDateStrings(dateString) { - if (!dateString) return dateString; - const ar = dateString.split(':') - if (ar[1] == '00' || ar[1] == '30') { - return dateString - } - const miniute = parseInt(ar[1]); - if (miniute < 30 || miniute == 60) { - return [ar[0], '30'].join(':') - } - if (miniute < 60) { - // 加一个小时 - const tempStr = [ar[0], '00'].join(':'); - const format = "YYYY-MM-DD HH:mm"; - const _moment = moment(tempStr, format) - _moment.add(1, 'hours') - return _moment.format(format) - } - - return dateString -} - -// 恢复数据 -function md_rec_data(k,mdu,id, editor){ - if(window.sessionStorage.getItem(k+mdu) !== null){ - editor.setValue(window.sessionStorage.getItem(k+mdu)); - md_clear_data(k,mdu,id); - } -} - -// 保存数据 -function md_add_data(k,mdu,d){ - window.sessionStorage.setItem(k+mdu,d); -} - -// 清空保存的数据 -function md_clear_data(k,mdu,id){ - window.sessionStorage.removeItem(k+mdu); - var id1 = "#e_tip_"+id; - var id2 = "#e_tips_"+id; - if(k == 'content'){ - $(id2).html(""); - }else{ - $(id1).html(""); - } -} - -function md_elocalStorage(editor,mdu,id){ - if (window.sessionStorage){ - var oc = window.sessionStorage.getItem('content'+mdu); - if(oc !== null ){ - $("#e_tips_"+id).data('editor', editor); - var h = '您上次有已保存的数据,是否恢复 ? / 不恢复'; - $("#e_tips_"+id).html(h); - } - setInterval(function() { - var d = new Date(); - var h = d.getHours(); - var m = d.getMinutes(); - var s = d.getSeconds(); - h = h < 10 ? '0' + h : h; - m = m < 10 ? '0' + m : m; - s = s < 10 ? '0' + s : s; - if(editor.getValue().trim() != ""){ - md_add_data("content",mdu,editor.getValue()); - var id1 = "#e_tip_"+id; - var id2 = "#e_tips_"+id; - - $(id1).html(" 数据已于 " + h + ':' + m + ':' + s +" 保存 "); - $(id2).html(""); - } - },10000); - - }else{ - $("#e_tip_"+id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!'); - } -} - -function create_editorMD(id, width, high, placeholder, imageUrl,initValue, callback) { - var editorName = window.editormd(id, { - width: width, - height: high, - path: path, // "/editormd/lib/" - markdown : initValue, - syncScrolling: "single", - tex: true, - tocm: true, - emoji: true, - taskList: true, - codeFold: true, - searchReplace: true, - htmlDecode: "style,script,iframe", - sequenceDiagram: true, - autoFocus: false, - placeholder: placeholder, - toolbarIcons: function () { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] - }, - toolbarCustomIcons: { - testIcon: "
    ", - testIcon1: "
    " - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea: true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity: 0.6, - imageUpload: true, - imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL: imageUrl,//url - onload: function () { - // this.previewing(); - $("#" + id + " [type=\"latex\"]").bind("click", function () { - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - - $("#" + id + " [type=\"inline\"]").bind("click", function () { - editorName.cm.replaceSelection("`$$$$`"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - callback && callback() - } - }); - return editorName; -} - - -function updatamakedown(id){ - setTimeout(()=>{ - var shixunDescr = window.editormd.markdownToHTML(id, { - htmlDecode: "style,script,iframe", - taskList: true, - tex: true, - flowChart: true, - sequenceDiagram: true - }); - $("#"+id+" p:first").addClass("ReactMarkdown"); - $('#collaborators_list_info').show() - }, 200) -} - -function range(start, end) { - const result = []; - for (let i = start; i < end; i++) { - result.push(i); - } - return result; -} -function disabledDateTime() { - return { - // disabledHours: () => range(0, 24).splice(4, 20), - disabledMinutes: () => range(1, 30).concat(range(31, 60)), - // disabledSeconds: () => [0, 60], - }; -} - -function disabledDate(current) { - return current && current < moment().endOf('day').subtract(1, 'days'); -} -export default class TPMsettings extends Component { - constructor(props) { - super(props) - this.state = { - fileList: [], - commandLine: 0, - Openpublic: 0, - settingsData: undefined, - webssh: 0, - use_scope: 0, - shixunsstatus: 0, - shixunsID: undefined, - exec_time: undefined, - trainee: undefined, - can_copy: undefined, - task_pass: undefined, - test_set_permission: undefined, - code_edit_permission: undefined, - hide_code: undefined, - code_hidden: undefined, - forbid_copy: undefined, - vnc: undefined, - name: undefined, - scope_partment: undefined, - scopetype: false, - departmentslist: undefined, - description: '', - evaluate_script:undefined, - standard_scripts: undefined, - choice_main_type: "", - choice_small_type: [], - choice_standard_scripts:undefined, - editordescriptios: undefined, - editorevaluate_scripts: undefined, - choice_standard_scriptssum: undefined, - visibleTemplate: false, - Executiveordervalue: "", - Compilecommandvalue: "", - Executivetyoe: false, - postapplyvisible: false, - sendsure_applyvalue: undefined, - postapplytitle: false, - shixunnametype: false, - shixunmaintype: false, - evaluate_scripttype: false, - exec_timetype: false, - traineetype: false, - standard_scriptsModal:false, - standard_scriptsModals:false, - SelectTheCommandtype:false, - multi_webssh:false, - status:0, - opers:false, - operss:false, - testscripttiptype:false, - opersss:false, - operateshixunstype:false, - opening_time:"", - opensmail:false, - scope_partmenttype:false, - newuse_scope:undefined, - scope_partments:0, - shixun_service_configs:undefined, - shixun_service_configlist:undefined, - pod_exist_time: undefined, - pod_exist_timetype: false, - shixunmemoMDvalue:"", - language:"", - deleteisnot:true - } - } - descriptionMD=(initValue, id)=> { - - this.contentChanged = false; - const placeholder = ""; -// amp; -// 编辑时要传memoId - const imageUrl = `/api/attachments.json`; -// 创建editorMd - - const description_editormd =create_editorMD(id, '100%', 400, placeholder, imageUrl, initValue,()=> { - setTimeout(() => { - description_editormd.resize() - description_editormd.cm && description_editormd.cm.refresh() - }, 500) - - if (initValue != undefined) { - description_editormd.setValue(initValue) - } - description_editormd.cm.on("change", (_cm, changeObj) => { - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - md_elocalStorage(description_editormd, `MemoQuestion_${id}`, `${id}Question`); - this.description_editormd = description_editormd; - window.description_editormd = description_editormd; - } - - evaluate_scriptMD=(initValue, id)=> { - this.contentChanged = false; - const placeholder = ""; -// amp; -// 编辑时要传memoId - const imageUrl = `/api/attachments.json`; -// 创建editorMd - - const evaluate_script_editormd =create_editorMD(id, '100%', 400, placeholder, imageUrl, initValue,()=> { - setTimeout(() => { - evaluate_script_editormd.resize() - evaluate_script_editormd.cm && evaluate_script_editormd.cm.refresh() - }, 500) - - if (initValue != undefined) { - evaluate_script_editormd.setValue(initValue) - } - evaluate_script_editormd.cm.on("change", (_cm, changeObj) => { - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - md_elocalStorage(evaluate_script_editormd, `MemoQuestion_${id}`, `${id}Question`); - this.evaluate_script_editormd = evaluate_script_editormd; - window.evaluate_script_editormd = evaluate_script_editormd; - - } - - - - componentDidMount() { - - let id=this.props.match.params.shixunId; - - let Url=`/shixuns/`+id+`/settings.json`; - - axios.get(Url).then((response)=> { - // alert(response.data.shixun.choice_standard_scripts) - if(response.status===200){ - this.setState({ - shixunsID: id, - settingsData: response.data, - webssh: response.data.shixun.webssh, - use_scope: response.data.shixun.use_scope, - shixunsstatus: response.data.shixun.status, - exec_time: response.data.shixun.exec_time, - trainee: response.data.shixun.trainee, - can_copy: response.data.shixun.can_copy, - task_pass: response.data.shixun.task_pass, - test_set_permission: response.data.shixun.test_set_permission, - hide_code: response.data.shixun.hide_code, - code_edit_permission: response.data.shixun.code_edit_permission, - code_hidden: response.data.shixun.code_hidden, - is_secret_repository: response.data.shixun.is_secret_repository, - init_is_secret_repository: response.data.shixun.is_secret_repository, - forbid_copy: response.data.shixun.forbid_copy, - vnc: response.data.shixun.vnc, - vnc_evaluate: response.data.shixun.vnc_evaluate, - name: response.data.shixun.name, - scope_partment: response.data.shixun.scope_partment, - description: response.data.shixun.description, - evaluate_script: response.data.shixun.evaluate_script, - choice_main_type: response.data.shixun.choice_main_type, - choice_small_type: response.data.shixun.choice_small_type, - choice_standard_scripts: response.data.shixun.choice_standard_scripts, - standard_scripts:response.data.shixun.standard_scripts, - multi_webssh:response.data.shixun.multi_webssh, - status:response.data.shixun.status, - opening_time:response.data.shixun.opening_time, - newuse_scope:response.data.shixun.use_scope, - scope_partments: response.data.shixun.scope_partment.length, - shixunmemoMDvalue:response.data.shixun.evaluate_script, - shixun_service_configs:response.data.shixun.shixun_service_configs, - shixun_service_configlist:response.data.shixun.shixun_service_configs, - }) - - // if(response.data.status===403){ - // message: "您没有权限进行该操作" - // this.setState({ - // :true - // message403:response.data.message - // }) - // } - - - if(response.data.shixun.multi_webssh===true){ - this.setState({ - SelectTheCommandtype:true - }) - }else{ - this.setState({ - SelectTheCommandtype:false - }) - } - if (response.data.shixun.scope_partment.length > 0) { - this.setState({ - scopetype: true - }) - } - // console.log(response.data.shixun.description) - // console.log(response.data.shixun.evaluate_script) - // console.log(response.data.shixun.description) - // this.props.identity<4&&this.props.status==0||this.props.identity===1&&this.props.status==2 - - - // this.evaluate_scriptMD(response.data.shixun.evaluate_script, "shixunmemoMD"); - - this.descriptionMD(response.data.shixun.description, "shixundescription"); - - // this.bigClass() - // if (response.data.shixun.status === 2) { - // - // } else if (response.data.shixun.status === 1) { - // this.props.showSnackbar("这个实训已发布不能修改!"); - // } else if (response.data.shixun.status === 3) { - // this.props.showSnackbar("这个实训已关闭不能修改!"); - // } - } - - }); - - - let departmentsUrl = `/shixuns/departments.json`; - axios.get(departmentsUrl).then((response) => { - if (response.status === 200) { - if (response.data.message === undefined) { - this.setState({ - departmentslist: response.data.shools_name - }); - } - } - }).catch((error) => { - console.log(error) - }); - - - - } - - SelectshixunCommand=(e)=>{ - // console.log( e.target.value) - const webssh = e.target.value - if (webssh == 2) { - this.setState({ - webssh: webssh, - SelectTheCommandtype: true, - multi_webssh:false - }); - } else { - if (this.state.init_is_secret_repository && !this.state.vnc && this.state.is_secret_repository == true) { - this.confirmDeleteSecretRepo({ - onOk: () => { - this.setState({ - webssh: webssh, - SelectTheCommandtype: false, - multi_webssh:false - }); - } - }) - } else { - if (!this.state.vnc) { - this.setState({ - is_secret_repository: false, - }) - } - this.setState({ - webssh: webssh, - SelectTheCommandtype: false, - multi_webssh:false - }); - } - } - - // this.setState({ - // webssh: webssh, - // }); - // if(webssh===2){ - // this.setState({ - // SelectTheCommandtype: true, - // multi_webssh:false - // }); - // }else{ - // this.setState({ - // SelectTheCommandtype: false, - // multi_webssh:false - // }); - // } - } - - SelectOpenpublic=(e)=>{ - this.setState({ - Openpublic: e.target.value - }); - } - - can_copy=(e)=>{ - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - can_copy: sum, - }); - - } - - task_pass=(e)=>{ - - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - task_pass: sum, - }); - } - - test_set_permission=(e)=>{ - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - test_set_permission: sum, - }); - - } - - hide_code=(e)=>{ - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - hide_code: sum, - }); - - } - code_edit_permission = (e) => { - this.setState({ - code_edit_permission: e.target.checked - }) - } - code_hidden=(e)=>{ - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - code_hidden: sum, - }); - - } - confirmDeleteSecretRepo = ({title, onOk}) => { - confirm({ - title: title ||
    -
    已创建的私密版本库及其内容,将在“保存”时被删除。
    -
    是否确认取消勾选?
    -
    , - okText: '确定', - cancelText: '取消', - onOk: () => { - this.setState({ is_secret_repository: false }) - onOk && onOk() - }, - onCancel() { - }, - }); - } - is_secret_repository = (e) => { - const checked = e.target.checked - if (!checked) { - if (this.state.init_is_secret_repository) { - this.confirmDeleteSecretRepo({ - }) - } else { - this.setState({ is_secret_repository: false }) - } - } else { - this.setState({ is_secret_repository: true }) - } - } - forbid_copy = (e) => { - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - forbid_copy: sum, - }); - } - shixun_vnc_evaluate=(e) => { - this.setState({ - vnc_evaluate: e.target.checked, - }); - - } - - shixun_vnc=(e)=>{ - // let sum = "" - // if (e.target.checked === false) { - // sum = 0 - // } else if (e.target.checked === true) { - // sum = 1 - // } - const vnc = e.target.checked; - if (!vnc) { - if (this.state.init_is_secret_repository && this.state.webssh != 2 && this.state.is_secret_repository == true) { - this.confirmDeleteSecretRepo({ - onOk: () => { - this.setState({ - vnc: e.target.checked, - vnc_evaluate: false, - }); - } - }) - } else { - if (this.state.webssh != 2) { - this.setState({ - is_secret_repository: false - }) - } - this.setState({ - vnc: e.target.checked, - vnc_evaluate: false, - }); - } - } else { - this.setState({ - vnc: e.target.checked, - vnc_evaluate: false, - }); - } - } - shixunsname = (e) => { - // let {shixunsstatus}=this.state; - // if(shixunsstatus>0){ - // return - // } - this.setState({ - name: e.target.value, - shixunnametype:false - }) - } - - bigClass = (value) => { - // choice_main_type - // choice_small_type - let {settingsData,shixun_service_configs,choice_main_type,choice_small_type}=this.state; - - let list=[] - list.push(choice_main_type) - choice_small_type.map((item,key)=>{ - list.push(item) - }) - - let newshixun_service_configs=shixun_service_configs; - - let newshixun_service_configsagin=[] - - newshixun_service_configs.map((item,key)=>{ - list.map((its,index)=>{ - if(item.mirror_repository_id===its){ - newshixun_service_configsagin.push(item) - } - }) - }) - - - settingsData.shixun.main_type.some((item,key)=> { - if (item.id === value) { - newshixun_service_configsagin[0]={ - mirror_repository_id:value, - name:item.type_name, - cpu_limit:1, - lower_cpu_limit:0.1, - memory_limit:1024, - request_limit:10 - } - return true - } - } - ) - let url = `/shixuns/get_mirror_script.json?mirror_id=`+value; - axios.get(url).then((response) => { - if (response.status === 200) { - // console.log(response.data) - this.setState({ - choice_main_type: value, - standard_scripts:response.data, - choice_standard_scripts:null, - shixun_service_configs:newshixun_service_configsagin, - shixun_service_configlist:newshixun_service_configsagin, - }) - } - }).catch((error) => { - console.log(error) - }); - - - - } - Deselectlittle=(value)=>{ - - let {shixun_service_configs,choice_small_type}=this.state; - let newshixun_service_configs=shixun_service_configs; - let newchoice_small_type=choice_small_type; - - newshixun_service_configs.some((item,key)=> { - if (item.mirror_repository_id === value) { - newshixun_service_configs.splice(key, 1) - return true - } - } - ) - - newchoice_small_type.some((item,key)=> { - if (item === value) { - newchoice_small_type.splice(key, 1) - return true - } - } - ) - - - this.setState({ - choice_small_type: newchoice_small_type, - shixun_service_configs:newshixun_service_configs, - shixun_service_configlist:newshixun_service_configs, - }) - } - littleClass = (value) => { - - let {settingsData,shixun_service_configs,choice_small_type,choice_main_type}=this.state; - let newshixun_service_configs=shixun_service_configs; - let newchoice_small_type=choice_small_type; - // if(Array.isArray(value)===true){ - // value.map((item,key)=>{ - // settingsData.shixun.small_type.some((items,keys)=> { - // if (items.id === item) { - // newshixun_service_configs.push({ - // mirror_repository_id:value, - // name:items.type_name, - // cpu_limit:1, - // lower_cpu_limit:0.1, - // memory_limit:1024, - // request_limit:10 - // }) - // return true - // } - // } - // ) - // }) - // } - - let list=[] - list.push(choice_main_type) - choice_small_type.map((item,key)=>{ - list.push(item) - }) - - let newshixun_service_configsagin=[] - - newshixun_service_configs.map((item,key)=>{ - list.map((its,index)=>{ - if(item.mirror_repository_id===its){ - newshixun_service_configsagin.push(item) - } - }) - }) - - settingsData.shixun.small_type.some((items,keys)=> { - if (items.id === value) { - newshixun_service_configsagin.push({ - mirror_repository_id:value, - name:items.type_name, - cpu_limit:1, - lower_cpu_limit:0.1, - memory_limit:1024, - request_limit:10 - }) - return true - } - } - ) - - newchoice_small_type.push(value) - - this.setState({ - choice_small_type: newchoice_small_type, - shixun_service_configs:newshixun_service_configsagin, - shixun_service_configlist:newshixun_service_configsagin, - }) - } - onPodExistTimeChange = (e) => { - this.setState({ - pod_exist_time: e.target.value, - pod_exist_timetype: false, - }) - } - Timevalue = (e) => { - this.setState({ - exec_time: e.target.value - }) - } - SelectOpenpublic = (e) => { - this.setState({ - scopetype: false, - use_scope: e.target.value, - }); - if (e.target.value === 1) { - this.setState({ - scopetype: true - }); - } - - } - deleteScopeInput = (key) => { - let {scope_partment} = this.state; - let datalist = scope_partment; - datalist.splice(key, 1); - this.setState({ - scope_partment: datalist - }); - } - - shixunScopeInput = (e) => { - let {scope_partment} = this.state; - let datalist = scope_partment; - if (datalist===undefined) { - datalist=[] - } - - datalist.push(e) - // else { - // datalist[id] = e - // } - this.setState({ - scope_partment: datalist - }); - } - // adduse_scopeinput = () => { - // let {scope_partment} = this.state; - // let array = scope_partment; - // let newarray = "" - // array.push(newarray) - // this.setState({ - // scope_partment: array, - // }); - // } - submit_edit_shixun = () => { - if (this.saving == true) return; - this.saving = true; - if(this.state.status===-1){ - this.props.showSnackbar("该实训已被删除,保存失败!"); - return - } - - let { - name, choice_main_type, choice_small_type, choice_standard_scripts, scope_partment, choice_standard_scriptssum, vnc_evaluate, - evaluate_script, webssh, use_scope, trainee, can_copy, task_pass, test_set_permission, hide_code, code_hidden, forbid_copy, vnc,multi_webssh, - opening_time,shixunmemoMDvalue,shixun_service_configlist, is_secret_repository, code_edit_permission - } = this.state; - - let newshixun_service_configlist = shixun_service_configlist.map(v => { - let v1 = Object.assign({},v); - delete v1.name; - return v1 - }); - - // let operateauthority= - // this.props.identity===1?true:this.props.identity<5&&this.state.status==0?true:false; - // this.props.identity<5&&this.state.status==0||this.props.identity===1&&this.state.status==2||this.props.identity===1&&this.state.status==1; - - const description_editormd = this.description_editormd.getValue(); - - let evaluate_script_editormd; - - if(this.state.status==0||this.state.status==1||this.state.status==2&&this.props.identity===1){ - // evaluate_script_editormd = this.evaluate_script_editormd.getValue(); - evaluate_script_editormd = shixunmemoMDvalue - }else{ - evaluate_script_editormd = evaluate_script; - } - - - - if (name === "") { - this.setState({ - shixunnametype: true - }) - $('html').animate({ - scrollTop: 10 - }, 1000); - return - } - if (choice_main_type === "") { - this.setState({ - shixunmaintype: true - }) - $('html').animate({ - scrollTop: 800 - }, 1000); - return - } - if (evaluate_script_editormd === "") { - this.setState({ - evaluate_scripttype: true - }) - $('html').animate({ - scrollTop: 1200 - }, 1000); - return - } - if(use_scope===1){ - - if(scope_partment===undefined||scope_partment.length===0){ - this.setState({ - scope_partmenttype: true - }) - $('html').animate({ - scrollTop: 2500 - }, 1000); - this.props.showSnackbar("公开程度,指定单位为空"); - return - } - } - // if (exec_time === "") { - // this.setState({ - // exec_timetype: true - // }) - // $('html').animate({ - // scrollTop: 1500 - // }, 1000); - // return - // } - - // if (!pod_exist_time) { - // this.setState({ - // pod_exist_timetype: true - // }) - // $("html, body").animate({ scrollTop: $('#pod_exist_time').offset().top - 100 }, 1000) - // return - // } - - if (trainee === "") { - this.setState({ - traineetype: true - }) - return - } - - let id = this.props.match.params.shixunId; - - let newmulti_webssh=multi_webssh; - - - if(newmulti_webssh===null){ - newmulti_webssh=false - } - - //exec_time: exec_time, - let Url = `/shixuns/` + id + `.json`; - let data = { - shixun:{ - - name: name, - webssh: webssh, - use_scope: use_scope, - can_copy: can_copy, - vnc: vnc===null?undefined:vnc, - vnc_evaluate: vnc_evaluate===null?undefined:vnc_evaluate, - test_set_permission: test_set_permission, - code_hidden: code_hidden, - code_edit_permission: code_edit_permission, - trainee: trainee, - task_pass: task_pass, - hide_code: hide_code, - forbid_copy: forbid_copy, - multi_webssh:newmulti_webssh, - opening_time:opening_time, - mirror_script_id:choice_standard_scriptssum===undefined?choice_standard_scripts:choice_standard_scriptssum, - }, - shixun_info:{ - description: description_editormd, - evaluate_script: evaluate_script_editormd, - }, - is_secret_repository: is_secret_repository, - main_type: choice_main_type, - small_type: choice_small_type, - scope_partment: scope_partment, - shixun_service_configs:newshixun_service_configlist - } - - axios.put(Url, data).then((response) => { - // console.log(response) - this.saving = false; - if(response.status){ - if (response.data.status === -1) { - this.props.showSnackbar(response.data.message); - return - } else { - window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges"; - } - } - - }).catch((error) => { - console.log(error) - this.saving = false; - }) - - - } - shixunsfetch = (value, callback) => { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - currentValue = value; - - function fake() { - let departmentsUrl = `/shixuns/departments.json?q=` + currentValue; - axios.get(departmentsUrl).then((response) => { - callback(response.data.shools_name); - }).catch((error) => { - console.log(error) - }); - } - - timeout = setTimeout(fake, 300); - } - shixunHandleSearch = (value) => { - this.shixunsfetch(value, departmentslist => this.setState({departmentslist})); - } - - - - - shixunsclose = () => { - let id = this.props.match.params.shixunId; - let cul = `/shixuns/` + id + `/close.json`; - axios.post(cul).then((response) => { - if(response.data.status===1){ - this.props.showSnackbar("操作成功"); - this.setState({ - operateshixunstype: false, - }); - - window.location.href = "/shixuns/" + id + "/challenges"; - } - }).catch((error) => { - console.log(error) - }) - } - - shixunsdel= () => { - let id = this.props.match.params.shixunId; - let cul = `/shixuns/` + id +`.json`; - - axios.delete(cul).then((response) => { - if(response.data.status===1){ - this.props.showSnackbar("操作成功"); - this.setState({ - operateshixunstype: false, - }); - - window.location.href = "/shixuns"; - } - }).catch((error) => { - console.log(error) - }) - } - - Executiveorder = (e) => { - this.setState({ - Executiveordervalue: e.target.value - }) - } - - Compilecommand = (e) => { - this.setState({ - Compilecommandvalue: e.target.value - }) - } - - handleCancelTemplate = (e) => { - this.setState({ - Executiveordervalue: "", - Compilecommandvalue: "", - visibleTemplate: false - }) - } - - hideModalTemplate = (e) => { - let id = this.props.match.params.shixunId; - let {Executiveordervalue, Compilecommandvalue} = this.state; - - if (Executiveordervalue === "") { - this.setState({ - Executivetyoe: true, - }); - return - } - // Executiveordervalue=String(Executiveordervalue); - // Compilecommandvalue=String(Compilecommandvalue); - let trl = `/shixuns/${id}/get_custom_script.json?compile=${Executiveordervalue}&excutive=${Compilecommandvalue}` - axios.get(trl).then((response) => { - // this.evaluate_scriptMD(response.data.shixun_script, "shixunmemoMD"); - this.setState({ - shixunmemoMDvalue:response.data.shixun_script - }) - }).catch((error) => { - console.log(error) - }); - this.setState({ - visibleTemplate: false - }) - } - - showModal = () => { - this.setState({ - visibleTemplate: true, - }); - } - Selecttrainee = (value) => { - this.setState({ - trainee: value, - }); - } - - post_apply = () => { - this.setState({ - postapplyvisible: true - }) - } - - sendsure_applyvalues = (e) => { - this.setState({ - sendsure_applyvalue: e.target.value - }) - } - - setlanguagewrite = (e)=>{ - this.setState({ - languagewrite: e.target.value - }) - } - - setsystemenvironment = (e) => { - this.setState({ - systemenvironment: e.target.value - }) - } - - settestcoderunmode = (e) => { - this.setState({ - testcoderunmode: e.target.value - }) - - } - - sendsure_apply = () => { - let {languagewrite,systemenvironment,testcoderunmode} = this.state; - // console.log("点击确定") - // console.log("languagewrite"+languagewrite); - // console.log("systemenvironment"+systemenvironment); - // console.log("testcoderunmode"+testcoderunmode); - - // let attachment_ids = undefined - // if (this.state.fileList) { - // attachment_ids = this.state.fileList.map(item => { - // return item.response ? item.response.id : item.id - // }) - // } - if(languagewrite === undefined || languagewrite === "" ){ - // this.props.showNotification(`请填写该镜像是基于什么语言`); - this.setState({ - languagewritetype:true - }) - return - } - if(systemenvironment === undefined || systemenvironment === ""){ - // this.props.showNotification(`请填写该镜像是基于什么语言系统环境`); - this.setState({ - systemenvironmenttype:true - }) - return; - - } - if(testcoderunmode === undefined || testcoderunmode === "") { - // this.props.showNotification(`请填写该镜像中测试代码运行方式`); - this.setState({ - testcoderunmodetype:true - }) - return; - } - var attachment_ids=undefined; - if (this.state.fileList) { - attachment_ids = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) - } - - if( attachment_ids === undefined || attachment_ids.length===0){ - - // notification.open( - // { - // message: '提示', - // description: - // '请上传附件!', - // - // } - // ) - this.setState({ - attachmentidstype:true - }) - return; - } - // console.log("attachment_ids"+attachment_ids); - - // alert(languagewrite +" "+systemenvironment +" "+testcoderunmode + " "+attachment_ids); - - var data={ - language:languagewrite, - runtime:systemenvironment, - run_method:testcoderunmode, - attachment_id:attachment_ids[0], - } - var url =`/shixuns/apply_shixun_mirror.json`; - axios.post(url,data - ).then((response) => { - - try { - if (response.data) { - // const { id } = response.data; - // if (id) { - if(this.state.file !== undefined){ - console.log("549"); - // this.deleteAttachment(this.state.file); - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - }else { - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - } - // this.props.showNotification('提交成功!'); - notification.open( - { - message: '提示', - description: - '提交成功!', - - } - ) - this.sendhideModaly() - // this.props.history.push(`/courses/${cid}/graduation_topics`); - // } - } - }catch (e) { - - } - - }) - - } - - sendhideModaly = () => { - this.setState({ - postapplyvisible: false, - }) - if(this.state.file !== undefined){ - console.log("580"); - // this.deleteAttachment(this.state.file); - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - }else { - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - } - } - - yeshidemodel = () => { - this.setState({ - postapplytitle: false - }) - } - - SelectScput = (value, e) => { - this.setState({ - choice_standard_scriptssum: value, - language:e.props.name, - choice_standard_scripts: {id:e.props.value,value:""}, - standard_scriptsModal:true - }) - } - - hidestandard_scriptsModal=()=>{ - this.setState({ - standard_scriptsModal:false, - standard_scriptsModals:false - }) - } - - get_mirror_script=()=>{ - let {choice_standard_scriptssum}=this.state; - let id = this.props.match.params.shixunId; - let pul = "/shixuns/" + id + "/get_script_contents.json?script_id=" + choice_standard_scriptssum; - axios.get(pul).then((response) => { - if(response.status===200){ - // this.evaluate_scriptMD(response.data.content, "shixunmemoMD"); - this.setState({ - standard_scriptsModal:false, - standard_scriptsModals:true, - shixunmemoMDvalue:response.data.content - }) - } - - }).catch((error) => { - console.log(error) - }) - } - - - SelectTheCommandonChange=(e)=>{ - this.setState({ - multi_webssh:e.target.checked - }) - } - - bigopen=()=>{ - this.setState({ - opers:true - }) - - } - - bigopens=()=>{ - this.setState({ - opers:false, - operss:false, - opersss:false, - opensmail:false - }) - - } - bigopensmal=(e)=>{ - this.setState({ - opensmail:true - }) - - } - sbigopen=(e)=>{ - this.setState({ - operss:true - }) - - } - - sbigopens=()=>{ - this.setState({ - operss:false - }) - } - sbigopenss=(e)=>{ - this.setState({ - opersss:true - }) - - } - - sbigopensss=()=>{ - this.setState({ - opersss:false - }) - } - testscripttip=(val)=>{ - if(val===0){ - this.setState({ - testscripttiptype:true - }) - }else if(val===1){ - this.setState({ - testscripttiptype:false - }) - } - } - - operateshixuns=(value)=>{ - this.setState({ - operateshixunstype:true, - delType:value - }) - } - - hideoperateshixuns=()=>{ - this.setState({ - operateshixunstype:false - }) - } - onChangeTimePicker =(value, dateString)=> { - this.setState({ - opening_time: dateString=== ""?"":moment(handleDateStrings(dateString)) - }) - } - - getshixunmemoMDvalue=(value, e)=>{ - - this.setState({ - shixunmemoMDvalue:value - }) - } - - setConfigsInputs=(e,keys,str)=>{ - - let {shixun_service_configs}=this.state; - let newshixun_service_configs=shixun_service_configs; - newshixun_service_configs.map((item,key)=>{ - if(key===keys){ - switch (str) { - case 1: - item.cpu_limit=e.target.value - break; - case 2: - item.lower_cpu_limit=e.target.value - break; - case 3: - item.memory_limit=e.target.value - break; - case 4: - item.request_limit=e.target.value - break; - } - } - }) - - this.setState({ - shixun_service_configs:newshixun_service_configs, - shixun_service_configlist:newshixun_service_configs, - }) - - } - - handleChange = (info) => { - let {fileList}=this.state; - - if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { - console.log("handleChange1"); - - // if(fileList.length===0){ - let fileLists = info.fileList; - this.setState({ fileList:fileLists, - deleteisnot:false}); - // } - } - } - - onAttachmentRemove = (file) => { - if(!file.percent || file.percent == 100){ - confirm({ - title: '确定要删除这个附件吗?', - okText: '确定', - cancelText: '取消', - // content: 'Some descriptions', - onOk: () => { - console.log("665") - this.deleteAttachment(file) - }, - onCancel() { - console.log('Cancel'); - }, - }); - return false; - } - - } - - deleteAttachment = (file) => { - console.log(file); - let id=file.response ==undefined ? file.id : file.response.id - const url = `/attachments/${id}.json` - axios.delete(url, { - }) - .then((response) => { - if (response.data) { - const { status } = response.data; - if (status == 0) { - // console.log('--- success') - - this.setState((state) => { - - const index = state.fileList.indexOf(file); - const newFileList = state.fileList.slice(); - newFileList.splice(index, 1); - return { - fileList: newFileList, - deleteisnot:true - }; - }); - } - } - }) - .catch(function (error) { - console.log(error); - }); - } - - - - render() { - let { - postapplyvisible, - postapplytitle, - shixunnametype, - shixunmaintype, - evaluate_scripttype, - traineetype, - standard_scripts, - name, - settingsData, - webssh, - is_secret_repository, - use_scope, - shixunsID, - can_copy, - choice_standard_scripts, - Executiveordervalue, - Executivetyoe, - Compilecommandvalue, - task_pass, - test_set_permission, - hide_code, - forbid_copy, - code_edit_permission, - code_hidden, - vnc, - vnc_evaluate, - scopetype, - scope_partment, - departmentslist, - trainee, - choice_main_type, - choice_small_type, - standard_scriptsModal, - standard_scriptsModals, - SelectTheCommandtype, - testscripttiptype, - operateshixunstype, - opening_time, - scope_partmenttype, - newuse_scope, - scope_partments, - shixunmemoMDvalue,delType, - shixun_service_configs, - fileList, - } = this.state; - - let options; - - if (departmentslist != undefined) { - options = this.state.departmentslist.map((d, k) => { - return ( - - ) - }) - } - const uploadProps = { - width: 600, - fileList, - multiple: true, - // https://github.com/ant-design/ant-design/issues/15505 - // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // showUploadList: false, - action: `${getUploadActionUrl()}`, - onChange: this.handleChange, - onRemove: this.onAttachmentRemove, - beforeUpload: (file, fileList) => { - if (this.state.fileList.length >= 1) { - return false - } - // console.log('beforeUpload', file.name); - const isLt150M = file.size / 1024 / 1024 < 50; - if (!isLt150M) { - // this.props.showNotification(`文件大小必须小于50MB`); - notification.open( - { - message: '提示', - description: - '文件大小必须小于50MB', - - } - ) - } - if(this.state.file !== undefined){ - console.log("763") - this.setState({ - file:file - }) - }else { - this.setState({ - file:file - }) - } - - console.log("handleChange2"); - return isLt150M; - }, - } - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; - let operateauthority=this.props.identity===1?true:this.props.identity<5&&this.state.status==0?true:false; - - return ( -
    - - 实训详情 - 配置 - - -
    -
    - 配置 - { - this.props.identity===1&&this.state.status==2? - this.operateshixuns(2)}> - 永久关闭 - :"" - } - { - this.props.identity < 5 && this.state.status==0? - this.operateshixuns(1)}> - 删除实训 - :"" - } - { - this.props.identity == 1 && this.state.status == 2 ? - this.operateshixuns(1)}> - 删除实训 - :"" - } - - -
    - {delType===1?

    是否确认删除 ?

    :

    关闭后,
    用户不能再开始挑战了是否确认关闭 ?

    } -
    -
    - 取消 - {delType===1?确定:确定} -
    -
    - -
    - -
    - -

    实训名称

    - -
    - * -
    -
    - {settingsData === undefined ? "" : - } -
    -
    - 必填项 -
    -
    - - -
    - -
    -
    - -
    - -

    简介

    - -
    - -
    -
    -
    -

    -

    -
    - -
    -
    -

    技术平台

    - - -
    - * -
    - -

    - 列表中没有? - 申请新建 -

    - - -
    -
  • - - -
  • -
    {this.state.languagewritetype===true?"请填写该镜像语言":""}
    -
  • - - -
  • -
    {this.state.systemenvironmenttype===true?"请填写该镜像语言系统环境":""}
    -
  • - - - -
  • -
    {this.state.testcoderunmodetype===true?"请填写该镜像测试代码运行方式":""}
    -
  • - -
    - - - 上传附件 - (单个文件50M以内) - -
    -
  • -
    - {this.state.attachmentidstype===true?"请上传附件":""} -
    -
  • - this.sendhideModaly()} - >取消 - -
  • -
    -
    - -
    - - - - - -
    -

    新建申请已提交,请等待管理员的审核

    -
  • 我们将在1-2个工作日内与您联系 -
  • -
    -
    - 知道啦 -
    -
    -
    -
    - -
    - -
    -
    - 必填项 -
    - {/*

    请在配置页面完成后续的评测脚本设置操作

    */} - -
    -
    - {/*
    */} - {/*
    */} -
    -

    评测脚本

    -
    - - -
    -

    原有脚本将被新的脚本覆盖,无法撤销

    -

    是否确认执行覆盖操作

    -
    - - -
    - - -

    评测脚本生成成功!

    - -
    - - { - this.props.identity<5||this.props.power==true? - 使用自定义脚本 : "" - } -
    - this.testscripttip(0)}> -
    - -
    -

    - 使用自定义模板,平台无法自动更新脚本,
    - 请在关卡创建完后手动更新脚本中的必填参
    - 数和以下2个数组元素:
    - challengeProgramNames
    - sourceClassNames

    - 示例:有2个关卡的实训

    - 各关卡的待编译文件为:
    - src/step1/HelloWorld.java
    - src/step2/Other.java

    - 各关卡的编译后生成的执行文件为:
    - step1.HelloWorld
    - step2.Other

    - 则数组元素更新如下:
    - challengeProgramNames=("src/step1/
    - HelloWorld.java" "src/step2/Other.java")
    - sourceClassNames=("step1.HelloWorld
    - " "step2.Other")

    - 其它参数可按实际需求定制 -

    -
    -

    - this.testscripttip(1)}>知道了 -

    -
    -
    - - -
    -
  • - - -

    执行命令不能为空

    -
  • - -
  • - - -
  • -
    -
    -
    -
    - -
    -
    - * -
    - - -
    - {/**/} - -
    - - - {/*
    */} - {/*{evaluate_script===undefined?"":evaluate_script}*/} - - {/*
    */} - - - -
    - -
    -
    -
    - - 必填项 -
    -

    -

    -
    -
    - - {/*
    */} - {/***/} - - {/*

    程序最大执行时间

    */} - - {/* 秒*/} - - {/*
    */} - {/*必填项*/} - {/*
    */} - {/*
    */} - - {/*
    - * - -

    Pod存活时间

    - - - -
    - 必填项 -
    -
    */} - - -
    -

    命令行

    - - 无命令行窗口 (选中则不给学员的实践任务提供命令窗口) - 命令行练习窗口 (选中则给学员提供用于练习操作的命令行窗口) - 命令行评测窗口 (选中则给学员提供用于关卡评测的命令行窗口) - - 多个命令行窗口(选中则允许学员同时开启多个命令行窗口) - - -
    - -
    -

    公开程度

    - - 对所有公开 (选中则所有已被试用授权的用户可以学习) - 对指定单位公开 (选中则下方指定单位的已被试用授权的用户可以学习) - - -
    -
    -
    -
    -
    - -
    - (搜索并选中添加单位名称) -
    - {/*+*/} - {/*添加*/} -
    - -
    - - {/*{*/} - {/*scope_partment===undefined?"":scope_partment.map((item,key)=>{*/} - {/*return(*/} - {/*
    */} - {/*this.deleteScopeInput(key)} style={{ color: 'rgba(0,0,0,.25)' }} />}*/} - {/*value={item}*/} - {/*/>*/} - {/*
    */} - - {/*)*/} - {/*})*/} - {/*}*/} -
    - - - 请选择需要公开的单位 - -
    -
    -
    - -
    -

    发布信息

    - -
    - * - 面向学员: - -
    - -
    - 实训难易度定位,不限定用户群体 -
    - 必填项 -
    - -
    -
    - 复制: - - - - -
    - -
    - 跳关: - - - - -
    -
    - 测试集解锁: - - - - -
    - - {!code_hidden && !hide_code &&
    - 代码开放修改: - - - - -
    } - -
    - 隐藏代码窗口: - - - - -
    - -
    - 代码目录隐藏: - - - - -
    - - { (vnc || webssh == 2) &&
    - 私密版本库: - - - - -
    } - -
    - 禁用复制粘贴: - - - - -
    - -
    - 开启时间: - - - - -
    - - {this.props.identity<3?
    - VNC图形化: - - - - -
    :""} - {this.props.identity<3 && vnc ?
    - VNC图形化评测: - - - - -
    :""} - - - -
    - - {this.props.identity<3?
    -

    服务配置

    - { shixun_service_configs&&shixun_service_configs.map((item,key)=>{ - - return( -
    -
    -
    - {item.name} - {/*this.Deselectlittle(item.mirror_repository_id)}>*/} -
    -
    - -
    - this.setConfigsInputs(e,key,1)} - className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> -
    -
    -
    -
    - -
    - this.setConfigsInputs(e,key,2)} - className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> -
    -
    -
    -
    - -
    - this.setConfigsInputs(e,key,3)} - className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> -
    -
    -
    -
    - -
    - this.setConfigsInputs(e,key,4)} - className="panel-box-sizing task-form-100 task-height-40" placeholder="请输入类别名称" /> -
    - -
    -
    -
    -
    - ) - - })} -
    :""} - -

    - { - // this.props.identity<4&&this.props.status==0? - this.props.identity<5? -

    - 保存 - 取消 -
    :"" - } - -

    - -
    - ); - } -} - - diff --git a/public/react/src/tpm/TPMsettings/css/TPMsettings.css b/public/react/src/tpm/TPMsettings/css/TPMsettings.css deleted file mode 100644 index 8047bbde8..000000000 --- a/public/react/src/tpm/TPMsettings/css/TPMsettings.css +++ /dev/null @@ -1,113 +0,0 @@ -.radioStyle{ - display: block; - height: 30px; - } -#settingsMarkdown{ - background:transparent; -} -#challenge_begin{ - height: 30px; - line-height: 30px; -} -#shixundescription .CodeMirror{ - margin-top: 31px !important; - height: 364px !important; -} -#shixundescription .editormd-preview{ - width:578px !important; - top: 40px !important; - height: 364px !important; -} - -#shixunmemoMD .CodeMirror{ - margin-top: 31px !important; - height: 578px !important; -} - -#shixunmemoMD .editormd-preview{ - width: 578px !important; - top: 40px !important; - height: 578px !important; -} - -.radioStyle { - display: block; - height: 30px; -} - -a.white-btn.use_scope-btn:hover { - color: #FFF !important; -} - -.shixunScopeInput { - width: 218px; - height: 33px; - display: block; - margin-bottom: 15px; -} - -.ant-modal-title { - text-align: center; -} - -a.newuse_scope-btn:hover { - border: 1px solid #F06200; - color: #fff !important; - background: #FF7500; -} - -a.newuse_scope-btn { - border: 1px solid #FF7500; - color: #FF7500 !important; -} - -.tpmprompt { - padding-left: 20px; - margin-top: -4px; -} -.ml36{ - margin-left: 26px; -} - -#shixunmemoMD{ - width:98% !important; - height: 620px !important; -} -#shixunmemoMDs{ - width: 98% !important; - height: 420px !important; -} -#shixunmemoMDs .CodeMirror { - /* width: 548px !important; */ - margin-top: 31px !important; - height: 402px !important; -} -.pdr20{ - padding-right:20px; -} - -.nonemodel{ - width: 59%; - height: 468px; - /*background: rgba(0, 0, 0, 0.65);*/ - background: #f5f5f5; - position: absolute; - z-index: 100; - opacity: 0.5; - left: 21.5%; -} - -.shixunmemoMDdiv{ - width: 99%; - height: 615px; -} - -.shixunspanred{ - margin-left: 142px; - margin-top: 5px; - margin-bottom: 5px; -} - -.ml82{ - margin-left:82px; -} diff --git a/public/react/src/tpm/beian.png b/public/react/src/tpm/beian.png deleted file mode 100755 index 9f763946d..000000000 Binary files a/public/react/src/tpm/beian.png and /dev/null differ diff --git a/public/react/src/tpm/challengesnew/TPMMDEditor.js b/public/react/src/tpm/challengesnew/TPMMDEditor.js deleted file mode 100644 index 11b88a037..000000000 --- a/public/react/src/tpm/challengesnew/TPMMDEditor.js +++ /dev/null @@ -1,355 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -// import "antd/dist/antd.css"; - -import { getImageUrl, toPath, getUrl } from 'educoder'; -import '../../courses/css/Courses.css' - -import axios from 'axios'; - -import './css/TPMchallengesnew.css'; -require('codemirror/lib/codemirror.css'); - -let origin = getUrl(); - -let path = '/editormd/lib/' - path = getUrl("/editormd/lib/") -const $ = window.$; - -let timeout; - -let currentValue; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; - - - -// 保存数据 -function md_add_data(k,mdu,d){ - window.sessionStorage.setItem(k+mdu,d); -} - -// 清空保存的数据 -function md_clear_data(k,mdu,id){ - window.sessionStorage.removeItem(k+mdu); - var id1 = "#e_tip_"+id; - var id2 = "#e_tips_"+id; - if(k == 'content'){ - $(id2).html(" "); - }else{ - $(id1).html(" "); - } -} -window.md_clear_data = md_clear_data -// editor 存在了jquery对象上,应用不需要自己写md_rec_data方法了 -function md_rec_data(k, mdu, id) { - if (window.sessionStorage.getItem(k + mdu) !== null) { - var editor = $("#e_tips_" + id).data('editor'); - editor.setValue(window.sessionStorage.getItem(k + mdu)); - // debugger; - // /shixuns/b5hjq9zm/challenges/3977/tab=3 setValue可能导致editor样式问题 - md_clear_data(k, mdu, id); - } -} -window.md_rec_data = md_rec_data; - -function md_elocalStorage(editor,mdu,id){ - if (window.sessionStorage){ - var oc = window.sessionStorage.getItem('content'+mdu); - if(oc !== null && oc != editor.getValue()){ - console.log("#e_tips_"+id) - $("#e_tips_"+id).data('editor', editor); - var h = '您上次有已保存的数据,是否恢复 ? / 不恢复'; - $("#e_tips_"+id).html(h); - } - setInterval(function() { - var d = new Date(); - var h = d.getHours(); - var m = d.getMinutes(); - var s = d.getSeconds(); - h = h < 10 ? '0' + h : h; - m = m < 10 ? '0' + m : m; - s = s < 10 ? '0' + s : s; - if(editor.getValue().trim() != ""){ - md_add_data("content",mdu,editor.getValue()); - var id1 = "#e_tip_"+id; - var id2 = "#e_tips_"+id; - - var textStart = " 数据已于 " - var text = textStart + h + ':' + m + ':' + s +" 保存 "; - // 占位符 - var oldHtml = $(id2).html(); - if (oldHtml && oldHtml != ' ' && oldHtml.startsWith(textStart) == false) { - $(id2).html( oldHtml.split(' (')[0] + ` (${text})`); - } else { - $(id2).html(text); - } - // $(id2).html(""); - } - },10000); - - }else{ - $("#e_tip_"+id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!'); - } -} - - -function create_editorMD(id, width, high, placeholder, imageUrl, callback, initValue, - onchange, watch, { noStorage, showNullButton, emoji }, that) { - // 还是出现了setting只有一份,被共用的问题 - - var editorName = window.editormd(id, { - width: width, - height: high===undefined?400:high, - path: path, // "/editormd/lib/" - markdown : initValue, - - dialogLockScreen: false, - watch:watch===undefined?true:watch, - syncScrolling: "single", - tex: true, - tocm: true, - emoji: !!emoji , - taskList: true, - codeFold: true, - searchReplace: true, - htmlDecode: "style,script,iframe", - sequenceDiagram: true, - autoFocus: false, - - // mine - - toolbarIcons: function (mdEditor) { - let react_id = `react_${mdEditor.id}`; - const __that = window[react_id] - - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - const icons = ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "link", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"]; - // 试卷处用到的填空题新增按钮 - if (__that.props.showNullButton) { - icons.push('nullBtton') - } - return icons - }, - toolbarCustomIcons: { - testIcon: "
    ", - testIcon1: "
    ", - nullBtton: "
    点击插入填空项
    ", - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea: true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity: 0.6, - placeholder: placeholder, - imageUpload: true, - imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL: imageUrl,//url - onchange: onchange, - onload: function() { - let _id = this.id // 如果要使用this,这里不能使用箭头函数 - let _editorName = this; - let react_id = `react_${_editorName.id}`; - const __that = window[react_id] - - // this.previewing(); - // let _id = id; - $("#" + _id + " [type=\"latex\"]").bind("click", function () { - _editorName.cm.replaceSelection("```latex"); - _editorName.cm.replaceSelection("\n"); - _editorName.cm.replaceSelection("\n"); - _editorName.cm.replaceSelection("```"); - var __Cursor = _editorName.cm.getDoc().getCursor(); - _editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - - $("#" + _id + " [type=\"inline\"]").bind("click", function () { - _editorName.cm.replaceSelection("`$$$$`"); - var __Cursor = _editorName.cm.getDoc().getCursor(); - _editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); - _editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - if (__that.props.showNullButton) { - const NULL_CH = '▁' - // const NULL_CH = '〇' - // const NULL_CH = '🈳' - - $("#" + _id + " [type=\"nullBtton\"]").bind("click", function () { - _editorName.cm.replaceSelection(NULL_CH); - // var __Cursor = _editorName.cm.getDoc().getCursor(); - // _editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - } - - if (noStorage == true) { - - } else { - md_elocalStorage(_editorName, `MDEditor__${_id}`, _id); - } - - callback && callback(_editorName) - } - }); - return editorName; -} - - -export default class TPMMDEditor extends Component { - constructor(props) { - super(props) - this.state = { - initValue: '' - } - } - componentDidUpdate(prevProps, prevState) { - // 不能加,影响了试卷填空题 - // if (this.props.initValue != prevProps.initValue) { - // this.answers_editormd.setValue(this.props.initValue) - // } - } - - // react_mdEditor_ - componentDidMount = () => { - const { mdID, initValue, placeholder, showNullButton} = this.props; - - let _id = `mdEditor_${mdID}` - this.contentChanged = false; - const _placeholder = placeholder || ""; - // amp; - // 编辑时要传memoId - const imageUrl = `/api/attachments.json`; - // 创建editorMd - let react_id = `react_${_id}`; - // 将实例存到了window - window[react_id] = this - const answers_editormd = create_editorMD(_id, '100%', this.props.height, _placeholder, imageUrl, (_editorName) => { - const __editorName = _editorName; - react_id = `react_${__editorName.id}`; - const that = window[react_id] - - // 一个延迟的recreate或resize,不加这段代码,md初始化可能会出现样式问题 - setTimeout(() => { - if (that.props.needRecreate == true) { - __editorName.recreate() // 注意 必须在setValue之前触发,不然会清空 - } else { - __editorName.resize() - } - console.log('timeout', __editorName.id) - __editorName.cm && __editorName.cm.refresh() - }, that.props.refreshTimeout || 500) - if (this.props.noSetValueOnInit) { - that.onEditorChange() - } else { - if (that.props.initValue != undefined && that.props.initValue != '') { - __editorName.setValue(that.props.initValue) - } - if (that.state.initValue) { - __editorName.setValue(that.state.initValue) - } - } - - __editorName.cm.on("change", (_cm, changeObj) => { - that.contentChanged = true; - if (that.state.showError) { - that.setState({showError: false}) - } - that.onEditorChange() - }) - that.props.onCMBlur && __editorName.cm.on('blur', () => { - that.props.onCMBlur() - }) - that.props.onCMBeforeChange && __editorName.cm.on('beforeChange', (cm,change) => { - that.props.onCMBeforeChange(cm,change) - }) - that.answers_editormd = __editorName; - // 这里应该可以去掉了,方便调试加的 - window[__editorName.id+'_'] = __editorName; - }, initValue, this.onEditorChange,this.props.watch, { - noStorage: this.props.noStorage, - showNullButton: this.props.showNullButton, - emoji: this.props.emoji - }, this); - - } - // 用在form里时,validate失败时出现一个红色边框 - showError = () => { - this.setState({showError: true}) - } - onEditorChange = () => { - if (!this.answers_editormd) return; - const val = this.answers_editormd.getValue(); - //console.log('onEditorChange', this.props.id, val) - try { - this.props.onChange && this.props.onChange(val) - } catch(e) { - // http://localhost:3007/courses/1309/common_homeworks/6566/setting - // 从这个页面,跳转到编辑页面,再在编辑页面点击返回的时候,这里会报错 - console.error('出错') - console.error(e) - } - } - resize = () => { - if (!this.answers_editormd) { // 还未初始化 - return; - } - this.answers_editormd.resize() - this.answers_editormd.cm && this.answers_editormd.cm.refresh() - this.answers_editormd.cm.focus() - } - - getValue = () => { - try { - return this.answers_editormd.getValue() - } catch (e) { - return '' - } - } - setValue = (val) => { - try { - this.answers_editormd.setValue(val) - } catch (e) { - // TODO 这里多实例的时候,前一个实例的state会被后面这个覆盖 参考NewWork.js http://localhost:3007/courses/1309/homework/9300/edit/1 - // 未初始化 - this.setState({ initValue: val }) - } - } - - render() { - - let { - showError - } = this.state; - let { mdID, className, noStorage, imageExpand } = this.props; - let _style = {} - if (showError) { - _style.border = '1px solid red' - } - return ( - -
    - {/* padding10-20 */} -
    - -
    -
    -
    -
    -
    - {noStorage == true ? ' ' :

     

    } - {/* {noStorage == true ? ' ' :

     

    } */} -
    -
    - ) - } -} - - diff --git a/public/react/src/tpm/challengesnew/TPManswer.js b/public/react/src/tpm/challengesnew/TPManswer.js deleted file mode 100644 index bc9523422..000000000 --- a/public/react/src/tpm/challengesnew/TPManswer.js +++ /dev/null @@ -1,366 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -// import "antd/dist/antd.css"; - -import { getImageUrl, toPath, getUrl } from 'educoder'; - -import axios from 'axios'; - -import './css/TPMchallengesnew.css'; - -let origin = getUrl(); - -let path = getUrl("/editormd/lib/") - -const $ = window.$; - -let timeout; - -let currentValue; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; - - -// 恢复数据 -function md_rec_data(k,mdu,id, editor){ - if(window.sessionStorage.getItem(k+mdu) !== null){ - editor.setValue(window.sessionStorage.getItem(k+mdu)); - md_clear_data(k,mdu,id); - } -} - -// 保存数据 -function md_add_data(k,mdu,d){ - window.sessionStorage.setItem(k+mdu,d); -} - -// 清空保存的数据 -function md_clear_data(k,mdu,id){ - window.sessionStorage.removeItem(k+mdu); - var id1 = "#e_tip_"+id; - var id2 = "#e_tips_"+id; - if(k == 'content'){ - $(id2).html(""); - }else{ - $(id1).html(""); - } -} - -function md_elocalStorage(editor,mdu,id){ - if (window.sessionStorage){ - var oc = window.sessionStorage.getItem('content'+mdu); - if(oc !== null ){ - console.log("#e_tips_"+id) - $("#e_tips_"+id).data('editor', editor); - var h = '您上次有已保存的数据,是否恢复 ? / 不恢复'; - $("#e_tips_"+id).html(h); - } - setInterval(function() { - var d = new Date(); - var h = d.getHours(); - var m = d.getMinutes(); - var s = d.getSeconds(); - h = h < 10 ? '0' + h : h; - m = m < 10 ? '0' + m : m; - s = s < 10 ? '0' + s : s; - if(editor.getValue().trim() != ""){ - md_add_data("content",mdu,editor.getValue()); - var id1 = "#e_tip_"+id; - var id2 = "#e_tips_"+id; - - $(id1).html(" 数据已于 " + h + ':' + m + ':' + s +" 保存 "); - $(id2).html(""); - } - },10000); - - }else{ - $("#e_tip_"+id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!'); - } -} - - -function create_editorMD(id, width, high, placeholder, imageUrl, callback) { - var editorName = window.editormd(id, { - width: width, - height: high, - path: path, // "/editormd/lib/" - - syncScrolling: "single", - tex: true, - tocm: true, - emoji: true, - taskList: true, - codeFold: true, - searchReplace: true, - htmlDecode: "style,script,iframe", - sequenceDiagram: true, - autoFocus: false, - toolbarIcons: function () { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] - }, - toolbarCustomIcons: { - testIcon: "
    ", - testIcon1: "
    " - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea: true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity: 0.6, - placeholder: placeholder, - imageUpload: true, - imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL: imageUrl,//url - onload: function () { - // this.previewing(); - $("#" + id + " [type=\"latex\"]").bind("click", function () { - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - - $("#" + id + " [type=\"inline\"]").bind("click", function () { - editorName.cm.replaceSelection("`$$$$`"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - md_elocalStorage(editorName, `answers__${id}`, "Memoanswers"); - - callback && callback() - } - }); - return editorName; -} - - -export default class TPManswer extends Component { - constructor(props) { - super(props) - this.state = { - choice_url: undefined, - practice_url: undefined, - go_back_url: undefined, - value: 1, - answer:"", - id:undefined, - checkpointId:undefined, - power: false, - prev_challenge: undefined, - next_challenge: undefined, - } - } - - answerMD(initValue, id) { - - this.contentChanged = false; - const placeholder = ""; - // amp; - // 编辑时要传memoId - const imageUrl = `/api/attachments.json`; - // 创建editorMd - - const answers_editormd = create_editorMD(id, '100%', 400, placeholder, imageUrl, () => { - setTimeout(() => { - answers_editormd.resize() - answers_editormd.cm && answers_editormd.cm.refresh() - }, 500) - - if (initValue != undefined) { - answers_editormd.setValue(initValue) - } - answers_editormd.cm.on("change", (_cm, changeObj) => { - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - this.answers_editormd = answers_editormd; - window.answers_editormd = answers_editormd; - - } - - componentDidMount() { - let id = this.props.match.params.shixunId; - let checkpointId=this.props.match.params.checkpointId; - - let newchoice_url= "/shixuns/"+id+"/challenges/newquestion"; - let newpractice_url= "/shixuns/"+id+"/challenges/new"; - let newgo_back_url="/shixuns/"+id+"/challenges"; - this.setState({ - shixunId:id, - checkpointId:checkpointId - }) - - - let url = "/shixuns/" + id + "/challenges/" + checkpointId + "/edit.json?tab=2"; - axios.get(url).then((response) => { - let newprev_challenge = response.data.prev_challenge; - let next_challenge = response.data.next_challenge; - if (newprev_challenge != undefined) { - if(newprev_challenge.st===0){ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint"; - }else{ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion"; - } - } - if (next_challenge != undefined) { - - if(next_challenge.st===0){ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint"; - }else{ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion"; - } - } - this.setState({ - answer:response.data.answer, - power: response.data.power, - choice_url: newchoice_url, // 导航中的新建选择题url - practice_url: newpractice_url, //string 导航中新建实践题url - go_back_url: newgo_back_url, //string 导航中的返回url - position: response.data.position, //int 关卡位置,导航栏中的第几关 - prev_challenge: newprev_challenge, - next_challenge: next_challenge, - }) - - if(response.data.power===false){ - this.props.showSnackbar("没有权限修改"); - } - if(response.data.answer===undefined||response.data.answer===null){ - this.answerMD("", "answerMD"); - }else{ - this.answerMD(response.data.answer, "answerMD"); - } - - }).catch((error) => { - console.log(error) - }); - } - - challenge_answer_submit=()=> { - let id = this.props.match.params.shixunId; - let{checkpointId}=this.state; - let url = "/shixuns/"+id+"/challenges/"+checkpointId+".json"; - const answer_editormdvalue = this.answers_editormd.getValue(); - - axios.put(url,{ - tab:2, - identifier:id, - id:checkpointId, - challenge:{ - answer:answer_editormdvalue - } - } - ).then((response) => { - this.props.showSnackbar(response.data.messages); - - }).catch((error) => { - console.log(error) - }); - } - - render() { - - let { - choice_url, - practice_url, - go_back_url, - position, - task_pass_default, - submit_url, - shixunId, - checkpointId, - power, - prev_challenge, - next_challenge, - } = this.state; - let tab1url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/editcheckpoint"; - let tab2url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=2"; - let tab3url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=3"; - // console.log(this.props) - return ( - -
    -
    - - - - 第{position}关 - 返回 - - {prev_challenge === undefined ? "" : - 上一关 - } - - {next_challenge === undefined ? "" : - 下一关 - } - - + 实践类型 - + 选择题类型 - -
    - -
    - -
  • - 本关任务 -
  • - -
  • - 评测设置 -
  • - -
  • - 参考答案 -
  • -
    - -
    - -
    -

    参考答案

    -
    -
    - -
    -
    -
    -
    -

    -

    -
    - -
    - -
    4||this.props.identity===undefined||power===false?"none":"block"}}> - 提交 - 取消 -
    -
    -
    - ) - } -} - - diff --git a/public/react/src/tpm/challengesnew/TPManswer2.js b/public/react/src/tpm/challengesnew/TPManswer2.js deleted file mode 100644 index 6cbfcd081..000000000 --- a/public/react/src/tpm/challengesnew/TPManswer2.js +++ /dev/null @@ -1,368 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, InputNumber, Select, Radio, Checkbox, Popconfirm, message, Modal, Tooltip} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -// import "antd/dist/antd.css"; - -import { getImageUrl, toPath, getUrl } from 'educoder'; - -import axios from 'axios'; - -import './css/TPMchallengesnew.css'; - -import TPMMDEditor from './TPMMDEditor'; - - -let origin = getUrl(); - -let path = getUrl("/editormd/lib/") - -const $ = window.$; - -let timeout; - -let currentValue; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; - -// const testAnswers = [{ -// "id": 4337, -// "name": "解题思路1", -// "contents": "答案的解题思路1", -// "level": 1, -// "score": 25 -// }, -// { -// "id": 4338, -// "name": "解题思路2", -// "contents": "答案的解题思路2", -// "level": 2, -// "score": 25 -// }] -export default class TPManswer extends Component { - constructor(props) { - super(props) - this.state = { - choice_url: undefined, - practice_url: undefined, - go_back_url: undefined, - value: 1, - answer:"", - id:undefined, - checkpointId:undefined, - power: false, - prev_challenge: undefined, - next_challenge: undefined, - answers: [] //testAnswers - } - } - - componentDidMount() { - let id = this.props.match.params.shixunId; - let checkpointId=this.props.match.params.checkpointId; - - let newchoice_url= "/shixuns/"+id+"/challenges/newquestion"; - let newpractice_url= "/shixuns/"+id+"/challenges/new"; - let newgo_back_url="/shixuns/"+id+"/challenges"; - this.setState({ - shixunId:id, - checkpointId:checkpointId - }) - - - let url = "/shixuns/" + id + "/challenges/" + checkpointId + "/edit.json?tab=2"; - axios.get(url).then((response) => { - let newprev_challenge = response.data.prev_challenge; - let next_challenge = response.data.next_challenge; - if (newprev_challenge != undefined) { - if(newprev_challenge.st===0){ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint"; - }else{ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion"; - } - } - if (next_challenge != undefined) { - - if(next_challenge.st===0){ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint"; - }else{ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion"; - } - } - this.setState({ - answer:response.data.answer, - power: response.data.power, - choice_url: newchoice_url, // 导航中的新建选择题url - practice_url: newpractice_url, //string 导航中新建实践题url - go_back_url: newgo_back_url, //string 导航中的返回url - position: response.data.position, //int 关卡位置,导航栏中的第几关 - prev_challenge: newprev_challenge, - next_challenge: next_challenge, - }) - - if(response.data.power===false){ - this.props.showSnackbar("没有权限修改"); - } - // if(response.data.answer===undefined||response.data.answer===null){ - // this.answerMD("", "answerMD"); - // }else{ - // this.answerMD(response.data.answer, "answerMD"); - // } - - }).catch((error) => { - console.log(error) - }); - - - let urlAnswer = `/shixuns/${id}/challenges/${checkpointId}/answer.json`; - axios.get(urlAnswer).then((response) => { - if (response.data.status === 401) { - - } else if (response.data) { - this.setState({ answers: response.data }) - } - }) - } - - challenge_answer_submit=()=> { - // `levelSection${index}` - // this.refs.md0 - const { answers } = this.state; - const answersParams = answers.slice(0) - console.log(answersParams) - let isValidate = true; - let totalScore = 0; - answersParams.forEach( (item, index) => { - if (!isValidate) { - return; - } - const sectionId = `#levelSection${index}`; - const mdContnet = this.refs[`md${index}`].getValue().trim();; - item.contents = mdContnet; - item.name = item.name.trim() - totalScore += item.score; - delete item.id; - if (!item.name) { - this.props.showSnackbar("请先填写参考答案名称"); - isValidate = false; - } else if (!mdContnet) { - this.props.showSnackbar("请先填写参考答案内容"); - isValidate = false; - } - if (!isValidate) { - $("html, body").animate({ scrollTop: $(`${sectionId}`).offset().top - 100}) - } - }) - if (!isValidate) { - return; - } - if (answersParams.length != 0 && totalScore != 100) { - this.props.showSnackbar("请先保证占比和为100%"); - return; - } - let id = this.props.match.params.shixunId; - let {checkpointId} = this.state; - let url = `/shixuns/${id}/challenges/${checkpointId}/crud_answer.json`; - - axios.post(url,{ - challenge_answer: answersParams - } - ).then((response) => { - if (response.data) { - if (response.data.message) { - this.props.showSnackbar(response.data.message); - } - if (response.data.status == 1) { - $("html").animate({ scrollTop: 0 }) - } - } - - }).catch((error) => { - console.log(error) - }); - } - onNameChange = (e, index) => { - const newAnswer = Object.assign({}, this.state.answers[index]) - newAnswer.name = e.target.value - const newAnswers = this.state.answers.slice(0) - newAnswers[index] = newAnswer - this.setState({ answers: newAnswers}) - } - onScoreChange = (val, index) => { - const newAnswer = Object.assign({}, this.state.answers[index]) - newAnswer.score = val - const newAnswers = this.state.answers.slice(0) - newAnswers[index] = newAnswer - this.setState({ answers: newAnswers}) - } - answerOnChange = (val, index) => { - if (!this.state.answers[index]) { - // 1、2、3删除2会走到这里 - return; - } - const newAnswer = Object.assign({}, this.state.answers[index]) - newAnswer.contents = val - const newAnswers = this.state.answers.slice(0) - newAnswers[index] = newAnswer - this.setState({ answers: newAnswers}) - } - addAnswer = () => { - const newAnswers = this.state.answers.slice(0) - newAnswers.push({ - "name": `解题思路${newAnswers.length + 1}`, - "contents": "", - "score": 10 - }) - this.setState({ answers: newAnswers }) - } - - delanswers=(index)=>{ - let {answers}=this.state; - let newanswers=answers; - newanswers.splice(index,1) - this.setState({ - answers:newanswers - }, () => { - for(let i = index; i < newanswers.length; i ++) { - this.refs[`md${i}`].setValue(newanswers[i].contents) - } - }) - } - render() { - - let { - choice_url, - practice_url, - go_back_url, - position, - task_pass_default, - submit_url, - shixunId, - checkpointId, - power, - prev_challenge, - next_challenge, - answers, - } = this.state; - let tab1url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/editcheckpoint"; - let tab2url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=2"; - let tab3url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=3"; - // console.log(this.props) - return ( - -
    -
    - - - - 第{position}关 - 返回 - - {prev_challenge === undefined ? "" : - 上一关 - } - - {next_challenge === undefined ? "" : - 下一关 - } - - + 实践类型 - + 选择题类型 - -
    - -
    - -
  • - 本关任务 -
  • - -
  • - 评测设置 -
  • - -
  • - 参考答案 -
  • -
    - -
    - -
    -

    - 可以将参考答案分级设置,让学员自行选择级别,每级查看后按照比例扣分值(学员已完成任务再查看,则不影响原因已获得的成绩) -

    -

    - 示例:级别1,扣减分值占比25%;级别2,扣减分值占比35%;级别3,扣减分值占比40%;则学员选择查看级别1的答案,将被扣减25%的分值; - 选择查看级别2的答案,将被扣减60%的分值;选择查看级别3的答案,将被扣减100%的分值。 -

    - - - - { - answers.map((answer, index) => { - return
    - * -

    级别{index + 1}

    - - this.delanswers(index)}> - - - -
    -
    - 名称: - this.onNameChange(e, index)}> - - 扣减分值占比: - this.onScoreChange(e, index)} >% -
    -
    - 参考答案: - this.answerOnChange(val, index)}> -
    -
    -
    - }) - } - -
    4||this.props.identity===undefined||power===false?"none":"block"}}> - 新增 -
    -
    - - -
    - -
    4||this.props.identity===undefined||power===false?"none":"block"}}> - 提交 - 取消 -
    -
    -
    - ) - } -} - - diff --git a/public/react/src/tpm/challengesnew/TPMchallengesnew.js b/public/react/src/tpm/challengesnew/TPMchallengesnew.js deleted file mode 100644 index 9da0b79f5..000000000 --- a/public/react/src/tpm/challengesnew/TPMchallengesnew.js +++ /dev/null @@ -1,615 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -// import "antd/dist/antd.css"; - -import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; - -import axios from 'axios'; - -import './css/TPMchallengesnew.css'; - -import { getImageUrl, toPath } from 'educoder'; - -import {getUrl} from 'educoder'; - -let origin = getUrl(); - -let path = getUrl("/editormd/lib/") - -const $ = window.$; - -let timeout; - -let currentValue; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; - -export default class TPMchallengesnew extends Component { - constructor(props) { - super(props) - this.exercisememoMDRef=React.createRef(); - this.state = { - choice_url: undefined, - practice_url: undefined, - go_back_url: undefined, - task_pass_default: undefined, - submit_url: undefined, - shixunCreatePracticeGroup: 1, - optionsums:[100,200], - activetype:0, - setopen: false, - shixunCreatePractice: undefined, - onshixunsmarkvalue: 100, - shixunsskillvalue: undefined, - shixunsskillvaluelist: [], - tab2url: "", - tab3url: "", - prev_challenge:undefined, - next_challenge:undefined, - power: false, - shixunCreatePracticetype: false, - shixunsskillvaluelisttype: false, - marktype:false, - editPracticesendtype:false, - CreatePracticesendtype:false, - exec_time:20, - shixunExec_timeType:false - } - } - - - componentDidMount() { - let id = this.props.match.params.shixunId; - let checkpointId=this.props.match.params.checkpointId; - - let newchoice_url= "/shixuns/"+id+"/challenges/newquestion"; - let newpractice_url= "/shixuns/"+id+"/challenges/new"; - let newgo_back_url="/shixuns/"+id+"/challenges" - if(checkpointId===undefined){ - //新建模式 - let url = "/shixuns/" + id + "/challenges/new.json" - axios.get(url).then((response) => { - this.setState({ - choice_url: newchoice_url, - practice_url: newpractice_url, - go_back_url: newgo_back_url, - position: response.data.position, - task_pass_default: response.data.task_pass_default, - submit_url: response.data.submit_url, - checkpointId:checkpointId, - exercisememoMDRefval:response.data.task_pass_default - }) - - this.exercisememoMDRef.current.setValue(response.data.task_pass_default||'') - }).catch((error) => { - console.log(error) - }); - }else{ - //编辑模式 - let url="/shixuns/"+id+"/challenges/"+checkpointId+".json?tab=0"; - axios.get(url).then((response) => { - - let optionsum; - if(response.data.difficulty===1){ - optionsum=[100,200]; - }else if(response.data.difficulty===2){ - optionsum=[300,400,500,600]; - }else if(response.data.difficulty===3){ - optionsum=[700,800,900,1000] - } - let newprev_challenge=response.data.prev_challenge; - let next_challenge=response.data.next_challenge; - if (newprev_challenge != undefined) { - if(newprev_challenge.st===0){ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint"; - }else{ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion"; - } - } - if (next_challenge != undefined) { - if(next_challenge.st===0){ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint"; - }else{ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion"; - } - } - this.setState({ - power: response.data.power, - prev_challenge:newprev_challenge, - next_challenge:next_challenge, - choice_url: newchoice_url, - practice_url: newpractice_url, - go_back_url: newgo_back_url, - shixunCreatePractice:response.data.subject, - position:response.data.position, - shixunCreatePracticeGroup:response.data.difficulty, - optionsums:optionsum, - onshixunsmarkvalue:response.data.score, - shixunsskillvaluelist:response.data.tags, - checkpointId:checkpointId, - exec_time:response.data.exec_time, - tab2url: "/shixuns/" + id + "/challenges/"+checkpointId+"/tab=2", - tab3url: "/shixuns/" + id + "/challenges/"+checkpointId+"/tab=3", - exercisememoMDRefval:response.data.task_pass - }) - if(response.data.power===false){ - this.props.showSnackbar("你没有权限修改"); - } - - this.exercisememoMDRef.current.setValue(response.data.task_pass||'') - }).catch((error) => { - console.log(error) - }); - - } - - } - - onshixunCreatePracticeChange = (e) => { - let optionsum; - let onshixunsmark; - if(e.target.value===1){ - optionsum=[100,200]; - onshixunsmark=100; - }else if(e.target.value===2){ - optionsum=[300,400,500,600]; - onshixunsmark=300; - }else if(e.target.value===3){ - optionsum=[700,800,900,1000] - onshixunsmark=700; - } - this.setState({ - shixunCreatePracticeGroup: e.target.value, - optionsums:optionsum, - onshixunsmarkvalue:onshixunsmark - }) - } - - shixunCreatePractice = (e) => { - this.setState({ - shixunCreatePractice: e.target.value - }) - } - - CreatePracticesend = () => { - - - this.setState({ - CreatePracticesendtype:true - }) - - if(this.props.status===2){ - this.props.showSnackbar("该实训已经发布不能新建") - this.setState({ - CreatePracticesendtype:false - }) - return - } - let {shixunCreatePractice, shixunCreatePracticeGroup, onshixunsmarkvalue, shixunsskillvaluelist,exec_time} = this.state; - if (shixunCreatePractice === undefined||shixunCreatePractice=="") { - this.setState({ - shixunCreatePracticetype: true - }) - this.props.showSnackbar("任务名称为空") - $('html').animate({ - scrollTop: 10 - }, 1000); - - this.setState({ - CreatePracticesendtype:false - }) - return - } - - if (shixunsskillvaluelist.length === 0) { - this.setState({ - shixunsskillvaluelisttype: true, - CreatePracticesendtype:false - }) - this.props.showSnackbar("技能标签为空") - return - } - if(exec_time===null||exec_time===undefined||exec_time===""){ - - this.setState({ - shixunExec_timeType:false - }) - return - } - - const exercise_editormdvalue = this.exercisememoMDRef.current.getValue().trim(); - let id = this.props.match.params.shixunId; - - let url = "/shixuns/" + id + "/challenges.json"; - - axios.post(url, { - identifier:id, - subject: shixunCreatePractice, - task_pass: exercise_editormdvalue, - difficulty: shixunCreatePracticeGroup, - score: onshixunsmarkvalue, - challenge_tag: shixunsskillvaluelist, - st: 0, - exec_time:exec_time - }).then((response) => { - if (response.data.status === 1) { - // $("html").animate({ scrollTop: 0 }) - - window.location.href=`/shixuns/${id}/challenges/${response.data.challenge_id}/editcheckpoint`; - // this.setState({ - // setopen: true, - // CreatePracticesendtype:false, - // tab2url: "/shixuns/" + id + "/challenges/"+response.data.challenge_id+"/tab=2", - // tab3url: "/shixuns/" + id + "/challenges/"+response.data.challenge_id+"/tab=3", - // }) - - } - // this.props.showSnackbar(response.data.messages); - }).catch((error) => { - console.log(error) - }); - - - - } - - onshixunsmark = (value) => { - this.setState({ - onshixunsmarkvalue: value - }) - } - - shixunsskill = (e) => { - this.setState({ - shixunsskillvalue: e.target.value - }) - } - - clickshixunsskill = () => { - - let {shixunsskillvalue, shixunsskillvaluelist} = this.state; - if (shixunsskillvalue === "") { - return - } else if (shixunsskillvalue === undefined) { - return - } - - if(shixunsskillvalue == "" || shixunsskillvalue == undefined || shixunsskillvalue == null || (shixunsskillvalue.length>0 && shixunsskillvalue.trim().length == 0)){ - message.error("输入为空,不能保存!"); - return - } - - let list = shixunsskillvaluelist; - list.push(shixunsskillvalue); - this.setState({ - shixunsskillvaluelist: list, - shixunsskillvalue: "" - }) - } - - delshixunsskilllist = (key) => { - let {shixunsskillvaluelist} = this.state; - let newshixunsskillvaluelist = shixunsskillvaluelist; - newshixunsskillvaluelist.splice(key, 1); - this.setState({ - shixunsskillvaluelist: newshixunsskillvaluelist - }) - } - - editPracticesend=()=>{ - - this.setState({ - editPracticesendtype:true - }) - - let {shixunCreatePractice, shixunCreatePracticeGroup, onshixunsmarkvalue, shixunsskillvaluelist,checkpointId,exec_time} = this.state; - - const exercise_editormdvalue = this.exercisememoMDRef.current.getValue().trim(); - - let id = this.props.match.params.shixunId; - - let url = "/shixuns/"+id+"/challenges/"+checkpointId+".json"; - - if (shixunCreatePractice === undefined||shixunCreatePractice=="") { - // this.setState({ - // shixunCreatePracticetype: true - // }) - this.props.showSnackbar("任务名称为空") - $('html').animate({ - scrollTop: 10 - }, 1000); - this.setState({ - editPracticesendtype:false - }) - return - } - - if (shixunsskillvaluelist.length === 0) { - // this.setState({ - // shixunsskillvaluelisttype: true - // }) - this.props.showSnackbar("技能标签为空") - this.setState({ - editPracticesendtype:false - }) - return - } - - if(exec_time===null||exec_time===undefined||exec_time===""){ - - this.setState({ - shixunExec_timeType:false - }) - return - } - axios.put(url, { - tab:0, - identifier:id, - id:checkpointId, - challenge:{ - subject: shixunCreatePractice, - task_pass: exercise_editormdvalue, - difficulty: shixunCreatePracticeGroup, - score: onshixunsmarkvalue, - exec_time:exec_time - }, - challenge_tag:shixunsskillvaluelist - }).then((response) => { - this.props.showSnackbar(response.data.messages); - if (response.data.status === 1) { - this.setState({ - setopen: true, - editPracticesendtype:false, - tab2url: "/shixuns/" + id + "/challenges/"+checkpointId+"/tab=2", - tab3url: "/shixuns/" + id + "/challenges/"+checkpointId+"/tab=3", - }) - // window.location.href = "/shixuns/" + id + "/challenges/"+response.data.challenge_id+"/tab=2" - } - }).catch((error) => { - console.log(error) - }); - - - } - - onshixunsmarks=()=> { - this.setState({ - marktype:true - }) - } - - onshixunsmarkss=()=> { - this.setState({ - marktype:false - }) - } - - setexec_time=(e)=>{ - this.setState({ - exec_time:e.target.value - }) - } - render() { - - let shixuntype = this.props.match.params.type; - - - let {marktype, - shixunCreatePracticetype, shixunsskillvaluelisttype, - choice_url, practice_url, go_back_url, position, task_pass_default, submit_url, setopen,checkpointId,prev_challenge,next_challenge,power, - shixunCreatePractice, shixunCreatePracticeGroup, onshixunsmarkvalue, shixunsskillvalue, shixunsskillvaluelist, tab2url, tab3url,optionsums, - CreatePracticesendtype,editPracticesendtype - } = this.state; - - let options; - if(optionsums!=undefined){ - options = optionsums.map((d, k) => { - return ( - - ) - }) - } - - return ( - -
    - - -
    - -
  • - 本关任务 -
  • - -
  • - {tab2url === "" ? 评测设置 : 评测设置} -
  • - -
  • - {tab3url === "" ? 参考答案 : 参考答案} - -
  • -
    - -
    -
    -

    任务名称

    -
    - * -
    - -
    -
    - 必填项 -
    -
    -
    -
    - - -
    - -

    过关任务

    - - - -

    -

    -
    - - -
    -

    难度系数

    -
    - - - 简单 - 中等 - 困难 - - -
    -

    奖励经验值

    -
    - * - - - -

    - 如果学员答题错误,则不能得到相应的经验值
    - 如果学员成功得到经验值,那么将同时获得等值的金币奖励,如:+10经验值、+10金币 -

    - - 必填项 -
    -
    - - -
    -

    技能标签

    -
    - * -
    - - {/*+ 添加*/} -
    学员答题正确将获得技能,否则不能获得技能
    -
    - - { - shixunsskillvaluelist===undefined?"":shixunsskillvaluelist.length === 0 ? "" : shixunsskillvaluelist.map((itme, key) => { - return ( -
  • {itme} - this.delshixunsskilllist(key)}>× -
  • - ) - }) - } - - -
    -
    - - 必填项 -
    -
    - -
    -

    服务配置

    -
    - * - -
    - -
    - 必填项 -
    -
    -
    - -
    4||this.props.identity===undefined?"none":'block'}} - > - {checkpointId===undefined?提交: - 提交} - 取消 -
    -
    -
    - ) - } -} - - diff --git a/public/react/src/tpm/challengesnew/TPMevaluation.js b/public/react/src/tpm/challengesnew/TPMevaluation.js deleted file mode 100644 index f29e9311e..000000000 --- a/public/react/src/tpm/challengesnew/TPMevaluation.js +++ /dev/null @@ -1,1213 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal,Button,Icon,Tooltip} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -// import "antd/dist/antd.css"; - -import axios from 'axios'; - -import { getImageUrl, toPath } from 'educoder'; - -import './css/TPMchallengesnew.css'; - -import {getUrl} from 'educoder'; - -let origin = getUrl(); - -let path = getUrl("/editormd/lib/") - -const $ = window.$; - -let timeout; - -let currentValue; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; - -const { TextArea } = Input; - -function create_editorMD(id, width, high, placeholder, imageUrl, callback) { - var editorName = window.editormd(id, { - width: width, - height: high, - path: path, // "/editormd/lib/" - - syncScrolling: "single", - tex: true, - tocm: true, - emoji: true, - taskList: true, - codeFold: true, - searchReplace: true, - htmlDecode: "style,script,iframe", - sequenceDiagram: true, - autoFocus: false, - toolbarIcons: function () { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] - }, - toolbarCustomIcons: { - testIcon: "
    ", - testIcon1: "
    " - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea: true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity: 0.6, - placeholder: placeholder, - imageUpload: true, - imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL: imageUrl,//url - onload: function () { - // this.previewing(); - $("#" + id + " [type=\"latex\"]").bind("click", function () { - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - - $("#" + id + " [type=\"inline\"]").bind("click", function () { - editorName.cm.replaceSelection("`$$$$`"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - window.md_elocalStorage(editorName, `exercise__${id}`, "Memochallengesnew"); - - callback && callback() - } - }); - return editorName; -} - - -export default class TPMevaluation extends Component { - constructor(props) { - super(props) - this.state = { - choice_url: undefined, - practice_url: undefined, - go_back_url: undefined, - task_pass_default: undefined, - submit_url: undefined, - value: 1, - evaluationlist:[], - shixunId:undefined, - power:false, - shixunfilepath:undefined, - evaluationvisible:false, - trees:undefined, - path:"", - main:[], - saveshixunfilepath:undefined, - selectpath:undefined, - shixunfilepathplay:undefined, - shixunfileexpectpicturepath:undefined, - shixunfilestandardpicturepath:undefined, - shixunfilepicturepath:undefined, - pathoptionvalue:-1, - showrepositoryurltiptype: false, - prev_challenge: undefined, - next_challenge: undefined, - StudentTaskPapers:false, - StudentTaskDocs:false, - selectpatharr:[], - handpathopt:false, - scorevalue:false, - markvalue:true, - scoretype:undefined, - web_route:null - } - } - - - exerciseMD(initValue, id) { - - this.contentChanged = false; - const placeholder = ""; -// amp; -// 编辑时要传memoId - const imageUrl = `/api/attachments.json`; -// 创建editorMd - - const exercise_editormd = create_editorMD(id, '100%', 400, placeholder, imageUrl, () => { - setTimeout(() => { - exercise_editormd.resize() - exercise_editormd.cm && exercise_editormd.cm.refresh() - }, 500) - - if (initValue != undefined) { - exercise_editormd.setValue(initValue) - } - exercise_editormd.cm.on("change", (_cm, changeObj) => { - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - this.exercise_editormd = exercise_editormd; - window.exercise_editormd = exercise_editormd; - - } - - componentDidMount() { - let id = this.props.match.params.shixunId; - let checkpointId=this.props.match.params.checkpointId; - this.setState({ - shixunId:id, - checkpointId:checkpointId - }) - let newchoice_url= "/shixuns/"+id+"/challenges/newquestion"; - let newpractice_url= "/shixuns/"+id+"/challenges/new"; - let newgo_back_url="/shixuns/"+id+"/challenges"; - - let url = "/shixuns/" + id + "/challenges/" + checkpointId + "/edit.json?tab=1"; - axios.get(url).then((response) => { - let newprev_challenge = response.data.prev_challenge; - let next_challenge = response.data.next_challenge; - if (newprev_challenge != undefined) { - if(newprev_challenge.st===0){ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint"; - }else{ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion"; - } - } - if (next_challenge != undefined) { - - if(next_challenge.st===0){ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint"; - }else{ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion"; - } - } - let newevaluationlist=[] - if(response.data.test_sets.length===0){ - let newlist=[ - {hidden:0,input:"",output:"",score:50}, - {hidden:0,input:"",output:"",score:50} - ] - newevaluationlist=newlist - }else{ - newevaluationlist=response.data.test_sets - } - - this.setState({ - power: response.data.power, - evaluationlist:newevaluationlist, - shixunfilepath:response.data.path, - shixunfilepathplay:response.data.exec_path, - pathoptionvalue:response.data.show_type, - shixunfileexpectpicturepath:response.data.original_picture_path, - shixunfilestandardpicturepath:response.data.expect_picture_path, - shixunfilepicturepath:response.data.picture_path, - prev_challenge: newprev_challenge, - next_challenge: next_challenge, - choice_url: newchoice_url, // 导航中的新建选择题url - practice_url: newpractice_url, //string 导航中新建实践题url - go_back_url: newgo_back_url, //string 导航中的返回url - position: response.data.position, //int 关卡位置,导航栏中的第几关 - scorevalue:response.data.test_set_score, - markvalue:response.data.test_set_average, - web_route:response.data.web_route, - has_web_route:response.data.has_web_route - }) - this.evaluationoninputvalueonload(); - if(response.data.power===false){ - this.props.showSnackbar("你没有权限修改"); - } - if(response.data.answer===undefined){ - this.answerMD("", "answerMD"); - }else{ - this.answerMD(response.data.answer, "answerMD"); - } - - }).catch((error) => { - console.log(error) - }); - - } - - - setevaluationlist=(newevaluationlist)=>{ - this.setState({ - evaluationlist:newevaluationlist - }) - console.log(newevaluationlist) - } - - - addevaluationon=()=>{ - let {evaluationlist,markvalue}=this.state; - let newevaluationlist=evaluationlist; - newevaluationlist.push({hidden:0,input:"",output:"",score:0}); - newevaluationlist=this.oneditevaluationlist(newevaluationlist,markvalue); - this.setevaluationlist(newevaluationlist); - } - - del_test_array=(key)=>{ - let {evaluationlist,markvalue}=this.state; - let newevaluationlist=evaluationlist; - newevaluationlist.splice(key,1); - newevaluationlist=this.oneditevaluationlist(newevaluationlist,markvalue); - this.setevaluationlist(newevaluationlist); - } - - getfilepath=(e,shixunfilepath,type)=>{ - this.setState({ - evaluationvisible: true, - selectpath:e.target.value, - selectpatharr:[], - pathtype:type - }); - let id = this.props.match.params.shixunId; - let url ="/shixuns/"+id+"/repository.json"; - axios.post(url,{ - path: "" - }).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - this.setState({ - trees:response.data.trees, - saveshixunfilepath:shixunfilepath, - path:"", - main:[], - }) - } - - }).catch((error) => { - console.log(error) - }); - } - - sendgetfilepath=(newpath,type,newpathtype)=>{ - let id = this.props.match.params.shixunId; - let{path,main,pathtype}=this.state; - let ary=main; - let paths=path; - - this.setState({ - selectpatharr:[], - }) - if(paths===""&&type==="tree"){ - newpath=newpath+"/"; - paths=""; - if(main.length===0){ - ary.push({val:"根目录/",path:""},{val:newpath,path:paths+newpath}) - }else{ - ary.push({val:newpath,path:paths+newpath}) - } - - }else if(paths!=""&&type==="tree"){ - newpath=newpath+"/"; - ary.push({val:newpath,path:paths+newpath}) - } - - - let url ="/shixuns/"+id+"/repository.json"; - if(type==="tree"){ - - axios.post(url,{ - path: paths+newpath - }).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - this.setState({ - trees:response.data.trees, - path:paths+newpath, - main:ary, - // selectpath:"" - }) - } - - }).catch((error) => { - console.log(error) - }); - } - - if(pathtype===2){ - this.setState({ - selectpath: newpathtype, - }) - } - } - - goblakepath=(path,key)=>{ - let {main,selectpath,pathtype} =this.state; - let newmain=[] - for(var i=0;i<=key;i++){ - newmain.push(main[i]) - } - let id = this.props.match.params.shixunId; - let url ="/shixuns/"+id+"/repository.json"; - axios.post(url,{ - path: path - }).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else { - this.setState({ - trees: response.data.trees, - path: path, - main: newmain, - // selectpath:selectpath - }) - } - }).catch((error) => { - console.log(error) - }); - - if(pathtype===2){ - let paths = path.substring(0,path.length-1); - console.log(paths) - this.setState({ - selectpath: paths, - }) - } - - - } - - - - - - // delesavegetfilepath=(value)=>{ - // let {selectpatharr} = this.state - // let newarr =selectpatharr; - // let newselectpath=""; - // for(var i=0; i{ - let {selectpath,saveshixunfilepath,pathtype} = this.state - - if(pathtype===1){ - let newselectpath; - - if(saveshixunfilepath==="shixunfilepathplay"){ - newselectpath=value - }else{ - const type = selectpath.split(';'); - let types=false; - for(var i=0; i1&&arrtype===false){ - // for(var i=0; i{ - let {saveshixunfilepath,selectpath}=this.state; - this.setState({ - evaluationvisible: false, - [saveshixunfilepath]:selectpath - }); - } - evaluationhideModal=()=>{ - this.setState({ - evaluationvisible: false, - }); - } - handpathoptionvalue=(value)=>{ - this.setState({ - pathoptionvalue:value, - shixunfileexpectpicturepath:undefined, - shixunfilestandardpicturepath:undefined, - shixunfilepicturepath:undefined - }) - } - showrepositoryurltip=(type)=>{ - if(type===1){ - this.setState({ - showrepositoryurltiptype:true - }) - }else{ - this.setState({ - showrepositoryurltiptype:false - }) - } - } - - evaluationonChange=(e,key)=>{ - let {evaluationlist}=this.state; - let newevaluationlist=evaluationlist; - let newtype; - if(e===1){ - newtype=0; - }else{ - newtype=1; - } - // newevaluationlist[key].is_public=newtype; - // for(var i=0; i{ - let {evaluationlist,scoretype}=this.state; - - if(scoretype===key){ - this.setState({ - scoretype:undefined - }) - } - let newevaluationlist=evaluationlist; - let sum =parseInt(e.target.value); - if(isNaN(sum)){ - sum=0 - } - newevaluationlist[key].score=sum; - - this.setState({ - evaluationlist:newevaluationlist, - markvalue:false - }) - this.setevaluationlist(newevaluationlist); - } - - // 修改测试集的匹配规则 - changeEvaluationRule=(e,key)=>{ - let {evaluationlist}=this.state; - let newevaluationlist=evaluationlist; - newevaluationlist[key].match_rule=e.target.value - this.setevaluationlist(newevaluationlist); - } - - evaluationoninputvalue=(e,key,type)=>{ - $.fn.autoHeight = function(){ - function autoHeight(elem){ - elem.style.height = 'auto'; - elem.style.maxHeight = '140px'; - elem.scrollTop = 0; //防抖动 - elem.style.height = elem.scrollHeight + 'px'; - } - this.each(function(){ - autoHeight(this); - $(this).on('keyup', function(){ - autoHeight(this); - }); - }); - } - $('textarea[autoHeight]').autoHeight(); - - let {evaluationlist}=this.state; - let newevaluationlist=evaluationlist; - if(type==="sr"){ - newevaluationlist[key].input=e.target.value - }else if(type==="yq"){ - // 统一转成\r\n - newevaluationlist[key].output= e.target.value ? e.target.value.replace(/\r?\n/g, "\r\n") : e.target.value - } - this.setevaluationlist(newevaluationlist); - } - - - evaluationoninputvalueonload=()=>{ - $.fn.autoHeight = function(){ - function autoHeight(elem){ - elem.style.height = 'auto'; - elem.style.maxHeight = '140px'; - elem.scrollTop = 0; //防抖动 - elem.style.height = elem.scrollHeight + 'px'; - } - this.each(function(){ - autoHeight(this); - $(this).on('keyup', function(){ - autoHeight(this); - }); - }); - } - $('textarea[autoHeight]').autoHeight(); - } - submitarbitrationevaluation=()=>{ - let{evaluationlist,shixunfilepath,shixunfilepathplay,shixunfileexpectpicturepath,shixunfilestandardpicturepath,shixunfilepicturepath,pathoptionvalue,scorevalue,markvalue,web_route}=this.state; - - - let newscorevalue; - if(scorevalue===false){ - newscorevalue=false - }else{ - //判断占比 - newscorevalue=true - - let sum=0; - for(var i=0; i100){ - this.props.showSnackbar("测试集的评分占比不能大于100"); - this.setState({ - scoretype:i - }) - return - } - sum=sum+evaluationlist[i].score - } - - if(sum>100||sum<100){ - this.props.showSnackbar("测试集的评分占比之和必须等于100"); - return - } - - - } - if(shixunfilepath===undefined||shixunfilepath===""||shixunfilepath===null){ - this.props.showSnackbar("学员任务文件路径为空"); - this.setState({ - StudentTaskPapers:true - }) - $('html').animate({ - scrollTop: 120 - }, 1000); - return - } - - if(shixunfilepathplay===undefined||shixunfilepathplay===""||shixunfilepathplay===null){ - this.props.showSnackbar("评测执行文件路径为空"); - this.setState({ - StudentTaskDocs:true - }) - $('html').animate({ - scrollTop: 130 - }, 1000); - return - } - - if(evaluationlist.length===0){ - this.props.showSnackbar("测试集不能为空"); - return - } - let id = this.props.match.params.shixunId; - let{checkpointId}=this.state; - let url = "/shixuns/"+id+"/challenges/"+checkpointId+".json"; - let newchallenge={ - path:shixunfilepath, - exec_path:shixunfilepathplay, - show_type:pathoptionvalue, - original_picture_path:pathoptionvalue===-1?undefined:shixunfileexpectpicturepath===undefined?null:shixunfileexpectpicturepath, - expect_picture_path:pathoptionvalue===-1?undefined:shixunfilestandardpicturepath===undefined?null:shixunfilestandardpicturepath, - picture_path:pathoptionvalue===-1?undefined:shixunfilepicturepath===undefined?null:shixunfilepicturepath, - test_set_score:newscorevalue, - test_set_average:markvalue, - web_route:web_route===null?undefined:web_route - } - axios.put(url,{ - tab:1, - challenge:newchallenge, - test_set:evaluationlist - } - ).then((response) => { - this.props.showSnackbar(response.data.messages); - // if(response.data.status===1){ - // window.location.href = "/shixuns/" + id + "/challenges/"+response.data.challenge_id+"/tab=3" - // } - }).catch((error) => { - console.log(error) - }); - } - handpathoptionvalues=()=>{ - this.setState({ - handpathopt:true - }) - } - handpathoptionvaluess=()=>{ - this.setState({ - handpathopt:false - }) - } - saveselectpath=(e)=>{ - - this.setState({ - selectpath:e.target.value - }) - - } - updatepath=(e,name,type)=>{ - this.setState({ - [name]:e.target.value, - pathtype:type - }) - } - - - oneditevaluationlist=(newevaluationlist,markvalue)=>{ - - if(markvalue===true){ - if(100%newevaluationlist.length===0){ - let sum=100/newevaluationlist.length; - for(var i=0; i{ - - let {markvalue,evaluationlist}=this.state; - let newevaluationlist=evaluationlist; - - if(e.target.value===true){ - newevaluationlist=this.oneditevaluationlist(newevaluationlist,markvalue) - } - - this.setState({ - scorevalue: e.target.value, - evaluationlist:newevaluationlist - }); - - this.setevaluationlist(newevaluationlist); - } - - //均匀比例 - onChangemarkvalue=(e)=>{ - let {evaluationlist}=this.state; - - if(e.target.value===true){ - let newevaluationlist=evaluationlist; - newevaluationlist=this.oneditevaluationlist(newevaluationlist,e.target.value); - this.setevaluationlist(newevaluationlist); - } - - this.setState({ - markvalue: e.target.value, - }); - - } - - updatewebroute=(e)=>{ - this.setState({ - web_route:e.target.value - }) - } - render() { - - let { - choice_url, - practice_url, - go_back_url, - position, - evaluationlist, - shixunId, - checkpointId, - power, - shixunfileexpectpicturepath, - shixunfilestandardpicturepath, - shixunfilepicturepath, - shixunfilepath, - evaluationvisible, - trees, - path, - main, - selectpath, - shixunfilepathplay, - pathoptionvalue, - showrepositoryurltiptype, - prev_challenge, - next_challenge, - StudentTaskPapers, - StudentTaskDocs, - web_route, - scorevalue, - markvalue, - scoretype, - has_web_route - } = this.state; - - let tab1url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/editcheckpoint"; - let tab2url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=2"; - let tab3url="/shixuns/" + shixunId + "/challenges/"+checkpointId+"/tab=3"; - // console.log(this.props) - const radioStyle = { - display: 'block', - height: '30px', - lineHeight: '30px', - marginLeft: '20px', - }; - return ( - -
    -
    - - - - 第{position}关 - 返回 - - {prev_challenge === undefined ? "" : - 上一关 - } - - {next_challenge === undefined ? "" : - 下一关 - } - - 4||this.props.identity===undefined||this.props.status===2||this.props.status===1? "none":'block'}} - data-tip-down="新增代码编辑类型的任务">+ 实践类型 - 4||this.props.identity===undefined||this.props.status===2||this.props.status===1?"none":'block'}} - data-tip-down="新增选择题类型的任务">+ 选择题类型 - -
    - -
    - -
  • - 本关任务 -
  • - -
  • - 评测设置 -
  • - -
  • - 参考答案 -
  • -
    - -

    - 请先上传本关任务的所有代码文件、标准图片等所有必要的文件到 - 版本库 -

    - - -
    -
    -

    学员任务文件

    -
    - * -
    - this.updatepath(e,"shixunfilepath",1)} - onClick={(e)=>this.getfilepath(e,"shixunfilepath",1)} - /> -

    该文件将直接显示给学生,需要学生在其中填写代码

    -
    -
    - 必填项 -
    -
    -
    -
    - -
    -
    - -
    - - this.saveselectpath(e)} - value={selectpath}/> -
    - - this.evaluationenter()}>确定 - this.evaluationhideModal()}>取消 -
    -
    -
    - -
    -
    -

    评测执行文件

    -
    - * -
    - this.updatepath(e,"shixunfilepathplay",1)} - onClick={(e)=>this.getfilepath(e,"shixunfilepathplay",1)} - /> -

    该文件由平台执行,用来测试平台学员代码是否正确

    -
    -
    - 必填项 -
    -
    -
    -
    - - -
    -
    -

    效果展现方式

    -
    - - this.showrepositoryurltip(1)}> -
    - -
    -

    - 图片:处理或输出图片类型的任务,请选填此项
    - 可以通过设置图片路径和学员答案文件路径,展示代码对应的图片效果

    - apk/exe:写可执行文件的任务,请选填此项
    - 可以通过设置学员答案文件路径,展示二维码以供扫码下载

    - txt:输出txt文档类型的任务,请选填此项
    - 可以通过学员答案文件路径设置,展示txt文件内容

    - html:web类型的任务,请选填此项
    - 可以通过Web路由设置,展示html效果预览页 -

    -

    this.showrepositoryurltip(2)} - >知道了 -

    -
    -
    -

    该选项用来配置学员评测本关任务时,查看效果页上需要展现的文件类型

    -
    -
    - - {pathoptionvalue===4&&web_route!=null||pathoptionvalue===4&&has_web_route===true?
    -
    -

    Web路由

    -
    -
    - this.updatewebroute(e)} - placeholder="网站类型实训,请填写Web路由地址。例:java/mypage"/> -
    -
    -
    -
    :""} - - {pathoptionvalue===1||pathoptionvalue===5||pathoptionvalue===6?
    -
    -

    待处理文件路径

    -
    -
    - this.updatepath(e,"shixunfileexpectpicturepath",2)} - onClick={(e)=>this.getfilepath(e,"shixunfileexpectpicturepath",2)} - /> -

    - 该路径下的文件将在学员评测本关任务时,作为原始文件显示在查看效果页,供学员参考;任务为文件处理时请指定该路径,并注意与程序文件所在文件夹分开。 -

    -
    -
    -
    -
    -
    :""} - - - {pathoptionvalue===1||pathoptionvalue===5||pathoptionvalue===6?
    -
    -

    标准答案文件路径

    -
    -
    - this.updatepath(e,"shixunfilestandardpicturepath",2)} - onClick={(e)=>this.getfilepath(e,"shixunfilestandardpicturepath",2)} - /> -

    - 该路径下的文件将在学员评测本关任务时,作为参考答案显示在查看效果页,供学员参考;任务输出结果为文件时请指定该路径,并注意与程序文件所在文件夹分开。 -

    -
    -
    -
    -
    -
    :""} - - - {pathoptionvalue===-1?"":
    -
    -

    学员答案文件路径

    -
    -
    - this.updatepath(e,"shixunfilepicturepath",2)} - onClick={(e)=>this.getfilepath(e,"shixunfilepicturepath",2)} - placeholder="请在版本库中指定用来保存学员代码实际输出结果的路径。例:src/step1/outputfiles"/> -

    - 学员评测本关任务时生成的文件将保存在该路径下,并作为实际输出显示在查看效果页,供学员确认;任务输出结果为文件时请指定该路径,并注意与程序文件所在文件夹分开。 -

    -
    -
    -
    -
    -
    } - - -
    -
    - {/*

    测试集

    */} -

    测试集和系统评分规则

    -

    - 得分规范: - - - 通过全部测试集 - (学员评测,仅当所有测试集都正确时,才获得一次性奖励) - - - 通过部分测试集 - (学员评测,当至少有一组测试集正确时,即可获得其对应比例的奖励) - -

    - -

    - - 系统评分占比: - - 均分比例 - 自定义比例 - - - -

    - -
    -
    - -
    - - {evaluationlist===undefined?"":evaluationlist.length===0?"":evaluationlist.map((item,key)=>{ - return( -
    -

    - * - 组{key+1} - - {/*checked={item.is_public===1?false:true}*/} - - this.editpercentage(e,key)} - value={item.score} /> - % - - - this.evaluationonChange(item.hidden,key)} checked={item.hidden===1?true:false}>隐藏 - - - - this.del_test_array(key)}> - - - -

    - - -
    - 匹配规则: - this.changeEvaluationRule(e,key)}> - 完全匹配 - 末尾匹配 - -
    -
    - ) - })} - -
    -
    - -

    - - 新增测试集 - -

    -

    温馨提示:建议公开测试集和隐藏测试集结合使用,降低作弊的几率;隐藏测试集,在“提交评测”时也将被自动检测

    -
    -
    -
    - - -
    4||this.props.identity===undefined||power===false?"none":"block"}}> - 提交 - 取消 -
    - - -
    -
    - ) - } -} - - diff --git a/public/react/src/tpm/challengesnew/TPMquestion.js b/public/react/src/tpm/challengesnew/TPMquestion.js deleted file mode 100644 index b76e17b17..000000000 --- a/public/react/src/tpm/challengesnew/TPMquestion.js +++ /dev/null @@ -1,1052 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal,Tooltip,notification} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -// import "antd/dist/antd.css"; - -import axios from 'axios'; - -import { getImageUrl, toPath } from 'educoder'; - -import './css/TPMchallengesnew.css'; - -import {getUrl} from 'educoder'; - -import TpmQuestionMain from './TpmQuestionMain'; - -import TpmQuestionNew from './TpmQuestionNew'; - -import TpmQuestionEdit from './TpmQuestionEdit'; - -let origin = getUrl(); - -let path = getUrl("/editormd/lib/") - -const $ = window.$; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; - -var letterArr = []; -for (var i = 65, j = 0; i < 91; i++, j++) { - letterArr[j] = String.fromCharCode(i); -} - - -export default class TPMquestion extends Component { - constructor(props) { - super(props) - this.contentMdRef = React.createRef(); - this.newquestioMDMdRef = React.createRef(); - this.newquestioMDMdCont=React.createRef(); - this.neweditanswerRef=React.createRef(); - this.editanswersRef=React.createRef(); - this.state = { - choice_url: undefined, - practice_url: undefined, - go_back_url: undefined, - position: undefined, - task_pass_default: undefined, - submit_url: undefined, - questionsInputvalue:undefined, - questionaddsum:0, - questionaddarray:[], - questionaddtype:true, - activetype:"", - questionlists:[{str:"A",val:"",type:false},{str:"B",val:"",type:false},{str:"C",val:"",type:false},{str:"D",val:"",type:false}], - answeshixunsGroup: 1, - answeoptions:[10,20], - answeonshixunsmark:10, - shixunssanswerkillvalue:"", - shixunsskillanswerlist:[], - challenge_id:"", - challenge_choose_id:undefined, - questionlistss:[], - newcnttype:false, - newquestioMDvaluetype:false, - challenge_tagtype:false, - editquestionaddtype:false, - mancheckpointId:undefined, - power:false, - questionInputvaluetype:false, - questioMD:"", - standard_answer:"", - subject:"", - newquestioMDvaluetypes:false, - questionInputvaluetypes:false, - prev_challenge:undefined, - next_challenge:undefined, - newcnttypesum:1, - marktype:false, - answer:"", - sumittype:false - } - } - - - questionInputvalue=(e)=>{ - this.setState({ - questionsInputvalue: e.target.value - }) - } - - componentDidMount() { - if(this.props.status===2){ - - } - let id = this.props.match.params.shixunId; - let checkpointId=this.props.match.params.checkpointId; - - this.setState({ - mancheckpointId:id, - }) - - let newchoice_url= "/shixuns/"+id+"/challenges/newquestion"; - let newpractice_url= "/shixuns/"+id+"/challenges/new"; - let newgo_back_url="/shixuns/"+id+"/challenges"; - - if(this.props.match.params.choose_id===undefined){ - if(checkpointId===undefined){ - //新建模式 - let nurl = "/shixuns/" + id + "/challenges/new.json" - axios.get(nurl).then((response) => { - - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else { - this.setState({ - choice_url: newchoice_url, - practice_url: newpractice_url, - go_back_url: newgo_back_url, - position: response.data.position, - task_pass_default: response.data.task_pass_default, - submit_url: response.data.submit_url, - power:true, - activetype:"first", - - }) - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - this.setState({ - contentMdRefval:"" - }) - } else { - - this.setState({ - contentMdRefval:response.data.task_pass_default - }) - this.contentMdRef.current.setValue(response.data.task_pass_default || '') - } - this.shixunsautoHeight() - } - - }).catch((error) => { - console.log(error) - }); - - }else{ - //编辑模式 - let url = "/shixuns/"+ id +"/challenges/"+checkpointId+"/edit.json?st=1" - axios.get(url).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else { - let newprev_challenge=response.data.prev_challenge; - let next_challenge=response.data.next_challenge; - if (newprev_challenge != undefined) { - if(newprev_challenge.st===0){ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint"; - }else{ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion"; - } - } - if (next_challenge != undefined) { - if(next_challenge.st===0){ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint"; - }else{ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion"; - } - } - this.setState({ - questionaddtype:false, - newquestionaddtype:false, - activetype:"first", - prev_challenge:newprev_challenge, - next_challenge:next_challenge, - questionsInputvalue:response.data.subject, - questionaddarray:response.data.chooses, - challenge_id:response.data.id, - mancheckpointId:checkpointId, - position: response.data.position, - choice_url: newchoice_url, - practice_url: newpractice_url, - go_back_url: newgo_back_url, - power:response.data.power, - // questioMD:response.data.task_pass, - answer:response.data.answer - - }) - - this.setState({ - contentMdRefval:response.data.task_pass - }) - // this.contentMdRef.current.setValue(response.data.task_pass || '') - if(response.data.chooses.length===0){ - // 新建选择题时,没法切回 ‘本关任务’ tab - // this.questionadd() - } - - this.shixunsautoHeight() - } - - }).catch((error) => { - console.log(error) - }); - } - - }else{ - $('html').animate({ - scrollTop:10 - }, 500); - - let{challenge_id} =this.state; - - let id = this.props.match.params.shixunId; - let url = "/shixuns/"+ id +"/challenges/"+checkpointId+"/edit.json?st=1" - axios.get(url).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else { - let newprev_challenge=response.data.prev_challenge; - let next_challenge=response.data.next_challenge; - if (newprev_challenge != undefined) { - if(newprev_challenge.st===0){ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editcheckpoint"; - }else{ - newprev_challenge = "/shixuns/" + id + "/challenges/" + newprev_challenge.id + "/editquestion"; - } - } - if (next_challenge != undefined) { - if(next_challenge.st===0){ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editcheckpoint"; - }else{ - next_challenge = "/shixuns/" + id + "/challenges/" + next_challenge.id+ "/editquestion"; - } - } - this.setState({ - questionaddtype:false, - newquestionaddtype:false, - prev_challenge:newprev_challenge, - next_challenge:next_challenge, - questionsInputvalue:response.data.subject, - questionaddarray:response.data.chooses, - challenge_id:response.data.id, - mancheckpointId:checkpointId, - position: response.data.position, - choice_url: newchoice_url, - practice_url: newpractice_url, - go_back_url: newgo_back_url, - power:response.data.power, - // questioMD:response.data.task_pass, - - }) - - this.setState({ - contentMdRefval:response.data.task_pass - }) - // this.contentMdRef.current.setValue(response.data.task_pass || '') - if(response.data.chooses.length===0){ - this.questionadd() - } - this.shixunsautoHeight() - } - - }).catch((error) => { - console.log(error) - }); - - let zrl ='/shixuns/'+this.props.match.params.shixunId+'/challenges/'+this.props.match.params.checkpointId+'/edit_choose_question.json?choose_id='+this.props.match.params.choose_id; - axios.get(zrl).then((response) => { - if(response.status===200){ - let choose_contents=response.data.choose_contents; - let newchoose_contentslist=[] - for(var i=0; i { - }); - - } - } - - clickquestionsumit=()=>{ - this.setState({ - sumittype:true - }) - let checkpointId=this.props.match.params.checkpointId; - if(this.props.status===2&&checkpointId===undefined){ - this.props.showSnackbar("该实训已经发布不能新建") - this.setState({ - sumittype:false - }) - return - } - let {questionsInputvalue} =this.state; - // const exercise_editormdvalue = this.questio_editormd.getValue(); - const exercise_editormdvalue = this.contentMdRef.current.getValue().trim(); - let id = this.props.match.params.shixunId; - - if(questionsInputvalue===undefined||questionsInputvalue===null||questionsInputvalue===""){ - this.setState({ - questionInputvaluetype:true - }) - $('html').animate({ - scrollTop: 10 - }, 1000); - this.setState({ - sumittype:false - }) - return - } - - - if(exercise_editormdvalue===null ||exercise_editormdvalue===""){ - this.setState({ - questionInputvaluetypes:true - }) - $('html').animate({ - scrollTop: 500 - }, 1000); - this.setState({ - sumittype:false - }) - return - } - if(checkpointId===undefined){ - - let url = "/shixuns/" + id + "/challenges.json"; - - axios.post(url, { - identifier:id, - subject: questionsInputvalue, - task_pass: exercise_editormdvalue, - st: 1 - }).then((response) => { - this.props.showSnackbar(response.data.messages); - // if(response.data.status===1){ - // - // this.setState({ - // questionaddtype:false, - // challenge_id:response.data.challenge_id - // }) - // - // this.questionadd() - // } - window.location.href = '/shixuns/'+id+'/challenges/'+response.data.challenge_id+'/editquestion'; - - }).catch((error) => { - console.log(error) - }); - }else{ - let url ="/shixuns/"+id+"/challenges/"+checkpointId+".json"; - axios.put(url, { - tab:0, - subject: questionsInputvalue, - task_pass: exercise_editormdvalue, - }).then((response) => { - if(response.data.status===1){ - this.setState({ - questionaddtype:false, - challenge_id:response.data.challenge_id - }) - } - $('html').animate({ - scrollTop: 10 - }, 200); - this.props.showSnackbar(response.data.messages); - window.location.href = '/shixuns/'+id+'/challenges/'+response.data.challenge_id+'/editquestion'; - }).catch((error) => { - console.log(error) - }); - } - - } - - questionall=()=>{ - // this.setState({ - // activetype:"first", - // newquestionaddtype:false, - // editquestionaddtype:false, - // questionaddtype:false - // }) - - window.location.href = '/shixuns/'+this.props.match.params.shixunId+'/challenges/'+this.props.match.params.checkpointId+'/editquestion'; - } - questionadd=()=>{ - - let{questionaddarray}=this.state; - - let questionaddsums=questionaddarray.length; - - if(questionaddsums-1>9){ - this.props.showSnackbar("选择题目最大支持设置9道题") - return - } - - let questionaddarrays=questionaddarray; - - questionaddarrays.map((item,key)=>{ - if(item.choose_id===0){ - questionaddarrays.splice(key,1) - } - }) - - questionaddarrays.push({type:0,choose_id:0}); - this.setState({ - activetype:0, - questionaddarray:questionaddarrays, - questionaddtype:true, - editquestionaddtype:false, - newquestionaddtype:true, - questionlists:[{str:"A",val:"",type:false},{str:"B",val:"",type:false},{str:"C",val:"",type:false},{str:"D",val:"",type:false}], - answeshixunsGroup: 1, - answeoptions:[10,20], - answeonshixunsmark:10, - shixunssanswerkillvalue:"", - shixunsskillanswerlist:[], - contentMdRefval:"", - newquestioMDMdContval:"", - }) - - - setTimeout(() => { - this.newquestioMDMdRef.current.setValue('') - }, 1000) - setTimeout(() => { - this.newquestioMDMdCont.current.setValue('') - }, 1500) - // this.shixunsautoHeight() - } - - editquestionlists=(newquestionlists)=>{ - let newlist=newquestionlists; - let list=[] - for(var i=0; i{ - let{questionlists} = this.state; - let newquestionlists=questionlists; - let newli={str:letterArr[questionlists.length],val:"",type:false}; - newquestionlists.push(newli); - this.editquestionlists(newquestionlists); - } - - - delquestionlists=(key)=>{ - let{questionlists} = this.state; - let newquestionlists=questionlists; - newquestionlists.splice(key,1); - for(var i=0; i{ - let{questionlists} = this.state; - let newquestionlists=questionlists; - if(newquestionlists[key].type===true){ - newquestionlists[key].type=false; - }else if(newquestionlists[key].type===false){ - newquestionlists[key].type=true; - } - - this.editquestionlists(newquestionlists); - } - - onshixunGroupanswe=(e)=> { - let optionsum; - let onshixunsmark; - if(e.target.value===1){ - optionsum=[10,20]; - onshixunsmark=10; - }else if(e.target.value===2){ - optionsum=[30,40,50,60]; - onshixunsmark=30; - }else if(e.target.value===3){ - optionsum=[70,80,90,100] - onshixunsmark=70; - } - this.setState({ - answeshixunsGroup: e.target.value, - answeoptions:optionsum, - answeonshixunsmark:onshixunsmark - }) - } - shixunssanswerkill = (e) => { - this.setState({ - shixunssanswerkillvalue: e.target.value - }) - - } - clickshixunsanswerskill = () => { - - let {shixunssanswerkillvalue, shixunsskillanswerlist} = this.state; - if (shixunssanswerkillvalue === "") { - return - } else if (shixunssanswerkillvalue === undefined) { - return - } - - if(shixunssanswerkillvalue == "" || shixunssanswerkillvalue == undefined || shixunssanswerkillvalue == null || (shixunssanswerkillvalue.length>0 && shixunssanswerkillvalue.trim().length == 0)){ - message.error("输入为空,不能保存!"); - return - } - - let list = shixunsskillanswerlist; - list.push(shixunssanswerkillvalue); - this.setState({ - shixunsskillanswerlist: list, - shixunssanswerkillvalue: "" - }) - } - delshixunssnswerllist=(key)=>{ - let {shixunsskillanswerlist} = this.state; - let newshixunsskillanswerlist = shixunsskillanswerlist; - newshixunsskillanswerlist.splice(key, 1); - this.setState({ - shixunsskillanswerlist: newshixunsskillanswerlist - }) - } - onInputoquestionption=(e,key)=>{ - - $.fn.autoHeight = function(){ - function autoHeight(elem){ - elem.style.height = 'auto'; - elem.style.maxHeight = '140px'; - elem.scrollTop = 0; //防抖动 - elem.style.height = elem.scrollHeight + 'px'; - } - this.each(function(){ - autoHeight(this); - $(this).on('keyup', function(){ - autoHeight(this); - }); - }); - } - $("#"+e.target.id).autoHeight(); - - let {questionlists}=this.state; - let newquestionlists=questionlists; - newquestionlists[key].val=e.target.value; - this.editquestionlists(newquestionlists); - } - - onshixunsansweSelect=(value)=>{ - this.setState({ - answeonshixunsmark: value - }) - } - - answer_subit=(sumtype,challenge_choose_id)=>{ - $('html').animate({ - scrollTop:10 - }, 500); - - let {challenge_id,questionlists,shixunsskillanswerlist,answeonshixunsmark,answeshixunsGroup,questionaddarray} =this.state; - if(challenge_id===undefined){ - message.error("关卡id为空"); - return - } - let newquestionlists=questionlists; - let newlist=""; - let newtype=[]; - let newcnt=[]; - let list=0; - for(var i=0; i { - console.log(error) - }); - }else{ - - let newquestioMDvalue = this.newquestioMDMdRef.current.getValue().trim(); - if(newquestioMDvalue===""||newquestioMDvalue==="请输入选择题的题干内容"){ - this.setState({ - newquestioMDvaluetype:true, - }) - $('html').animate({ - scrollTop:100 - }, 200); - message.error("题干为空"); - return - } - let newnewanswerMDvalue = this.newquestioMDMdCont.current.getValue().trim(); - - if(newnewanswerMDvalue===""||newnewanswerMDvalue===" "){ - newnewanswerMDvalue=undefined - } - url="/shixuns/" + id + "/challenges/" + challenge_id + "/create_choose_question.json"; - axios.post(url, { - challenge_choose: {subject: newquestioMDvalue, answer: newnewanswerMDvalue, standard_answer:newlist , score: answeonshixunsmark, difficult: answeshixunsGroup}, - challenge_tag: shixunsskillanswerlist, - question: {cnt: newcnt}, - choice: {answer: newtype} - }).then((response) => { - - let questionaddsums=questionaddarray.length; - let questionaddarrays=questionaddarray; - questionaddarrays[questionaddsums-1].choose_id=response.data.challenge_choose_id; - if(newlist.length===1){ - questionaddarrays[questionaddsums-1].type=1; - }else if(newlist.length>1){ - questionaddarrays[questionaddsums-1].type=2; - } - this.setState({ - challenge_choose_id:response.data.challenge_choose_id, - questionaddtype:false, - editquestionaddtype:false, - newquestioMDvaluetype:false, - newquestioMDvaluetypes:false, - questionaddarray:questionaddarrays - }) - $('html').animate({ - scrollTop: 10 - }, 200); - - notification.open({ - message: '提示', - description: - '新建成功,请点击右侧加号继续添加', - }); - window.location.href=`/shixuns/${id}/challenges/${checkpointId}/editquestion/${response.data.challenge_choose_id}`; - - // this.getanswer_subitlist() - // this.gochooseid("/shixuns/"+this.props.match.params.shixunId+"/challenges/"+this.props.match.params.checkpointId+"/editquestion"+"/"+response.data.challenge_choose_id) - }).catch((error) => { - console.log(error) - }); - } - - - } - - questionlist=(key,challenge_choose_id,type)=>{ - $('html').animate({ - scrollTop:10 - }, 500); - - let{challenge_id} =this.state; - - if(challenge_choose_id===""||type===0){ - - - // this.neweditanswerRef.current.setValue('') - // this.editanswersRef.current.setValue('') - this.setState({ - activetype:challenge_choose_id, - editquestionaddtype:true, - questionaddtype:true, - newquestionaddtype:false, - questionlists:[{str:"A",val:"",type:false},{str:"B",val:"",type:false},{str:"C",val:"",type:false},{str:"D",val:"",type:false}], - answeshixunsGroup: 1, - answeoptions:[10,20], - answeonshixunsmark:10, - shixunssanswerkillvalue:"", - shixunsskillanswerlist:[], - neweditanswerRefval:'', - editanswersRefval:'' - }) - this.newquestioMDMdRef.current.setValue('') - this.newquestioMDMdCont.current.setValue('') - }else{ - let id = this.props.match.params.shixunId; - let url ='/shixuns/'+id+'/challenges/'+challenge_id+'/edit_choose_question.json?choose_id='+challenge_choose_id; - axios.get(url).then((response) => { - if(response.status===200){ - let choose_contents=response.data.choose_contents; - let newchoose_contentslist=[] - for(var i=0; i { - }); - - } - - } - - shixunsautoHeight=()=>{ - $.fn.autoHeight = function(){ - function autoHeight(elem){ - elem.style.height = 'auto'; - elem.style.maxHeight = '140px'; - elem.scrollTop = 0; //防抖动 - if(elem.scrollHeight===0){ - elem.style.height = 62 + 'px'; - }else{ - - elem.style.height = elem.scrollHeight + 'px'; - } - - } - this.each(function(){ - autoHeight(this); - $(this).on('keyup', function(){ - autoHeight(this); - }); - }); - } - $('textarea[autoHeight]').autoHeight(); - } - - gochooseid=(url)=>{ - window.location.href =url - // window.location.Reload(url) - // this.props.history.replace( url ); - // this.props.history.push( url ); - // 返回 - // this.props.history.goBack(); - } - - render() { - - let {choice_url, - practice_url, - go_back_url, - position, - answeoptions, - questionaddarray, - questionaddtype, - activetype, - newquestionaddtype, - editquestionaddtype, - challenge_choose_id, - prev_challenge, - next_challenge, - answer, - - } = this.state; - - let options; - - - options = answeoptions.map((d, k) => { - return ( - - ) - }) - - return ( - -
    - - -
    - - -
  • - 本关任务 -
  • -
    - - { - questionaddarray.length===0?"":questionaddarray.map((item,key)=>{ - return( -
  • this.questionlist(key,item.choose_id,item.type):""} - > - - { - item.choose_id!=0? - this.gochooseid("/shixuns/"+this.props.match.params.shixunId+"/challenges/"+this.props.match.params.checkpointId+"/editquestion"+"/"+item.choose_id)}> - {key+1}.{item.type===2?"多选题":item.type===1?"单选题":'选择题'} - :activetype==="first"?"":{key+1}.{item.type===2?"多选题":item.type===1?"单选题":'选择题'} - } - -
  • - ) - }) - } - - -
  • - - + - -
  • - -
    - - {/*x选择题首页*/} - {activetype==="first"?this.questionInputvalue(e)} - clickquestionsumit={(e)=>this.clickquestionsumit(e)} - - />:""} - - {/*新建*/} - - {newquestionaddtype===true? - this.selquestionlists(key)} - onInputoquestionption={(e,key)=>this.onInputoquestionption(e,key)} - delquestionlists={(key)=>this.delquestionlists(key)} - addquestionlists={(e)=>this.addquestionlists(e)} - onshixunGroupanswe={(e)=>this.onshixunGroupanswe(e)} - onshixunsansweSelect={(e)=>this.onshixunsansweSelect(e)} - shixunssanswerkill={(e)=>this.shixunssanswerkill(e)} - clickshixunsanswerskill={(e)=>this.clickshixunsanswerskill(e)} - delshixunssnswerllist={(key)=>this.delshixunssnswerllist(key)} - answer_subit={()=>this.answer_subit()} - />:""} - - - {/*修改*/} - {editquestionaddtype===true? - this.selquestionlists(key)} - onInputoquestionption={(e,key)=>this.onInputoquestionption(e,key)} - delquestionlists={(key)=>this.delquestionlists(key)} - addquestionlists={(e)=>this.addquestionlists(e)} - onshixunGroupanswe={(e)=>this.onshixunGroupanswe(e)} - onshixunsansweSelect={(e)=>this.onshixunsansweSelect(e)} - shixunssanswerkill={(e)=>this.shixunssanswerkill(e)} - clickshixunsanswerskill={(e)=>this.clickshixunsanswerskill(e)} - delshixunssnswerllist={(key)=>this.delshixunssnswerllist(key)} - answer_subit={()=>this.answer_subit("edit",challenge_choose_id)} - /> - :""} - -
    -
    - ) - } -} - diff --git a/public/react/src/tpm/challengesnew/TpmQuestionEdit.js b/public/react/src/tpm/challengesnew/TpmQuestionEdit.js deleted file mode 100644 index d0e6f98bd..000000000 --- a/public/react/src/tpm/challengesnew/TpmQuestionEdit.js +++ /dev/null @@ -1,229 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal,Tooltip} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -import axios from 'axios'; - -import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; - -export default class TpmQuestionEdit extends Component { - constructor(props) { - super(props) - this.state = { - - } - } - - componentDidMount() { - - } - delecbtns=()=>{ - let url=`/shixuns/${this.props.match.params.shixunId}/challenges/${this.props.match.params.checkpointId}/destroy_challenge_choose.json`; - axios.delete((url), { data: { - choose_id:this.props.match.params.choose_id - }}) - .then((result)=>{ - if(result.data.status===1){ - window.location.href=`/shixuns/${this.props.match.params.shixunId}/challenges/${this.props.match.params.checkpointId}/editquestion`; - } - }) - } - - render() { - - return ( -
    - -
    -
    -

    题干

    -
    - * -
    - -
    - - -
    - 必填项 -
    - -
    -

    -

    -
    - { - this.props.questionlists===undefined||this.props.questionlists.length===0?"":this.props.questionlists.map((item,key)=>{ - return( -
  • - - - this.props.delquestionlists(key)}> - - -
  • - ) - }) - } -

    - this.props.addquestionlists()} - className="fl edu-default-btn edu-greyline-btn mb20 option_icon_add">新增选项 - - - {this.props.newcnttypesum===0?"请选择答案":"选项内容不能为空"} - -

    -
  • - - -
  • -
    -
    -
    - - -
    -
    -

    参考答案

    -
    -
    - -
    -
    - 必填项 -
    -
    -

    -

    -
    -
    - -
    -

    难度系数

    -
    - - this.props.onshixunGroupanswe(e)}> - 简单 - 中等 - 困难 - - -
    -

    奖励经验值

    -
    - * - - -

    - 如果学员答题错误,则不能得到相应的经验值
    - 如果学员成功得到经验值,那么将同时获得等值的金币奖励,如:+10经验值、+10金币 -

    - - 必填项 -
    -
    - -
    -

    技能标签

    -
    - * -
    - this.props.shixunssanswerkill(e)} - value={this.props.shixunssanswerkillvalue} - onPressEnter={(e)=>this.props.clickshixunsanswerskill(e)} - onBlur={(e)=>this.props.clickshixunsanswerskill(e)} - /> - {/*+ 添加*/} -
    学员答题正确将获得技能,否则不能获得技能 - - 必填项 - -
    -
    - - { - this.props.shixunsskillanswerlist.length === 0 ? "" : this.props.shixunsskillanswerlist.map((itme, key) => { - return ( -
  • {itme} - this.props.delshixunssnswerllist(key)}>× -
  • - ) - }) - } - - -
    - -
    - -
    -
    - - -
    4||this.props.identity===undefined||this.props.power===false?"none":"block"}}> - this.props.answer_subit()}>提交 - 取消 - - this.delecbtns()} - className="delectshixuncdbtn fr">删除 -
    - -
    - - ) - } -} - - - diff --git a/public/react/src/tpm/challengesnew/TpmQuestionMain.js b/public/react/src/tpm/challengesnew/TpmQuestionMain.js deleted file mode 100644 index 614842ab8..000000000 --- a/public/react/src/tpm/challengesnew/TpmQuestionMain.js +++ /dev/null @@ -1,84 +0,0 @@ -import React, {Component} from 'react'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; -import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; - - -export default class TpmQuestionMain extends Component { - constructor(props) { - super(props) - this.state = { - - } - } - - componentDidMount() { - - } - - - render() { - return ( -
    -
    -
    -

    任务名称

    -
    - * -
    - -
    -
    - 必填项 -
    -
    -
    -
    - - -
    -

    过关任务

    -
    - * -
    - -
    -
    - 必填项 -
    -
    -

    -

    -
    - - -
    4 || this.props.identity === undefined || this.props.power === false ? "none" : "block"}}> - 提交 - 取消 - -
    - -
    - - ) - } - } - - - diff --git a/public/react/src/tpm/challengesnew/TpmQuestionNew.js b/public/react/src/tpm/challengesnew/TpmQuestionNew.js deleted file mode 100644 index 861c4f879..000000000 --- a/public/react/src/tpm/challengesnew/TpmQuestionNew.js +++ /dev/null @@ -1,219 +0,0 @@ -import React, {Component} from 'react'; - -import {Input, Select, Radio, Checkbox, Popconfirm, message, Modal,Tooltip} from 'antd'; - -import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom"; - -import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor'; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; - -export default class TpmQuestionNew extends Component { - constructor(props) { - super(props) - this.state = { - - } - } - - componentDidMount() { - - } - - - render() { - // console.log( this.props.questionlists) - return ( -
    - -
    -
    -

    题干

    -
    - * -
    - -
    - - -
    - 必填项 -
    - -
    -

    -

    - - -
    - { - this.props.questionlists===undefined||this.props.questionlists.length===0?"":this.props.questionlists.map((item,key)=>{ - return( -
  • - - - this.props.delquestionlists(key)}> - - - - - -
  • - ) - }) - } -

    - this.props.addquestionlists()} - className="fl edu-default-btn edu-greyline-btn mb20 option_icon_add">新增选项 - - - {this.props.newcnttypesum===0?"请选择答案":"选项内容不能为空"} - -

    -
  • - - -
  • -
    -
    -
    - - -
    -
    -

    参考答案

    -
    -
    - -
    -
    - 必填项 -
    -
    -

    -

    - -
    -
    - -
    -

    难度系数

    -
    - - this.props.onshixunGroupanswe(e)} - > - 简单 - 中等 - 困难 - - -
    -

    奖励经验值

    -
    - * - - - -

    - 如果学员答题错误,则不能得到相应的经验值
    - 如果学员成功得到经验值,那么将同时获得等值的金币奖励,如:+10经验值、+10金币 -

    - - 必填项 -
    -
    - -
    -

    技能标签

    -
    - * -
    - this.props.shixunssanswerkill(e)} - value={this.props.shixunssanswerkillvalue} - onPressEnter={(e)=>this.props.clickshixunsanswerskill(e)} - onBlur={(e)=>this.props.clickshixunsanswerskill(e)} - /> - {/*+ 添加*/} -
    学员答题正确将获得技能,否则不能获得技能 - - 必填项 - -
    -
    - - { - this.props.shixunsskillanswerlist.length === 0 ? "" : this.props.shixunsskillanswerlist.map((itme, key) => { - return ( -
  • {itme} - this.props.delshixunssnswerllist(key)}>× -
  • - ) - }) - } - - -
    - -
    - -
    -
    - - -
    4||this.props.identity===undefined||this.props.power===false?"none":"block"}}> - 提交 - 取消 -
    - -
    - - ) - } -} - - - diff --git a/public/react/src/tpm/challengesnew/css/TPMchallengesnew.css b/public/react/src/tpm/challengesnew/css/TPMchallengesnew.css deleted file mode 100644 index 37a65ef97..000000000 --- a/public/react/src/tpm/challengesnew/css/TPMchallengesnew.css +++ /dev/null @@ -1,269 +0,0 @@ -.CodeMirror-scroll { - overflow: auto !important; - margin-bottom: -30px; - margin-right: -30px; - padding-bottom: 30px; - height: 100%; - outline: none; - position: relative; -} -a.white-btn.orange-btn:hover { - border: 1px solid #F06200; - color: #FFF !important; -} -.flex1 a.white-btn.orange-btn:hover { - border: 1px solid #F06200; - color: #FFF !important; -} - -/*.challenge_nav li a{*/ - /*color:#000 !important;*/ -/*}*/ - -.questionli{ - width: 95%; - margin-left: 37px; -} -#directory_file{ - height:200px; - overflow-y:auto; - background:#f5f5f5; - padding:10px; -} -.directory_filepath{ - width:120px; - text-align:left; -} - -a{ - text-decoration: none; - color: #05101a; -} -.repository_url_tippostion{ - position: absolute; - left: 22%; - width: 500px; - top: 100%; -} - -.top-black-trangleft { - display: block; - border-width: 8px; - position: absolute; - top: -16px; - /* right: 4px; */ - border-style: dashed solid dashed dashed; - border-color: transparent transparent rgba(5,16,26,0.6) transparent; - font-size: 0; - line-height: 0; -} - -#exercisememoMD .CodeMirror { - margin-top: 31px !important; - height: 370px !important; - /*width: 579px !important;*/ -} - -#exercisememoMD .editormd-preview { - top: 40px !important; - height: 370px !important; - width: 578px !important; -} -#exercisememoMD{ - /*height: 700px !important;*/ -} -#questioMD{ - /*width: 95% !important;*/ - height: 417px !important; - margin-left: 0% !important; -} - - -#questioMD .CodeMirror { - /*width: 550.5px !important;*/ - margin-top: 31px !important; - height: 374px !important; -} - -#questioMD .editormd-preview { - top: 40px !important; - height: 375px !important; - width: 550px !important; -} - -#newquestioMD .CodeMirror { - /*width: 549px !important;*/ - margin-top: 31px !important; - height: 364px !important; -} - -#newquestioMD .editormd-preview { - top: 40px !important; - height: 364px !important; - width: 578px !important; -} - -#challenge_choose_answer .CodeMirror { - margin-top: 31px !important; - height: 364px !important; - /*width: 578px !important;*/ -} - - -#challenge_choose_answer .editormd-preview { - top: 40px !important; - height: 364px !important; - width: 578px !important; -} - -#neweditanswer .CodeMirror { - margin-top: 31px !important; - height: 364px !important; - /*width: 549.5px !important;*/ -} - -#neweditanswer .editormd-preview { - top: 40px !important; - height: 364px !important; - width: 551px !important; -} - -#repository_url_tip { - top: 30px !important; - left: 249px !important; - width: 292px !important; -} - -#editanswers .CodeMirror{ - /*width: 548px !important;*/ - height: 358px !important; - margin-top: 30px !important; -} -#editanswers .editormd-preview{ - width: 578px !important; - height: 358px !important; - -} -#newquestioMDs .CodeMirror{ - /*width: 510px !important;*/ - height: 358px !important; - margin-top: 30px !important; -} - -#newquestioMDs .editormd-preview{ - width: 578px !important; - height: 358px !important; -} - -.choose_names{ - width: 80px; - margin-left: 20px; -} - -#answerMD .CodeMirror{ - /*width: 569px !important;*/ - height: 600px !important; - margin-top: 30px !important; -} - -#answerMD .editormd-preview{ - width: 578px !important; - height: 600px !important; -} - -#answerMD { - height: 600px !important; -} - -.textareavalue{ - width: 100%; - padding: 5px; - - box-sizing: border-box; -} -.greyInput{ - width: 107%; -} -.greyInpus{ - width: 100%; -} - -.pdr20{ - padding-right:20px; -} - -.winput-240-40s { - background-color: #F5F5F5; -} - - -.winput-240-40s:focus{ - background-color: #fff; -} -.input-100-45{ - background-color: #F5F5F5; -} -.input-100-45:focus{ - background-color: #fff; - } - -.wind100{ - width:100% !important; -} - -.color-bule-tip { - color: #5485f7 !important; -} -.martopf4{ - margin-top:-4px; -} - -.headdfgf{ - display: block; - width: 100px; - height: 30px; - line-height: 30px; - float: left; -} - -.color979797{ - color: #979797 !important; -} - -.border-left{ - width: 0; - height: 0; - border-bottom: 6px solid transparent; - border-right: 6px solid #cccbcb; - border-top: 6px solid transparent; - position: absolute; - left: 30px; - top: 12px; -} -.border-left span{ - display: block; - width: 0; - height: 0; - border-bottom: 6px solid transparent; - border-right: 6px solid #fff; - border-top: 6px solid transparent; - position: absolute; - left: 1px; - top: -6px; - z-index: 10; -} -.fillTip{ - position: absolute; - left: 36px; - top: 2px; - width: 125px; - font-size: 12px; - display: block; - padding: 5px; - border: 1px solid #eaeaea; - border-radius: 5px; - box-sizing: border-box; - height: 32px; - line-height: 20px; - font-family: "微软雅黑","宋体"; -} \ No newline at end of file diff --git a/public/react/src/tpm/challengesnew/editorMD.js b/public/react/src/tpm/challengesnew/editorMD.js deleted file mode 100644 index 50f15b601..000000000 --- a/public/react/src/tpm/challengesnew/editorMD.js +++ /dev/null @@ -1,122 +0,0 @@ -import React, {Component} from 'react'; - -import {getUrl} from 'educoder'; - -let path = getUrl("/editormd/lib/"); - -const $ = window.$; - -function create_editorMD(id, width, high, placeholder, imageUrl, callback) { - var editorName = window.editormd(id, { - width: width, - height: high, - path: path, // "/editormd/lib/" - - syncScrolling: "single", - tex: true, - tocm: true, - emoji: true, - taskList: true, - codeFold: true, - searchReplace: true, - htmlDecode: "style,script,iframe", - sequenceDiagram: true, - autoFocus: false, - toolbarIcons: function () { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] - }, - toolbarCustomIcons: { - testIcon: "
    ", - testIcon1: "
    " - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea: true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity: 0.6, - placeholder: placeholder, - imageUpload: true, - imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL: imageUrl,//url - onload: function () { - // this.previewing(); - $("#" + id + " [type=\"latex\"]").bind("click", function () { - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - - $("#" + id + " [type=\"inline\"]").bind("click", function () { - editorName.cm.replaceSelection("`$$$$`"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - window.md_elocalStorage(editorName, `MemoQuestion_${id}`, `${id}Question`); - - callback && callback() - } - }); - return editorName; -} - - -export default class TPMeditorMD extends Component { - constructor(props) { - super(props) - - } - componentDidMount() { - - - } - - questioMD=(initValue, id)=> { - - this.contentChanged = false; - const placeholder = ""; -// amp; -// 编辑时要传memoId - // const imageUrl = `/upload_with_markdown?container_id=&container_type=Memo`; - const imageUrl = `/api/attachments.json`; -// 创建editorMd - - let questio_editormd = create_editorMD(id, '100%', 400, placeholder, imageUrl, () => { - setTimeout(() => { - questio_editormd.resize() - questio_editormd.cm && questio_editormd.cm.refresh() - }, 500) - - if (initValue != undefined) { - questio_editormd.setValue(initValue) - } - questio_editormd.cm.on("change", (_cm, changeObj) => { - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - this.questio_editormd = questio_editormd; - window.questio_editormd = questio_editormd; - - } - - componentWillReceiveProps(newProps) { - this.questioMD(newProps.value,newProps.id) - } - render() { - return ( -
    - -
    -
    -
    - ) - } -} diff --git a/public/react/src/tpm/component/TPMNav.js b/public/react/src/tpm/component/TPMNav.js deleted file mode 100644 index ff8f57aa5..000000000 --- a/public/react/src/tpm/component/TPMNav.js +++ /dev/null @@ -1,57 +0,0 @@ -import React, { Component } from 'react'; - -import { BrowserRouter as Router, Route, Link } from "react-router-dom"; - -class TPMNav extends Component { - - render() { - const { user, match, shixun, secret_repository } = this.props; - let isAdminOrCreator = false; - if (user) { - isAdminOrCreator = user.admin || user.manager - } - const shixunId = match.params.shixunId; - // const challengesPath = `/shixuns/${shixunId}/challenges`; - // console.log(this.props.propaedeutics) - const challengesPath = `/shixuns/${shixunId}/challenges`; - // console.log(match.path) - return ( -
    - 任务 - - { - this.props.propaedeutics===undefined?"":this.props.propaedeutics===false?"":背景知识 - } - - { this.props.identity >4||this.props.identity===undefined ?"":版本库} - {this.props.identity >4||this.props.identity===undefined ?"": secret_repository && 私密版本库} - - 合作者 - - 评论 - - 排行榜 - - {this.props.identity >2||this.props.identity===undefined?"":审核情况} - - 4||this.props.identity===undefined ? "none" : 'block'}} - >配置 -
    - ); - } -} - -export default TPMNav; diff --git a/public/react/src/tpm/component/TPMRightSection.js b/public/react/src/tpm/component/TPMRightSection.js deleted file mode 100644 index 4306fc6e3..000000000 --- a/public/react/src/tpm/component/TPMRightSection.js +++ /dev/null @@ -1,205 +0,0 @@ -import React, { Component } from 'react'; - -import { BrowserRouter as Router, Route, Link } from "react-router-dom"; - -import axios from 'axios'; - -import { getImageUrl,} from "educoder"; - -import './TPMright.css'; - -import {Icon,Tooltip} from 'antd'; - -// import "antd/dist/antd.css"; - -class TPMRightSection extends Component { - constructor(props) { - super(props) - this.state = { - - TPMRightSection:false, - clickNewsubscripttype:false - } - } - - // componentDidMount() { - // let id=this.props.match.params.shixunId; - // - // let shixunsDetailsURL=`/shixuns/`+id+`/show_right.json`; - // - // axios.get(shixunsDetailsURL).then((response)=> { - // if(response.status===200){ - // this.setState({ - // TPMRightSectionData: response.data - // }); - // } - // }).catch((error)=>{ - // console.log(error) - // }); - // } - - // shouldComponentUpdate(nextProps, nextState) { - // return nextProps.TPMRightSectionData !== this.state.TPMRightSectionData - // } - clickNewsubscript=(val)=>{ - if(val===0){ - this.setState({ - TPMRightSection:true, - clickNewsubscripttype:true - }) - }else{ - this.setState({ - TPMRightSection:false, - clickNewsubscripttype:false - }) - } - - } - render() { - let {TPMRightSection,clickNewsubscripttype}=this.state; - let {TPMRightSectionData}=this.props - - return ( -
    - { - TPMRightSectionData===undefined?"": -
    -
    -

    创建者

    -
    - - 头像 - -
    - -

    {TPMRightSectionData===undefined?"":TPMRightSectionData.creator===undefined?"":TPMRightSectionData.creator.name}

    -
    - 发布 {TPMRightSectionData.user_shixuns_count} - {/*粉丝 {TPMRightSectionData.fans_count}*/} - {/* 取消关注 */} -
    - -
    -
    -
    - { - TPMRightSectionData === undefined ? "" :TPMRightSectionData.tags===undefined?"": TPMRightSectionData.tags.length === 0 ? "" : -
    -

    技能标签 {TPMRightSectionData.tags.length}

    -
    -
    - { TPMRightSectionData.tags.map((item,key)=>{ - return( - {item.tag_name} - )}) - } -
    -
    - - -
    15&&clickNewsubscripttype===false?"newsubscript mb9 color-grey-9":"newsubscript mb9 color-grey-9 none"} - - data-tip-down="显示全部" - onClick={()=>this.clickNewsubscript(0)}>... -
    - - -
    this.clickNewsubscript(1)}> -
    - -
    - - - } - - -
    -

    所属课程

    -
    - { - TPMRightSectionData===undefined?"":TPMRightSectionData.paths===undefined?"":TPMRightSectionData.paths.map((i,k)=>{ - - return( - -
    - - - 实训 - - -
    - {i.name} -

    - - - {i.stages_count} - - - {/**/} - {/*{i.score_count}*/} - {/**/} - - - {i.members_count} - - -

    -
    - -
    - - ) - }) - } -
    -
    - - {TPMRightSectionData === undefined?"":TPMRightSectionData.paths===undefined?"":TPMRightSectionData.paths.length === 0 ? "" : - this.props.user&&this.props.user.main_site===true?
    -

    推荐实训

    -
    - { - TPMRightSectionData===undefined?"":TPMRightSectionData.recommands===undefined?"":TPMRightSectionData.recommands.map((item,key)=>{ - return( -
    - - 69?1526971094 - -
    - - {item.name} - -

    - {item.stu_num} 人学习 -

    -

    {item.level}

    -
    -
    - ) - }) - } -
    -
    :"" - } -
    - } -
    - ) - - - } -} - -export default TPMRightSection; diff --git a/public/react/src/tpm/component/TPMright.css b/public/react/src/tpm/component/TPMright.css deleted file mode 100644 index c664d75c4..000000000 --- a/public/react/src/tpm/component/TPMright.css +++ /dev/null @@ -1,79 +0,0 @@ -/*b新标签*/ -.newedu-filter-btn{ - display: block; - float: left; - padding: 0 9px; - /*height: 28px;*/ - line-height: 28px; - border-radius: 14px; - background-color: #F5F5F5; - color: #666; - margin-right: 10px; - margin-bottom: 9px; -} -.newedbox{ - /*flex-wrap: wrap;*/ - /*display: -webkit-flex; !* Safari *!*/ - /*display: flex;*/ - width: 360px; - position:relative; - overflow: hidden; -} -.newsubscript{ - position: absolute; - right: 23px; - bottom: 16px; - cursor: pointer; -} -.newsubscript:hover{ - color:deepskyblue; -} -.edu-filter-btn29BD8B{ - display: block; - float: left; - padding: 0 9px; - height: 28px; - line-height: 28px; - border-radius: 14px; - background-color: #29BD8B; - color: #FFF; - margin-right: 10px; - margin-bottom: 9px; -} -.relative{ - position:relative; -} -.newedboxheight{ - max-height: 177px; - overflow-y: hidden; -} -.newminheight{ - /*max-height: 670px;*/ - max-height: 300px; - overflow-y: auto; -} - -.delSubentry{ - font-size:7px; - font-family:MicrosoftYaHei; - font-weight:400; - color:rgba(76,172,255,1); - line-height:9px; - cursor: pointer; -} -.operationalter .delSubentry{ - font-size:15px !important; - line-height: 25px; -} -/*临时的tpi关闭按钮样式*/ -.headerRight a { - color: #1a3f5f; -} -/*实训做成弹窗a标签样式调整*/ -.-task-list-title a:link, .-task-list-title a:visited {color: #bcc6cd;} -.-task-list-title a:hover{ - color: #459be5; -} -.headerLeft .-header-right{ - height: 32px; -} \ No newline at end of file diff --git a/public/react/src/tpm/component/modal/RepositoryChooseModal.js b/public/react/src/tpm/component/modal/RepositoryChooseModal.js deleted file mode 100644 index 4b72ae2bd..000000000 --- a/public/react/src/tpm/component/modal/RepositoryChooseModal.js +++ /dev/null @@ -1,153 +0,0 @@ -// import React, { useState, useEffect, memo } from 'react'; -// import axios from 'axios' -// import { Modal, Input } from 'antd'; - -// function RepositoryChooseModal(props) { -// const [trees, setTrees] = useState([]) -// const [path, setPath] = useState('') -// const [pathArray, setPathArray] = useState([{val: "根目录/", path: ""}]) -// const [modalVisible, setModalVisible] = useState(true) - -// useEffect(() => { -// repository('') -// }, []) -// function onOk() { - -// } -// function onCancel() { - -// } -// /** -// 点nav 会传入key -// 点item 会传入 newPath - -// item => name, type type tree/leaf -// */ -// const repository=(item, key, newPath)=>{ -// let newPathArray = [] // -// // -// if (key) { -// for(var i=0; i<=key; i++){ -// newPathArray.push(pathArray[i]) -// } -// } else if (item) { -// newPathArray = pathArray.slice(0) -// newPathArray.push({val: item.name, path: pathArray[pathArray.length - 1] + "/" + item.name}) -// } - -// const path = item || key ? newPathArray[newPathArray.length - 1] : '' - -// let id = props.match.params.shixunId; -// let url ="/shixuns/"+id+"/repository.json"; -// axios.post(url,{ -// path: path -// }).then((response) => { -// if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - -// }else{ -// setTrees(response.data.trees) -// setPath(path) -// pathArray(newPathArray) -// } - -// }).catch((error) => { -// console.log(error) -// }); -// } -// const savegetfilepath=(value)=>{ -// const state = {} -// let {selectpath,saveshixunfilepath,pathtype} = state - -// if(pathtype===1){ -// let newselectpath; - -// if(saveshixunfilepath==="shixunfilepathplay"){ -// newselectpath=value -// }else{ -// const type = selectpath.split(';'); -// let types=false; -// for(var i=0; i{ - -// } -// function sendgetfilepath() { - -// } -// return ( -// -//
    -//
    -// -//
    -// -// saveselectpath(e)} -// value={path}/> -//
    - -// onOk()}>确定 -// onCancel()}>取消 -//
    -//
    -//
    -// ) - -// } - -// export default RepositoryChooseModal \ No newline at end of file diff --git a/public/react/src/tpm/newshixuns/Newshixuns.js b/public/react/src/tpm/newshixuns/Newshixuns.js deleted file mode 100644 index 1eaee9ad6..000000000 --- a/public/react/src/tpm/newshixuns/Newshixuns.js +++ /dev/null @@ -1,1356 +0,0 @@ -import React, {Component} from 'react'; - -import {TPMIndexHOC} from '../TPMIndexHOC'; - -import {SnackbarHOC,appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder'; - -import {Input, Select, Radio, Checkbox, Modal, Icon, DatePicker,Upload,Button,message,Form,notification,Tooltip} from 'antd'; - -// import "antd/dist/antd.css"; - -import locale from 'antd/lib/date-picker/locale/zh_CN'; - -import axios from 'axios'; - -import './css/Newshixuns.css'; - -import {getUrl} from 'educoder' - -import moment from 'moment'; - -let path = getUrl("/editormd/lib/") - -const $ = window.$; - -let timeout; - -let currentValue; - -const Option = Select.Option; - -const RadioGroup = Radio.Group; -const confirm = Modal.confirm; - - -// 处理整点 半点 -// 取传入时间往后的第一个半点 -export function handleDateStrings(dateString) { - if (!dateString) return dateString; - const ar = dateString.split(':') - if (ar[1] == '00' || ar[1] == '30') { - return dateString - } - const miniute = parseInt(ar[1]); - if (miniute < 30 || miniute == 60) { - return [ar[0], '30'].join(':') - } - if (miniute < 60) { - // 加一个小时 - const tempStr = [ar[0], '00'].join(':'); - const format = "YYYY-MM-DD HH:mm"; - const _moment = moment(tempStr, format) - _moment.add(1, 'hours') - return _moment.format(format) - } - - return dateString -} - - - -// 恢复数据 -function md_rec_data(k, mdu, id, editor) { - if (window.sessionStorage.getItem(k + mdu) !== null) { - editor.setValue(window.sessionStorage.getItem(k + mdu)); - md_clear_data(k, mdu, id); - } -} - -// 保存数据 -function md_add_data(k, mdu, d) { - window.sessionStorage.setItem(k + mdu, d); -} - -// 清空保存的数据 -function md_clear_data(k, mdu, id) { - window.sessionStorage.removeItem(k + mdu); - var id1 = "#e_tip_" + id; - var id2 = "#e_tips_" + id; - if (k == 'content') { - $(id2).html(""); - } else { - $(id1).html(""); - } -} - -function md_elocalStorage(editor, mdu, id) { - if (window.sessionStorage) { - var oc = window.sessionStorage.getItem('content' + mdu); - if (oc !== null) { - $("#e_tips_" + id).data('editor', editor); - var h = '您上次有已保存的数据,是否恢复 ? / 不恢复'; - $("#e_tips_" + id).html(h); - } - setInterval(function () { - var d = new Date(); - var h = d.getHours(); - var m = d.getMinutes(); - var s = d.getSeconds(); - h = h < 10 ? '0' + h : h; - m = m < 10 ? '0' + m : m; - s = s < 10 ? '0' + s : s; - if (editor.getValue().trim() != "") { - md_add_data("content", mdu, editor.getValue()); - var id1 = "#e_tip_" + id; - var id2 = "#e_tips_" + id; - - $(id1).html(" 数据已于 " + h + ':' + m + ':' + s + " 保存 "); - $(id2).html(""); - } - }, 10000); - - } else { - $("#e_tip_" + id).after('您的浏览器不支持localStorage.无法开启自动保存草稿服务,请升级浏览器!'); - } -} - - -function create_editorMD(id, width, high, placeholder, imageUrl, callback) { - var editorName = window.editormd(id, { - width: width, - height: high, - path: path, // "/editormd/lib/" - - syncScrolling: "single", - tex: true, - tocm: true, - emoji: true, - taskList: true, - codeFold: true, - searchReplace: true, - htmlDecode: "style,script,iframe", - sequenceDiagram: true, - autoFocus: false, - toolbarIcons: function () { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table", '|', "watch", "clear"] - }, - toolbarCustomIcons: { - testIcon: "
    ", - testIcon1: "
    " - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea: true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity: 0.6, - placeholder: placeholder, - imageUpload: true, - imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL: imageUrl,//url - onload: function () { - // this.previewing(); - $("#" + id + " [type=\"latex\"]").bind("click", function () { - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line - 1, 0); - }); - - $("#" + id + " [type=\"inline\"]").bind("click", function () { - editorName.cm.replaceSelection("`$$$$`"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - md_elocalStorage(editorName, `memoNew_${id}`, "memoNew"); - - callback && callback() - } - }); - return editorName; -} - -function range(start, end) { - const result = []; - for (let i = start; i < end; i++) { - result.push(i); - } - return result; -} -function disabledDateTime() { - return { - // disabledHours: () => range(0, 24).splice(4, 20), - disabledMinutes: () => range(1, 30).concat(range(31, 60)), - // disabledSeconds: () => [0, 60], - }; -} - -function disabledDate(current) { - return current && current < moment().endOf('day').subtract(1, 'days'); -} -class Newshixuns extends Component { - constructor(props) { - super(props) - this.state = { - fileList: [], - newshixunlist: undefined, - departmentslist: undefined, - name: "", - main_type: "", - small_type: "", - trainee: "", - webssh: 0, - use_scope: 0, - can_copy: "", - scope_partment: undefined, - vnc: "", - scopetype: false, - postapplyvisible: false, - sendsure_applyvalue: undefined, - postapplytitle: false, - shixun_nametype: false, - main_types: false, - trainee_types: false, - SelectTheCommandtype: false, - opers: false, - operss: false, - TimePickervalue: "", - opensmail: false, - onSearchvalue: "", - scope_partmenttype: false, - languagewrite: undefined, - systemenvironment:undefined, - testcoderunmode:undefined, - file:undefined, - deleteisnot:true, - languagewritetype:false, - systemenvironmenttype:false, - testcoderunmodetype:false, - attachmentidstype:false, - datalisttype:false, - bottonloading:false - } - } - - initMD(initValue) { - this.contentChanged = false; - const placeholder = ""; - // amp; - // 编辑时要传memoId - const imageUrl = `/api/attachments.json`; - // 创建editorMd - - const taskpass_editormd = create_editorMD("memoMD", '100%', 400, placeholder, imageUrl, () => { - setTimeout(() => { - taskpass_editormd.resize() - taskpass_editormd.cm && taskpass_editormd.cm.refresh() - }, 500) - - if (initValue) { - taskpass_editormd.setValue(initValue) - } - taskpass_editormd.cm.on("change", (_cm, changeObj) => { - // console.log('....contentChanged') - this.contentChanged = true; - }) - }); - this.taskpass_editormd = taskpass_editormd; - window.taskpass_editormd = taskpass_editormd; - - } - - componentDidMount() { - let newshixunUrl = `/shixuns/new.json`; - axios.get(newshixunUrl).then((response) => { - if (response.status === 200) { - if (response.data.message===undefined) { - this.setState({ - newshixunlist: response.data - }); - this.initMD(response.data.sample[0][1]); - } - - } - }).catch((error) => { - console.log(error) - }); - - let departmentsUrl = `/shixuns/departments.json`; - axios.get(departmentsUrl).then((response) => { - if (response.status === 200) { - if (response.data.message===undefined) { - this.setState({ - departmentslist: response.data.shools_name - }); - } - } - }).catch((error) => { - console.log(error) - }); - } - - setlanguagewrite = (e)=>{ - this.setState({ - languagewrite: e.target.value - }) - } - - setsystemenvironment = (e) => { - this.setState({ - systemenvironment: e.target.value - }) - } - settestcoderunmode = (e) => { - this.setState({ - testcoderunmode: e.target.value - }) - - } - shixunname = (e) => { - this.setState({ - name: e.target.value, - shixun_nametype: false - }); - } - - bigClass = (value) => { - this.setState({ - main_type: value - }) - } - - littleClass = (value) => { - this.setState({ - small_type: value - }) - } - - Selectthestudent = (value) => { - this.setState({ - trainee: value - }) - } - - SelectTheCommand = (e) => { - this.setState({ - webssh: e.target.value, - }); - - if (e.target.value === 2) { - this.setState({ - SelectTheCommandtype: true, - multi_webssh: false - }); - } else { - this.setState({ - SelectTheCommandtype: false, - multi_webssh: false - }); - } - } - - Selectpublic = (e) => { - this.setState({ - scopetype: false, - use_scope: e.target.value, - }); - if (e.target.value === 1) { - this.setState({ - scopetype: true - }); - } - - } - - Teacherscopy = (e) => { - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - can_copy: sum, - }); - } - - TeachersUbuntu = (e) => { - let sum = "" - if (e.target.checked === false) { - sum = 0 - } else if (e.target.checked === true) { - sum = 1 - } - this.setState({ - vnc: sum, - }); - } - - adduse_scopeinput = () => { - let {scope_partment} = this.state; - let array = scope_partment; - let newarray = "" - array.push(newarray) - this.setState({ - scope_partment: array, - }); - } - - shixunScopeInput = (e, id) => { - let types=false - let {scope_partment} = this.state; - let datalist = scope_partment; - if (datalist === undefined) { - datalist = [] - } - - datalist.map((item,key)=>{ - if(e===item){ - types=true - this.setState({ - datalisttype:true - }) - return - } - }) - - if(types===false){ - datalist.push(e) - this.setState({ - scope_partment: datalist, - onSearchvalue: "" - }); - } - - - } - - deleteScopeInput = (key) => { - let {scope_partment} = this.state; - let datalist = scope_partment; - datalist.splice(key, 1); - this.setState({ - scope_partment: datalist - }); - } - - //提交数据 - submit_new_shixun = () => { - const mdVal = this.taskpass_editormd.getValue(); - let {can_copy, main_type, name, scope_partment, small_type, trainee, use_scope, vnc, webssh, multi_webssh, TimePickervalue} = this.state; - let Url = `/shixuns.json` - if (name === "") { - this.setState({ - shixun_nametype: true - }) - this.props.showSnackbar("实训名称为空"); - $('html').animate({ - scrollTop: 10 - }, 1000); - return - } - if (main_type === "") { - this.setState({ - main_types: true - }) - $('html').animate({ - scrollTop: 700 - }, 1000); - this.props.showSnackbar("请选择技术平台大类别"); - - return - } - - if (use_scope === 1) { - if (scope_partment === undefined || scope_partment.length === 0) { - this.setState({ - scope_partmenttype: true - }) - $('html').animate({ - scrollTop: 900 - }, 1000); - this.props.showSnackbar("公开程度,指定单位为空"); - return - } - } - if (trainee === "") { - this.setState({ - trainee_types: true - }) - // $('html').animate({ - // scrollTop: 700 - // }, 1000); - this.props.showSnackbar("请选择发布信息"); - return - } - let newmulti_webssh = multi_webssh; - if (newmulti_webssh === true) { - newmulti_webssh = 1 - } else { - newmulti_webssh = "" - } - this.setState({ - bottonloading:true - }) - axios.post(Url, { - name: name, - can_copy: can_copy, - description: mdVal, - main_type: main_type, - scope_partment: scope_partment, - small_type: small_type, - trainee: trainee, - use_scope: use_scope, - vnc: vnc, - webssh: webssh, - multi_webssh: newmulti_webssh, - task_pass: 1, - opening_time: TimePickervalue - } - ).then((response) => { - if (response.status === 200) { - window.location.href = "/shixuns/" + response.data.shixun_identifier + "/challenges"; - // window.open("/shixuns/"+response.data.shixun_identifier+"/challenges"); - }else{ - this.setState({ - bottonloading:false - }) - } - }).catch((error) => { - console.log(error) - this.setState({ - bottonloading:false - }) - }) - } - - - shixunsfetch = (value, callback) => { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - currentValue = value; - - function fake() { - let departmentsUrl = `/shixuns/departments.json?q=` + currentValue; - axios.get(departmentsUrl).then((response) => { - if (response.data.message===undefined) { - callback(response.data.shools_name); - } - }).catch((error) => { - console.log(error) - }); - } - - timeout = setTimeout(fake, 300); - } - - shixunHandleSearch = (value) => { - - this.shixunsfetch(value, departmentslist => this.setState({departmentslist})); - - this.setState({ - onSearchvalue: "" - }) - } - - post_apply = () => { - this.setState({ - postapplyvisible: true - }) - } - sendsure_apply = () => { - let {languagewrite,systemenvironment,testcoderunmode} = this.state; - // console.log("点击确定") - // console.log("languagewrite"+languagewrite); - // console.log("systemenvironment"+systemenvironment); - // console.log("testcoderunmode"+testcoderunmode); - - // let attachment_ids = undefined - // if (this.state.fileList) { - // attachment_ids = this.state.fileList.map(item => { - // return item.response ? item.response.id : item.id - // }) - // } - if(languagewrite === undefined || languagewrite === "" ){ - // this.props.showNotification(`请填写该镜像是基于什么语言`); - this.setState({ - languagewritetype:true - }) - return - } - if(systemenvironment === undefined || systemenvironment === ""){ - // this.props.showNotification(`请填写该镜像是基于什么语言系统环境`); - this.setState({ - systemenvironmenttype:true - }) - return; - - } - if(testcoderunmode === undefined || testcoderunmode === "") { - // this.props.showNotification(`请填写该镜像中测试代码运行方式`); - this.setState({ - testcoderunmodetype:true - }) - return; - } - var attachment_ids=undefined; - if (this.state.fileList) { - attachment_ids = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) - } - - if( attachment_ids === undefined || attachment_ids.length===0){ - - // notification.open( - // { - // message: '提示', - // description: - // '请上传附件!', - // - // } - // ) - this.setState({ - attachmentidstype:true - }) - return; - } - // console.log("attachment_ids"+attachment_ids); - - // alert(languagewrite +" "+systemenvironment +" "+testcoderunmode + " "+attachment_ids); - - var data={ - language:languagewrite, - runtime:systemenvironment, - run_method:testcoderunmode, - attachment_id:attachment_ids[0], - } - var url =`/shixuns/apply_shixun_mirror.json`; - axios.post(url,data - ).then((response) => { - - try { - if (response.data) { - // const { id } = response.data; - // if (id) { - if(this.state.file !== undefined){ - console.log("549"); - // this.deleteAttachment(this.state.file); - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - }else { - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - } - // this.props.showNotification('提交成功!'); - notification.open( - { - message: '提示', - description: - '提交成功!', - - } - ) - this.sendhideModaly() - // this.props.history.push(`/courses/${cid}/graduation_topics`); - // } - } - }catch (e) { - - } - - }) - - } - sendhideModaly = () => { - this.setState({ - postapplyvisible: false, - }) - if(this.state.file !== undefined){ - console.log("580"); - // this.deleteAttachment(this.state.file); - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - }else { - this.setState({ - file:undefined, - deleteisnot:true, - languagewrite:"", - systemenvironment:"", - testcoderunmode:"", - fileList:[] - }) - } - } - sendsure_applyvalues = (e) => { - this.setState({ - sendsure_applyvalue: e.target.value - }) - } - yeshidemodel = () => { - this.setState({ - postapplytitle: false - }) - } - - SelectTheCommandonChange = (e) => { - this.setState({ - multi_webssh: e.target.checked - }) - } - - - bigopen = (e) => { - this.setState({ - opers: true - }) - - } - - bigopens = (e) => { - this.setState({ - opers: false, - operss: false, - opensmail: false - }) - - } - - bigopensmal = (e) => { - this.setState({ - opensmail: true - }) - - } - - sbigopen = (e) => { - this.setState({ - operss: true - }) - - } - - // sbigopens=()=>{ - // this.setState({ - // operss:false - // }) - // } - - onChangeTimePicker = (value, dateString) => { - this.setState({ - TimePickervalue: dateString=== ""?"":moment(handleDateStrings(dateString)) - }) - } - - // 附件相关 START - handleChange = (info) => { - if(info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { - let {fileList} = this.state; - - if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') { - console.log("handleChange1"); - // if(fileList.length===0){ - let fileLists = info.fileList; - this.setState({ - // fileList:appendFileSizeToUploadFileAll(fileList), - fileList: fileLists, - deleteisnot: false - }); - // } - } - } - } - onAttachmentRemove = (file) => { - if(!file.percent || file.percent == 100){ - confirm({ - title: '确定要删除这个附件吗?', - okText: '确定', - cancelText: '取消', - // content: 'Some descriptions', - onOk: () => { - console.log("665") - this.deleteAttachment(file) - }, - onCancel() { - console.log('Cancel'); - }, - }); - return false; - } - - } - deleteAttachment = (file) => { - console.log(file); - let id=file.response ==undefined ? file.id : file.response.id - const url = `/attachments/${id}.json` - axios.delete(url, { - }) - .then((response) => { - if (response.data) { - const { status } = response.data; - if (status == 0) { - // console.log('--- success') - - this.setState((state) => { - - const index = state.fileList.indexOf(file); - const newFileList = state.fileList.slice(); - newFileList.splice(index, 1); - return { - fileList: newFileList, - deleteisnot:true - }; - }); - } - } - }) - .catch(function (error) { - console.log(error); - }); - } - - - handleSubmit=()=>{ - // console.log(this.state.languagewrite) - // console.log(this.state.systemenvironment) - // console.log(this.state.testcoderunmode) - var attachment_ids; - if (this.state.fileList) { - attachment_ids = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) - } - // console.log(attachment_ids); - // var data={ - // language:"", - // runtime:"", - // run_method:"", - // attachment_id:"", - // } - // axios.post(url,data - // ).then((response) => { - // if (response.data) { - // // const { id } = response.data; - // // if (id) { - // this.props.showNotification('提交成功!'); - // // this.props.history.push(`/courses/${cid}/graduation_topics`); - // // } - // } - // }) - - - - } - render() { - const { getFieldDecorator } = this.props.form; - let {testcoderunmode ,systemenvironment,languagewrite,deleteisnot, fileList,TimePickervalue, scope_partmenttype, opensmail, newshixunlist, name, scope_partment, departmentslist, postapplyvisible, sendsure_applyvalue, postapplytitle, shixun_nametype, main_types, trainee_types, SelectTheCommandtype, opers, datalisttype, onSearchvalue} = this.state; - let options - if (departmentslist != undefined) { - options = this.state.departmentslist.map((d, k) => { - return ( - - ) - }) - } - const uploadProps = { - width: 600, - fileList, - multiple: true, - // https://github.com/ant-design/ant-design/issues/15505 - // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // showUploadList: false, - action: `${getUploadActionUrl()}`, - onChange: this.handleChange, - onRemove: this.onAttachmentRemove, - beforeUpload: (file, fileList) => { - - if (this.state.fileList.length >= 1) { - return false - } - // console.log('beforeUpload', file.name); - const isLt150M = file.size / 1024 / 1024 < 50; - if (!isLt150M) { - // this.props.showNotification(`文件大小必须小于50MB`); - notification.open( - { - message: '提示', - description: - '文件大小必须小于50MB', - - } - ) - } - if(this.state.file !== undefined){ - console.log("763") - this.setState({ - file:file - }) - }else { - this.setState({ - file:file - }) - } - - console.log("handleChange2"); - return isLt150M; - }, - } - // const uploadProps = { - // width: 600, - // fileList, - // multiple: true, - // // https://github.com/ant-design/ant-design/issues/15505 - // // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // // showUploadList: false, - // action: `${getUrl()}/api/attachments.json`, - // onChange: this.handleChange, - // onRemove: this.onAttachmentRemove, - // beforeUpload: (file) => { - // // console.log('beforeUpload', file.name); - // const isLt50M = file.size / 1024 / 1024 < 50; - // if (!isLt50M) { - // this.props.showNotification('文件大小必须小于150MB!'); - // } - // return isLt50M; - // }, - // }; - - return ( - -
    -
    -
    - -
    -

    - 创建实训 - {this.props.user&&this.props.user.main_site===true?实训制作指南:""} -

    - -
    -

    实训名称

    -
    - * -
    - - - 必填项 - -
    - -
    -
    - -
    - - -
    - -

    简介

    - -
    -
    - -
    -
    -

    -

    -
    - -
    -

    技术平台

    -
    - * -
    - -

    - 列表中没有? - 申请新建 -

    - - - {/*
    */} -
    -
  • - - -
  • -
    {this.state.languagewritetype===true?"请填写该镜像语言":""}
    -
  • - - -
  • -
    {this.state.systemenvironmenttype===true?"请填写该镜像语言系统环境":""}
    -
  • - - - -
  • -
    {this.state.testcoderunmodetype===true?"请填写该镜像测试代码运行方式":""}
    -
  • - -
    - - - 上传附件 - (单个文件50M以内) - - -
    - -
  • -
    - {this.state.attachmentidstype===true?"请上传附件":""} -
    -
  • - this.sendhideModaly()} - >取消 - -
  • -
    -
    - {/**/} -
    - - - - -
    -

    新建申请已提交,请等待管理员的审核

    -
  • 我们将在1-2个工作日内与您联系 -
  • -
    -
    - 知道啦 -
    -
    -
    -
    -
    - -
    -

    请在配置页面完成后续的评测脚本设置操作

    -
    - 必填项 -
    -
    -
    - - -
    -

    命令行

    -
    - - 无命令行窗口 (选中则不给学员的实践任务提供命令窗口) - 命令行练习窗口 (选中则给学员提供用于练习操作的命令行窗口) - 命令行评测窗口 (选中则给学员提供用于关卡评测的命令行窗口) - - 多个命令行窗口(选中则允许学员同时开启多个命令行窗口) - - -
    -
    - - -
    -

    公开程度

    -
    - - 对所有公开 (选中则所有已被试用授权的用户可以学习) - 对指定单位公开 (选中则下方指定单位的已被试用授权的用户可以学习) - - -
    -
    -
    -
    -
    - -
    - (搜索选中添加单位名称) - {this.state.datalisttype===true?请勿选择重复单位:""} - {/*+ 添加*/} -
    -
    - -
    -
    - { - scope_partment === undefined ? "" : scope_partment.map((item, key) => { - return ( -
  • {item} - this.deleteScopeInput(key)}>× -
  • - ) - }) - } -
    - {/*{*/} - {/*scope_partment===undefined?"":scope_partment.map((item,key)=>{*/} - {/*return(*/} - {/*
    */} - {/*this.deleteScopeInput(key)} style={{ color: 'rgba(0,0,0,.25)' }} />}*/} - {/*value={item}*/} - {/*/>*/} - {/*
    */} - - {/*)*/} - {/*})*/} - {/*}*/} -
    - - - - 请选择需要公开的单位 - -
    -
    -
    -
    - - -
    -

    发布信息

    -
    -
    - *面向学员: -
    - -
    - 实训难易度定位,不限定用户群体 -
    - 必填项 -
    -
    -
    -
  • - 复制: - - -
  • -
    - 开启时间: -
  • - - -
  • -
    -
    - {/*
    */} - {/*

    VNC图形化

    */} - {/*
  • */} - {/**/} - {/**/} - {/*
  • */} - {/*
    */} - - -
    - - 取消 -
    - - -
    -
    -
    - - ); - } -} -const NewshixunsNew = Form.create({ name: 'newshixunsnew' })(Newshixuns); -export default SnackbarHOC()(TPMIndexHOC(NewshixunsNew)); - - - - - - diff --git a/public/react/src/tpm/newshixuns/TPMNewshixuns/TPMNewshixuns.js b/public/react/src/tpm/newshixuns/TPMNewshixuns/TPMNewshixuns.js deleted file mode 100644 index 8b102651f..000000000 --- a/public/react/src/tpm/newshixuns/TPMNewshixuns/TPMNewshixuns.js +++ /dev/null @@ -1,19 +0,0 @@ -import React, { Component } from 'react'; - -import axios from 'axios'; - -export default class TPMNewshixuns extends Component { - constructor(props) { - super(props) - this.state = { - - } - } - render() { - return ( - - ); - } -} - - diff --git a/public/react/src/tpm/newshixuns/css/Newshixuns.css b/public/react/src/tpm/newshixuns/css/Newshixuns.css deleted file mode 100644 index e241dcf0d..000000000 --- a/public/react/src/tpm/newshixuns/css/Newshixuns.css +++ /dev/null @@ -1,397 +0,0 @@ -/* BASICS */ - -.CodeMirror { - /* Set height, width, borders, and global font properties here */ - font-family: monospace; - height: 300px; - color: black; - direction: ltr; -} - -/* PADDING */ - -.CodeMirror-lines { - padding: 4px 0; /* Vertical padding around content */ -} -.CodeMirror pre { - padding: 0 4px; /* Horizontal padding of content */ -} - -.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - background-color: white; /* The little square between H and V scrollbars */ -} - -/* GUTTER */ - -.CodeMirror-gutters { - border-right: 1px solid #ddd; - background-color: #f7f7f7; - white-space: nowrap; -} -.CodeMirror-linenumbers {} -.CodeMirror-linenumber { - padding: 0 3px 0 5px; - min-width: 20px; - text-align: right; - color: #999; - white-space: nowrap; -} - -.CodeMirror-guttermarker { color: black; } -.CodeMirror-guttermarker-subtle { color: #999; } - -/* CURSOR */ - -.CodeMirror-cursor { - border-left: 1px solid black; - border-right: none; - width: 0; -} -/* Shown when moving in bi-directional text */ -.CodeMirror div.CodeMirror-secondarycursor { - border-left: 1px solid silver; -} -.cm-fat-cursor .CodeMirror-cursor { - width: auto; - border: 0 !important; - background: #7e7; -} -.cm-fat-cursor div.CodeMirror-cursors { - z-index: 1; -} -.cm-fat-cursor-mark { - background-color: rgba(20, 255, 20, 0.5); - -webkit-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; -} -.cm-animate-fat-cursor { - width: auto; - border: 0; - -webkit-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; - background-color: #7e7; -} -@-webkit-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} - -/* Can style cursor different in overwrite (non-insert) mode */ -.CodeMirror-overwrite .CodeMirror-cursor {} - -.cm-tab { display: inline-block; text-decoration: inherit; } - -.CodeMirror-rulers { - position: absolute; - left: 0; right: 0; top: -50px; bottom: -20px; - overflow: hidden; -} -.CodeMirror-ruler { - border-left: 1px solid #ccc; - top: 0; bottom: 0; - position: absolute; -} - -/* DEFAULT THEME */ - -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-link {text-decoration: underline;} -.cm-strikethrough {text-decoration: line-through;} - -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} -.cm-s-default .cm-variable, -.cm-s-default .cm-punctuation, -.cm-s-default .cm-property, -.cm-s-default .cm-operator {} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} - -.cm-s-default .cm-error {color: #f00;} -.cm-invalidchar {color: #f00;} - -.CodeMirror-composing { border-bottom: 2px solid; } - -/* Default styles for common addons */ - -div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} -.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } -.CodeMirror-activeline-background {background: #e8f2ff;} - -/* STOP */ - -/* The rest of this file contains styles related to the mechanics of - the editor. You probably shouldn't touch them. */ - -.CodeMirror { - position: relative; - overflow: hidden; - background: white; -} - -.CodeMirror-scroll { - overflow: scroll !important; /* Things will break if this is overridden */ - /* 30px is the magic margin used to hide the element's real scrollbars */ - /* See overflow: hidden in .CodeMirror */ - margin-bottom: -30px; margin-right: -30px; - padding-bottom: 30px; - height: 100%; - outline: none; /* Prevent dragging from highlighting the element */ - position: relative; -} -.CodeMirror-sizer { - position: relative; - border-right: 30px solid transparent; -} - -/* The fake, visible scrollbars. Used to force redraw during scrolling - before actual scrolling happens, thus preventing shaking and - flickering artifacts. */ -.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - position: absolute; - z-index: 6; - display: none; -} -.CodeMirror-vscrollbar { - right: 0; top: 0; - overflow-x: hidden; - overflow-y: scroll; -} -.CodeMirror-hscrollbar { - bottom: 0; left: 0; - overflow-y: hidden; - overflow-x: scroll; -} -.CodeMirror-scrollbar-filler { - right: 0; bottom: 0; -} -.CodeMirror-gutter-filler { - left: 0; bottom: 0; -} - -.CodeMirror-gutters { - position: absolute; left: 0; top: 0; - min-height: 100%; - z-index: 3; -} -.CodeMirror-gutter { - white-space: normal; - height: 100%; - display: inline-block; - vertical-align: top; - margin-bottom: -30px; -} -.CodeMirror-gutter-wrapper { - position: absolute; - z-index: 4; - background: none !important; - border: none !important; -} -.CodeMirror-gutter-background { - position: absolute; - top: 0; bottom: 0; - z-index: 4; -} -.CodeMirror-gutter-elt { - position: absolute; - cursor: default; - z-index: 4; -} -.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } -.CodeMirror-gutter-wrapper ::selection { background-color: transparent } -.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } - -.CodeMirror-lines { - cursor: text; - min-height: 1px; /* prevents collapsing before first draw */ -} -.CodeMirror pre { - /* Reset some styles that the rest of the page might have set */ border-radius: 0; - border-width: 0; - background: transparent; - font-family: inherit; - font-size: inherit; - margin: 0; - white-space: pre; - word-wrap: normal; - line-height: inherit; - color: inherit; - z-index: 2; - position: relative; - overflow: visible; - -webkit-tap-highlight-color: transparent; - -webkit-font-variant-ligatures: contextual; - font-variant-ligatures: contextual; -} -.CodeMirror-wrap pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: normal; -} - -.CodeMirror-linebackground { - position: absolute; - left: 0; right: 0; top: 0; bottom: 0; - z-index: 0; -} - -.CodeMirror-linewidget { - position: relative; - z-index: 2; - padding: 0.1px; /* Force widget margins to stay inside of the container */ -} - -.CodeMirror-widget {} - -.CodeMirror-rtl pre { direction: rtl; } - -.CodeMirror-code { - outline: none; -} - -/* Force content-box sizing for the elements where we expect it */ -.CodeMirror-scroll, -.CodeMirror-sizer, -.CodeMirror-gutter, -.CodeMirror-gutters, -.CodeMirror-linenumber { - -webkit-box-sizing: content-box; - box-sizing: content-box; -} - -.CodeMirror-measure { - position: absolute; - width: 100%; - height: 0; - overflow: hidden; - visibility: hidden; -} - -.CodeMirror-cursor { - position: absolute; - pointer-events: none; -} -.CodeMirror-measure pre { position: static; } - -div.CodeMirror-cursors { - visibility: hidden; - position: relative; - z-index: 3; -} -div.CodeMirror-dragcursors { - visibility: visible; -} - -.CodeMirror-focused div.CodeMirror-cursors { - visibility: visible; -} - -.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } -.CodeMirror-crosshair { cursor: crosshair; } -.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } -.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } -.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } - -.cm-searching { - background-color: #ffa; - background-color: rgba(255, 255, 0, .4); -} - -/* Used to force a border model for a node */ -.cm-force-border { padding-right: .1px; } - -@media print { - /* Hide the cursor when printing */ - .CodeMirror div.CodeMirror-cursors { - visibility: hidden; - } -} - -/* See issue #2901 */ -.cm-tab-wrap-hack:after { content: ''; } - -/* Help users use markselection to safely style text background */ -span.CodeMirror-selectedtext { background: none; } - - - - -.radioStyle{ - display: block; - height: 30px; - } -a.white-btn.use_scope-btn:hover{ - -} -.shixunScopeInput{ - width:218px; - height:33px; - display:block; - margin-bottom:15px; -} - -#memoMD .CodeMirror { - /*width: 576px !important;*/ - margin-top: 31px !important; - height: 364px !important; -} - -#memoMD .editormd-preview { - width: 578px !important; - top: 40px !important; - height: 364px !important; -} - -.ml36{ - margin-left: 26px; -} -#person-unit a.white-btn.use_scope-btn:hover { - border: 1px solid #F06200; - color:#FFF !important; -} - -.shixunspanred{ - margin-left: 142px; - margin-top: 5px; - margin-bottom: 5px; -} - -.ml82{ - margin-left: 82px; -} - -.ant-btn-primary.active, .ant-btn-primary:active { - color: #fff; - background-color: #096dd9; - border-color: #096dd9; -} - -.ant-btn:hover, .ant-btn:focus, .ant-btn:active, .ant-btn.active{ - background-color: #4CACFF; -} \ No newline at end of file diff --git a/public/react/src/tpm/roundedRectangle.png b/public/react/src/tpm/roundedRectangle.png deleted file mode 100755 index 0d2d0b0dc..000000000 Binary files a/public/react/src/tpm/roundedRectangle.png and /dev/null differ diff --git a/public/react/src/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/tpm/shixunchild/Challenges/Challenges.js deleted file mode 100644 index 1470d45db..000000000 --- a/public/react/src/tpm/shixunchild/Challenges/Challenges.js +++ /dev/null @@ -1,676 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import { getImageUrl ,markdownToHTML, configShareForCustom} from 'educoder' - -import { CircularProgress } from 'material-ui/Progress'; - -import { Modal, Spin, Tooltip ,message,Icon} from 'antd'; - -import 'antd/lib/pagination/style/index.css'; - -import '../shixunchildCss/Challenges.css' - -import axios from 'axios'; - -import AccountProfile from"../../../user/AccountProfile"; - -const $ = window.$; - -class Challenges extends Component { - constructor(props) { - super(props) - this.state = { - ChallengesDataList: undefined, - operate: true, - startbtns: false, - sumid: "", - sumidtype: false, - startshixunCombattype:false, - shixunsreplace:false, - shixunsmessage:"", - hidestartshixunsreplacevalue:"", - operationstrue:false, - isSpin:false, - } - } - - ChallengesList = () => { - let id = this.props.match.params.shixunId; - let ChallengesURL = `/shixuns/` + id + `/challenges.json`; - - axios.get(ChallengesURL).then((response) => { - if (response.status === 200) { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - configShareForCustom(this.props.shixunsDetails.name, response.data.description) - this.setState({ - ChallengesDataList: response.data, - sumidtype: false, - }); - } - } - }).catch((error) => { - console.log(error) - }); - } - - componentDidMount() { - setTimeout(this.ChallengesList(), 1000); - } - - updatamakedown = (id) => { - setTimeout(() => { - var shixunDescr = window.editormd.markdownToHTML(id, { - htmlDecode: "style,script,iframe", - taskList: true, - tex: true, - flowChart: true, - sequenceDiagram: true - }); - $("#" + id + " p:first").addClass("ReactMarkdown"); - }, 200) - } - - // 关卡的上移下移操作 - operations = (sumid, type) => { - this.setState({ - operationstrue:true - }) - let { ChallengesDataList } = this.state; - let operationUrl; - if (type === "up") { - operationUrl = "/shixuns/" + ChallengesDataList.shixun_identifier + "/challenges/" + sumid + "/index_up.json"; - } else if (type === "down") { - operationUrl = "/shixuns/" + ChallengesDataList.shixun_identifier + "/challenges/" + sumid + "/index_down.json"; - } - if (this.state.operate) { - - this.setState({ - operate: false - }); - axios.get(operationUrl).then((response) => { - if (response.status === 200) { - this.setState({ - operate: true, - operationstrue:false - }); - this.ChallengesList(); - - } - }).catch((error) => { - console.log(error); - this.setState({ - operate: true, - operationstrue:false - }); - this.ChallengesList() - }) - } - } - delOperations = (sumid) => { - this.setState({ - sumid: sumid, - sumidtype: true - }) - } - - clonedelOperationss = () => { - this.setState({ - sumidtype: false - }) - } - delOperationss = () => { - let { ChallengesDataList, sumid } = this.state; - let operationUrl = "/shixuns/" + ChallengesDataList.shixun_identifier + "/challenges/" + sumid+".json" - - if (this.state.operate) { - this.setState({ - operate: false, - sumidtype: false - }) - axios.delete(operationUrl, { - withCredentials: true - }).then((response) => { - if (response.status === 200) { - this.setState({ - operate: true, - sumidtype: false - }); - this.ChallengesList(); - } - this.ChallengesList() - }).catch((error) => { - console.log(error); - this.setState({ - operate: true, - sumidtype: false - }); - this.ChallengesList() - }) - } - } - - startgameid=(id)=>{ - - let url = "/shixuns/" + id + "/shixun_exec.json"; - axios.get(url).then((response) => { - - if (response.data.status === -2) { - this.setState({ - shixunsreplace:true, - hidestartshixunsreplacevalue:response.data.message+".json" - }) - } else if (response.data.status === -1) { - console.log(response) - }else if(response.data.status===-3){ - this.setState({ - shixunsmessage:response.data.message, - startshixunCombattype:true, - }) - } else { - window.location.href = "/tasks/" + response.data.game_identifier; - // window.location.href = path - // let path="/tasks/"+response.data.game_identifier; - // this.props.history.push(path); - } - }).catch((error) => { - - }); - - - } - - hidestartshixunsreplace=(url)=>{ - this.setState({ - isSpin:true, - }) - axios.get(url).then((response) => { - if(response.status===200){ - // let path="/shixuns/"+response.data.shixun_identifier+"/challenges"; - // this.props.history.push(path); - message.success('重置成功,正在进入实训!'); - this.startgameid(response.data.shixun_identifier); - this.setState({ - shixunsreplace:false, - isSpin:false, - }) - - // message.success('重置成功,正在进入实训!'); - // this.startshixunCombat(); - }} - ).catch((error) => { - - }); - - } - - //编辑实训题目选择题 - EditTraining=(type, ids, path)=>{ - let { ChallengesDataList } = this.state; - window.location.href = "/shixuns/" + ChallengesDataList.shixun_identifier + "/challenges/" + ids + path; - } - - //开始实战按钮 - startshixunCombat = (type, ids, id) => { - - if(this.props.checkIfLogin()===false){ - this.props.showLoginDialog() - return - } - - if(this.props.checkIfProfileCompleted()===false){ - this.setState({ - AccountProfiletype:true - }) - return - } - - // if(this.props.checkIfProfessionalCertification()===false){ - // this.setState({ - // AccountProfiletype:true - // }) - // return - // } - - - let { ChallengesDataList } = this.state; - // let id = this.props.match.params.shixunId; - this.setState({ - startbtns: true - }) - let url = "/shixuns/" + ChallengesDataList.shixun_identifier + "/shixun_exec.json?challenge_id="+id; - axios.get(url).then((response) => { - - if (response.data.status === -2) { - this.setState({ - startbtns:false, - shixunsreplace:true, - hidestartshixunsreplacevalue:response.data.message+".json" - }) - } else if (response.data.status === -1) { - this.setState({ - startbtns: false - }) - console.log(response) - }else if(response.data.status===-3){ - this.setState({ - shixunsmessage:response.data.message, - startshixunCombattype:true, - startbtns:false - }) - } else { - window.location.href = "/tasks/" + response.data.game_identifier; - // window.location.href = path - // let path="/tasks/"+response.data.game_identifier; - // this.props.history.push(path); - } - }).catch((error) => { - - }); - - - // if(path===null){ - // }else{ - // if (type > 4 || type === false) { - // window.location.href = path; - // } else { - // - // } - // } - - - } - hidestartshixunCombattype=()=>{ - this.setState({ - startshixunCombattype:false - }) - } - - hideAccountProfile=()=>{ - this.setState({ - AccountProfiletype:false - }) - } - - render() { - let { ChallengesDataList, startbtns, sumidtype ,startshixunCombattype,shixunsreplace,shixunsmessage,hidestartshixunsreplacevalue,operationstrue,AccountProfiletype} = this.state; - let { loadingContent } = this.props; - if (ChallengesDataList != undefined) { - this.updatamakedown("ReactMarkdown") - } - let id = this.props.match.params.shixunId; - const antIcon = ; - return ( - - {AccountProfiletype===true?this.hideAccountProfile()} - {...this.props} - {...this.state} - />:""} - - {loadingContent ? - : - -
    -

    - {this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status=== 0 ? - - - - 实践任务 - - - : "" - } - {this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status=== 0 ? - - - - 选择题任务 - - : "" - } -

    -

    - 简介 - - - - - - -

    - -
    -

    - {ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"": -

    - } -

    - - {/* - - */} -
    - -

    - 全部任务 - {this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status=== 0 ? - - - - 实践任务 - - - : "" - } - {this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status=== 0 ? - - - - 选择题任务 - - : "" - } -

    - -
    - {ChallengesDataList === undefined ?
    -
    - -

    暂时还没有相关数据哦!

    -
    -
    : ChallengesDataList.challenge_list === undefined ? -
    -
    - -

    暂时还没有相关数据哦!

    -
    -
    - : ChallengesDataList.challenge_list.length === 0 ? -
    -
    - -

    暂时还没有相关数据哦!

    -
    -
    - : ChallengesDataList.challenge_list.map((item, key) => { - - let newstatus = 2; - if(ChallengesDataList.challenge_list[key - 1]!=undefined){ - newstatus=ChallengesDataList.challenge_list[key - 1].status; - } - return ( -
    - -
    - - {item.st === 0 ? - - - - : - - - - } - - 第{key+1}关 - - {this.props.identity<5? - item.st === 1 ? - this.EditTraining(this.props.identity, item.challenge_id, "/editquestion")} - className="font-16 color05101a">{item.name} - : - this.EditTraining(this.props.identity, item.challenge_id, "/editcheckpoint")} - className="font-16 color05101a">{item.name}: this.startshixunCombat(this.props.identity, item.challenge_id, "/editcheckpoint")} - className="font-16 color05101a">{item.name} - } - - - - - - - - {item.delete_url != undefined && - - this.delOperations(item.challenge_id)} - style={{ display:this.props.user.admin===true?"block":this.props.identity < 5 && ChallengesDataList.shixun_status === 0 ? "block" : 'none' }} - className="fl ring-op-green mr25"> - - - - } - - - {item.up_url != undefined && - - this.operations(item.challenge_id, "up")} - style={{ display:this.props.user.admin===true?"block":this.props.identity < 5 && ChallengesDataList.shixun_status === 0 ? "block" : 'none' }} - className="fl ring-op-green mr25"> - - - - } - {item.down_url != undefined && - - this.operations(item.challenge_id, "down")} - style={{ display: this.props.user.admin===true?"block":this.props.identity < 5 && ChallengesDataList.shixun_status=== 0 ? "block" : 'none' }} - className="fl ring-op-green mr25"> - - - - - } - - { - item.st === 1 ? - - - - - - : - - - - - - - } - - -
    -
    - {item.passed_count} 人完成挑战 - {item.playing_count} 人正在挑战 - 完成挑战可获得经验值 {item.score} - - - {/*判断比较复杂 有排第一不能是灰色按钮*/} - {item.status === 2 ? - this.startshixunCombat(false,undefined, item.challenge_id)} - // onClick={() => this.startshixunCombat(false)} - title={"查看挑战关卡"} - >已完成 : "" - } - - { - ChallengesDataList.allow_skip === true && item.status === 1? - this.startshixunCombat(false,undefined, item.challenge_id)} - // onClick={() => this.startshixunCombat(false)} - >直接挑战 : "" - } - - - { - ChallengesDataList.allow_skip === false ? item.status === 1? - - this.startshixunCombat(false,undefined, item.challenge_id)} - style={{marginTop: '-2px'}}>直接挑战 - :"":"" - - } - - - - { - item.status === 0 ? - - this.startshixunCombat(false,undefined, item.challenge_id):""} - style={{marginTop: '-2px'}}>直接挑战 - :"" - } - - - -
    -
    - ) - })} -
    - - - - - - -
    -

    目前该实训项目尚在内测中,将于{shixunsmessage}之后开放,谢谢!

    -
    -
    - {/*取消*/} - 知道了啦 -
    - {/*

    */} - {/*知道了*/} - {/*

    */} -
    - - - -
    -

    实训已经更新了,正在为您重置!

    -
    - -
    -
    -
    - } -
    - - ) - } -} - -export default Challenges; - // { - // ChallengesDataList.allow_skip === false ? item.status === 1 && newstatus === 2 ? - // - // this.startshixunCombat(false,undefined, item.challenge_id)} - // style={{marginTop: '-2px'}}>直接挑战 - // - // - // : item.status === 1 && newstatus === 1 ? - // - // this.startshixunCombat(false,undefined, item.challenge_id)} - // style={{marginTop: '-2px'}}>直接挑战 - // : "" : "" - // - // } \ No newline at end of file diff --git a/public/react/src/tpm/shixunchild/Collaborators/Collaborators.css b/public/react/src/tpm/shixunchild/Collaborators/Collaborators.css deleted file mode 100644 index 31917086f..000000000 --- a/public/react/src/tpm/shixunchild/Collaborators/Collaborators.css +++ /dev/null @@ -1,9 +0,0 @@ -.height40 { - height: 30px; - line-height: 30px; -} - -.line27{ - line-height: 27px; - vertical-align: 1px; -} \ No newline at end of file diff --git a/public/react/src/tpm/shixunchild/Collaborators/Collaborators.js b/public/react/src/tpm/shixunchild/Collaborators/Collaborators.js deleted file mode 100644 index d67599bf1..000000000 --- a/public/react/src/tpm/shixunchild/Collaborators/Collaborators.js +++ /dev/null @@ -1,658 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import {Modal, Button, Radio, Input, Checkbox,message,Spin, Icon} from 'antd'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import { CircularProgress } from 'material-ui/Progress'; - -import { getImageUrl, toPath } from 'educoder' - -import axios from 'axios'; - -import NoneData from "../../../courses/coursesPublic/NoneData"; - -import './Collaborators.css'; - - -const $ = window.$; - -const RadioGroup = Radio.Group; - -const Search = Input.Search; - -class Collaborators extends Component { - constructor(props) { - super(props) - this.state = { - collaboratorList: [], - Collaboratorsvisible: false, - Collaboratorsvisibleadmin: false, - value: 1, - page: 1, - Searchadmin: undefined, - allChangechecked: false, - Collaboratorslist: [], - Collaboratorslisttype: false, - collaborators_deletetype: false, - collaborators_deletevalue: null, - onSearchcalue:"", - collaboratorListsum:10, - collaboratorListsumtype:true, - user_name:undefined, - school_name:undefined, - spinnings:false, - useristrue:false - } - } - componentDidMount() { - let id=this.props.match.params.shixunId; - - let collaborators=`/shixuns/`+id+`/collaborators.json`; - axios.get(collaborators).then((response)=> { - if(response.status===200){ - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - this.setState({ - collaboratorList: response.data - }); - } - - } - }).catch((error)=>{ - console.log(error) - }); - } - - updatacomponentDiddata = () => { - let id = this.props.match.params.shixunId; - - let collaborators = `/shixuns/` + id + `/collaborators.json`; - axios.get(collaborators).then((response) => { - if (response.status === 200) { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - this.setState({ - collaboratorList: response.data - }); - } - } - }).catch((error) => { - console.log(error) - }); - } - CollaboratorsshowModal = (type) => { - - if (type === "cooperation") { - this.setState({ - Collaboratorsvisibleadmin: false, - Collaboratorslist:[], - Searchadmin:[] - }); - } else if (type === "admin") { - this.setState({ - Collaboratorsvisible: false, - Collaboratorslist:[], - Searchadmin:[] - }); - } else if (type === "collaborators_deletetype") { - this.setState({ - collaborators_deletetype: false, - }); - } - } - - showCollaboratorsvisible = (type) => { - - this.setState({ - Collaboratorslist: [], - Searchadmin:undefined, - onSearchcalue:"" - }) - let admintype = this.props.identity; - if (admintype>4) { - this.props.showSnackbar("您没有权限"); - return - } - if (type === "cooperation") { - this.setState({ - Collaboratorsvisibleadmin: true, - }); - } else if ("admin") { - let id = this.props.match.params.shixunId; - let url = "/shixuns/" + id + "/change_manager.json"; - axios.get(url).then((response) => { - if (response.status === 200) { - // this.setState({ - // Collaboratorsvisible: true - // }) - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - this.setState({ - Collaboratorsvisible: true, - Collaboratorslist: response.data - }) - } - } - }).catch((error) => { - console.log(error) - }); - - } - } - - onChange = (e) => { - this.setState({ - value: e.target.value, - }); - } - onSearchadmins=(e)=>{ - this.setState({ - onSearchcalue:e.target.value - }) - } - onSearchadmin = (value) => { - - let {collaboratorList,user_name,school_name} = this.state; - this.setState({ - // Searchadmin: undefined, - spinnings:true, - }) - // if (value === "") { - // this.setState({ - // Searchadmin: [], - // collaboratorList: collaboratorList - // }) - // } else { - // - // } - let id = this.props.match.params.shixunId; - let url = "/shixuns/" + id + "/add_collaborators.json"; - axios.get(url,{params:{ - user_name:user_name , - school_name:school_name, - }}).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - this.setState({ - spinnings:false - }) - }else{ - let newlist = response.data.users; - for (var i = 0; i < newlist.length; i++) { - newlist[i].checked = false - } - this.setState({ - Searchadmin: newlist, - collaboratorList: collaboratorList, - spinnings:false - }) - } - - }).catch((error) => { - console.log(error) - }); - } - - selectChangenickname = (e, key) => { - - let {Searchadmin} = this.state; - let newlist = Searchadmin; - for (var i = 0; i < newlist.length; i++) { - newlist[key].checked = e.target.checked - } - - let arrlist = []; - let alltype = false; - for (var z = 0; z < newlist.length; z++) { - if (newlist[z].checked === true) { - arrlist.push(newlist[z]) - } - } - - if (Searchadmin.length === arrlist.length) { - alltype = true - } else { - alltype = false - } - - if(newlist.length===0){ - this.setState({ - Searchadmin: newlist, - allChangechecked: alltype, - }) - }else{ - this.setState({ - Searchadmin: newlist, - allChangechecked: alltype, - useristrue:false - }) - } - - - } - allChange = (e) => { - - let {Searchadmin} = this.state; - let newlist = Searchadmin; - for (var i = 0; i < newlist.length; i++) { - newlist[i].checked = e.target.checked - } - this.setState({ - Searchadmin: newlist, - allChangechecked: e.target.checked - }) - } - submit_add_collaborators_form = () => { - - let id = this.props.match.params.shixunId; - let {Searchadmin,collaboratorList} = this.state; - let newlist = Searchadmin; - let user_ids = [] - if (newlist.length === 0) { - this.setState({ - Collaboratorslisttype: true - }) - return - } - for (var i = 0; i < newlist.length; i++) { - if (newlist[i].checked === true) { - user_ids.push(newlist[i].user_id) - } - } - - for(var i=0; i { - this.updatacomponentDiddata(); - this.props.showSnackbar(response.data.message); - this.setState({ - Collaboratorsvisibleadmin: false, - Collaboratorslist:[], - Searchadmin:[] - }) - }).catch((error) => { - console.log(error) - }); - } - addadminredio = (e) => { - this.setState({ - addadminrediovalue: e - }) - - } - submit_addadminredio = () => { - - let {addadminrediovalue} = this.state; - - let id = this.props.match.params.shixunId; - - let url = "/shixuns/" + id + "/change_manager.json"; - if(addadminrediovalue===undefined){ - this.setState({ - Collaboratorsvisible: false, - Collaboratorslist:[], - Searchadmin:[] - }); - this.props.showSnackbar("所选人员为空,没有更换成功"); - this.CollaboratorsshowModal("admin") - return - } - - - axios.post(url, { - user_id: addadminrediovalue - }).then((response) => { - this.setState({ - Collaboratorsvisible: false, - Collaboratorslist:[], - Searchadmin:[] - }); - this.updatacomponentDiddata(); - this.props.showSnackbar(response.data.message); - }).catch((error) => { - console.log(error) - }); - } - - collaborators_delete = (value) => { - this.setState({ - collaborators_deletetype: true, - collaborators_deletevalue: value - }) - - } - collaborators_deletes = () => { - let {collaborators_deletevalue} = this.state; - if (collaborators_deletevalue === null) { - return - } - let id = this.props.match.params.shixunId; - let url = "/shixuns/" + id + "/collaborators_delete.json?user_id=" + collaborators_deletevalue; - axios.delete(url).then((response) => { - if (this.props.current_user.user_id == collaborators_deletevalue) { - this.props.history.push('/shixuns') - return; - } - this.props.showSnackbar(response.data.message); - this.updatacomponentDiddata(); - this.setState({ - collaborators_deletetype: false - }) - }).catch((error) => { - console.log(error) - }); - } - - loadMore=()=>{ - let {collaboratorList}=this.state; - this.setState({ - collaboratorListsum:collaboratorList.length, - collaboratorListsumtype:false - }) - } - - - contentViewScrolledit=(e)=>{ - - //滑动到底判断 - let newscrollTop=parseInt(e.currentTarget.scrollTop); - let allclientHeight=e.currentTarget.clientHeight+newscrollTop; - - if(e.currentTarget.scrollHeight-allclientHeight===0||e.currentTarget.scrollHeight-allclientHeight===1||e.currentTarget.scrollHeight-allclientHeight===-1){ - let {page,collaboratorList,user_name,school_name,Searchadmin} = this.state; - let newpage=page+1; - let newSearchadmin=Searchadmin - let id = this.props.match.params.shixunId; - let url = "/shixuns/" + id + "/add_collaborators.json"; - axios.get(url,{params:{ - user_name:user_name , - school_name:school_name, - page:newpage - }}).then((response) => { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - let newlist = response.data.users; - for (var i = 0; i < newlist.length; i++) { - newlist[i].checked = false - newSearchadmin.push(newlist[i]) - } - - this.setState({ - Searchadmin: newSearchadmin, - collaboratorList: collaboratorList, - page:newpage - }) - } - - }).catch((error) => { - console.log(error) - }); - - } - - } - - render() { - let { - collaboratorList, - Collaboratorsvisible, - Collaboratorsvisibleadmin, - Searchadmin, - allChangechecked, - Collaboratorslist, - Collaboratorslisttype, - collaborators_deletetype, - onSearchcalue, - collaboratorListsum, - collaboratorListsumtype, - user_name, - school_name, - useristrue - } = this.state; - let {loadingContent} = this.props; - const radioStyle = { - display: 'block', - height: '30px', - lineHeight: '30px', - }; - - const antIcon = ; - - console.log(Searchadmin) - return ( - -

    - this.showCollaboratorsvisible("cooperation")} - className="edu-default-btn edu-greenback-btn fr mr20 height40" - data-remote="true"> - + 添加合作者 - - this.showCollaboratorsvisible("admin")} - style={{display:this.props.identity===1?"block":"none"}} - data-remote="true" - className="edu-default-btn edu-greenback-btn fr mr20 height40">更换管理员 -

    - - - -
    - 选择的成员将会成为新的管理员
    您将不再拥有管理员的权限,但您仍是合作团队的一员 -
    - - -
    -
      -
    • - - - { - Collaboratorslist.length === 0 ? "" : Collaboratorslist.map((item, key) => { - return ( - this.addadminredio(item.user_id)}>{item.name} - ) - }) - } - - -
    • -
    -
    - - - -
    - - {Collaboratorsvisibleadmin===true? - {/* this.onSearchadmin(value)}*/} - {/*onInput={this.onSearchadmins}*/} - {/*style={{width: '100%'}}*/} - {/*/>*/} - 姓名或手机号: - - {this.setState({user_name: e.target.value})}} - style={{ width: '215px'}} - > - 单位: - {this.setState({school_name: e.target.value})}} - style={{ width: '215px'}} - > - - - this.onSearchadmin()} - style={{ height: '30px', lineHeight: '30px', width: '70px'}} - >搜索 -

    - 姓名 - 职业 - 单位 -

    -
    - -
    -
      - {Searchadmin === undefined ?
    • - 请试试搜索一下 -
    • :Searchadmin.length === 0 ?: Searchadmin.map((item, key) => { - return ( -
    • - this.selectChangenickname(e, key)} - id={item.user_id}> - {item.nickname} - {item.identify} - {item.school_name} -
    • - ) - }) - - } -
    -
    -
    -
    -
    - - - 全选 -
    - 请至少选择一个用户 -
    -
    - - -
    - {useristrue===true?请先选择用户:""} - -
    :""} - -
    - { - collaboratorList===undefined?"":collaboratorList.map((item,key)=>{ - if(key - - 用户头像 -
    -

    - {item.user.name} - - {item.user.shixun_manager === true ? "(管理员)" : ""} -

    - -

    {item.user.identity}{item.user.school_name}

    - -

    - 发布  {item.user.user_shixuns_count} - {/*粉丝  */} - {/*{item.user.fans_count}*/} - {/**/} -

    - - {/*

    {item.user.brief_introduction}

    */} - - -
    - - {item.user.shixun_manager === true ? "" : this.collaborators_delete(item.user.user_id)}>删除} - {/*取消关注*/} -
    - - ) - } - }) - } - -
    -
    确定要删除吗?
    -
    - - -
    - - -
    10&&collaboratorListsumtype===true?"":"none"} - style={{textAlign:'center',borderTop:'1px solid #eee'}}> - 加载更多 -
    - -
    - - ); - } -} - -export default Collaborators; diff --git a/public/react/src/tpm/shixunchild/Propaedeutics/Propaedeu_tics.js b/public/react/src/tpm/shixunchild/Propaedeutics/Propaedeu_tics.js deleted file mode 100644 index f40e9fa63..000000000 --- a/public/react/src/tpm/shixunchild/Propaedeutics/Propaedeu_tics.js +++ /dev/null @@ -1,114 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import { getImageUrl, toPath } from 'educoder'; - -import { Tooltip } from 'antd'; - -import axios from 'axios'; - -import { CircularProgress } from 'material-ui/Progress'; - -const $ = window.$; - -class Propaedeutics extends Component { - constructor(props) { - super(props) - this.state={ - PropaedeuticsListcontent:undefined, - shixunId:undefined - } - } - - componentDidMount() { - let id = this.props.match.params.shixunId; - this.setState({ - shixunId:id - }) - let url="/shixuns/"+id+"/propaedeutics.json"; - axios.get(url).then((response) => { - - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - if(response.data.content!=null){ - this.setState({ - PropaedeuticsListcontent:response.data.content - }) - }else{ - this.setState({ - PropaedeuticsListcontent:"" - }) - } - } - }).catch((error) => { - console.log(error) - }); - - } - - updatamakedown=(id)=>{ - setTimeout(()=>{ - var shixunDescr = window.editormd.markdownToHTML(id, { - htmlDecode: "style,script,iframe", - taskList: true, - tex: true, - flowChart: true, - sequenceDiagram: true - }); - $("#"+id+" p:first").addClass("ReactMarkdown"); - $('#collaborators_list_info').show() - }, 200) - } - render() { - let {loadingContent} = this.props; - let {PropaedeuticsListcontent,shixunId}=this.state - - if(PropaedeuticsListcontent!=undefined){ - this.updatamakedown("ReactMarkdown") - } - - return ( - -

    - - - - -

    - { - loadingContent ? - : -
    - {PropaedeuticsListcontent===undefined?"": -

    - - {PropaedeuticsListcontent === undefined ||PropaedeuticsListcontent === ""? -

    -
    -
    - -

    暂时还没有相关数据哦!

    -
    -
    -
    - :} - -

    - } -
    - } -
    - ); - } -} - -export default Propaedeutics; diff --git a/public/react/src/tpm/shixunchild/Ranking_list/Ranking_list.js b/public/react/src/tpm/shixunchild/Ranking_list/Ranking_list.js deleted file mode 100644 index 0e5d0498b..000000000 --- a/public/react/src/tpm/shixunchild/Ranking_list/Ranking_list.js +++ /dev/null @@ -1,145 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import { getImageUrl, toPath } from 'educoder'; - -import { CircularProgress } from 'material-ui/Progress'; - -import axios from 'axios'; - -const $ = window.$; - -class Ranking_list extends Component { - constructor(props) { - super(props) - this.state = { - Ranking_listData:[] - } - } - - Ranking_listList = (id) => { - let Ranking_listURL = `/shixuns/` + id + `/ranking_list.json`; - axios.get(Ranking_listURL).then((response) => { - if (response.status === 200) { - if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { - - }else{ - this.setState({ - Ranking_listData: response.data - }); - } - } - - }).catch((error) => { - console.log(error) - }); - } - - componentDidMount() { - let id = this.props.match.params.shixunId; - setTimeout(this.Ranking_listList(id), 1000); - } - checkAddZone=(num)=>{ - return num<10 ? '0' + num.toString() : num - } - dateTimeFormatter=(t)=> { - if (!t) return '' - t = new Date(t).getTime() - t = new Date(t) - var year = t.getFullYear() - var month = (t.getMonth() + 1) - month = this.checkAddZone(month) - - var date = t.getDate() - date = this.checkAddZone(date) - - var hour = t.getHours() - hour = this.checkAddZone(hour) - - var min = t.getMinutes() - min = this.checkAddZone(min) - - return year + '-' + month + '-' + date + ' ' + hour + ':' + min - } - - formatSeconds=(value)=> { - var theTime = parseInt(value);// 秒 - var theTime1 = 0;// 分 - var theTime2 = 0;// 小时 - if(theTime > 60) { - theTime1 = parseInt(theTime/60); - theTime = parseInt(theTime%60); - if(theTime1 > 60) { - theTime2 = parseInt(theTime1/60); - theTime1 = parseInt(theTime1%60); - } - } - var result = ""+parseInt(theTime)+"秒"; - if(theTime1 > 0) { - result = ""+parseInt(theTime1)+"分"+result; - } - if(theTime2 > 0) { - result = ""+parseInt(theTime2)+"小时"+result; - } - return result; - } - - render() { - let { Ranking_listData } = this.state; - let { loadingContent } = this.props; - - // console.log(Ranking_listData) - return ( - - { loadingContent ? - : - -
    - {Ranking_listData===undefined||Ranking_listData.length===0? -
    - -

    我们在等你,不轻言放弃

    -
    - :Ranking_listData.map((item,key)=>{ - var keys=key+1 - return( -
    -
  • - - 2?"block":"none"}} - >{key+1} - - 头像 - - - {item.users.name} -
  • - -
  • {this.dateTimeFormatter(item.time)}通关
  • - {/*
  • */} - {/*/!*{item.accuracy} %准确率*!/*/} - {/*
  • */} -
  • {this.formatSeconds(item.use_time)}
  • -
  • +{item.gold}金币
  • -
    - ) - })} -
    - } -
    - - ); - } -} - -export default Ranking_list; diff --git a/public/react/src/tpm/shixunchild/Repository/Repository.js b/public/react/src/tpm/shixunchild/Repository/Repository.js deleted file mode 100644 index c477422e8..000000000 --- a/public/react/src/tpm/shixunchild/Repository/Repository.js +++ /dev/null @@ -1,266 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import axios from 'axios'; - -import { trace, trace_collapse ,getImageUrl, toPath} from "educoder"; - -import RepositoryDirectories from './RepositoryDirectories' - -import { ActionBtn , NoneData } from 'educoder' -import RepositoryCombinePath from './RepositoryCombinePath' -const $ = window.$; - -// 点击按钮复制功能 -function jsCopy(){ - var e = document.getElementById("copy_rep_content"); - e.select(); - document.execCommand("Copy"); -} -/** - 提交记录 - 使用指南 - */ -class Repository extends Component { - constructor(props) { - super(props); - this.state={ - - } - } - componentDidMount() { - } - onRepoFileClick = (item) => { - - this.props.fetchRepo(item) - - } - render() { - let { match, author, git_url, lastest_commit,repositoryLoading, commits,trees,pathArray , TPMRightSectionData } = this.props; - - if (!author) { - author = {} - } - let userauthority=false; - if(this.props.author!=undefined){ - userauthority=this.props.author.login===""||this.props.author.user_id===""||this.props.author.login===null||this.props.author.user_id===null; - } - return ( - - {/* jfinalshop/WebRoot */} - {/*
    - - - 分支 1 - - Git使用指南 -
    */} - - { repositoryLoading ?
    : - -
    -
    -
    -
    -
    - {/*
    - -
    - -
    - - - - */} - - Git使用指南 - { - this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ? - !this.props.secret_repository_tab && - +添加文件 - :"" - } - - - -
    - - - { - jsCopy() - }} data-tip-down="点击复制版本库地址" - className="fl ml5"> - - - - - {/* Git使用指南 */} - - - { $('#repository_url_tip').css('display') === 'none' - ? $('#repository_url_tip').show() - : $('#repository_url_tip').hide() }} - className="fl ml6 mt1"> - - - - -
    -
    - - {this.props.secret_repository_tab && - - } - -
    -
    - - - {/* 用户、最近提交时间 */} - { - trees === undefined || trees === null ||trees.length===0? : -
    - {commits===undefined?"":commits===null||commits.length===0?"":
    - {author.name} - {commits[0].author.name} - 提交于 - - {commits===undefined?"":commits[0].time} - :{commits===undefined?"":commits[0].title} - - - - 提交记录 - -
    } - -
    -
    - {/* 当前目录位置 */} - - -
    - { trees === undefined ?"": trees === null || trees.length===0?"":trees.map((item, index) => { - return ( -
  • - - - this.onRepoFileClick(item)}> -  {item.name} - - -
  • - ) - })} -
    -
    -
    -
    - } - - {/* 当前分支的文件 */} - -
    -
    - } -
    - - ); - } -} -/* - 提交记录 -
    - { RepositoryList===undefined?"":RepositoryList.commits.map((item,key)=>{ - // {"email":"李暾","title":"2\n","id":"80cb6fc55a14bdd64a9c99913f416966238ed3de","time":"49年前"} - return( -
    -
    {item.email}
    -
    {item.title}
    -
    {item.id}
    -
    {item.time}
    -
    - ) - }) } -
    - - - -
  • - - - 1-1.py - -
  • - - - -*/ - -export default Repository; diff --git a/public/react/src/tpm/shixunchild/Repository/RepositoryAddFile.js b/public/react/src/tpm/shixunchild/Repository/RepositoryAddFile.js deleted file mode 100644 index 9ca535bb4..000000000 --- a/public/react/src/tpm/shixunchild/Repository/RepositoryAddFile.js +++ /dev/null @@ -1,198 +0,0 @@ -import React, { Component } from 'react'; -import { ActionBtn } from 'educoder' - -import { Form , Modal , Input , Breadcrumb , Button } from 'antd' - -import { Link } from 'react-router-dom' - -import axios from 'axios' - -/** - ---------------------------- START - */ -function getModeByMirrorName(mirror_name) { - let mode = 'javascript' - if (mirror_name && mirror_name.length) { - for (let i = 0; i < mirror_name.length; i++) { - let modeVal = mirrorNameModeMap[mirror_name[i]]; - if (modeVal) { - mode = modeVal; - break; - } - } - } - return mode; -} -const _extraKeys = {"Alt-/": "autocomplete"}; -function createCMOptions(mirror_name) { - let mode = getModeByMirrorName(mirror_name) - - let cmOptions = { - lineNumbers: true, - mode: mode, - theme: "railscasts", - indentUnit:4, - matchBrackets: true, - autoRefresh: true, - smartIndent: true,//智能换行 - extraKeys: _extraKeys, - autofocus: true, - styleActiveLine: true, - lint: true, - gutters: ["CodeMirror-linenumbers", "breakpoints", "CodeMirror-lint-markers"] - }; - return cmOptions; -} - -const mirrorNameModeMap = { - 'JFinal': 'text/x-java', - 'Java': 'text/x-java', - 'Kotlin': 'text/x-kotlin', - 'C/C++' : 'text/x-c++src', - 'MachineLearning': { - name: "python", - version: 3, - singleLineStringErrors: false - }, - 'Python2.7': { - name: "python", - version: 3, - singleLineStringErrors: false - }, - 'Python3.6': { - name: "python", - version: 3, - singleLineStringErrors: false - }, -} -/** - ---------------------------- END -*/ - -class RepositoryAddFile extends Component { - constructor(props) { - super(props); - } - - componentDidMount(){ - let cmOptions = createCMOptions(this.props.mirror_name) - const extend_editor = window.CodeMirror.fromTextArea(window.$('#codemirror-file-edit')[0] - , cmOptions); - - // tpi没setValue也可以 - extend_editor.setValue('') - extend_editor.refresh(); - - // 拖拽也需要用 : window.editor_CodeMirror.refresh() - window.editor_tempCodeMirror = extend_editor; - this.extend_editor = extend_editor; - } - - checkPath= (rule, value, callback) =>{ - if(!value){ - callback('文件名不能为空'); - }else if (value == "/" || value.indexOf('.') == -1 ) { - callback('请输入正确的文件路径,如:src/HelloWorld.java'); - }else{ - callback(); - } - } - - handleSubmit = () =>{ - this.props.form.validateFieldsAndScroll((err, values) => { - if(!err){ - let shixunId = this.props.match.params.shixunId; - let url = `/shixuns/${shixunId}/add_file.json` - axios.post(url,{ - path:values.path, - message:values.message, - content:this.extend_editor.getValue() - }).then((result)=>{ - if(result){ - this.props.history.push(`${result.data.url}`) - } - }).catch((error)=>{ - console.log(error); - }) - } - }) - } - render(){ - const {getFieldDecorator} = this.props.form; - let { shixunId } = this.props.match.params; - return( -
    - -

    - - 实训项目 - 版本库 - 添加新文件 - -

    -
    -
    - - {getFieldDecorator('path', { - rules: [ - { - validator:this.checkPath - }] - })( - - )} - -
    -
    -

    - -

    - -
    - -
    - - - {getFieldDecorator('message', { - rules: [{required: true, message: "请输入提交信息"}], - })( - - )} - -
    -
    - - 取消 -
    - - -
    - ) - } -} -const WrappedRepositoryAddFile = Form.create({name: 'taskRepositoryAddFile'})(RepositoryAddFile); -// RouteHOC() -export default (WrappedRepositoryAddFile); \ No newline at end of file diff --git a/public/react/src/tpm/shixunchild/Repository/RepositoryCodeEditor.js b/public/react/src/tpm/shixunchild/Repository/RepositoryCodeEditor.js deleted file mode 100644 index 51f6e35f2..000000000 --- a/public/react/src/tpm/shixunchild/Repository/RepositoryCodeEditor.js +++ /dev/null @@ -1,185 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import axios from 'axios'; - -import RepositoryDirectories from './RepositoryDirectories' - -import { trace_collapse } from 'educoder' - -import Popconfirm from 'antd/lib/popconfirm'; -import 'antd/lib/popconfirm/style/css'; - -import { message } from 'antd'; - -require('codemirror/lib/codemirror.css'); - -const $ = window.$; - - -/** - ---------------------------- START - */ -function getModeByMirrorName(mirror_name) { - let mode = 'javascript' - if (mirror_name && mirror_name.length) { - for (let i = 0; i < mirror_name.length; i++) { - let modeVal = mirrorNameModeMap[mirror_name[i]]; - if (modeVal) { - mode = modeVal; - break; - } - } - } - return mode; -} -const _extraKeys = {"Alt-/": "autocomplete"}; -function createCMOptions(mirror_name) { - let mode = getModeByMirrorName(mirror_name) - - let cmOptions = { - lineNumbers: true, - mode: mode, - theme: "railscasts", - indentUnit:4, - matchBrackets: true, - autoRefresh: true, - smartIndent: true,//智能换行 - extraKeys: _extraKeys, - autofocus: true, - styleActiveLine: true, - lint: true, - gutters: ["CodeMirror-linenumbers", "breakpoints", "CodeMirror-lint-markers"] - }; - return cmOptions; -} - -const mirrorNameModeMap = { - 'JFinal': 'text/x-java', - 'Java': 'text/x-java', - 'Kotlin': 'text/x-kotlin', - 'C/C++' : 'text/x-c++src', - 'MachineLearning': { - name: "python", - version: 3, - singleLineStringErrors: false - }, - 'Python2.7': { - name: "python", - version: 3, - singleLineStringErrors: false - }, - 'Python3.6': { - name: "python", - version: 3, - singleLineStringErrors: false - }, -} -/** - ---------------------------- END - */ - -class RepositoryCodeEditor extends Component { - constructor(props) { - super(props) - this.state = { - codeSaving: false - } - } - componentDidUpdate = (prevProps, prevState) => { - - if (this.props.fileContent && this.props.fileContent != prevProps.fileContent) { - // window.setTimeout(() => { - this.extend_editor.setValue(this.props.fileContent) - // }, 2000) - } - } - componentDidMount(){ - let cmOptions = createCMOptions(this.props.mirror_name) - const extend_editor = window.CodeMirror.fromTextArea(window.$('#codemirror-file-edit')[0] - , cmOptions); - - // tpi没setValue也可以 - extend_editor.setValue('') - extend_editor.refresh(); - - // 拖拽也需要用 : window.editor_CodeMirror.refresh() - window.editor_tempCodeMirror = extend_editor; - this.extend_editor = extend_editor; - } - - saveCode = () => { - const { shixunId, pathArray } = this.props; - const url = `/shixuns/${shixunId}/update_file.json` - const path = pathArray.join('/') - this.setState({ codeSaving: true }) - axios.post(url, { - secret_repository: this.props.secret_repository_tab, - content: this.extend_editor.getValue(), - // type: forTest === true ? 1 : 0, - path: path - } - ).then((response) => { - if (response.data.content) { - message.success('保存成功'); - this.setState({ codeSaving: false }) - } - }) - } - render() { - const { fileContent, match, saveCode } = this.props; - const { codeSaving } = this.state; - return ( - - -
    - - -
    -
    -
    -
    - { codeSaving ? - 保存中... - : this.saveCode(this.extend_editor.getValue())} - okText="确定" cancelText="取消"> - {/* onClick={this.saveCode} - onClick={() => saveCode(this.extend_editor.getValue())} - */} - 保存 - } -
    -
    -
    - - -
    - -
    -
    - -
    - - ); - } -} -export default RepositoryCodeEditor; diff --git a/public/react/src/tpm/shixunchild/Repository/RepositoryCombinePath.js b/public/react/src/tpm/shixunchild/Repository/RepositoryCombinePath.js deleted file mode 100644 index aba008e20..000000000 --- a/public/react/src/tpm/shixunchild/Repository/RepositoryCombinePath.js +++ /dev/null @@ -1,82 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import axios from 'axios'; - -import { trace_collapse, WordsBtn } from 'educoder' - -import { message, Input } from 'antd'; - - -const $ = window.$; - - -class RepositoryCombinePath extends Component { - constructor(props) { - super(props) - this.state = { - value: this.props.secret_dir_path || '', - isEdit: false, - } - } - - onSave = () => { - const { shixunId, pathArray } = this.props; - const url = `/shixuns/${shixunId}/set_secret_dir.json` - - this.setState({ codeSaving: true }) - axios.post(url, { - secret_dir_path: this.state.value - } - ).then((response) => { - if (response.data) { - message.success('保存成功'); - this.setState({isEdit: false}) - } - }) - } - onChange = (e) => { - const { value } = e.target; - this.setState({ value }) - } - onEdit = () => { - this.setState({isEdit: true}, () => { - window.$('.combinePathEditRow input')[0].focus() - }); - } - render() { - const { fileContent, match, saveCode } = this.props; - const { isEdit, value } = this.state; - return ( - -
    - - 第一版本库合并路径: - - {!isEdit && 修改} - {isEdit && 保存} -
    - - - ); - } -} -export default RepositoryCombinePath; diff --git a/public/react/src/tpm/shixunchild/Repository/RepositoryDirectories.js b/public/react/src/tpm/shixunchild/Repository/RepositoryDirectories.js deleted file mode 100644 index 7c6eca37a..000000000 --- a/public/react/src/tpm/shixunchild/Repository/RepositoryDirectories.js +++ /dev/null @@ -1,66 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import axios from 'axios'; - -import { trace_collapse } from 'educoder' -const $ = window.$; - - -class RepositoryDirectories extends Component { - constructor(props) { - super(props) - this.state = { - - } - } - componentDidMount() { - } - render() { - const { match, pathArray, fetchRepo - } = this.props; - let { RepositoryList } = this.state; - return ( - - - { pathArray.length !== 0 && -
    - fetchRepo(0)} - > - {match.params.shixunId} - - / - { pathArray.map((item, index) => { - // /shixuns/3ozvy5f8/repository/3ozvy5f8/master/shixun_show/src - return ( - - { this.props.nameTypeMap[item] === 'tree' || item.indexOf('.') === -1 - ? fetchRepo(index + 1)} - className="color-blue"> - {item} - : - - {item} - } - {index !== pathArray.length - 1 && /} - - ) - }) - } -
    } - -
    - - ); - } -} -export default RepositoryDirectories; diff --git a/public/react/src/tpm/shixunchild/Repository/TPMRepositoryCommits.js b/public/react/src/tpm/shixunchild/Repository/TPMRepositoryCommits.js deleted file mode 100644 index 663c5fcf3..000000000 --- a/public/react/src/tpm/shixunchild/Repository/TPMRepositoryCommits.js +++ /dev/null @@ -1,145 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import axios from 'axios'; - -import TPMNav from '../../component/TPMNav' -import TPMRightSection from '../../component/TPMRightSection' -import { CircularProgress } from 'material-ui/Progress'; - -import { trace_collapse } from 'educoder' -const $ = window.$; - -// 点击按钮复制功能 -function jsCopy(){ - var e = document.getElementById("copy_rep_content"); - e.select(); - document.execCommand("Copy"); -} -class TPMRepositoryCommits extends Component { - constructor(props) { - super(props) - this.state = { - RepositoryList: undefined, - } - } - componentDidMount() { - let id = this.props.match.params.shixunId; - - let collaborators=`/shixuns/`+id+`/commits.json`; - axios.post(collaborators, { - secret_repository: this.props.secret_repository_tab - }).then((response)=> { - - if(response.status===200){ - this.setState({ - RepositoryList: response.data - }); - } - trace_collapse('repo commits res', response.data) - - }).catch((error)=>{ - console.log(error) - }); - - } - render() { - const { loadingContent, creator, shixun, myshixun, recommend_shixuns, current_user, watched, - aboutFocus, user, match - } = this.props; - let { RepositoryList } = this.state; - return ( - - -
    - {/* 可能会影响到其他页面的样式,需要测试、协商 */} -
    - - { loadingContent ? - - : - -
    -
    - - 提交记录 - - {/*  35 */} - - 返回 - -
    - - -
    -
      - { RepositoryList === undefined ? "" : RepositoryList.commits.map( (item, key)=>{ - return ( -
    • - {item.email} -

      - {item.title} -

      - {item.time} - -
      -
    • ) - }) - } -
    -
    -
    - } -
    - -
    - -
    -
    - - -
    - - ); - } -} - -/** - { RepositoryList === undefined ? "" : RepositoryList.commits.map( (item, key)=>{ - // {"email":"李暾","title":"2\n","id":"80cb6fc55a14bdd64a9c99913f416966238ed3de","time":"49年前"} - return ( -
    -
    {item.email}
    -
    {item.title}
    -
    {item.id}
    -
    {item.time}
    -
    - ) - }) - */ -export default TPMRepositoryCommits; diff --git a/public/react/src/tpm/shixunchild/ShixunDiscuss/ShixunDiscuss.js b/public/react/src/tpm/shixunchild/ShixunDiscuss/ShixunDiscuss.js deleted file mode 100644 index 4e9470f89..000000000 --- a/public/react/src/tpm/shixunchild/ShixunDiscuss/ShixunDiscuss.js +++ /dev/null @@ -1,170 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import { getImageUrl, toPath } from 'educoder' - -import axios from 'axios'; - -const $ = window.$; - -class ShixunDiscuss extends Component { - constructor(props) { - super(props) - this.state = { - TPMRightSectionData: undefined - } - } - getshixunsDetailsList = (id) => { - let shixunsDetailsURL = `/shixuns/` + id + `/discusses.json`; - axios.get(shixunsDetailsURL).then((response) => { - if (response.status === 200) { - this.setState({ - TPMRightSectionData: response.data - }); - } - }).catch((error) => { - console.log(error) - }); - } - - componentDidMount() { - let id = this.props.match.params.shixunId; - setTimeout(this.getshixunsDetailsList(id), 1000); - } - render() { - let { TPMRightSectionData } = this.state; - - return ( -
    -
    -
    - - - { - TPMRightSectionData===undefined?"":TPMRightSectionData.map((item,key)=>{ - return( -
    -
    - - 用户头像 - -
    - -
    -
    -
    - -
    -
    - {item.user.name} - {item.time} - [第{item.round}关] -
    -
    - -
    -
    -

    {item.content}

    -
    -
    -
    -
    - - { - item.replies.map((i,k)=>{ - return( -
    -
    -
    -
    -
    - {i.user.name} - {i.time} -
    -

    - - - - - - - -

    -
    -
    -
    -
    -

    {i.content}

    -
    -
    -
    -
    -
    -
    - - ) - }) - } - - -

    - - - - - - - - - - - - - - - - - 3 - - -

    - - -
    -
    - - 0?1442652658 - -
    - -
    -
    - -
    -
    调整高度
    - 发送 -
    -
    -
    -
    -
    -
    - ) - }) - } - -
    -
    -
    - ) - } - } - - export default ShixunDiscuss; diff --git a/public/react/src/tpm/shixunchild/Shixunfork_list.js b/public/react/src/tpm/shixunchild/Shixunfork_list.js deleted file mode 100644 index f813441f1..000000000 --- a/public/react/src/tpm/shixunchild/Shixunfork_list.js +++ /dev/null @@ -1,69 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link} from "react-router-dom"; - -import { Switch } from 'antd'; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames' - -import { TPMIndexHOC } from '../TPMIndexHOC' - -import { SnackbarHOC } from 'educoder' - -import ShixunCard from '.././shixuns/ShixunCard'; - -import { Pagination,Row,Col,Rate } from 'antd'; - - import './shixunchildCss/Shixunfork_list.css'; - -import 'antd/lib/rate/style/index.css'; - -const $ = window.$; - -class Shixunforklist extends Component { - constructor(props) { - super(props) - this.state = { - - } - } - - handleChange = (value) => { - console.log('Page: ', value); - // this.setState({ value }); - } - //JSX - render() { - const { match, history } = this.props - - return ( -
    - -
    -
    - Fork实训列表 - 返回 -
    - - - - - - -
    -
    -
      - -
    -
    -
    -
    -
    -
    - ); - } -} -export default SnackbarHOC() (TPMIndexHOC ( Shixunforklist )); diff --git a/public/react/src/tpm/shixunchild/shixunchildCss/Challenges.css b/public/react/src/tpm/shixunchild/shixunchildCss/Challenges.css deleted file mode 100644 index 493a95301..000000000 --- a/public/react/src/tpm/shixunchild/shixunchildCss/Challenges.css +++ /dev/null @@ -1,28 +0,0 @@ -.editormd-html-preview, .editormd-preview-container { - width: 95% !important; -} -.Finish_button{ - height: 30px; - line-height: 30px; - margin-top: -8px; -} -.startbtnModal .ant-modal-content{ - background: transparent; - box-shadow: 0 4px 12px transparent; -} - -.startbtnModal .ant-modal-content .ant-modal-body .ant-spin-spinning{ - margin-left: 45%; -} - -.color05101a{ - color:#05101a; -} - -.mtf3{ - margin-top: -3px; -} -.addshixuns{ - height: 27px; - line-height: 25px; -} \ No newline at end of file diff --git a/public/react/src/tpm/shixunchild/shixunchildCss/Shixunfork_list.css b/public/react/src/tpm/shixunchild/shixunchildCss/Shixunfork_list.css deleted file mode 100644 index d6ef5ebfe..000000000 --- a/public/react/src/tpm/shixunchild/shixunchildCss/Shixunfork_list.css +++ /dev/null @@ -1,6 +0,0 @@ -.ant-rate{ - color: #FFAA05 !important; -} -.ant-pagination-options-quick-jumper input{ - height: 22 !important; -} \ No newline at end of file diff --git a/public/react/src/tpm/shixuns/ShixunCard.js b/public/react/src/tpm/shixuns/ShixunCard.js deleted file mode 100644 index 9f62ed6b7..000000000 --- a/public/react/src/tpm/shixuns/ShixunCard.js +++ /dev/null @@ -1,200 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import { Rating ,Pagination} from "@icedesign/base"; - -import {getImageUrl,setImagesUrl, toPath,getUrl} from 'educoder'; - -import { Spin,Icon,Tooltip ,Rate} from 'antd'; -import LoadingSpin from '../../../common/LoadingSpin'; -import './shixunCss/shixunCard.css'; - -// 引入业务组件样式 - -import axios from 'axios'; - -const $ = window.$; - -class ShixunCard extends Component { - constructor(props) { - super(props) - - this.state = { - startValue:[], - order_by:"", - page:1, - limit:16, - keyword:"", - status:0, - diff:0, - hideme:false, - tag_level:3, - tag_id:'' - } - - } - - PaginationonChange=(pageNumber)=> { - this.props.shixunsPage(pageNumber); - } - - render() { - let {middleshixundata, pagination, typepvisible, pages, totalcount} = this.props; - const MyRate = ({ defaultValue, ...rest }) => { - let myValue = defaultValue; - // console.log(myValue-Math.floor(myValue)) - // if (myValue < Math.ceil(myValue)) { - // myValue = Math.floor(myValue) + 0.5; - // } - - return ; - }; - return ( -
    - - - - { middleshixundata === undefined?"":middleshixundata.length === 0 ?
    - - -

    暂时还没有相关数据哦!

    -
    :""} - - -
    -
    -
    - {middleshixundata === undefined || middleshixundata.length === 0?" ":middleshixundata.map((item,key)=>{ - return( -
    - - { - item.tag_name === null ? "": -
    - {item.tag_name} - {/**/} -
    - } -
    - -

    非试用内容,需要授权

    -
    - - - {/**/} - - - {/*target="_blank"*/} - -
    -

    - - {item.name} - -

    - - {/*target="_blank"*/} - {/**/} -

    - - {/**/} - - - {item.score_info===null?"5分":item.score_info+"分"} -

    - -

    - - - {item.challenges_count} - - - - {/**/} - {/**/} - {/*{item.exp}*/} - {/**/} - {/**/} - - - - {item.stu_num} - - - - {item.level} -

    - -
    -
    - ) - }) - } - -
    - -
    - {/*totalcount*/} -
    - {/**/} - {/* 不加参数请求的时候,没返回总数了。加了个比较大的数字,让他可以翻页 */} - -
    - -
    - -
    -
    -
    - ) - } -} - -export default ShixunCard; diff --git a/public/react/src/tpm/shixuns/ShixunCardList.js b/public/react/src/tpm/shixuns/ShixunCardList.js deleted file mode 100644 index d95ef75fe..000000000 --- a/public/react/src/tpm/shixuns/ShixunCardList.js +++ /dev/null @@ -1,253 +0,0 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route} from "react-router-dom"; - -import { Switch ,Input,Tooltip,Icon} from 'antd'; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames' - -import 'antd/lib/switch/style/index.css' - -import './shixunCss/ShixunCardList.css'; - -import { on, off } from 'educoder' - -const $ = window.$; - -const Search = Input.Search; - -class ShixunCardList extends Component { - - constructor(props) { - super(props); - this.state={ - allevent:"desc", - mine:0, - InputValue: props.keyword || "", - typemy:0, - hots:0, - news:0, - shixunid:"", - upcircle:false, - typekeyid:undefined, - } - } - - componentDidUpdate = (prevProps, prevState) => { - if (this.props.keyword != prevProps.keyword) { - this.setState({ - InputValue: this.props.keyword - }) - } - } - componentDidMount = () => { - on('searchKeywordChange', (event, data) => { - // console.log(data) - this.Input_search(data) - }) - } - componentWillUnmount = () => { - off('searchKeywordChange') - } - - - latestHot=(e,key)=>{ - - let{upcircle,typekeyid}=this.state; - - let id = e.target.id; - $("#"+id).siblings().removeClass("active"); - $("#"+id).addClass("active"); - - let type; - - // if(id==="all"){ - // type="publish_time"; - // } - if(id==="hot"){ - type="hot"; - }else if(id==="new"){ - type="new"; - - } - if(typekeyid===key){ - if(upcircle===true){ - this.setState({ - upcircle:false, - }) - this.props.Shixunsupcircles("desc") - }else if(upcircle===false){ - this.setState({ - upcircle:true, - }) - this.props.Shixunsupcircles("asc") - } - }else{ - this.setState({ - typekeyid:key - }) - } - - //allevent - this.props.ShixunsState(false,type); - } - - - onSwitchChange=(e,key)=>{ - let id=e.target.id - $("#"+id).siblings().removeClass("active"); - $("#"+id).addClass("active"); - let {typemy,upcircle,typekeyid}=this.state; - - if(typekeyid===key){ - if(upcircle===true){ - this.setState({ - upcircle:false, - }) - this.props.Shixunsupcircles("desc") - }else if(upcircle===false){ - this.setState({ - upcircle:true - }) - this.props.Shixunsupcircles("asc") - } - }else{ - this.setState({ - typekeyid:key - }) - } - - - if(typemy===0){ - this.setState({ - typemy:1 - }) - }else{ - this.setState({ - typemy:0 - }) - } - // allevent - this.props.ShixunsSwitch(); - } - //输入框搜索 - Input_search = (value) => { - this.setState({ - InputValue: value - }) - this.props.OnSearchInput(value,true); - } - - Input_searchs = (e) => { - this.setState({ - InputValue: e.target.value - }) - this.props.OnSearchInput(e.target.value,false); - } - upcircles=(val)=>{ - if(val==="asc"){ - this.setState({ - upcircle:false, - }) - this.props.Shixunsupcircles("desc") - }else if(val==="desc"){ - this.setState({ - upcircle:true - }) - this.props.Shixunsupcircles("asc") - } - } - render(){ - let {mine,InputValue,upcircle}=this.state; - return ( -
    -
    - - {/*
    this.latestHot(e,1)}>全部*/} - {/*
    */} - {/*
    this.onSwitchChange(e,2)}>我的*/} - {/*
    */} - -
    this.latestHot(e,4)}>最新 -
    - -
    this.latestHot(e,3)}>最热 -
    - - - {/*
    this.upcircles("asc")}*/} - {/*>*/} - {/**/} - {/**/} - {/*/!**!/*/} - {/**/} - {/*
    */} - {/*
    this.upcircles("desc")}*/} - {/*style={{display:upcircle===true?"none":"block"}}*/} - {/*>*/} - {/**/} - {/**/} - {/*/!**!/*/} - {/**/} - {/*
    */} - - {/*
    */} - {/* this.Input_search(value)}*/} - {/*enterButton*/} - {/*/>*/} - - {/* this.Input_search(value)} - autoComplete="off" - > */} - {/*
    */} - {/*
    */} - {/*{*/} - {/*this.props.search_tags === null ? "" : this.props.search_tags*/} - {/*}*/} - {/*
    */} - {/*/!*
    */} - {/* *!/*/} - {/**/} - {/*
    */} - {/*隐藏我的*/} - - {/*
    */} - {/**/} -
    -
    - ); - } -} - -export default ShixunCardList; diff --git a/public/react/src/tpm/shixuns/ShixunSearchBar.js b/public/react/src/tpm/shixuns/ShixunSearchBar.js deleted file mode 100644 index f9c4a7936..000000000 --- a/public/react/src/tpm/shixuns/ShixunSearchBar.js +++ /dev/null @@ -1,292 +0,0 @@ -import React, { Component } from 'react'; - -import { Select, Input,Menu, Dropdown } from 'antd'; - -import 'antd/lib/style/index.css'; - -import 'antd/lib/select/style/index.css'; - -import 'antd/lib/input/style/index.css'; - -import './shixunCss/ShixunSearchBar.css'; - -import axios from 'axios'; - -const $ = window.$; - -const Option = Select.Option; - -const Search = Input.Search; - - -class ShixunSearchBar extends Component { - - constructor(props) { - super(props) - this.state = { - status: undefined, - diff: 0, - InputValue: undefined, - shixunhoverData: [], - shixunchildValues:'', - shixunsearchAllvalue:"a", - openStatus:false, - openLevel:false - } -} - - //状态筛选 - status_search = (value) => { - let newvalue = value; - if (newvalue === "0") { - newvalue = " " - } else if (newvalue === "1") { - newvalue = 2 - } else if (newvalue === "2") { - newvalue = 1 - } else if (newvalue === "3") { - newvalue = 3 - } - - this.setState({ - status: newvalue, - openStatus:false - }) - let list = [{'type': 1}, {'value': newvalue}]; - this.props.StatusEnquiry(list); -} - - //难度筛选 -diff_search = (value) => { - this.setState({ - diff: value, - openLevel:false - }) - let list=[{'type':2},{'value':value}]; - this.props.StatusEnquiry(list); -} - - //输入框搜索 -Input_search = (value) => { - this.setState({ - InputValue: value - }) - this.props.OnSearchInput(value); -} - //查询 -shixunsearchAll = (e) => { - let{shixunsearchAllvalue}=this.state; - let id = e.target.value; - - if(shixunsearchAllvalue===id){ - return - } - if(id===0){ - id=" " - this.setState({ - InputValue: " " - }) - this.props.OnSearchInput(""); - } - let list=[{'tag_level':1},{'tag_id':id}]; - if(id!=undefined){ - this.setState({ - shixunsearchAllvalue:id, - shixunchildValues:"" - }) - this.props.Updatasearchlist(list); - } - -} - - shixunsearchall=(e)=>{ - let{shixunsearchAllvalue}=this.state; - let id = "a"; - - if(shixunsearchAllvalue===id){ - return - } - this.setState({ - shixunsearchAllvalue:"a", - shixunchildValues:"" - }) - this.props.allUpdatashixunlist(); - } - - //选择Tab页详情 - getshixunchildValue = (e) => { - - debugger - let id = e.target.name; - let newid=e.target.id; - let list=[{'tag_level':2},{'tag_id':id}]; - if(id!=undefined||newid!=undefined){ - this.setState({ - shixunsearchAllvalue:newid - }) - this.props.Updatasearchlist(list); - } - } - -getshixunchildValues = (e) => { - let id = e.target.id; - let newid=e.target.name; - let list=[{'tag_level':3},{'tag_id':id}]; - if(id!=undefined||newid!=undefined){ - this.setState({ - shixunchildValues:id, - shixunsearchAllvalue:newid - }) - this.props.Updatasearchlist(list); - } - -} - -componentDidMount() { - let hoverUrlArr = []; - let hoverUrl = `/shixuns/menus.json`; - axios.get(hoverUrl - ).then((response) => { - hoverUrlArr = response.data; - // hoverUrlArr.reverse(); - this.setState({ - shixunhoverData: hoverUrlArr - }) - }).catch((error) => { - console.log(error) - }) -} - -render() { - let {shixunhoverData, shixunchildValues, shixunsearchAllvalue, InputValue,openStatus,openLevel} = this.state; - let {typepvisible} = this.props; - // //实训首页筛选的移入和点击事件 - // $(".shaiItem").hover(function(){ - // var hei=parseInt($(".shaiAllItem").height())-2; - // $(this).find(".subshaicontent").css("top", '34px'); - // $(this).find(".subshaicontent").show(); - // },function(){ - // $(this).find(".subshaicontent").hide(); - // }); - // - // $(".shaiItem").live("click",function(){ - // $(".shaiItem").removeClass("active"); - // $(this).addClass("active"); - // $(".subshaicontent").hide(); - // }); - // - // $(".subshaicontent").live("click", function(event){ - // $(".subshaicontent").hide(); - // event.stopPropagation(); - // }); - - let overlaymenu=(item,id)=>( - - { - item.map((list,k)=>{ - return( - -
    - {list.name} -
    - { - list.tags.map((tag,e)=>{ - return( - {tag.name} - ) - }) - } -
    -
    -
    - ) - }) - } -
    - ) - - return ( -
    -
    -
    -
    - 方向: -
    -
  • 全部
  • - - { - shixunhoverData.map((item,key)=>{ - return( - -
  • - {item.name} -
  • -
    - ) - }) - } - - -
    -
    -
    - 筛选: - { - - } -
    -
  • this.diff_search(0)}>全部难度
  • -
  • this.diff_search(1)}>初级学员
  • -
  • this.diff_search(2)}>中级学员
  • -
  • this.diff_search(3)}>高级学员
  • -
  • this.diff_search(4)}>顶级学员
  • -
    - -
    -
    -
    -
    - ); -} -} - -export default ShixunSearchBar; diff --git a/public/react/src/tpm/shixuns/ShixunsIndex.js b/public/react/src/tpm/shixuns/ShixunsIndex.js deleted file mode 100644 index 15579610d..000000000 --- a/public/react/src/tpm/shixuns/ShixunsIndex.js +++ /dev/null @@ -1,422 +0,0 @@ -import React, { Component } from 'react'; - -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import axios from 'axios'; - -import { Spin } from 'antd'; - -import { TPMIndexHOC } from '../TPMIndexHOC'; - -import { SnackbarHOC } from 'educoder'; - -import ShixunCardList from './ShixunCardList'; - -import ShixunSearchBar from './ShixunSearchBar'; - -import ShixunCard from './ShixunCard'; - -import UpgradeModals from '../../modals/UpgradeModals'; - -const queryString = require('query-string'); - -const $ = window.$; - -class ShixunsIndex extends Component { - constructor(props) { - super(props) - this.state={ - order_by: "new", - page:1, - limit:16, - keyword:"", - status:0, - diff:0, - tag_level: 1, - tag_id:'', - middleshixundata:[], - typepvisible:true, - pages:1, - search_tags:null, - parsedid:undefined, - newtag_level:undefined, - newpalce:undefined, - sort:"desc" - } - } - componentDidMount(){ - - const upsystem=`/users/system_update.json`; - axios.get(upsystem).then((response)=>{ - let updata=response.data; - this.setState({ - updata:updata - }) - }).catch((error)=>{ - console.log(error); - }) - - - - let _keyword; - if (window.__headSearchKeyword) { - this.setState({ keyword: window.__headSearchKeyword }) - _keyword = window.__headSearchKeyword - delete window.__headSearchKeyword - } - const parsed = queryString.parse(this.props.location.search); - if(parsed.id===undefined&&parsed.type===undefined){ - let {order_by, tag_level, tag_id, page, limit, keyword, status, diff} = this.state; - let params={ - order_by:order_by, - tag_level:tag_level, - tag_id:tag_id, - page:page, - limit:limit, - keyword: _keyword || keyword , - status:status, - diff:diff, - sort: "desc" - } - this.shixunresultend(params); - }else{ - let {order_by,page, limit, keyword, status, diff} = this.state; - let nawparsed=parsed.type; - let newpalce=parsed.palce; - if(nawparsed==="rep"){ - nawparsed=1 - } - else if(nawparsed==="sub"){ - nawparsed=2 - }else if(nawparsed==="tag"){ - nawparsed=3 - } - let params={ - order_by:order_by, - tag_level:nawparsed, - tag_id:parsed.id, - page:page, - limit:limit, - keyword: _keyword || keyword, - status:status, - diff:diff, - sort: "desc" - } - this.setState({ - parsedid:parsed.id, - newtag_level:nawparsed, - newpalce:newpalce - }) - this.shixunresultend(params); - } - - } - - allUpdatashixunlist=()=>{ - let{sort,order_by}=this.state; - - this.setState({ - tag_level: 1, - tag_id:'', - page: 1, - limit: 16, - keyword:'', - status: 0, - diff: 0, - }) - - let params={ - order_by:order_by, - tag_level: 1, - tag_id:'', - page: 1, - limit: 16, - keyword:'', - status: 0, - diff: 0, - sort:sort - } - this.shixunresultend(params) - } - Updatasearchlist=(value)=>{ - if (value[1].tag_id === " ") { - this.setState({ - keyword: "" - }) - } - this.setState({ - tag_level:value[0].tag_level, - tag_id:value[1].tag_id, - typepvisible:true - }) - - let {order_by, sort, limit, keyword, status, diff} = this.state; - - let params={ - order_by:order_by, - tag_level:value[0].tag_level, - tag_id:value[1].tag_id, - page:1, - limit:limit, - keyword:keyword, - status:status, - diff:diff, - sort:sort - } - - this.shixunresultend(params) - } - - StatusEnquiry=(key)=>{ - - let Vrl=`/shixuns.json`; - let newstatus; - let newdiff; - if(key[0].type===1){ - this.setState({ - status: key[1].value, - typepvisible:true - }) - newstatus=key[1].value; - newdiff=this.state.diff; - }else if(key[0].type===2){ - this.setState({ - diff: key[1].value, - typepvisible:true - }) - newdiff=key[1].value; - newstatus=this.state.status; - } - let params= { - order_by:this.state.order_by, - tag_level:this.state.tag_level, - tag_id:this.state.tag_id, - page:1, - limit:this.state.limit, - keyword:this.state.keyword, - status:newstatus, - diff:newdiff, - } - this.shixunresultend(params) - - } - - OnSearchInput=(value,type)=>{ - if(type===true){ - this.setState({ - keyword:value, - typepvisible:true, - pages:1 - }) - let {order_by, tag_level, tag_id, sort, limit, status, diff} = this.state; - let params= { - order_by:order_by, - tag_level:tag_level, - tag_id:tag_id, - page:1, - limit:limit, - keyword:value, - status:status, - diff:diff, - sort:sort - } - this.shixunresultend(params) - }else{ - this.setState({ - keyword:value, - pages:1 - }) - } - - - } - - ShixunsSwitch=()=>{ - //types - this.setState({ - order_by:"mine", - typepvisible:true, - pages:1, - }) - let{tag_level,tag_id,page,limit,keyword,status,diff,sort}=this.state; - let newsort=sort; - if(newsort===undefined){ - newsort="desc" - } - let params= { - order_by:"mine", - tag_level:tag_level, - tag_id:tag_id, - page:1, - limit:limit, - keyword:keyword, - status:status, - diff:diff, - sort:newsort - } - this.shixunresultend(params) - } - - - shixunsPage=(value)=>{ - this.setState({ - page:value, - typepvisible:true, - pages:value - }) - let {order_by, tag_level, tag_id, limit, keyword, status, diff,sort} = this.state; - let params= { - order_by:order_by, - tag_level:tag_level, - tag_id:tag_id, - page:value, - limit:limit, - keyword:keyword, - status:status, - diff:diff, - sort:sort - } - - let Url=`/shixuns.json`; - axios.get(Url,{ - params - }).then((response)=> { - if(response.status===200){ - this.setState({ - middleshixundata: response.data, - typepvisible:false, - }); - } - }).catch((error)=>{ - console.log(error) - }); - } - ShixunsState=(val,type)=>{ - // sort, - let {tag_level, tag_id, page, limit, keyword, status, diff,sort} = this.state; - let newsort=sort; - this.setState({ - order_by:type, - typepvisible:true, - pages:1, - // sort:sort - }) - - let params - // let vals=false - if(newsort===undefined){ - newsort="desc" - } - params= { - order_by:type, - tag_level:tag_level, - tag_id:tag_id, - page:1, - limit:limit, - keyword:keyword, - status:status, - diff:diff, - sort:newsort - } - this.shixunresultend(params) - } - - Shixunsupcircles=(sort)=>{ - console.log(sort) - this.setState({ - sort:sort - }) - let { - order_by, - tag_level, - tag_id, - limit, - keyword, - status, - diff, - } = this.state; - - - - let params= { - order_by:order_by, - tag_level:tag_level, - tag_id:tag_id, - page:1, - limit:limit, - keyword:keyword, - status:status, - diff:diff, - sort:sort - } - this.shixunresultend(params) - } - - - - - shixunresultend=(params)=>{ - let Url=`/shixuns.json`; - axios.get(Url,{ - params - }).then((response)=> { - // TODO 有keyword返回值时 显示一共有多少条记录 - if(response.status===200){ - this.setState({ - search_tags:response.data.search_tags, - middleshixundata: response.data, - typepvisible:false, - pages:1 - }); - } - }).catch((error)=>{ - console.log(error) - }); - } - render() { - let {middleshixundata, typepvisible, pages, search_tags, keyword,parsedid,newtag_level,newpalce} = this.state; - - // console.log(this.state.updata) - return ( -
    - {this.state.updata===undefined?"":} - {/**/} - - - - - - {/**/} -
    - ); - } -} - -export default SnackbarHOC() (TPMIndexHOC ( ShixunsIndex )); diff --git a/public/react/src/tpm/shixuns/css/TPMBanner.css b/public/react/src/tpm/shixuns/css/TPMBanner.css deleted file mode 100644 index fe059fccd..000000000 --- a/public/react/src/tpm/shixuns/css/TPMBanner.css +++ /dev/null @@ -1,114 +0,0 @@ -.shixunsdiffcult{ - width: 40px; - height: 21px; - overflow: hidden; - margin-left: 8px; - } - - .rateYo{ - text-align: center; - cursor: default; - width: 111px; - } - - a:link, a:visited { - color: #05101a; -} - -a:link{text-decoration:none;} - -a:visited{text-decoration:none;} - -a:hover{text-decoration:none;} - -a:active{text-decoration:none;} - - -.next-rating-overlay .next-icon{ - color: #FFA800!important; -} - -.displayblock{ - display:block; - text-align: center; - margin-bottom: 20px; -} - -.totalScore{ - justify-content: center; - align-items: center; - display: -webkit-flex; - height: 100%; -} - -.next-progress-line{ - width: 210px !important; - margin-left: 10px; - margin-top: 4px; -} - -.next-progress-line-overlay-normal{ - background-color: #FFA800 !important; -} -.next-rating-base-disabled{ - cursor: default!important; -} -/*#challenge_begin {*/ -/*!*height: 40px !important;*!*/ -/*line-height: 30px;*/ -/*}*/ -.ant-modal-title{ - font-size: 16px; - font-weight: bold !important; - color: #333; -} - -.ml60{ - margin-left:20px; -} - -.marginauto{ - margin:0 auto; -} -.margin152{ - margin-left: 152px; -} - -.margin-tp26{ - margin-top: -26px; -} -.edu-h315{ - height:315px; -} - -.height39 { - height: 39px !important; -} - -#commentsStar{ - margin-top: -7px; - width: 90px; - height: 80px; -} - -.startbtnModal .ant-modal-content{ - background: transparent; - box-shadow: 0 4px 12px transparent; -} - -.startbtnModal .ant-modal-content .ant-modal-body .ant-spin-spinning{ - margin-left: 45%; -} - -.mr51{ - margin-right:51px; -} - -.flexbannerright{ - display: flex; - justify-content: flex-end; -} - -.width360{ - width:360px; -} \ No newline at end of file diff --git a/public/react/src/tpm/shixuns/shixunCss/ShixunCardList.css b/public/react/src/tpm/shixuns/shixunCss/ShixunCardList.css deleted file mode 100644 index c806434f5..000000000 --- a/public/react/src/tpm/shixuns/shixunCss/ShixunCardList.css +++ /dev/null @@ -1,13 +0,0 @@ -#myshixuns_count{ - text-decoration:none !important; -} -#created_at{ - text-decoration:none !important; -} -.shixun_repertoire{ - cursor: pointer ; -} -.next-btn-medium:hover{ - color: #4CACFF; - border:1px solid #4CACFF; -} \ No newline at end of file diff --git a/public/react/src/tpm/shixuns/shixunCss/ShixunSearchBar.css b/public/react/src/tpm/shixuns/shixunCss/ShixunSearchBar.css deleted file mode 100644 index 9fba271ce..000000000 --- a/public/react/src/tpm/shixuns/shixunCss/ShixunSearchBar.css +++ /dev/null @@ -1,20 +0,0 @@ -.iconfontShixunSearchBar{ - z-index: 1000; - position: absolute; - right: 3px; - top: 0px; -} - -.diffSelect{ - margin-left:20px !important; - } - .ant-input-search-button{ - /*margin-right: 10px;*/ - border: 1px solid transparent; - } -.Mousebox{ - width: 800px !important; -} -.subshaicontent a{ - height:30px; -} \ No newline at end of file diff --git a/public/react/src/tpm/shixuns/shixunCss/shixunCard.css b/public/react/src/tpm/shixuns/shixunCss/shixunCard.css deleted file mode 100644 index 1ec00a26e..000000000 --- a/public/react/src/tpm/shixuns/shixunCss/shixunCard.css +++ /dev/null @@ -1,42 +0,0 @@ -.ml350 { - margin-left: 40%; -} - -.ml32 { - margin-left: 32%; -} - -.square-img{ - min-height: 210px; -} -.task-hide{ - margin-bottom: 0em; -} -.backFAFAFA{ - background:#FAFAFA; -} - -.demo { - width: 500px; - background-color: #0dcecb; - text-align: center; - padding:50px; -} -.next-loading { - margin-bottom: 5px; - width:100%; -} - -.next-rating-overlay .next-icon{ - color: #FFA800!important; -} - -.custom-pagination { - display: inline-block; - margin-left: 10px; -} - -.ml425{ - margin-left:42.5%; - margin-top:20px; -} \ No newline at end of file diff --git a/public/react/src/tpm/shixuns/shixunCss/tag2.png b/public/react/src/tpm/shixuns/shixunCss/tag2.png deleted file mode 100644 index 423d2f7e3..000000000 Binary files a/public/react/src/tpm/shixuns/shixunCss/tag2.png and /dev/null differ diff --git a/public/react/src/tpm/shixuns/shixusFunction/ShixunSearchBar.js b/public/react/src/tpm/shixuns/shixusFunction/ShixunSearchBar.js deleted file mode 100644 index 4211e3196..000000000 --- a/public/react/src/tpm/shixuns/shixusFunction/ShixunSearchBar.js +++ /dev/null @@ -1,142 +0,0 @@ -const $ = window.$; - - -$(function(){ - //实训首页筛选的移入和点击事件 - $(".shaiItem").hover(function(){ - var hei=parseInt($(".shaiAllItem").height())-2; - $(this).find(".subshaicontent").css("top",hei); - $(this).find(".subshaicontent").show(); - },function(){ - $(this).find(".subshaicontent").hide(); - }); - - $(".shaiItem").live("click",function(){ - $(".shaiItem").removeClass("active"); - $(this).addClass("active"); - $(".subshaicontent").hide(); - }); - - $(".subshaicontent").live("click", function(event){ - $(".subshaicontent").hide(); - event.stopPropagation(); - }); - - //最新、最热 - $(".bestChoose").click(function(){ - $(".bestChoose").removeClass("active"); - $(this).addClass("active"); - }) - - //实训路径选择导航条 - $(".path-nav li a").live("click",function(){ - $(".path-nav li").removeClass("active"); - $(this).parent().addClass("active"); - }) -}); - -//隐藏我的学习 - function clickControl(item, type){ - var wid=$(item).width(); - var wid1=$(".controlring").width(); - var hidden_course = 1; - if($(".controlring").css("left")=="1px"){ - $(".controlring").animate({left:parseInt(wid-wid1-1)+"px"}); - $(".controlblue").animate({width:wid+"px"}); - $("input[name='hidden_learn']").val('1'); - }else{ - $(".controlring").animate({left:"1px"}); - $(".controlblue").animate({width:"0px"}); - $("input[name='hidden_learn']").val(''); - hidden_course = 0; - } - if(type == "l_shixun"){ - $("#shixun_search_condition").submit(); - } else{ - $.get("/courses?select="+$("#select_type").val()+"&order="+$("#select_order").val()+"&hidden="+hidden_course); - } -} - -// 清空条件 - function clear_style(){ - $("#shixun_search_condition").find('input[type=hidden]').each(function() { - $(this).val(''); - }); -} - -// 精选实训的搜索 #type参数( status:实训状态; diff:实训难度; search:实训搜索; order:最新最热排序) -function filter_search(values, type){ - switch(type){ - case "status": - $("input[name='status']").val(values); - break; - case "diff": - $("input[name='diff']").val(values); - break; - case "search": - $("input[name='search']").val(values); - break; - } - $("#shixun_search_condition").submit(); -} - -// 点击实训体系名称 # type参数(rep:体系大类别; sub:体系子类别; tags 实训标签; order: 排序) -// # name参数: 列表显示使用 -// # values参数: 赋值给表单的值 -$(".shixun_repertoire").live("click", function(event){ - var type = $(this).attr("data-type"); - var name = $(this).attr("data-name"); - var values = $(this).attr("data-values"); - if(type != 'order'){ - $(".subshaicontent a").removeClass("active"); - $(".shaiItem").removeClass("active"); - $("input[name='repertoire'], input[name='sub_repertoire'], input[name='tag_repertoire']").val(''); - } - $(this).closest(".shaiItem").addClass("active"); - $(".subshaicontent").hide(); - $("#search_name").html(name); - - switch(type){ - case "rep": - $("input[name='repertoire']").val(values); - $("#shixun_search_input").val(""); - $("input[name='search']").val(""); - break; - case "sub": - $("input[name='sub_repertoire']").val(values); - break; - case "tag": - $("input[name='tag_repertoire']").val(values); - break; - case "order": - var $sort = $("input[name='sort']"); - var oldValue = $("input[name='order']").val(); - $("input[name='order']").val(values); - var newValue = $("input[name='order']").val(); - if(oldValue != newValue){ - $("input[name='sort']").val("desc"); - }else { - if($sort.val() == "desc"){ - $sort.val("asc"); - }else{ - $sort.val("desc"); - } - } - break; - } - $(this).addClass("active"); // 因为order需要判断样式因此写在switch之后 - $("#shixun_search_condition").submit(); - event.stopPropagation(); -}); - - -// 实训首页回车搜索 -$("#shixun_search_input").live("keyup", function(e){ - // 兼容FF和IE和Opera - var theEvent = e || window.event; - var code = theEvent.keyCode || theEvent.which || theEvent.charCode; - if (code == 13) { - //回车执行查询 - filter_search($(this).val(), "search"); - } -}); \ No newline at end of file diff --git a/public/stylesheets/educoder/edu-all.css b/public/stylesheets/educoder/edu-all.css index 6fcbd3b5c..5eca4c649 100644 --- a/public/stylesheets/educoder/edu-all.css +++ b/public/stylesheets/educoder/edu-all.css @@ -3795,3 +3795,7 @@ a.singlepublishtwo{ .fontweightbold{ font-weight: bold !important; } + +.ant-drawer{ + z-index: 10000 !important; +} \ No newline at end of file
    ID序号ID 实训名称 技术平台 权限技术体系上传图片小程序封面技术体系上传图片小程序封面 创建者 关闭 复制 操作
    - ssh/隐藏/首页/跳关/隐藏目录 + ssh/隐藏/首页/跳关/隐藏目录/vip
    <%= page_no %> <%= shixun.identifier %> @@ -47,6 +48,7 @@ <%= check_box_tag :homepage_show,!shixun.homepage_show,shixun.homepage_show,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form",title:"首页" %> <%= check_box_tag :task_pass,!shixun.task_pass,shixun.task_pass,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"跳关"%> <%= check_box_tag :code_hidden,!shixun.code_hidden,shixun.code_hidden,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"隐藏目录"%> + <%= check_box_tag :vip,!shixun.vip,shixun.vip,remote:true,data:{id:shixun.id,toggle:"tooltip",placement:"top"},class:"shixun-setting-form" ,title:"vip"%>