dev_aliyun2
杨树明 5 years ago committed by harry
parent a6a162442e
commit ccd152dc82

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

@ -770,11 +770,10 @@ class ExercisesController < ApplicationController
ex_group_setting = exercise.exercise_group_settings
old_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", g_course) #试卷的分组设置
left_course_groups = teacher_course_group_ids - g_course
all_left_groups = all_course_group_ids - g_course
left_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id", left_course_groups)
if left_exercise_groups.blank? && exercise.unified_setting
if all_left_groups.size > 0 #开始为统一设置但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting
all_left_groups.each do |g|
if left_course_groups.size > 0 #开始为统一设置但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting
left_course_groups.each do |g|
ex_group_options = {
:exercise_id => exercise.id,
:course_group_id => g,
@ -1236,7 +1235,7 @@ class ExercisesController < ApplicationController
normal_status(0, "正在下载中")
else
set_export_cookies
render exam_pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type: "pdf_attachment.content_type", stream: false
render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets, disposition: 'inline', type: "pdf_attachment.content_type", stream: false
end
end

@ -931,7 +931,7 @@ class HomeworkCommonsController < ApplicationController
def publish_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
group_ids = params[:group_ids]&.reject(&:blank?)&.map(&:to_i)
group_ids = params[:group_ids]&.reject(&:blank?).map(&:to_i)
if params[:detail].blank?
tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
@ -1071,7 +1071,7 @@ class HomeworkCommonsController < ApplicationController
homeworks = homeworks.published_no_end.includes(:homework_group_settings, :homework_detail_manual, :homework_challenge_settings)
course_students = @course.students
charge_group_ids = @course.charge_group_ids(current_user)
group_ids = params[:group_ids]&.reject(&:blank?)&.map(&:to_i)
group_ids = params[:group_ids]&.reject(&:blank?).map(&:to_i)
end_groups = charge_group_ids & group_ids if group_ids
begin

@ -711,7 +711,8 @@ class PollsController < ApplicationController
tip_exception("发布时间不能为空") if params[:publish_time].blank?
tip_exception("截止时间不能为空") if params[:end_time].blank?
tip_exception("截止时间必须晚于发布时间") if params[:publish_time].to_time >= params[:end_time].to_time
tip_exception("截止时间不能晚于课堂结束时间(#{@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
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
params_publish_time = params[:publish_time].to_time
params_end_time = params[:end_time].to_time

@ -25,7 +25,7 @@ class ShixunsController < ApplicationController
before_action :special_allowed, only: [:send_to_course, :search_user_courses]
before_action :shixun_marker, only: [:new, :create]
#before_action :validate_wachat_support, only: [:shixun_exec]
before_action :validate_wachat_support, only: [:shixun_exec]
skip_before_action :check_sign, only: [:download_file]
## 获取课程列表
@ -1186,11 +1186,11 @@ private
md5.hexdigest
end
# def validate_wachat_support
#
# if (params[:wechat].present? && !@shixun.is_wechat_support?)
# tip_exception(-5, "..")
# end
# end
def validate_wachat_support
if (params[:wechat].present? && !@shixun.is_wechat_support?)
tip_exception(-5, "..")
end
end
end

@ -17,13 +17,7 @@ class Weapps::SessionsController < Weapps::BaseController
# session[:wechat_user_extra].delete(:nickName)
# 绑定微信号
# open_user = OpenUsers::Wechat.find_by(uid: session_unionid)
# if open_user.present? && open_user.user_id.nil?
# open_user.update!(user_id: user.id)
# els
if user.wechat_open_user.blank?
OpenUsers::Wechat.create!(user: user, uid: session_unionid)
end
OpenUsers::Wechat.create!(user: user, uid: session_unionid) if user.wechat_open_user.blank?
successful_authentication(user)
end

@ -1,7 +1,7 @@
module SubjectsHelper
# 实训路径的发布状态
def publish_status subject, is_manager
def publish_status subject, is_manager, user
status = -1
if is_manager
status = 0 if subject.status == 0

@ -51,10 +51,7 @@ class Admins::ShixunSettingsQuery < ApplicationQuery
all_shixuns = all_shixuns.where(task_pass: params[:task_pass]) if params[:task_pass]
all_shixuns = all_shixuns.where(code_hidden: params[:code_hidden]) if params[:code_hidden]
all_shixuns = all_shixuns.where(vip: params[:vip]) if params[:vip]
if params[:no_subject]
shixun_ids = StageShixun.pluck(:shixun_id).uniq
all_shixuns = all_shixuns.published.where.not(id: shixun_ids)
end
all_shixuns = all_shixuns.where(is_wechat_support: params[:is_wechat_support]) if params[:is_wechat_support]
custom_sort(all_shixuns, params[:sort_by], params[:sort_direction])
end

@ -22,7 +22,7 @@ class Subjects::CourseUsedInfoService < ApplicationService
# choice_shixun_frequency: 选用该课程实训的次数
course_info = []
schools.find_in_batches do |s|
s.each do |school|
Parallel.each(s) do |school|
name = school.name
course_count = school.course_count
student_count = school.courses.joins(:course_members).where(course_members: {role: 4, course_id: course_ids}).size

@ -11,7 +11,7 @@ class Subjects::ShixunUsedInfoService < ApplicationService
position = stage.position
shixuns = stage.shixuns.includes(myshixuns: :games, homework_commons: :course)
shixuns.find_in_batches(batch_size: 1000) do |s|
s.each_with_index do |shixun, index|
Parallel.each_with_index(s, in_processes: 2) do |shixun, index|
stage = "#{position}-#{index+1}"
name = shixun.name
myshixuns = shixun.myshixuns

@ -13,7 +13,7 @@ class Subjects::UserUsedInfoService < ApplicationService
users_info = []
users = User.includes(myshixuns: :games).where(myshixuns: {shixun_id: shixun_ids}, games: {status: 2}, users: {is_test: false})
users.find_in_batches(batch_size: 500) do |u|
u.each do |user|
Parallel.each(u, in_processes: 2) do |user|
myshixuns = user.myshixuns.select{|m| shixun_ids.include?(m.shixun_id)}
name = "#{user.lastname}#{user.firstname}"
passed_myshixun_count = myshixuns.select{|m| m.status == 1}.size

@ -73,8 +73,8 @@
</div>
<div class="mr-5">
<label for="is_wechat_support">
<%= check_box_tag :no_subject, !@sort_json[:no_subject],@sort_json[:no_subject], class:"shixun-settings-select" %>
<span class="only_view">已发布没关联课程</span>
<%= check_box_tag :is_wechat_support, !@sort_json[:is_wechat_support],@sort_json[:is_wechat_support], class:"shixun-settings-select" %>
<span class="only_view">只看小程序可用</span>
</label>
</div>

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

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

@ -87,4 +87,4 @@
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack-bundle-analyzer": "^3.6.0"
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1378,11 +1378,26 @@
"unicode_decimal": 59237
},
{
<<<<<<< HEAD
"icon_id": "1881547",
"name": "大数据存储",
"font_class": "dashujucunchu",
"unicode": "e678",
"unicode_decimal": 59000
=======
"icon_id": "5327531",
"name": "过滤器",
"font_class": "guolvqi",
"unicode": "e71b",
"unicode_decimal": 59163
},
{
"icon_id": "5379378",
"name": "20从属连接",
"font_class": "congshulianjie",
"unicode": "e6ee",
"unicode_decimal": 59118
>>>>>>> bd8f30a...
},
{
"icon_id": "2584358",
@ -2253,11 +2268,33 @@
"unicode_decimal": 58967
},
{
<<<<<<< HEAD
"icon_id": "4187234",
"name": "文件夹",
"font_class": "wenjianjia",
"unicode": "e640",
"unicode_decimal": 58944
=======
"icon_id": "12621396",
"name": "加上2",
"font_class": "jiashang1",
"unicode": "e719",
"unicode_decimal": 59161
},
{
"icon_id": "12826208",
"name": "初始化",
"font_class": "chushihua",
"unicode": "e71c",
"unicode_decimal": 59164
},
{
"icon_id": "12826211",
"name": "测试集",
"font_class": "ceshiji",
"unicode": "e71e",
"unicode_decimal": 59166
>>>>>>> bd8f30a...
}
]
}

@ -572,7 +572,10 @@ Created by iconfont
<glyph glyph-name="reset" unicode="&#59390;" d="M256 384H170.666667c0-185.002667 156.288-341.333333 341.333333-341.333333s341.333333 156.330667 341.333333 341.333333-156.288 341.333333-341.333333 341.333333V810.666667L342.4 682.666667 512 554.666667V640c138.752 0 256-117.248 256-256s-117.248-256-256-256-256 117.248-256 256zM640 384c0 71.210667-56.704 128-128 128s-128-56.789333-128-128 56.704-128 128-128 128 56.789333 128 128z" horiz-adv-x="1024" />
<glyph glyph-name="zhongzhi1" unicode="&#58889;" d="M511.99872 892.544C229.93792 892.544 1.28 664.86016 1.28 384.00256 1.28 103.13984 229.93792-124.544 511.99872-124.544 794.06592-124.544 1022.72 103.13984 1022.72 384.00256 1022.72 664.86016 794.06592 892.544 511.99872 892.544L511.99872 892.544zM520.3072 23.71968c-188.20096 0-341.3312 152.47616-341.3312 339.87584 0 187.3984 153.13024 339.87456 341.3312 339.87456l0.02816 0L520.33536 777.35552l178.08384-118.21696-178.08384-118.21952L520.33536 614.8096l-0.02816 0c-139.10784 0-252.28544-112.69376-252.28544-251.21536 0-138.5152 113.1776-251.21152 252.28544-251.21152s252.28672 112.69632 252.28672 251.21152c0 24.50432 19.91168 44.33152 44.52224 44.33152 24.60928 0 44.52224-19.8272 44.52224-44.33152C861.63712 176.19584 708.50304 23.71968 520.3072 23.71968L520.3072 23.71968zM520.3072 23.71968" horiz-adv-x="1024" />
<glyph glyph-name="guolvqi" unicode="&#59163;" d="M908.6 761.3c6.5-15.5 3.8-28.8-8-39.7L620.9 441.9V21c0-15.8-7.4-27.1-22.1-33.5-4.9-2-9.7-2.9-14.2-2.9-10.3 0-18.7 3.6-25.5 10.7L413.8 140.8c-7.2 7.2-10.7 15.7-10.7 25.5V441.9L123.4 721.6c-11.7 11-14.3 24.2-8 39.7 6.5 14.8 17.5 22.1 33.5 22.1H875c16 0.1 27.2-7.3 33.6-22.1z" horiz-adv-x="1024" />
<glyph glyph-name="congshulianjie" unicode="&#59118;" d="M844.8 230.4a128 128 0 0 1-125.44-102.4H358.4a102.4 102.4 0 0 0 0 204.8h307.2a153.6 153.6 0 0 1 0 307.2H304.64a128 128 0 1 1 0-51.2H665.6a102.4 102.4 0 0 0 0-204.8H358.4a153.6 153.6 0 0 1 0-307.2h360.96a128 128 0 1 1 125.44 153.6z m0-204.8a76.8 76.8 0 1 0 76.8 76.8 76.8 76.8 0 0 0-76.8-76.8z" horiz-adv-x="1024" />
<glyph glyph-name="default" unicode="&#59007;" d="M512.020 822.323c-239.75 0-434.093-195.721-434.093-437.159s194.342-437.159 434.093-437.159 434.112 195.721 434.112 437.159-194.362 437.159-434.112 437.159zM729.087 372.55c0-18.589-14.961-33.649-33.397-33.649h-367.321c-18.434 0-33.377 15.058-33.377 33.649v33.61c0 18.59 14.941 33.649 33.377 33.649h367.321c18.435 0 33.397-15.058 33.397-33.649v-33.61z" horiz-adv-x="1024" />
@ -986,6 +989,12 @@ Created by iconfont
<glyph glyph-name="wenjianjia" unicode="&#58944;" d="M957.3 464.4v56.7c0 57.8-47 104.8-104.8 104.8H510.1v46.8c0 57.8-47 104.8-104.8 104.8H172.6c-57.8 0-104.8-47-104.8-104.8v-208.3h889.5zM67.8 394.8v-304.5c0-57.8 47-104.8 104.8-104.8h680c57.8 0 104.8 47 104.8 104.8V394.8H67.8z" horiz-adv-x="1024" />
<glyph glyph-name="chushihua" unicode="&#59164;" d="M511.682434-128A468.457376 468.457376 0 0 0 44.559694 340.457376a66.73182 66.73182 0 0 0 133.46364 0A333.6591 333.6591 0 1 1 511.682434 675.451113a330.989827 330.989827 0 0 1-235.785764-98.095776 66.73182 66.73182 0 0 0-111.2197 66.73182l60.503517 203.309612a66.798552 66.798552 0 1 0 128.125094-37.814698l-9.564894-31.808835A468.234937 468.234937 0 1 0 511.682434-128zM600.658194 183.41516h-133.46364a66.73182 66.73182 0 0 0-66.73182 66.73182V472.58638a66.73182 66.73182 0 0 0 133.46364 0v-155.70758h66.73182a66.73182 66.73182 0 0 0 0-133.46364z" horiz-adv-x="1024" />
<glyph glyph-name="ceshiji" unicode="&#59166;" d="M536.332172 333.97898a75.330291 75.330291 0 0 0-29.985844 6.338471l-463.195967 207.95061a73.136205 73.136205 0 0 0 0 133.351681l463.195967 207.95061a73.136205 73.136205 0 0 0 59.971688 0l463.195966-207.95061a73.136205 73.136205 0 0 0 0-133.351681l-463.195966-207.95061a75.330291 75.330291 0 0 0-29.985844-6.338471zM251.832333 614.822008L536.332172 487.321224l284.499838 127.500784L536.332172 742.56658zM536.332172 102.868571a73.136205 73.136205 0 0 0-31.204781 7.069834l-463.195967 219.408615a73.184963 73.184963 0 0 0 62.409562 132.376532L536.332172 257.429752l431.259823 215.020443a73.136205 73.136205 0 0 0 65.33501-130.913807l-463.195966-230.866621a73.136205 73.136205 0 0 0-33.398867-7.801196zM536.332172-127.99805a73.136205 73.136205 0 0 0-31.204781 7.069833l-463.195967 219.408616a73.136205 73.136205 0 0 0 62.409562 131.888957L536.332172 26.319343l431.259823 215.264231a73.136205 73.136205 0 0 0 65.33501-130.913807l-463.195966-230.866621A73.136205 73.136205 0 0 0 536.332172-127.99805z" horiz-adv-x="1073" />
</font>

Before

Width:  |  Height:  |  Size: 394 KiB

After

Width:  |  Height:  |  Size: 396 KiB

@ -70,6 +70,7 @@
} else if (href.indexOf('/paths/') != -1) {
document.write('<script type="text/javascript" src="https://newweb.educoder.net/javascripts/educoder/edu_application.js"><\/script>');
<<<<<<< HEAD
}
} else {
if (href.indexOf('/tasks/') != -1) {
@ -79,6 +80,43 @@
document.write('<script type="text/javascript" src="/javascripts/educoder/edu_application.js"><\/script>');
} else if (href.indexOf('/paths/') != -1) {
document.write('<script type="text/javascript" src="/javascripts/educoder/edu_application.js"><\/script>');
=======
<!-- width=device-width, initial-scale=1 , shrink-to-fit=no -->
<!-- <meta name="viewport" content=""> -->
<meta name=”Keywords” Content=”EduCoder,信息技术实践教学,精品课程网,慕课MOOC″>
<meta name=”Keywords” Content=”实践课程,项目实战,java实训,python实战,人工智能技术,后端开发学习,移动开发入门″>
<meta name=”Keywords” Content=”翻转课堂,高效课堂创建,教学模式″>
<meta name=”Keywords” Content=”实训项目,python教程,C语言入门,java书,php后端开发,app前端开发,数据库技术″>
<meta name=”Keywords” Content=”在线竞赛,计算机应用大赛,编程大赛,大学生计算机设计大赛,全国高校绿色计算机大赛″>
<meta name=”Description” Content=”EduCoder是信息技术类实践教学平台。EduCoder涵盖了计算机、大数据、云计算、人工智能、软件工程、物联网等专业课程。超10000个实训案例及22000个技能评测点建立学、练、评、测一体化实验环境。”>
<meta name=”Description” Content=”EduCoder实践课程旨在于通过企业级实战实训案例帮助众多程序员提升各项业务能力。解决学生、学员、企业员工等程序设计能力、算法设计能力、问题求解能力、应用开发能力、系统运维能力等。”>
<meta name=”Description” Content=”EduCoder翻转课堂教学模式颠覆了传统教学模式让教师与学生的关系由“权威”变成了“伙伴”。将学习的主动权转交给学生使学生可个性化化学学生的学习主体得到了彰显。”>
<meta name=”Description” Content=”EduCoder实训项目为单个知识点关卡实践训练帮助学生巩固单一弱点强化学习。 >
<meta name=”Description” Content=”EduCoder实践教学平台各类大赛为进一步提高各类学生综合运用高级语言程序设计能力培养创新意识和实践探索精神发掘优秀软件人才。 >
<meta name="viewport" id="viewport" content="width=device-width, initial-scale=0.3, maximum-scale=0.3">
<meta name="theme-color" content="#000000">
<!--<meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" />-->
<!--<meta http-equiv="pragma" content="no-cache" />-->
<!--<meta http-equiv="Expires" content="0" />-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">-->
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<!-- <title>EduCoder</title>-->
<!--react-ssr-head-->
<script type="text/javascript">
>>>>>>> bd8f30a... 合并
}
}

@ -264,6 +264,16 @@ const JupyterTPI = Loadable({
loader: () => import('./modules/tpm/jupyter'),
loading: Loading
});
// 微信代码编辑器
const WXCode = Loadable({
loader: () => import('./modules/wxcode'),
loading: Loading
});
// //个人竞赛报名
// const PersonalCompetit = Loadable({
// loader: () => import('./modules/competition/personal/PersonalCompetit.js'),
// loading: Loading,
// });
class App extends Component {
constructor(props) {
super(props)
@ -542,73 +552,7 @@ class App extends Component {
(props) => {
return (<JupyterTPI {...this.props} {...props} {...this.state} />)
}
}
/>
<Route path="/tasks/:stageId" component={IndexWrapperComponent} />
{/*<Route path="/shixuns/:shixunId" component={TPMIndexComponent}>*/}
{/*</Route>*/}
<Route path="/shixuns/:shixunId"
render={
(props) => (<TPMIndexComponent {...this.props} {...props} {...this.state}></TPMIndexComponent>)
}
></Route>
{/*列表页 实训项目列表*/}
<Route path="/shixuns"
render={
(props) => (<TPMShixunsIndexComponent {...this.props} {...props} {...this.state}></TPMShixunsIndexComponent>)
}
></Route>
{/*实训课程(原实训路径)*/}
<Route path="/paths" component={ShixunPaths}></Route>
<Route path="/search"
render={
(props) => (<SearchPage {...this.props} {...props} {...this.state}></SearchPage>)
}
></Route>
{/*课堂*/}
<Route path="/courses" component={CoursesIndex} {...this.props} {...this.state}></Route>
{/* 教学案例 */}
<Route path="/moop_cases" render={
(props) => (<MoopCases {...this.props} {...props} {...this.state} />)
} />
<Route path="/forums"
render={
(props) => (<ForumsIndexComponent {...this.props} {...props} {...this.state}></ForumsIndexComponent>)
}
>
</Route>
<Route path="/comment" component={CommentComponent} />
<Route path="/messages"
render={
(props) => (<Messagerouting {...this.props} {...props} {...this.state}></Messagerouting>)
}
></Route>
<Route path="/help/:type"
render={
(props) => (<Help {...this.props} {...props} {...this.state}></Help>)
} />
<Route path="/ecs"
render={
(props) => (<Ecs {...this.props} {...props} {...this.state}></Ecs>)
} />
<Route path="/problems/new/:id?"
render={
(props) => {
return (<NewOrEditTask {...this.props} {...props} {...this.state} />)
}
}
/>
/>
<Route path="/myproblems/record_detail/:id"
render={
@ -674,6 +618,11 @@ class App extends Component {
render={
(props) => (<Headplugselection {...this.props} {...props} {...this.state} />)
} />
<Route path="/wxcode/:identifier?" component={WXCode}
render={
(props) => (<WXCode {...this.props} {...props} {...this.state}></WXCode>)
}
/>
<Route exact path="/"
// component={ShixunsHome}
render={
@ -684,9 +633,9 @@ class App extends Component {
</Switch>
</Router>
</MuiThemeProvider>
</ConfigProvider>
</Provider>
</Provider >
);
}

@ -2,7 +2,7 @@
import axios from 'axios';
import md5 from 'md5';
import { requestProxy } from "./indexEduplus2RequestProxy";
import { isDev, queryString } from 'educoder';
import { broadcastChannelOnmessage, SetAppModel, isDev, queryString } from 'educoder';
import { notification } from 'antd';
import cookie from 'react-cookies';
import './index.css';
@ -20,6 +20,20 @@ function locationurl(list) {
}
}
function setCookier() {
const _params = window.location.search;
if (_params) {
let _search = _params.split('?')[1];
_search.split('&').forEach(item => {
console.log(item);
const _arr = item.split('=');
cookie.save('_educoder_session', _arr[0]);
cookie.save('autologin_trustie', _arr[1]);
});
}
}
// TODO 开发期多个身份切换
let debugType = ""
if (isDev) {
@ -143,7 +157,34 @@ export function initAxiosInterceptors(props) {
proxy = "https://pre-newweb.educoder.net"
proxy = "https://test-newweb.educoder.net"
// proxy="https://test-jupyterweb.educoder.net"
// proxy="https://test-newweb.educoder.net"
// proxy="https://test-jupyterweb.educoder.net"
//proxy="http://192.168.2.63:3001"
try {
const str = window.location.pathname;
if (str.indexOf("/wxcode") !== -1) {
// console.log("开始重写cookis");
const _params = window.location.search;
// console.log("1111");
if (_params) {
// console.log("22222");
let _search = _params.split('?')[1];
_search.split('&').forEach(item => {
const _arr = item.split('=');
if (_arr[0] === '_educoder_session') {
cookie.save('_educoder_session', _arr[1], { path: '/' });
cookie.save('_educoder_session', _arr[1], { domain: '.educoder.net', path: '/' });
} else {
cookie.save('autologin_trustie', _arr[1], { path: '/' });
cookie.save('autologin_trustie', _arr[1], { domain: '.educoder.net', path: '/' });
}
});
}
}
} catch (e) {
}
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
// 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制
@ -153,8 +194,7 @@ export function initAxiosInterceptors(props) {
requestMap[keyName] = false;
}
let proxy = "https://test-newweb.educoder.net"
//响应前的设置
axios.interceptors.request.use(
config => {
// config.headers['Content-Type']= 'no-cache'
@ -169,6 +209,56 @@ export function initAxiosInterceptors(props) {
// proxy = 'http://localhost:3000'
// }
// ---------------------------------------------
// console.log("开始请求了");
// console.log(config.url);
// console.log(window.location.pathname);
//
// try {
// const str =window.location.pathname;
// if(str.indexOf("/wxcode") !== -1){
// // console.log("开始重写cookis");
// const _params = window.location.search;
// // console.log("1111");
// if (_params) {
// // console.log("22222");
// let _search = _params.split('?')[1];
// var _educoder_sessionmys="";
// var autologin_trusties="";
// _search.split('&').forEach(item => {
// const _arr = item.split('=');
// if(_arr[0]==='_educoder_session'){
// cookie.save('_educoder_session',_arr[1], { domain: '.educoder.net', path: '/'});
// _educoder_sessionmys=_arr[1];
// }else{
// cookie.save('autologin_trustie',_arr[1], { domain: '.educoder.net', path: '/'});
// autologin_trusties=_arr[1];
// }
// });
// try {
// const autlogins= `_educoder_session=${_educoder_sessionmys}; autologin_trustie=${autologin_trusties} `;
// config.params = {'Cookie': autlogins}
// config.headers['Cookie'] =autlogins;
// // console.log("设置了cookis");
// } catch (e) {
//
// }
// try {
// const autloginysls= `_educoder_session=${_educoder_sessionmys}; autologin_trustie=${autologin_trusties} `;
// config.params = {'autloginysls': autloginysls}
// config.headers['Cookie'] =autloginysls;
// // console.log("设置了cookis");
// }catch (e) {
//
// }
// }
// }
// }catch (e) {
//
// }
if (config.url.indexOf(proxy) != -1 || config.url.indexOf(':') != -1) {
return config
}
@ -187,6 +277,7 @@ export function initAxiosInterceptors(props) {
if (window.location.port === "3007") {
// let timestamp=railsgettimes(proxy);
// console.log(timestamp)
// `https://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp`
railsgettimes(`${proxy}/api/main/first_stamp.json`);
let newopens = md5(opens + timestamp)
config.url = `${proxy}${url}`;
@ -197,6 +288,8 @@ export function initAxiosInterceptors(props) {
}
} else {
// 加api前缀
// railsgettimes(`http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp`);
railsgettimes(`/api/main/first_stamp.json`);
let newopens = md5(opens + timestamp)
config.url = url;
@ -209,15 +302,15 @@ export function initAxiosInterceptors(props) {
}
//
// console.log(config);
// if (config.method === "post") {
// if (requestMap[config.url] === true) { // 避免重复的请求 导致页面f5刷新 也会被阻止 显示这个方法会影响到定制信息
// // console.log(config);
// // console.log(JSON.parse(config));
// // console.log(config.url);
// // console.log("被阻止了是重复请求=================================");
// return false;
// }
// }
if (config.method === "post") {
if (requestMap[config.url] === true) { // 避免重复的请求 导致页面f5刷新 也会被阻止 显示这个方法会影响到定制信息
// console.log(config);
// console.log(JSON.parse(config));
// console.log(config.url);
// console.log("被阻止了是重复请求=================================");
return false;
}
}
// 非file_update请求
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;
@ -231,186 +324,255 @@ export function initAxiosInterceptors(props) {
return Promise.reject(err);
});
window.setfalseInRequestMap = function (keyName) {
requestMap[keyName] = false;
// --------------------------------------------- 測試3007连测试服的代码
// if (url.indexOf('file_update') != -1 || url.indexOf('game_build') != -1 || url.indexOf('game_status') != -1) {
// proxy = 'https://testbdweb.trustie.net'
// } else {
// proxy = 'http://localhost:3000'
// }
// ---------------------------------------------
if (config.url.indexOf(proxy) != -1 || config.url.indexOf(':') != -1) {
return config
}
requestProxy(config)
//响应前的设置
axios.interceptors.request.use(
config => {
setpostcookie()
clearAllCookie()
// config.headers['Content-Type']= 'no-cache'
// if (token) { // 每次发送请求之前判断是否存在token如果存在则统一在http请求的header都加上token不用每次请求都手动添加了
// config.headers.Authorization = token;
// }
let url = `/api${config.url}`;
// --------------------------------------------- 測試3007连测试服的代码
// if (url.indexOf('file_update') != -1 || url.indexOf('game_build') != -1 || url.indexOf('game_status') != -1) {
// proxy = 'https://testbdweb.trustie.net'
// } else {
// proxy = 'http://localhost:3000'
// }
// ---------------------------------------------
if (config.url.indexOf(proxy) != -1 || config.url.indexOf(':') != -1) {
return config
//qq登录去掉api
if (config.params && config.params.redirect_uri != undefined) {
if (config.params.redirect_uri.indexOf('otherloginqq') != -1) {
url = `${config.url}`;
}
}
if (`${config[0]}` != `true`) {
let timestamp = Date.parse(new Date()) / 1000;
if (window.location.port === "3007") {
// let timestamp=railsgettimes(proxy);
// console.log(timestamp)
railsgettimes(`${proxy}/api/main/first_stamp.json`);
let newopens = md5(opens + timestamp)
config.url = `${proxy}${url}`;
if (config.url.indexOf('?') == -1) {
config.url = `${config.url}?debug=${debugType}&randomcode=${timestamp}&client_key=${newopens}`;
} else {
config.url = `${config.url}&debug=${debugType}&randomcode=${timestamp}&client_key=${newopens}`;
}
requestProxy(config)
} else {
// 加api前缀
railsgettimes(`/api/main/first_stamp.json`);
let newopens = md5(opens + timestamp)
config.url = url;
if (config.url.indexOf('?') == -1) {
config.url = `${config.url}?randomcode=${timestamp}&client_key=${newopens}`;
} else {
config.url = `${config.url}&randomcode=${timestamp}&client_key=${newopens}`;
}
}
}
//
// console.log(config);
// if (config.method === "post") {
// if (requestMap[config.url] === true) { // 避免重复的请求 导致页面f5刷新 也会被阻止 显示这个方法会影响到定制信息
// // console.log(config);
// // console.log(JSON.parse(config));
// // console.log(config.url);
// // console.log("被阻止了是重复请求=================================");
// return false;
// }
// }
// 非file_update请求
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
}
// setTimeout("setfalseInRequestMap(" + config.url + ")", 1200)
return config;
},
err => {
return Promise.reject(err);
});
let url = `/api${config.url}`;
window.setfalseInRequestMap = function (keyName) {
requestMap[keyName] = false;
}
//qq登录去掉api
if (config.params && config.params.redirect_uri != undefined) {
if (config.params.redirect_uri.indexOf('otherloginqq') != -1) {
url = `${config.url}`;
}
//响应前的设置
axios.interceptors.request.use(
config => {
setpostcookie()
clearAllCookie()
// config.headers['Content-Type']= 'no-cache'
// if (token) { // 每次发送请求之前判断是否存在token如果存在则统一在http请求的header都加上token不用每次请求都手动添加了
// config.headers.Authorization = token;
// }
// --------------------------------------------- 測試3007连测试服的代码
// if (url.indexOf('file_update') != -1 || url.indexOf('game_build') != -1 || url.indexOf('game_status') != -1) {
// proxy = 'https://testbdweb.trustie.net'
// } else {
// proxy = 'http://localhost:3000'
// }
// ---------------------------------------------
if (config.url.indexOf(proxy) != -1 || config.url.indexOf(':') != -1) {
return config
}
requestProxy(config)
let url = `/api${config.url}`;
//qq登录去掉api
if (config.params && config.params.redirect_uri != undefined) {
if (config.params.redirect_uri.indexOf('otherloginqq') != -1) {
url = `${config.url}`;
}
if (`${config[0]}` != `true`) {
let timestamp = Date.parse(new Date()) / 1000;
if (window.location.port === "3007") {
railsgettimes(`${proxy}/api/main/first_stamp.json`);
let newopens = md5(opens + timestamp)
config.url = `${proxy}${url}`;
if (config.url.indexOf('?') == -1) {
config.url = `${config.url}?debug=${debugType}&randomcode=${timestamp}&client_key=${newopens}`;
} else {
config.url = `${config.url}debug=${debugType}&randomcode=${timestamp}&client_key=${newopens}`;
}
}
if (`${config[0]}` != `true`) {
let timestamp = Date.parse(new Date()) / 1000;
if (window.location.port === "3007") {
railsgettimes(`${proxy}/api/main/first_stamp.json`);
let newopens = md5(opens + timestamp)
config.url = `${proxy}${url}`;
if (config.url.indexOf('?') == -1) {
config.url = `${config.url}?debug=${debugType}&randomcode=${timestamp}&client_key=${newopens}`;
} else {
railsgettimes(`/api/main/first_stamp.json`);
let newopens = md5(opens + timestamp)
config.url = url;
if (config.url.indexOf('?') == -1) {
config.url = `${config.url}?randomcode=${timestamp}&client_key=${newopens}`;
} else {
config.url = `${config.url}&randomcode=${timestamp}&client_key=${newopens}`;
}
config.url = `${config.url}debug=${debugType}&randomcode=${timestamp}&client_key=${newopens}`;
}
setpostcookie();
}
if (config.method === "post") {
if (requestMap[config.url] === true) { // 避免重复的请求 导致页面f5刷新 也会被阻止 显示这个方法会影响到定制信息
return false;
} else {
railsgettimes(`/api/main/first_stamp.json`);
let newopens = md5(opens + timestamp)
config.url = url;
if (config.url.indexOf('?') == -1) {
config.url = `${config.url}?randomcode=${timestamp}&client_key=${newopens}`;
} else {
config.url = `${config.url}&randomcode=${timestamp}&client_key=${newopens}`;
}
}
// 非file_update请求
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
setpostcookie();
}
if (config.method === "post") {
if (requestMap[config.url] === true) { // 避免重复的请求 导致页面f5刷新 也会被阻止 显示这个方法会影响到定制信息
return false;
}
// setTimeout("setfalseInRequestMap(" + config.url + ")", 1200)
return config;
},
err => {
return Promise.reject(err);
});
axios.interceptors.response.use(function (response) {
}
// 非file_update请求
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;
if (response === undefined) {
return
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
}
if (response.data.status === -1) {
// console.error('error:', response.data.message)
// throw new Error()
// https://github.com/axios/axios/issues?utf8=%E2%9C%93&q=cancel+request+in+response+interceptors+
// https://github.com/axios/axios/issues/583
// message.info(response.data.message || '服务端返回status -1请联系管理员。');
// props.showSnackbar( response.data.message || '服务器异常,请联系管理员。' )
if (window.location.pathname.startsWith('/tasks/')) {
props.showSnackbar(response.data.message || '服务器异常,请联系管理员。')
} else {
notification.open({
message: "提示",
description: response.data.message || '服务器异常,请联系管理员。',
style: {
zIndex: 99999999
},
});
// notification['error']({
// message:"提示",
// description: response.data.message || '服务器异常,请联系管理员。',
// });
}
// setTimeout("setfalseInRequestMap(" + config.url + ")", 1200)
return config;
},
err => {
return Promise.reject(err);
});
axios.interceptors.response.use(function (response) {
throw new axios.Cancel('Operation canceled by the user.');
if (response === undefined) {
return
}
if (response.data.status === -1) {
// console.error('error:', response.data.message)
// throw new Error()
// https://github.com/axios/axios/issues?utf8=%E2%9C%93&q=cancel+request+in+response+interceptors+
// https://github.com/axios/axios/issues/583
// message.info(response.data.message || '服务端返回status -1请联系管理员。');
// props.showSnackbar( response.data.message || '服务器异常,请联系管理员。' )
if (window.location.pathname.startsWith('/tasks/')) {
props.showSnackbar(response.data.message || '服务器异常,请联系管理员。')
} else {
// hash跳转
// var hash = window.location.hash;
// if (hash) {
// hashTimeout && window.clearTimeout(hashTimeout)
// hashTimeout = setTimeout(() => {
// var element = document.querySelector(hash);
// if (element) {
// element.scrollIntoView();
// }
// }, 400)
// }
notification.open({
message: "提示",
description: response.data.message || '服务器异常,请联系管理员。',
style: {
zIndex: 99999999
},
});
// notification['error']({
// message:"提示",
// description: response.data.message || '服务器异常,请联系管理员。',
// });
}
// if(response.data.status === 401){
// console.log("401401401")
throw new axios.Cancel('Operation canceled by the user.');
} else {
// hash跳转
// var hash = window.location.hash;
// if (hash) {
// hashTimeout && window.clearTimeout(hashTimeout)
// hashTimeout = setTimeout(() => {
// var element = document.querySelector(hash);
// if (element) {
// element.scrollIntoView();
// }
// }, 400)
// }
if (response.data.status === 403 || response.data.status === "403") {
}
// if(response.data.status === 401){
// console.log("401401401")
// }
if (response.data.status === 403 || response.data.status === "403") {
locationurl('/403');
}
locationurl('/403');
}
if (response.data.status === 404) {
locationurl('/nopage');
}
if (response.data.status === 404) {
locationurl('/nopage');
}
if (response.data.status === 500) {
locationurl('/500');
}
if (response.data.status === 500) {
locationurl('/500');
}
if (response.data.status === 501) {
if (message501 === false) {
message501 = true
notification.open({
message: "提示",
description: response.data.message || '访问异常,请求不合理',
style: {
zIndex: 99999999
}
})
}
window.setTimeout(function () {
message501 = false
}, 2000);
if (response.data.status === 501) {
if (message501 === false) {
message501 = true
notification.open({
message: "提示",
description: response.data.message || '访问异常,请求不合理',
style: {
zIndex: 99999999
}
})
}
requestMap[response.config.url] = false;
setpostcookie();
return response;
}, function (error) {
return Promise.reject(error);
});
// -----------------------------------------------------------------------------------
window.setTimeout(function () {
message501 = false
}, 2000);
}
requestMap[response.config.url] = false;
setpostcookie();
return response;
}, function (error) {
return Promise.reject(error);
});
// -----------------------------------------------------------------------------------
}
}
function initOnlineOfflineListener() {
const $ = window.$
$(window).bind("online", () => {
notification.destroy()
notification.success({
duration: 2,
message: '网络恢复正常',
description:
'网络恢复正常,感谢使用。',
})
});
$(window).bind("offline", () => {
notification.destroy()
notification.warning({
duration: null,
message: '网络异常',
description:
'网络异常,请检测网络后重试。',
})
});
}
function initOnlineOfflineListener() {
const $ = window.$
$(window).bind("online", () => {
notification.destroy()
notification.success({
duration: 2,
message: '网络恢复正常',
description:
'网络恢复正常,感谢使用。',
})
});
$(window).bind("offline", () => {
notification.destroy()
notification.warning({
duration: null,
message: '网络异常',
description:
'网络异常,请检测网络后重试。',
})
});
}

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

@ -21,8 +21,23 @@ import _ from 'lodash'
import TPIContext from './TPIContext'
import {
EDU_ADMIN, EDU_SHIXUN_MANAGER, EDU_SHIXUN_MEMBER, EDU_CERTIFICATION_TEACHER
, EDU_TEACHER, EDU_NORMAL, EDU_BUSINESS, CNotificationHOC, getRandomNumber
, EDU_GAME_MANAGER, EDU_TEACHER, EDU_NORMAL, EDU_BUSINESS, CNotificationHOC, getRandomNumber
} from 'educoder'
import { MuiThemeProvider, createMuiTheme, withStyles } from 'material-ui/styles';
import MUIDialogStyleUtil from '../modules/page/component/MUIDialogStyleUtil'
const styles = MUIDialogStyleUtil.getTwoButtonStyle()
// 主题自定义
const theme = createMuiTheme({
palette: {
primary: {
main: '#4CACFF',
contrastText: 'rgba(255, 255, 255, 0.87)'
},
secondary: { main: '#4CACFF' }, // This is just green.A700 as hex.
},
});
const testSetsExpandedArrayInitVal = [false, false, false, false, false,
false, false, false, false, false,

@ -31,6 +31,17 @@
}
}
// .margin,
// .margin-view-overlays,
// .current-line{
// width: 40px !important;
// }
// .monaco-editor .margin-view-overlays .line-numbers{
// text-align: center;
// }
// .monaco-scrollable-element{
// left: 40px !important;
// }
}
.setting_drawer {
@ -71,6 +82,12 @@
animation-iteration-count: 3;
}
// .monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input,
// .monaco-editor .margin,
// .minimap slider-mouseover,
// .minimap-decorations-layer{
// background:rgba(3,19,40,1) !important;
// }
@keyframes blink {
50% {

@ -833,11 +833,32 @@ class MemoDetail extends Component {
</div>}
</div>
<Comments comments={comments} user={_current_user}
replyComment={this.replyComment}
deleteComment={this.deleteComment}
commentPraise={this.commentPraise}
rewardCode={this.rewardCode}
hiddenComment={this.hiddenComment}
></Comments>
{hasMoreComments ?
<div className="memoMore" style={{ cursor: 'default' }}>
<a onClick={this.moreMemos}>查看更多评论</a>
<div className="writeCommentBtn" onClick={this.showCommentInput}>写评论</div>
</div>
:
<div className="memoMore">
<div className="writeCommentBtn" onClick={this.showCommentInput}>写评论</div>
</div>}
</div>
</div>
</div>
</div>
</div >
</React.Fragment>
</React.Fragment >
);
}
}

@ -1,4 +1,4 @@
import './header.less';
import './header.scss';
import React, { Component } from 'react';
import { Tooltip, Drawer } from 'antd'

@ -189,15 +189,70 @@ class MainContent extends Component {
</div>
</div>
</div>
}
></VNCContainer>
<div id="actionView" className="-layout-h -center -bg-grey-90 -grey-20 -bg-darkblack">
<ActionView {...this.props}
onRunCodeTest={onRunCodeTest}
></ActionView>
</div>
</CodeRepositoryViewContainer>
:
<React.Fragment>
<div className="-layout-v -flex">
<div className="-flex -relative">
<div className="split-panel -fit -vertical" id="games_repository_valuation">
<div className="-layout -stretch -fit -vertical centerH">
<div className="-layout -vertical -flex -relative -flex-basic70 -bg-weightblack"
id="games_repository_contents" style={games_repository_contents_style} >
{/* 选择题或编程题 */}
{/* readRepoTimeout 如果读取代码超时,显示重新加载按钮,重新拉取代码 */}
{
st === 0
?
<React.Fragment>
<div style={{ display: (codeLoading ? 'block' : 'none'), textAlign: 'center' }}>
<CircularProgress size={40} thickness={3}
style={{ marginLeft: 'auto', marginRight: 'auto', marginTop: '18%' }} />
<span style={{ color: '#ddd', display: 'block' }}>正在加载中请稍后...</span>
</div>
<div style={{ display: (codeLoading ? 'none' : 'block') }}>
<CodeRepositoryViewContainer {...this.props} ></CodeRepositoryViewContainer>
</div>
</React.Fragment>
: <ChooseRepositoryView ref="chooseQ" chooseQfun={(ref) => this.chooseQfun(ref)}{...this.props}></ChooseRepositoryView>
}
<div id="actionView"
style={{ position: 'absolute', width: '100%', bottom: '0', height: '51px' }}
className="-layout-h -center -bg-grey-90 -grey-20 -bg-darkblack">
<ActionView {...this.props} onRunCodeTest={onRunCodeTest}></ActionView>
{/* */}
</div>
<div className="h-center" style={{ top: '438px' }}>
{/*<div className="-changebg -bg-weightblack" id="-bg-change-color"></div>*/}
</div>
<div className="split-panel--second -layout -vertical -flex -relative -bg-black -flex-basic60"
id="games_valuation_contents" style={{ height: '258px', minHeight: '85px' }}>
{/* 测试结果、评测信息区域 */}
{loading ? <CircularProgress size={40} thickness={3} style={{ marginLeft: 'auto', marginRight: 'auto', marginTop: '10%', display: 'block' }} />
:
st === 0
? <CodeEvaluateView output_sets={output_sets} latest_output={latest_output}
record={record} onTestSetHeaderClick={onTestSetHeaderClick} {...this.props}></CodeEvaluateView>
: <ChooseEvaluateView {...this.props}></ChooseEvaluateView>
}
</div>
</div>
</div>
</div>
</div>
<div id="actionView"
style={{ position: 'absolute', width: '100%', bottom: '0', height: '51px' }}
className="-layout-h -center -bg-grey-90 -grey-20 -bg-darkblack">
<ActionView {...this.props} onRunCodeTest={onRunCodeTest}></ActionView>
</div>
</React.Fragment>
</React.Fragment>
}
</div>
</div>

@ -145,7 +145,7 @@
border-width: 1px !important;
}
.monaco-editor .margin,
/* .monaco-editor .margin,
.monaco-editor .margin-view-overlays{
width: 54px !important;
text-align: center !important;
@ -157,4 +157,4 @@
.monaco-editor .margin-view-overlays .line-numbers{
text-align: center !important;
}
} */

@ -0,0 +1,6 @@
.headerRight .exit_btn{
color: rgba(237,237,237,1);
&:hover{
// color: #fff;
}
}

@ -7,6 +7,7 @@ import passpartImg from '../../../images/tpi/passpart.png'
import empiricgreenImg from '../../../images/tpi/empiricgreen.png'
import { trigger } from 'educoder';
import SecondTab from "../../paths/SchoolStatistics/SecondTab";
class TaskResultLayer extends Component {
@ -19,22 +20,27 @@ class TaskResultLayer extends Component {
stared: false,
timeRemain: 0,
}
}
componentWillReceiveProps(newProps, newContext) {
if (newProps.currentGamePassed && (!this.props.currentGamePassed
|| (newProps.currentGamePassed !== this.props.currentGamePassed))) {
// this.fakeRanking = this._fakeRanking()
const $ = window.$;
let isLastGame = newProps.game_count === newProps.challenge.position;
setTimeout(() => {
// true ||
if (isLastGame) {
var dClass = 'zoomInDown'; $('.passTaskContent').show().addClass(dClass + ' animated');
setTimeout(function () { $('.passTaskContent').removeClass(dClass + ' animated') }, 1000)
} else {
var dClass = 'zoomIn'; $('.passTaskContent').show().addClass(dClass + ' animated');
setTimeout(function () { $('.passTaskContent').removeClass(dClass + ' animated') }, 1000)
componentWillReceiveProps(newProps, newContext) {
if (newProps.currentGamePassed && (!this.props.currentGamePassed
|| (newProps.currentGamePassed !== this.props.currentGamePassed))) {
// this.fakeRanking = this._fakeRanking()
const $ = window.$;
let isLastGame = newProps.game_count === newProps.challenge.position;
setTimeout(() => {
// true ||
if (isLastGame) {
var dClass = 'zoomInDown'; $('.passTaskContent').show().addClass(dClass + ' animated');
setTimeout(function () { $('.passTaskContent').removeClass(dClass + ' animated') }, 1000)
} else {
var dClass = 'zoomIn'; $('.passTaskContent').show().addClass(dClass + ' animated');
setTimeout(function () { $('.passTaskContent').removeClass(dClass + ' animated') }, 1000)
}
}, 100)
if (newProps.challenge.showLanguagePictrue == true) {
// 开启倒计时
// this.initEffectDisplayServerTimer()
}
}, 100)
@ -43,22 +49,13 @@ class TaskResultLayer extends Component {
// this.initEffectDisplayServerTimer()
}
}
}
onStarChange(challenge, index, value) {
this.props.onStarChange(challenge, index, value);
this.setState({
stared: value ? true : false,
})
}
onStarChange(challenge, index, value) {
this.props.onStarChange(challenge, index, value);
onFinish(goNext) {
const { stared } = this.state;
const { game, challenge, shixun, showSnackbar, next_game } = this.props;
if (!stared && !this.props.game.star && shixun.status >= 2) { // 没点评星 && 未评星 && 实训已发布(模拟实战可以继续)
showSnackbar('请先给该任务评星,谢谢。')
return;
this.setState({
stared: value ? true : false,
})
}
// 点击了查看效果,而非查看下一关
@ -70,6 +67,35 @@ class TaskResultLayer extends Component {
} else {
trigger('showWebDisplayEvent')
}
// 点击了查看效果,而非查看下一关
if (!goNext) {
if (challenge.showWebDisplayButton === true && challenge.webDisplayUrl) {
// 打开web效果查看页面
window.open(challenge.webDisplayUrl, '_blank');
return;
} else {
trigger('showWebDisplayEvent')
}
}
if (!game.star) { // 当前关卡没有评星,评星后再跳转
this.props.saveChallengeStar(game, challenge.position);
}
// 跳转到下一关
// https://stackoverflow.com/questions/29244731/react-router-how-to-manually-invoke-link
// this.context.router.push('/sample');
if (goNext === true) {
if (next_game) { // https://www.trustie.net/issues/18573
this.goNext = true;
}
// 隐藏掉效果查看页面
window.$('#picture_display').hide()
}
this.props.onGamePassed();
this.setState({
stared: false
})
}
if (!game.star) { // 当前关卡没有评星,评星后再跳转
this.props.saveChallengeStar(game, challenge.position);
@ -85,15 +111,30 @@ class TaskResultLayer extends Component {
// 隐藏掉效果查看页面
window.$('#picture_display').hide()
}
this.props.onGamePassed();
this.setState({
stared: false
})
}
_fakeRanking() {
const { cost_time } = this.props.game
if (cost_time > 60 * 10) {
return Math.floor(Math.random() * 11) + 20
// componentDidUpdate(prevProps) {
// if (!this.props.challenge) {
// return;
// }
// const { showLanguagePictrue } = this.props.challenge;
// if ( prevProps.challenge.showLanguagePictrue != showLanguagePictrue &&
// showLanguagePictrue == true ) {
// }
// }
initEffectDisplayServerTimer = () => {
this.setState({ timeRemain: 5 * 60 }, () => {
this.intervalHandler = setInterval(() => {
let timeRemain = this.state.timeRemain
if (timeRemain > 0) {
timeRemain = timeRemain - 1;
} else {
clearInterval(this.intervalHandler);
}
this.setState({ timeRemain })
}, 1000)
})
}
return Math.floor(((600 - cost_time) / 600) * 100)
@ -191,6 +232,7 @@ class TaskResultLayer extends Component {
</React.Fragment>
: ''}
<p>
{/*<a href="javascript:void(0)" className="passNext">下一关</a>*/}
<a href="javascript:void(0)" className={`passed ${stared || game.star ? 'stared' : ''}`}
{...titleObj} onClick={() => this.onFinish(true)}>{next_game ? '下一关' : '完成'}</a>
@ -199,17 +241,38 @@ class TaskResultLayer extends Component {
<a href="javascript:void(0)" className={`passed ${stared || game.star ? 'stared' : ''}`}
{...titleObj} onClick={() => this.onFinish()}>
{`查看效果`}
{/* ${ moment(this.state.timeRemain * 1000).format('mm:ss') } */}
</a>
}
{/*
(this.state.timeRemain ?
<Tooltip title={"注意效果查看服务只会保留5分钟"} disableFocusListener={true}>
</Tooltip>
:
<Tooltip title={"效果查看服务已被终止运行,需要重新评测后才能查看"} disableFocusListener={true}>
<a href="javascript:void(0)" className={`passed ${ stared || game.star ? 'stared' : '' }`}
{...titleObj} onClick={()=>{}} style={{ backgroundColor: 'gray'}}>
{ `查看效果` }
</a>
</Tooltip>
)
*/}
{/*
注意效果查看服务只会保留5分钟
效果查看服务已被终止运行需要重新评测后才能查看
*/}
</p>
</div>
</div>
</div>
</div>
:
<div></div>
}
<div></div>
}
</div>
);
}

@ -6,7 +6,7 @@
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-14 16:30:05
*/
import './index.less';
import './index.scss';
import React, { useRef, useState, useEffect } from 'react';
import { Table } from 'antd';
import ReactDom from 'react-dom';

@ -6,7 +6,7 @@
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-10 11:15:28
*/
import './index.less';
import './index.scss';
import React from 'react';
import { Tooltip } from 'antd';
const numberal = require('numeral');

@ -1,12 +1,12 @@
/*
* @Description: 实践课程统计页面
* @Author: tangjiang
* @Github:
* @Github:
* @Date: 2020-01-10 09:33:45
* @LastEditors : tangjiang
* @LastEditTime : 2020-02-14 17:51:48
* @LastEditTime : 2020-01-14 17:01:32
*/
import './index.less';
import './index.scss';
import React, { useEffect } from 'react';
import StaticNumberAndTxt from './StaticNumberAndTxt';
import DisplayTableData from './DisplayTableData';
@ -25,7 +25,7 @@ const App = (props) => {
changeParams,
initTotal
} = props;
// const [datas, setDatas] = useState([]);
// const [datas, setDatas] = useState([]);
// const [sortedInfo, setSortedInfo] = useState({});
// console.log(props);
const { pathId } = props.match.params;
@ -64,7 +64,6 @@ const App = (props) => {
width: 150,
dataIndex: 'student_count',
align: 'center',
defaultSortOrder: 'descend',
sorter: (a, b) => a.student_count - b.student_count,
// sorter: (a, b) => a.age - b.age
},
@ -167,47 +166,36 @@ const App = (props) => {
{
title: '姓名',
dataIndex: 'username',
align: 'center',
width: 200
align: 'center'
},
{
title: '通关实训数',
dataIndex: 'passed_myshixun_count',
align: 'center',
with: 130,
render: (val) => val + '',
sorter: (a, b) => a.passed_myshixun_count - b.passed_myshixun_count
},
{
title: '完成关卡',
dataIndex: 'passed_games_count',
align: 'center',
with: 130,
render: (val) => val + '',
defaultSortOrder: 'descend',
sorter: (a, b) => a.passed_games_count - b.passed_games_count
},
// {
// title: '代码行',
// dataIndex: 'code_line_count',
// align: 'center',
// with: 130,
// render: (val) => val + '',
// sorter: (a, b) => a.code_line_count - b.code_line_count
// },
{
title: '代码行',
dataIndex: 'code_line_count',
align: 'center',
sorter: (a, b) => a.code_line_count - b.code_line_count
},
{
title: '评测次数',
dataIndex: 'evaluate_count',
align: 'center',
with: 130,
render: (val) => val + '',
sorter: (a, b) => a.evaluate_count - b.evaluate_count
},
{
title: '所用时间',
dataIndex: 'cost_time',
align: 'center',
with: 200,
render: (text) => (text && moment(text).format('HH:mm:ss')) || '-',
sorter: (a, b) => a.cost_time - b.cost_time
}
@ -224,14 +212,14 @@ const App = (props) => {
pathId && staticList(pathId);
}
// const {
// study_count,
// course_study_count,
// initiative_study,
// passed_count,
// course_used_count,
// school_used_count
// } = subject_info;
const {
study_count,
course_study_count,
initiative_study,
passed_count,
course_used_count,
school_used_count
} = subject_info;
const maps = {
1: 'subject_info', // 实践课程使用情况
@ -259,36 +247,36 @@ const App = (props) => {
<section className="static_section_header">
<div className="header_title">
<span className="title-p">学习统计</span>
<span className="title-sub"></span>
<span className="title-sub">Android综合实训之物联网移动应用</span>
</div>
<div className="header-number header-flex">
<StaticNumberAndTxt
count={subject_info === null ? 0 : subject_info.study_count} // 总数
count={study_count} // 总数
txt={'学习总人数'} // 文字描述
desc={'学习该课程的全部人数(学习总人数=课堂学习人数+自主学习人数)'}
/>
<StaticNumberAndTxt
count={subject_info === null ? 0 : subject_info.course_study_count} // 总数
count={course_study_count} // 总数
txt={'课堂学习人数'} // 文字描述
desc={'通过课堂学习该课程的人数'}
/>
<StaticNumberAndTxt
count={subject_info === null ? 0 : subject_info.initiative_study} // 总数
count={initiative_study} // 总数
txt={'自主学习人数'} // 文字描述
desc={'通过自主学习该课程的人数'}
/>
<StaticNumberAndTxt
count={subject_info === null ? 0 : subject_info.passed_count} // 总数
count={passed_count} // 总数
txt={'通关总人数'} // 文字描述
desc={'通关该课程所有实训的人数去重。一个人数计算1次'}
/>
<StaticNumberAndTxt
count={subject_info === null ? 0 : subject_info.course_used_count} // 总数
count={course_used_count} // 总数
txt={'使用课堂数'} // 文字描述
desc={'使用该课程的课堂数量'}
/>
<StaticNumberAndTxt
count={subject_info === null ? 0 : subject_info.school_used_count} // 总数
count={school_used_count} // 总数
txt={'使用单位数'} // 文字描述
desc={'使用该课程的单位数量(包括自主学习者所在单位)'}
/>

@ -0,0 +1,156 @@
.static_wrap {
.static_section_header,
.static_section_table{
background-color: #fff;
border-radius: 5px;
padding: 30px 20px 0;
margin-top: 20px;
}
.static_section_table{
margin-bottom: 140px;
padding-top: 5px;
}
.static_section_header{
.header_title{
line-height: 1;
.title-p,
.title-sub{
display: inline-block;
vertical-align: bottom;
color: #303133;
}
.title-p{
position: relative;
font-size: 20px;
height: 20px;
line-height: 1;
font-weight: bold;
&::before{
position: absolute;
content: '';
border-left: 1px solid rgba(192,196,204,1);
right: -10px;
top: 2px;
bottom: 0px;
margin-left: 10px;
}
}
.title-sub{
margin-left: 20px;
font-size: 16px;
max-width: 1000px;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
vertical-align: bottom;
}
}
.header-number{
height: 158px;
}
.header-flex{
display: flex;
justify-content: space-around;
align-items: center;
.static-flex-item{
display: flex;
flex-direction: column;
justify-content: center;
.item-count{
font-size: 24px;
color: #4CACFF;
font-weight: bold;
}
.item-txt{
font-size: 14px;
line-height: 1.5;
text-align: center;
color: #909399;
margin-top: 20px;
.icon{
margin-left: 5px;
font-size: 16px !important;
}
}
}
}
}
// .static_table{
// // .ant-table-header{
// // overflow: hidden !important;
// // margin-bottom: 0px !important;
// // }
// // .ant-table-row-cell-break-word{
// // background: rgba(241,248,255,1) !important;
// // }
// // .overflow_hidden{
// // max-width: 280px;
// // overflow: hidden;
// // text-overflow:ellipsis;
// // white-space: nowrap;
// // }
// }
.static_table{
.ant-table-header{
margin-bottom: 0px !important;
overflow: hidden !important;
}
.ant-table-thead{
th{
background: rgba(241,248,255,1);
}
.ant-table-column-title{
color: #303133;
font-weight: bold;
}
}
.ant-table-tbody tr:nth-child(2n) {
td{
background: rgba(241,248,255,.4);
}
}
.ant-table-tbody tr td{
color: #303133;
}
}
.ant-table-footer{
background-color: rgba(241,248,255,1);
padding: 16px 0px;
}
.footer_list{
display: flex;
// background: #fff;
box-sizing: border-box;
text-align: center;
li{
color: #303133;
}
// border-top: 1px solid green;
.footer_item{
width: 150px;
}
.footer_item:not(:first-child) {
padding-right: 10px;
}
.footer-total{
width: 100px;
}
.footer_name{
flex: 1;
}
}
}
.tool-clazz{
max-width: 200px !important;
}

@ -891,17 +891,17 @@ class NewHeader extends Component {
`
}
</style>
<li className={`pr questionbanks`}>
<Popover placement="bottom" content={contents} trigger="click" >
<div className=" sortinxdirection mr10">
<div style={{
color: "#fff"
}}>
题库
</div>
</div>
</Popover>
</li>
{/*<li className={`pr questionbanks`}>*/}
{/* <Popover placement="bottom" content={contents} trigger="click" >*/}
{/* <div className=" sortinxdirection mr10">*/}
{/* <div style={{*/}
{/* color:"#fff"*/}
{/* }}>*/}
{/* 题库*/}
{/* </div>*/}
{/* </div>*/}
{/* </Popover>*/}
{/*</li>*/}
<li
style={{ display: this.props.Headertop === undefined ? 'none' : this.props.Headertop.auth === null ? 'none' : 'block' }}
@ -992,19 +992,11 @@ class NewHeader extends Component {
<<<<<<< HEAD
<style>
{
`
.posi - searchs{
opacity: 1;
=======
<style>
{
`
<style>
{
`
.posi - searchs{
opacity: 1;
>>>>>>> fcf6d0f... 题库
position: absolute;
top: -2px;
background: #fff;
@ -1014,251 +1006,251 @@ class NewHeader extends Component {
`
}
</style>
<div className="posi-searchs" >
<div className="search-all clearfix">
{/*<!--<a href="javascript:void(0)" className="search-clear fl" onclick="closeSearch();">×</a>-->*/}
<div className="fl pr search-clear edu-menu-panel" style={{ display: 'none' }}>
<input type="hidden" id="search_type" value="1"></input>
<span className="searchkey">实训</span>
<i className="fa fa-angle-down ml5 font-16"></i>
<ul id="searchkey" className="edu-menu-list edu-txt-center" style={{ minWidth: '80px', right: '-10px', top: '50px' }}>
<li><a>实训</a></li>
<li><a>课堂</a></li>
<li><a>用户</a></li>
</ul>
</div>
{/*<input type="text" className="search-input fl" id="search-input" */}
{/*onKeyDown={this.onKeywordSearchKeyDown} name="search_keyword" placeholder="搜索实训项目"/>*/}
{/*搜索框*/}
{showSearchOpentype === true ? <div
className={"HeaderSearch"}
onBlur={(e) => this.hideshowSearchOpen(e)} onMouseLeave={() => this.setevaluatinghides()}>
<Search
id={"HeaderSearchs"}
placeholder="实践课程/教学课堂/实训项目/交流问答"
onInput={() => this.onKeywordSearchKeyDowns()}
onSearch={(value) => this.onKeywordSearchKeyDown(value)}
// onPressEnter={this.onKeywordSearchKeyDown}
style={{ width: 300, height: 32 }}
autoFocus={true}
/>
</div> : ""}
{/*<a className="search-icon fl" id="header_keyword_search" onClick={this.onKeywordSearch}>*/}
{/*/!*<i className="fa fa-search font-16 mt23 color-grey-6"></i>*!/*/}
{/*<i className="iconfont icon-sousuo color-blue"></i>*/}
{/*</a>*/}
{/* TODO
<div className="posi-searchs" >
<div className="search-all clearfix">
{/*<!--<a href="javascript:void(0)" className="search-clear fl" onclick="closeSearch();">×</a>-->*/}
<div className="fl pr search-clear edu-menu-panel" style={{ display: 'none' }}>
<input type="hidden" id="search_type" value="1"></input>
<span className="searchkey">实训</span>
<i className="fa fa-angle-down ml5 font-16"></i>
<ul id="searchkey" className="edu-menu-list edu-txt-center" style={{ minWidth: '80px', right: '-10px', top: '50px' }}>
<li><a>实训</a></li>
<li><a>课堂</a></li>
<li><a>用户</a></li>
</ul>
</div>
{/*<input type="text" className="search-input fl" id="search-input" */}
{/*onKeyDown={this.onKeywordSearchKeyDown} name="search_keyword" placeholder="搜索实训项目"/>*/}
{/*搜索框*/}
{showSearchOpentype === true ? <div
className={"HeaderSearch"}
onBlur={(e) => this.hideshowSearchOpen(e)} onMouseLeave={() => this.setevaluatinghides()}>
<Search
id={"HeaderSearchs"}
placeholder="实践课程/教学课堂/实训项目/交流问答"
onInput={() => this.onKeywordSearchKeyDowns()}
onSearch={(value) => this.onKeywordSearchKeyDown(value)}
// onPressEnter={this.onKeywordSearchKeyDown}
style={{ width: 300, height: 32 }}
autoFocus={true}
/>
</div> : ""}
{/*<a className="search-icon fl" id="header_keyword_search" onClick={this.onKeywordSearch}>*/}
{/*/!*<i className="fa fa-search font-16 mt23 color-grey-6"></i>*!/*/}
{/*<i className="iconfont icon-sousuo color-blue"></i>*/}
{/*</a>*/}
{/* TODO
<div className="search-content none" style="width: 86%;left: 0px;">
<div className="search-title">最近搜索</div>
<div><a href="javascript:void(0)" className="search_history">绿盟</a></div>
<div><a href="javascript:void(0)" className="search_history">qwe</a></div>
</div>*/}
</div>
</div>
</div>
{/*<span className="font-15 fr mt17">
<%= link_to '登录', signin_path, :className => "mr5" %>
<em className="vertical-line"></em>
<%= link_to '注册', user_join_path, :className => "ml5" %>
</span>*/}
{
user === undefined ?
<span className="font-15 fr mt17 ml5 mr25">
<a onClick={() => this.educoderlogin()} className="mr5 color-white">登录</a>
<em className="vertical-line"></em>
<a href={"/register"} className="mr5 color-white">注册</a>
</span> : user.login === "" ? <span className="font-15 fr mt17 ml5 mr25">
<a onClick={() => this.educoderlogin()} className="mr5 color-white">登录</a>
<em className="vertical-line"></em>
<a href={"/register"} className="mr5 color-white">注册</a>
</span> :
<div className="fr edu-menu-panel mr25" style={{ height: '60px' }}>
<a href={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/courses`} className="fl ml15">
<img alt="头像" className="radius mt13" height="34" id="nh_user_logo" name="avatar_image"
src={getImageUrl(`images/` + user.image_url)} width="34">
</img>
</a>
<ul className="edu-menu-list" style={{ top: '60px' }}>
{/*<span className="bor-bottom-greyE currentName task-hide">{user.username}</span>*/}
<li><Link to={`/users/${this.props.current_user.login}/courses`}>我的个人主页</Link></li>
{coursestypes === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/courses`}>{this.props.user && this.props.user.main_site === false ? "我的课堂" : "我的教学课堂"}</Link></li>}
{/* p 老师 l 学生 */}
{shixuntype === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/shixuns`}>我的实训项目</Link></li>}
{pathstype === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/paths`}>{this.props.user && this.props.user.main_site === false ? "我的课程" : "我的实践课程"}</Link></li>}
{this.props.user && this.props.user.main_site === true ? <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/projects`}>我的开发项目</Link></li> : ""}
{/*<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/package`}>我的众包</Link></li>*/}
<li style={{ display: this.props.Headertop === undefined ? 'none' : this.props.Headertop.customer_management_url === null || this.props.Headertop.customer_management_url === "" ? 'none' : 'block' }}>
<a href={this.props.Headertop === undefined ? '' : this.props.Headertop.customer_management_url}>客户管理</a>
</li>
{
this.props.Headertop && this.props.Headertop.college_identifier &&
<li><a href={`/colleges/${this.props.Headertop.college_identifier}/statistics`}>学院统计</a></li>
}
{
this.props.Headertop && this.props.Headertop.laboratory_user &&
<li><a href={this.props.Headertop.laboratory_admin_url}>后台管理</a></li>
}
{
user === undefined ?
<span className="font-15 fr mt17 ml5 mr25">
<a onClick={() => this.educoderlogin()} className="mr5 color-white">登录</a>
<em className="vertical-line"></em>
<a href={"/register"} className="mr5 color-white">注册</a>
</span> : user.login === "" ? <span className="font-15 fr mt17 ml5 mr25">
<a onClick={() => this.educoderlogin()} className="mr5 color-white">登录</a>
<em className="vertical-line"></em>
<a href={"/register"} className="mr5 color-white">注册</a>
</span> :
<div className="fr edu-menu-panel mr25" style={{ height: '60px' }}>
<a href={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/courses`} className="fl ml15">
<img alt="头像" className="radius mt13" height="34" id="nh_user_logo" name="avatar_image"
src={getImageUrl(`images/` + user.image_url)} width="34">
</img>
</a>
<ul className="edu-menu-list" style={{ top: '60px' }}>
{/*<span className="bor-bottom-greyE currentName task-hide">{user.username}</span>*/}
<li><Link to={`/users/${this.props.current_user.login}/courses`}>我的个人主页</Link></li>
{coursestypes === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/courses`}>{this.props.user && this.props.user.main_site === false ? "我的课堂" : "我的教学课堂"}</Link></li>}
{/* p 老师 l 学生 */}
{shixuntype === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/shixuns`}>我的实训项目</Link></li>}
{pathstype === true ? "" : <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/paths`}>{this.props.user && this.props.user.main_site === false ? "我的课程" : "我的实践课程"}</Link></li>}
{this.props.user && this.props.user.main_site === true ? <li><Link to={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/projects`}>我的开发项目</Link></li> : ""}
{/*<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/package`}>我的众包</Link></li>*/}
<li style={{ display: this.props.Headertop === undefined ? 'none' : this.props.Headertop.customer_management_url === null || this.props.Headertop.customer_management_url === "" ? 'none' : 'block' }}>
<a href={this.props.Headertop === undefined ? '' : this.props.Headertop.customer_management_url}>客户管理</a>
</li>
{
this.props.Headertop && this.props.Headertop.college_identifier &&
<li><a href={`/colleges/${this.props.Headertop.college_identifier}/statistics`}>学院统计</a></li>
}
{
this.props.Headertop && this.props.Headertop.laboratory_user &&
<li><a href={this.props.Headertop.laboratory_admin_url}>后台管理</a></li>
}
<li><a href={`/account/profile`}>账号管理</a></li>
{/*<li><a onClick={()=>this.educoderlogin()} >登入测试接口</a></li>*/}
{/*<li><a onClick={()=>this.trialapplications()} >试用申请</a> </li>*/}
{/*<li><Link to={`/interest`}>兴趣页</Link></li>*/}
<li><a href={`/account/profile`}>账号管理</a></li>
{/*<li><a onClick={()=>this.educoderlogin()} >登入测试接口</a></li>*/}
{/*<li><a onClick={()=>this.trialapplications()} >试用申请</a> </li>*/}
{/*<li><Link to={`/interest`}>兴趣页</Link></li>*/}
<li className="bor-top-greyE">
<li className="bor-top-greyE">
{/*<a onClick={()=>this.educoderlogin()} >登录</a>*/}
<a onClick={() => this.educoderloginysl()}>退出</a>
{/*<a onClick={()=>this.educoderlogin()} >登录</a>*/}
<a onClick={() => this.educoderloginysl()}>退出</a>
</li>
</ul>
</div>
}
{/*href="https://www.educoder.net/login"*/ }
<div className="fr head-right">
{/*{ loadHeader()}*/}
{showSearchOpentype === true ? "" : this.props.user && this.props.user.main_site === true ? <a id="search-open" className="fl mr30 headIcon" onClick={(e) => this.showSearchOpen(e)}>
{/*"/images/educoder/icon/search.svg"
</li>
</ul>
</div>
}
{/*href="https://www.educoder.net/login"*/}
<div className="fr head-right">
{/*{ loadHeader()}*/}
{showSearchOpentype === true ? "" : this.props.user && this.props.user.main_site === true ? <a id="search-open" className="fl mr30 headIcon" onClick={(e) => this.showSearchOpen(e)}>
{/*"/images/educoder/icon/search.svg"
<img src={getImageUrl(`images/educoder/icon/search.svg`)} /> */}
<i className="iconfont icon-sousuo color-white"></i>
</a> : ""}
<i className="iconfont icon-sousuo color-white"></i>
</a> : ""}
{/*</div>*/}
<div className="fl mr30 edu-menu-panel headIcon">
<i className="iconfont icon-tianjiafangda color-white"></i>
<div className="edu-menu-list" style={{ top: '60px', width: "240px" }}>
<div className="overPart"></div>
<ul className={coursestypes === true && this.props.user && this.props.user.main_site === false ? "fl headwith100b edu-txt-center pr ul-leftline" : "fl with50 edu-txt-center pr ul-leftline"}>
{this.props.current_user && this.props.current_user.user_identity === "学生" ? "" : coursestypes === false ?
<li><a onClick={(url) => this.getUser("/courses/new")}>{this.props.user && this.props.user.main_site === false ? "新建课堂" : "新建教学课堂"}</a></li> : ""
}
{shixuntype === true ? "" :
<li><a onClick={(url) => this.getUser("/shixuns/new", "newshixuns")}>新建实训项目</a></li>
}
{this.props.user && this.props.user.main_site === false ? "" : this.props.Headertop === undefined ? "" : <li><a onClick={(url) => this.getUser("/paths/new")} >新建实践课程</a></li>}
{this.props.user && this.props.user.main_site === true ? "" : this.props.Headertop === undefined ? "" :
pathstype === true ? "" : this.props.user && this.props.user.admin === true || this.props.user && this.props.user.is_teacher === true || this.props.user && this.props.user.business === true ? <li><a onClick={(url) => this.getUser("/paths/new")} >新建实践课程</a></li> : ""
}
{this.props.user && this.props.user.main_site === true ? <li><a onClick={(url) => this.getUser("/projects/new", "projects")} target="_blank">新建开发项目</a></li> : ""}
</ul>
{coursestypes === true && this.props.user && this.props.user.main_site === false ? "" : <ul className="fl with50 edu-txt-center">
{coursestypes === true ? "" : <li>
<a onClick={this.tojoinclass}>{this.props.user && this.props.user.main_site === false ? "加入课堂" : "加入教学课堂"}</a>
</li>}
{Addcoursestypes === true ? <Addcourses
Addcoursestype={Addcoursestypes}
hideAddcoursestype={this.hideAddcoursestypes}
HideAddcoursestypess={(i) => this.HideAddcoursestypess(i)}
/> : ""}
<Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} />
{/* /courses/join_course_multi_role */}
{this.props.user && this.props.user.main_site === true ? <li>
<a onClick={this.tojoinitem}>加入开发项目</a>
</li> : ""}
{tojoinitemtype === true ? <Modal
keyboard={false}
title="加入项目"
visible={tojoinitemtype}
closable={false}
footer={null}
>
<div className="task_popup_con">
<div className="mr15">
<ul>
<li className="clearfix mb10">
<label className="panel-form-label fl">项目邀请码</label>
<Input type="text" className="input-60-40 fl mt5" name="invite_code"
style={{ width: '275px' }}
placeholder="请输入6位开发项目邀请码" value={tojoinclasstitle} onInput={this.inputjoinclassvalue} />
</li>
{/*</div>*/}
<div className="fl mr30 edu-menu-panel headIcon">
<p id="none_invite_code_notice"
className="color-orange none f12"
style={{ marginLeft: '90px', display: code_notice === true ? 'block' : "none" }}>请输入6位项目邀请码</p>
<li className="clearfix ">
<i className="iconfont icon-tianjiafangda color-white"></i>
<label className="panel-form-label fl">身份</label>
<RadioGroup className="mt10" onChange={this.onChangeRadioGroup}>
<Radio value={"manager"}>管理人员</Radio>
<Radio value={"developer"}>开发人员</Radio>
<Radio value={"reporter"}>报告人员</Radio>
</RadioGroup>
<div className="edu-menu-list" style={{ top: '60px', width: "240px" }}>
<div className="overPart"></div>
<ul className={coursestypes === true && this.props.user && this.props.user.main_site === false ? "fl headwith100b edu-txt-center pr ul-leftline" : "fl with50 edu-txt-center pr ul-leftline"}>
{this.props.current_user && this.props.current_user.user_identity === "学生" ? "" : coursestypes === false ?
<li><a onClick={(url) => this.getUser("/courses/new")}>{this.props.user && this.props.user.main_site === false ? "新建课堂" : "新建教学课堂"}</a></li> : ""
}
{shixuntype === true ? "" :
<li><a onClick={(url) => this.getUser("/shixuns/new", "newshixuns")}>新建实训项目</a></li>
}
{this.props.user && this.props.user.main_site === false ? "" : this.props.Headertop === undefined ? "" : <li><a onClick={(url) => this.getUser("/paths/new")} >新建实践课程</a></li>}
{this.props.user && this.props.user.main_site === true ? "" : this.props.Headertop === undefined ? "" :
pathstype === true ? "" : this.props.user && this.props.user.admin === true || this.props.user && this.props.user.is_teacher === true || this.props.user && this.props.user.business === true ? <li><a onClick={(url) => this.getUser("/paths/new")} >新建实践课程</a></li> : ""
}
{this.props.user && this.props.user.main_site === true ? <li><a onClick={(url) => this.getUser("/projects/new", "projects")} target="_blank">新建开发项目</a></li> : ""}
</ul>
{coursestypes === true && this.props.user && this.props.user.main_site === false ? "" : <ul className="fl with50 edu-txt-center">
{coursestypes === true ? "" : <li>
<a onClick={this.tojoinclass}>{this.props.user && this.props.user.main_site === false ? "加入课堂" : "加入教学课堂"}</a>
</li>}
{Addcoursestypes === true ? <Addcourses
Addcoursestype={Addcoursestypes}
hideAddcoursestype={this.hideAddcoursestypes}
HideAddcoursestypess={(i) => this.HideAddcoursestypess(i)}
/> : ""}
<Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} />
{/* /courses/join_course_multi_role */}
{this.props.user && this.props.user.main_site === true ? <li>
<a onClick={this.tojoinitem}>加入开发项目</a>
</li> : ""}
{tojoinitemtype === true ? <Modal
keyboard={false}
title="加入项目"
visible={tojoinitemtype}
closable={false}
footer={null}
</li>
<p id="none_checked_notice" className="color-orange none f12"
style={{ marginLeft: '90px', display: checked_notice === true ? 'block' : "none" }}>请选择一个身份</p>
<li className="clearfix mt10 edu-txt-center">
<a className="task-btn mr10"
onClick={() => this.hidetojoinclass(1)}>取消</a>
<a
className="task-btn task-btn-orange ml20"
onClick={() => this.submittojoinclass(1)}>确定</a>
</li>
</ul>
</div>
</div>
</Modal> : ""}
</ul>}
</div>
</div>
{this.props.user && this.props.user.main_site === true ? <div className="fl mr30 edu-menu-panel headIcon">
{user === undefined ? "" : user.login === "" ? "" : <a
href={`/messages/${user.login}/user_tidings`}
style={{ position: 'relative' }}
>
<div className="task_popup_con">
<div className="mr15">
<ul>
<li className="clearfix mb10">
<label className="panel-form-label fl">项目邀请码</label>
<Input type="text" className="input-60-40 fl mt5" name="invite_code"
style={{ width: '275px' }}
placeholder="请输入6位开发项目邀请码" value={tojoinclasstitle} onInput={this.inputjoinclassvalue} />
</li>
<p id="none_invite_code_notice"
className="color-orange none f12"
style={{ marginLeft: '90px', display: code_notice === true ? 'block' : "none" }}>请输入6位项目邀请码</p>
<li className="clearfix ">
<label className="panel-form-label fl">身份</label>
<RadioGroup className="mt10" onChange={this.onChangeRadioGroup}>
<Radio value={"manager"}>管理人员</Radio>
<Radio value={"developer"}>开发人员</Radio>
<Radio value={"reporter"}>报告人员</Radio>
</RadioGroup>
</li>
<p id="none_checked_notice" className="color-orange none f12"
style={{ marginLeft: '90px', display: checked_notice === true ? 'block' : "none" }}>请选择一个身份</p>
<li className="clearfix mt10 edu-txt-center">
<a className="task-btn mr10"
onClick={() => this.hidetojoinclass(1)}>取消</a>
<a
className="task-btn task-btn-orange ml20"
onClick={() => this.submittojoinclass(1)}>确定</a>
</li>
</ul>
</div>
</div>
</Modal> : ""}
</ul>}
</div>
</div>
<i className="iconfont icon-xiaoxilingdang color-white"></i>
<span className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}>
{/*{this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count > 99 ? '99+'*/}
{/*: this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count}*/}
</span>
</a>
}
{this.props.user && this.props.user.main_site === true ? <div className="fl mr30 edu-menu-panel headIcon">
{user === undefined ? "" : user.login === "" ? "" : <a
href={`/messages/${user.login}/user_tidings`}
style={{ position: 'relative' }}
>
<i className="iconfont icon-xiaoxilingdang color-white"></i>
<span className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}>
{/*{this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count > 99 ? '99+'*/}
{/*: this.props.Headertop===undefined?"":this.props.Headertop.unread_message_count}*/}
</span>
</a>
}
</div> : ""}
<Modal
keyboard={false}
title="提示"
visible={submitapplications}
closable={false}
footer={null}
>
<div className="task_popup_con ml30">
<div className="mr15">
<ul>
<div className="task-popup-content">
<p className="task-popup-text-center font-16">
{submitapplicationsvalue}
</p>
</div>
<li className="clearfix mt10 edu-txt-center">
<a className="task-btn mr10"
onClick={this.hidesubmitapplications}>取消</a>
<a
className="task-btn task-btn-orange ml20"
onClick={this.submitsubmitapplications}>确定</a>
</li>
</div> : ""}
<Modal
keyboard={false}
title="提示"
visible={submitapplications}
closable={false}
footer={null}
>
<div className="task_popup_con ml30">
<div className="mr15">
<ul>
<div className="task-popup-content">
<p className="task-popup-text-center font-16">
{submitapplicationsvalue}
</p>
</ul>
</div>
<li className="clearfix mt10 edu-txt-center">
<a className="task-btn mr10"
onClick={this.hidesubmitapplications}>取消</a>
<a
className="task-btn task-btn-orange ml20"
onClick={this.submitsubmitapplications}>确定</a>
</li>
</ul>
</div>
</div>
</Modal>
</div>
</Modal>
</div>
</div>
</div >

@ -211,7 +211,7 @@ class ShixunCardList extends Component {
})
}
console.log(this.props.middleshixundata.search_tags)
return (
<div className="educontent mt20">
<div className="clearfix">

@ -0,0 +1,381 @@
/*
* @Description: 微信端代码编辑器
* @Author: tangjiang
* @Github:
* @Date: 2020-01-15 09:56:34
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-18 15:07:09
*/
import './index.scss';
import React, {useState, useEffect, useRef} from 'react';
import MonacoEditor from '@monaco-editor/react';
import { Input, Icon } from 'antd';
import { connect } from 'react-redux';
import actions from '../../redux/actions';
import cookie from 'react-cookies';
const { TextArea } = Input;
const App = (props) => {
const {
isShow,
wxCode,
path,
showLoading,
showDialog,
gold,
experience,
next_game,
// userCode,
testCase = [],
getWXCode,
last_compile_output,
test_sets_count,
sets_error_count,
getWXCodeTestCase,
restoreWXCode,
updateWXCodeForEditor,
updateWXCodeForInterval,
evaluateWxCode,
showWXCodeTextCase,
changeWXCodeEvaluateLoading,
changeWXCodeEvaluateDialog
} = props;
const {identifier} = props.match.params;
// 获取路径参数
const setCookier = () => {
const _params = window.location.search;
if (_params) {
let _search = _params.split('?')[1];
_search.split('&').forEach(item => {
// console.log(item);
const _arr = item.split('=');
cookie.remove(_arr[0], {
path: '/',
domain: '.educoder.net'
});
cookie.save(_arr[0], _arr[1], {
path: '/',
domain: '.educoder.net'
});
});
}
}
setCookier();
const [isActive, setIsActive] = useState(-1);
const [tip, setTip] = useState('');
const [codes, setCodes] = useState(wxCode);
// const [showInfo, setShowInfo] = useState(false);
// const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
if (codes !== props.wxCode) {
setCodes(props.wxCode);
}
}, [props]);
const editorRef = useRef(null);
let timer = null;
const loadResult = (identifier) => {
// 加载代码块内容
getWXCode(identifier);
// 加载测试集
const params = {
path,
status: 0,
retry: 1
};
getWXCodeTestCase(identifier, params);
}
useEffect(() => {
setTimeout(() => {
setCookier();
loadResult(identifier);
}, 0);
}, []);
// 关闭
const handleCloseTestCase = () => {
// setIsVisible(false);
showWXCodeTextCase(false)
}
// 测试集
const handleClickTestCase = () => {
// setIsVisible(true);
showWXCodeTextCase(true)
}
// 编辑器代码
const handleEditorChange = (origin, monaco) => {
editorRef.current = monaco; // 获取当前monaco实例
// setEditCode(origin); // 保存编辑器初始值
editorRef.current.onDidChangeModelContent(e => { // 监听编辑器内容的变化
// TODO 需要优化 节流
const val = editorRef.current.getValue();
// console.log('编辑器代码====>>>>', val);
// updateWXCodeForEditor(val);
codeChange(val);
});
};
const codeChange = (code) => {
// console.log(code);
updateWXCodeForEditor(code);
if (!timer) {
timer = setInterval(function () {
clearInterval(timer);
timer = null;
// 调用更新代码
updateWXCodeForInterval(identifier, path);
}, 5000);
}
}
// 关闭单个测试集
const handleCloseItem = (i, flag) => {
if (!flag) return;
setIsActive(isActive === i ? -1 : i);
}
// 初始化
const handleResetCode = () => {
clearInterval(timer);
timer = null;
const result = window.confirm('你在本文件中修改的内容将丢失, 是否确定重新加载初始代码?');
if (result) {
setTip('初始化中...');
changeWXCodeEvaluateLoading(true);
identifier && restoreWXCode(identifier, { path });
}
}
// 评测
const handleEvalateCode = () => {
changeWXCodeEvaluateLoading(true);
evaluateWxCode(identifier, path);
setTip('评测中...');
}
// 关闭弹框
const handleCloseDialog = () => {
changeWXCodeEvaluateDialog(false);
}
// 查看测试集
const handleClickShowResult = () => {
showWXCodeTextCase(true);
changeWXCodeEvaluateDialog(false);
}
// 下一关
const handleClickNext = () => {
changeWXCodeEvaluateDialog(false);
loadResult(next_game);
}
const tcclasses = isShow ? `wx-code-test-case active` : 'wx-code-test-case';
const loading = showLoading ? 'code-evaluate-loading active' : 'code-evaluate-loading';
const dialog = showDialog ? 'pass-dialog active' : 'pass-dialog';
const _val = +sets_error_count === 0;
let resultTxt = (_val) ? '全部通过' : `${sets_error_count}组测试结果不匹配`;
const iclasses = _val ? 'iconfont icon-wancheng icon success' : 'iconfont icon-tishi1 icon fail';
const tclasses = _val ? 'result-txt success' : 'result-txt fail';
const ulClasses = !!last_compile_output ? 'case-list hasResult' : 'case-list';
const resultFlag = !!last_compile_output ? 'wxcode-test-result active' : 'wxcode-test-result';
// console.log('==========>>>>>>>> 评测结果样式', last_compile_output, resultFlag);
return (
<div className="wx-code-area">
<div className="wx-code-flex">
<div className="wx-code-item">
<MonacoEditor
height="100%"
width="100%"
language="python"
value={codes}
options={{
selectOnLineNumbers: true,
automaticLayout: true,
fontSize: `42px`
}}
theme='dark'
editorDidMount={handleEditorChange}
/>
</div>
<div className="wx-code-test">
<div className="flex-btn">
<span className="icon-btn" onClick={handleResetCode}>
<i className="iconfont icon-chushihua icon"></i>
<span className="icon-txt">初始化</span>
</span>
<span className="icon-btn" onClick={handleClickTestCase}>
<i className="iconfont icon-ceshiji icon"></i>
<span className="icon-txt">测试集</span>
</span>
</div>
{/* <Button type="primary" shape="circle">评测</Button> */}
<button className="wx-pt-btn" onClick={handleEvalateCode}>评测</button>
</div>
</div>
{/* 测试集 */}
<div className={tcclasses}>
<div className="text-case-list">
<div className="list-header">
<span className="header-title">{testCase.length}个测试用例</span>
<span className="header-close" onClick={handleCloseTestCase}>关闭</span>
</div>
<div className={resultFlag}>
<i className={iclasses}></i>
<span className={tclasses}>{test_sets_count - sets_error_count}/{test_sets_count}</span>
<span className={`${tclasses} result-txt-desc`}>{resultTxt}</span>
</div>
<ul className={ulClasses}>
{
testCase.map((item, i) => {
const {input, output, actual_output, is_public, result, compile_success} = item;
const _classes = isActive === i ? 'case-item-desc active' : 'case-item-desc';
const iconclasses = isActive === i ? 'iconfont icon-sanjiaoxing-down icon active' : 'iconfont icon-triangle icon';
const headerClasses = is_public ? 'item-header-desc active' : 'item-header-desc';
// console.log(_classes);
return (
<li className="case-item" key={`item_${i}`}>
<div className="case-item-header" onClick={() => handleCloseItem(i, is_public)}>
<h2 className={headerClasses}>
<i className={iconclasses}></i>
测试集{i + 1}
</h2>
{
is_public
? compile_success > 0
? result ? <span className="iconfont icon-wancheng case_item_success"></span>
: <span className="iconfont icon-jinggao1 case_item_fail"></span>
: ''
:
<span className="case-item-tips">隐藏测试集暂不支持解锁和查看 </span>
// is_public
// ? result ? <span className="iconfont icon-wancheng case_item_success"></span>
// : <span className="iconfont icon-jinggao1 case_item_fail"></span>)
// : (
// 隐藏测试集,暂不支持解锁和查看
// {/* {result
// ? <span className="iconfont icon-wancheng case_item_success"></span>
// : <span className="iconfont icon-jinggao1 case_item_fail"></span>
// } */}
// </span>)
}
</div>
<div className={_classes}>
<span className="desc-title">测试输入</span>
<span className="test-input">{input || '-'}</span>
<span className="desc-title">预期输出</span>
{/* <textarea rows="5">预期输出</textarea> */}
<TextArea
readOnly={true}
className="text-area-style"
value={output}
onChange={this.onChange}
placeholder="Controlled autosize"
autoSize={{ minRows: 3, maxRows: 6 }}
/>
{/* <TextArea rows={5} className="hope-result">预期输出</TextArea> */}
<span className="desc-title">实际输出</span>
<TextArea
readOnly={true}
className="text-area-style"
value={actual_output}
autoSize={{ minRows: 1, maxRows: 3 }}
/>
</div>
</li>
)
})
}
</ul>
</div>
</div>
{/* 测评中 */}
<div className={loading}>
<span className="loading-flex">
<Icon className="loading-icon" type="loading" />
<span className="loading-txt">{tip}</span>
</span>
</div>
{/* 通过弹框 */}
<div className={dialog}>
<div className="pass-box">
<div className="pass-img"></div>
<div className="pass-ctx">
<div className="pass-title">{next_game ? '评测通过' : '恭喜通关'}</div>
<p className="pass-value">
金币 <span className="value_color">{gold > 0 ? `+${gold}` : 0}</span>,
经验值 <span className="value_color">{experience > 0 ? `+${experience}` : 0}</span>
</p>
{
next_game
? (
<div className="pass-btn">
<button className="btn btn-first" onClick={handleClickShowResult}>评测结果</button>
<button className="btn btn-second" onClick={handleClickNext}>下一关</button>
</div>
)
: (
<div className="pass-btn-all">
<button className="btn btn-second" onClick={handleClickShowResult}>评测结果</button>
</div>
)
}
</div>
</div>
<i className="iconfont icon-roundclose icon_close" onClick={handleCloseDialog}></i>
</div>
</div>
);
}
const mapStateToProps = (state) => {
const {
path,
isShow,
wxCode,
userCode,
gold,
experience,
next_game,
testCase,
showLoading,
showDialog,
last_compile_output,
test_sets_count,
sets_error_count
} = state.wxcodeReducer;
// console.log(state);
return {
path,
isShow,
wxCode,
userCode,
gold,
experience,
next_game,
testCase,
showLoading,
showDialog,
last_compile_output,
test_sets_count,
sets_error_count
};
}
const mapDispatchToProps = (dispatch) => ({
getWXCode: (identifier) => dispatch(actions.getWXCode(identifier)),
getWXCodeTestCase: (identifier, params) => dispatch(actions.getWXCodeTestCase(identifier, params)),
restoreWXCode: (identifier, params) => dispatch(actions.restoreWXCode(identifier, params)),
updateWXCodeForEditor: (code) => dispatch(actions.updateWXCodeForEditor(code)),
updateWXCodeForInterval: (identifier, path) => dispatch(actions.updateWXCodeForInterval(identifier, path)),
evaluateWxCode: (identifier, path) => dispatch(actions.evaluateWxCode(identifier, path)),
showWXCodeTextCase: (flag) => dispatch(actions.showWXCodeTextCase(flag)),
changeWXCodeEvaluateLoading: (flag) => dispatch(actions.changeWXCodeEvaluateLoading(flag)),
changeWXCodeEvaluateDialog: (flag) => dispatch(actions.changeWXCodeEvaluateDialog(flag))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(App);

@ -0,0 +1,367 @@
.wx-code-area{
height: 100vh;
overflow: hidden;
.wx-code-flex{
display: flex;
position: relative;
flex-direction: column;
height: 100%;
}
.wx-code-item{
flex: 1;
}
.wx-code-test{
display: flex;
justify-content: space-between;
align-items: center;
height: 150px;
background-color: #052645;
padding: 0 50px;
}
.flex-btn{
display: flex;
.icon-btn{
display: flex;
flex-direction: column;
color: #2EA4FF;
align-items: center;
.icon{
// font-size: 24px !important;
// transform: scale(2.4);
// line-height: 2;
font-size: 34px !important;
transform: scale(1.8);
position: relative;
// top: 10px;
}
// .icon-reset{
// transform: scale(2.4);
// }
// .icon:first-child{
// transform: scale((3));
// }
&:last-child{
margin-left: 60px;
}
.icon-txt{
// margin-top: 5px;
font-size: 32px;
}
}
}
.wx-pt-btn{
border: none;
outline: none;
border-radius: 9999px;
padding: 0 50px;
line-height: 92px;
font-size: 38px;
color: #fff;
background:#2EA4FF;
letter-spacing: 2;
}
.wx-code-test-case{
position: fixed;
bottom: 0;
left: 0;
right: 0;
top: 0;
transform: translateY(100%);
transition: transform, opacity .3s;
opacity: 0;
// border-top-left-radius: 16px;
// border-top-right-radius: 16px;
&::before{
position: absolute;
width: 100%;
height: 100%;
content: '';
background: rgba(0,0,0,.6);
}
.text-case-list{
position: absolute;
width: 100%;
bottom: 0;
top: 150px;
background:rgba(1,14,31,1);
border-top-left-radius: 16px;
border-top-right-radius: 16px;
border:2px solid rgba(33,56,87,1);
color: #fff;
}
.list-header{
display: flex;
justify-content: space-between;
align-items: center;
height: 88px;
padding: 30px;
box-sizing: border-box;
border-bottom: 2px solid #213857;
.header-title{
color:#637DA6;
// font-size: 24px;
font-size: 48px;
}
.header-close{
// font-size: 42px;
font-size: 48px;
color: #2EA4FF;
}
}
.wxcode-test-result{
// display: flex;
display: none;
height: 72px;
// background: gold;
align-items: center;
padding: 0 30px;
.success{
color: rgba(68,209,95,1);
}
.fail{
color: rgba(196, 79, 78, 1);
}
.icon{
font-size: 48px !important;
position: relative;
// top: -8px;
margin-right: 10px;
}
.result-txt{
// font-size: 34px;
font-size: 48px;
}
.result-txt-desc{
max-width: 500px;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
margin: 20px;
}
&.active{
display: flex;;
}
}
.case-list{
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0px;
overflow: auto;
margin-top: 88px;
padding: 0 30px 30px;
// margin: 88px 30px 0;
.case-item{
position: relative;
margin-top: 30px;
border-radius: 8px;
background:rgba(23,39,64,1);
padding: 30px;
}
&.hasResult{
margin-top: 170px;
.case-item:first-child{
margin-top: 0;
}
}
.case-item-header{
display: flex;
justify-content: space-between;
align-items: center;
.case_item_success,
.case_item_fail{
font-size: 24px !important;
transform: scale(2);
}
.case_item_success{
color: rgba(68,209,95,1);
}
.case_item_fail{
color: rgba(196, 79, 78, 1);
}
.case-item-tips{
color: #C67676;
font-size: 38px;
}
}
.item-header-desc{
font-size: 48px;
color: #405D8C;
line-height: 1.5;
// background: gold;
.icon{
position: relative;
top: -4px;
font-size: 42px !important;
margin-right: 10px;
}
&.active{
color: #fff;
}
}
.case-item-tips{
font-size: 42px;
}
.case-item-desc{
display: none;
flex-direction: column;
font-size: 42px;
line-height: 1.5;
&.active{
display: flex;
}
}
.desc-title{
color: #637DA6;
line-height: 2;
font-size: 48px;
}
.text-area-style{
background:#010E1F !important;
color: #fff;
font-size: 48px;
line-height: 1.5;
border: none;
}
}
&.active{
transform: translateY(0);
opacity: 1;
// .item-header-desc{
// color: #fff;
// }
}
}
.code-evaluate-loading,
.pass-dialog{
display: none;
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
justify-content: center;
align-items: center;
&::before{
position: absolute;
width: 100%;
height: 100%;
content: '';
background: rgba(0,0,0,.5);
}
&.active{
display: flex;
}
}
.code-evaluate-loading{
// display: none;
.loading-flex{
display: flex;
position: absolute;
flex-direction: column;
justify-content: center;
width: 100%;
height: 100%;
text-align: center;
color: #fff;
.loading-icon{
font-size: 100px !important;
}
.loading-txt{
font-size: 42px;
}
}
}
.pass-dialog{
flex-direction: column;
.pass-box{
position: relative;
z-index: 10;
background: #fff;
border-radius: 15px;
width: 490px;
height: 490px;
overflow: hidden;
}
.pass-img{
height: 200px;
background: url(../../images/wx-head.png) center center no-repeat;
// background: url(../../../public/images/wx-head.png) center center no-repeat;
}
.pass-ctx{
display: flex;
flex-direction: column;
// justify-content: center;
justify-content: space-between;
align-items: center;
height: 290px;
padding: 40px 0;
.pass-title,
.pass-value,
.pass-btn .btn,
.pass-btn-all .btn{
font-size: 42px;
line-height: 1.5;
}
.pass-value{
color: #888888;
.value_color{
color: rgb(234, 185, 35);
}
}
.pass-btn,
.pass-btn-all{
display: flex;
justify-content: space-between;
// background: gold;
padding: 0 40px;
width: 100%;
margin-top: 10px;
}
.pass-btn-all{
justify-content: center;
}
.btn{
outline: none;
border-radius: 999px;
padding: 0 30px;
height: 70px;
&.btn-first{
border: 1px solid #2EA4FF;
color: #2EA4FF;
}
&.btn-second{
background-color: #2EA4FF;
color: #fff;
}
}
.pass-title{
color: #2EA4FF;
}
}
}
.icon_close{
display: block;
position: relative;
z-index: 10;
color: #555;
font-size: 100px!important;
}
}

@ -110,6 +110,17 @@ import {
initTotal
} from './static';
import {
getWXCode,
getWXCodeTestCase,
restoreWXCode,
updateWXCodeForEditor,
updateWXCodeForInterval,
evaluateWxCode,
showWXCodeTextCase,
changeWXCodeEvaluateLoading,
changeWXCodeEvaluateDialog
} from './wxCode';
export default {
toggleTodo,
getOJList,
@ -193,4 +204,14 @@ export default {
staticList,
changeParams,
initTotal,
// 微信
getWXCode,
getWXCodeTestCase,
restoreWXCode,
updateWXCodeForEditor,
updateWXCodeForInterval,
evaluateWxCode,
showWXCodeTextCase,
changeWXCodeEvaluateLoading,
changeWXCodeEvaluateDialog
}

@ -0,0 +1,246 @@
/*
* @Description:
* @Author: tangjiang
* @Github:
* @Date: 2020-01-15 15:41:10
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-18 11:43:43
*/
import types from './actionTypes.js';
import {
fetchWxCode,
fetchWxCodeTextCase,
fetchRestoreWxCode,
fetchUpdateWxCode,
fetchWxCodeGameBuild,
fetchWxCodeGameStatus
} from '../../services/wxcodeService.js';
// 加载代码块
export const getWXCode = (identifier) => {
return (dispatch) => {
fetchWxCode(identifier).then(res => {
if (res.status === 200) {
dispatch({
type: types.GET_WXCODE_BY_IDENTIFIER,
payload: res.data.content
});
}
});
}
};
// 加载测试集
export const getWXCodeTestCase = (identifier, params) => {
return (dispatch) => {
fetchWxCodeTextCase(identifier, params).then(res => {
// console.log('加载测试集: ====>>>>>>', res);
try{
const {data = {}} = res;
console.log(data.test_sets);
const _path = data.challenge.path;
dispatch({
type: types.GET_WXCODE_TEST_CASE,
payload: {
test_sets: data.test_sets || [],
game_id: data.game && data.game.id,
myIdentifier: data.myshixun.identifier,
exec_time: data.challenge.exec_time,
path: _path.split('')[0] || _path.split(';')[0] || _path,
last_compile_output: data.last_compile_output,
test_sets_count: data.test_sets_count,
sets_error_count: data.sets_error_count
}
});
} catch(err) {
console.log(err);
};
});
}
}
// 初始化
export const restoreWXCode = (identifier, params) => {
return (dispatch) => {
fetchRestoreWxCode(identifier, params).then(res => {
console.log('点击了初始化代码: ', res);
const {data} = res;
dispatch({
type: types.SHOW_WX_CODE_LOADING,
payload: false
})
dispatch({
type: types.GET_WXCODE_BY_IDENTIFIER,
payload: data.content || ''
});
});
}
}
// 更新编辑器代码
export const updateWXCodeForEditor = (code) => {
return {
type: types.UPDATE_WXCODE_FOR_EDITOR,
payload: code
}
}
export const updateWxCode = (path, identifier, userCode, game_id, evaluate = 0,) => {
return fetchUpdateWxCode(identifier, {
path,
evaluate,
content: userCode,
game_id
});
}
// 定时更新代码内容
export const updateWXCodeForInterval = (identifier, $path) => {
return (dispatch, getState) => {
const {wxCode, userCode, game_id, myIdentifier, path} = getState().wxcodeReducer;
if (wxCode !== userCode) {
updateWxCode(path, myIdentifier, userCode, game_id, 0).then(res => {
dispatch({
type: types.GET_WXCODE_BY_IDENTIFIER,
payload: userCode
});
});
}
}
}
// 评测
export const evaluateWxCode = (identifier, path) => {
return (dispatch, getState) => {
const {
userCode,
wxCode,
game_id,
myIdentifier,
exec_time,
path,
last_compile_output,
test_sets_count,
sets_error_count
} = getState().wxcodeReducer;
updateWxCode(path, myIdentifier, userCode, game_id, 1).then(res => {
// build
// const {} = res;
console.log(res);
const _resubmit = res.data.resubmit;
const params = {
first: 1,
content_modified: userCode !== wxCode ? 1 : 0,
sec_key: res.data.sec_key,
resubmit: _resubmit
}
setTimeout(() => {
// console.log(params);
fetchWxCodeGameBuild(identifier, params).then(res => {
const {status} = res.data;
if (status === 1) {
// 定时调用 game_status fetchWxCodeGameStatus
let count = 1;
const intervalTime = 500;
let time_out = false;
function wxCodeGameStatus (intervalTime, finalTime, count, timer) {
const excuteTime = (count++) * intervalTime; // 当前执行时间
console.log(finalTime, count, excuteTime);
if ((excuteTime / 1000) > (finalTime + 1)) time_out = true;
fetchWxCodeGameStatus(identifier, {resubmit: _resubmit, time_out}).then(r => {
const { status, test_sets = [], gold, experience, next_game, sets_error_count, test_sets_count, last_compile_output} = r.data;
if (+status > -1 || ((excuteTime / 1000) > (finalTime + 1))) {
clearInterval(timer);
timer = null;
dispatch({
type: types.SHOW_WX_CODE_LOADING,
payload: false
});
setTimeout(() => {
// 显示测试集弹框
// dispatch({
// type: types.IS_SHOW_WXCODE_TEST_CASES,
// payload: true
// });
// 评测是否通过, 通过 弹通过,否则 弹测试集
if (status === 2 && sets_error_count === 0) {
dispatch({
type: types.SET_GOLD_AND_EXPERIENCE,
payload: {
gold,
experience,
next_game
}
});
dispatch({
type: types.SHOW_WX_CODE_DIALOG,
payload: true
});
} else {
dispatch({
type: types.IS_SHOW_WXCODE_TEST_CASES,
payload: true
});
}
dispatch({
type: types.GET_WXCODE_TEST_CASE,
payload: {
test_sets,
game_id,
myIdentifier,
exec_time,
path,
last_compile_output,
test_sets_count,
sets_error_count
}
});
}, 50);
}
}).catch(err => {
dispatch({
type: types.SHOW_WX_CODE_LOADING,
payload: false
});
});
}
let timer = setInterval(() => {
wxCodeGameStatus(intervalTime, exec_time, count++, timer);
}, intervalTime);
}
})
}, 50);
}).catch(err => {
dispatch({
type: types.SHOW_WX_CODE_LOADING,
payload: false
});
});
}
}
// 显示测试集
export const showWXCodeTextCase = (flag) => {
return {
type: types.IS_SHOW_WXCODE_TEST_CASES,
payload: flag
}
}
// 显示测评中的状态
export const changeWXCodeEvaluateLoading = (flag) => {
return {
type: types.SHOW_WX_CODE_LOADING,
payload: flag
}
}
// 关闭对话框
export const changeWXCodeEvaluateDialog = (flag) => {
return {
type: types.SHOW_WX_CODE_DIALOG,
payload: flag
}
}

@ -17,6 +17,7 @@ import jupyterReducer from './jupyterReducer';
import commentReducer from './commentReducer';
import tpiReducer from './tpiReducer';
import staticReducer from './staticReducer';
import wxcodeReducer from './wxcodeReducer';
export default combineReducers({
testReducer,
@ -29,4 +30,5 @@ export default combineReducers({
commentReducer,
tpiReducer,
staticReducer,
wxcodeReducer
});

@ -0,0 +1,85 @@
/*
* @Description:
* @Author: tangjiang
* @Github:
* @Date: 2020-01-15 15:37:44
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-18 09:46:04
*/
import types from "../actions/actionTypes";
const initialState = {
wxCode: '',
userCode: '',
testCase: [],
game_id: '',
myIdentifier: '',
exec_time: 0,
last_compile_output: '',
test_sets_count: 0,
sets_error_count: 0,
path: '',
isShow: false,
showLoading: false,
showDialog: false,
gold: 0,
experience: 0,
next_game: ''
};
const wxcodeReducer = (state = initialState, action) => {
const { payload, type } = action;
switch (type) {
case types.GET_WXCODE_BY_IDENTIFIER:
console.log('=====>>>>>', payload);
return {
...state,
wxCode: payload,
userCode: payload
}
case types.GET_WXCODE_TEST_CASE:
return {
...state,
testCase: payload.test_sets,
game_id: payload.game_id,
myIdentifier: payload.myIdentifier,
exec_time: payload.exec_time,
path: payload.path,
last_compile_output: payload.last_compile_output,
test_sets_count: payload.test_sets_count,
sets_error_count: payload.sets_error_count
}
case types.UPDATE_WXCODE_FOR_EDITOR:
return {
...state,
userCode: payload
}
case types.IS_SHOW_WXCODE_TEST_CASES:
return {
...state,
isShow: payload
}
case types.SHOW_WX_CODE_LOADING:
return {
...state,
showLoading: payload
}
case types.SHOW_WX_CODE_DIALOG:
return {
...state,
showDialog: payload
}
case types.SET_GOLD_AND_EXPERIENCE:
return {
...state,
gold: payload.gold,
experience: payload.experience,
next_game: payload.next_game
}
default:
return {
...state
}
}
}
export default wxcodeReducer;

@ -12,64 +12,64 @@ import cookie from 'react-cookies'
const setCookier = () => {
// const _params = window.location.search;
// if (_params) {
// let _search = _params.split('?')[1];
// _search.split('&').forEach(item => {
// // console.log(item);
// const _arr = item.split('=');
// cookie.remove(_arr[0], {
// path: '/',
// domain: '.educoder.net'
// });
// cookie.save(_arr[0], _arr[1], { domain: '.educoder.net', path: '/'});
// });
// }
const _params = window.location.search;
if (_params) {
let _search = _params.split('?')[1];
_search.split('&').forEach(item => {
// console.log(item);
const _arr = item.split('=');
cookie.remove(_arr[0], {
path: '/',
domain: '.educoder.net'
});
cookie.save(_arr[0], _arr[1], { domain: '.educoder.net', path: '/' });
});
}
}
// 获取代码块
export async function fetchWxCode (identifier, params) {
setCookier();
const url = `/tasks/${identifier}/rep_content.json`;
params = Object.assign({}, params, {withCredentials: true});
return axios.get(url, {params});
export async function fetchWxCode(identifier, params) {
setCookier();
const url = `/tasks/${identifier}/rep_content.json`;
params = Object.assign({}, params, { withCredentials: true });
return axios.get(url, { params });
}
// 获取测试值
export async function fetchWxCodeTextCase (identifier) {
setCookier();
const url = `/tasks/${identifier}.json`;
const params = Object.assign({}, {withCredentials: true});
return axios.get(url, {params});
export async function fetchWxCodeTextCase(identifier) {
setCookier();
const url = `/tasks/${identifier}.json`;
const params = Object.assign({}, { withCredentials: true });
return axios.get(url, { params });
}
// 更新代码块内容
export async function fetchUpdateWxCode (identifier, params) {
setCookier();
// /myshixuns/8etu3pilsa/update_file.json
const url = `/myshixuns/${identifier}/update_file.json`;
params = Object.assign({}, params, {withCredentials: true});
return axios.post(url, params);
export async function fetchUpdateWxCode(identifier, params) {
setCookier();
// /myshixuns/8etu3pilsa/update_file.json
const url = `/myshixuns/${identifier}/update_file.json`;
params = Object.assign({}, params, { withCredentials: true });
return axios.post(url, params);
}
// 恢复初始化
export async function fetchRestoreWxCode (identifier, params) {
setCookier();
const url = `/tasks/${identifier}/reset_original_code.json`;
params = Object.assign({}, params, {withCredentials: true});
return axios.get(url, {params});
export async function fetchRestoreWxCode(identifier, params) {
setCookier();
const url = `/tasks/${identifier}/reset_original_code.json`;
params = Object.assign({}, params, { withCredentials: true });
return axios.get(url, { params });
}
// 评测
export async function fetchWxCodeGameBuild (identifier, params) {
setCookier();
const url = `/tasks/${identifier}/game_build.json`;
params = Object.assign({}, params, {withCredentials: true});
return axios.get(url, {params});
export async function fetchWxCodeGameBuild(identifier, params) {
setCookier();
const url = `/tasks/${identifier}/game_build.json`;
params = Object.assign({}, params, { withCredentials: true });
return axios.get(url, { params });
}
export async function fetchWxCodeGameStatus (identifier, params) {
setCookier();
const url = `/tasks/${identifier}/game_status.json`;
params = Object.assign({}, params, {withCredentials: true});
return axios.get(url, {params});
export async function fetchWxCodeGameStatus(identifier, params) {
setCookier();
const url = `/tasks/${identifier}/game_status.json`;
params = Object.assign({}, params, { withCredentials: true });
return axios.get(url, { params });
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1378,11 +1378,18 @@
"unicode_decimal": 59237
},
{
"icon_id": "1881547",
"name": "大数据存储",
"font_class": "dashujucunchu",
"unicode": "e678",
"unicode_decimal": 59000
"icon_id": "5327531",
"name": "过滤器",
"font_class": "guolvqi",
"unicode": "e71b",
"unicode_decimal": 59163
},
{
"icon_id": "5379378",
"name": "20从属连接",
"font_class": "congshulianjie",
"unicode": "e6ee",
"unicode_decimal": 59118
},
{
"icon_id": "2584358",
@ -2253,11 +2260,25 @@
"unicode_decimal": 58967
},
{
"icon_id": "4187234",
"name": "文件夹",
"font_class": "wenjianjia",
"unicode": "e640",
"unicode_decimal": 58944
"icon_id": "12621396",
"name": "加上2",
"font_class": "jiashang1",
"unicode": "e719",
"unicode_decimal": 59161
},
{
"icon_id": "12826208",
"name": "初始化",
"font_class": "chushihua",
"unicode": "e71c",
"unicode_decimal": 59164
},
{
"icon_id": "12826211",
"name": "测试集",
"font_class": "ceshiji",
"unicode": "e71e",
"unicode_decimal": 59166
}
]
}
}

@ -572,7 +572,10 @@ Created by iconfont
<glyph glyph-name="reset" unicode="&#59390;" d="M256 384H170.666667c0-185.002667 156.288-341.333333 341.333333-341.333333s341.333333 156.330667 341.333333 341.333333-156.288 341.333333-341.333333 341.333333V810.666667L342.4 682.666667 512 554.666667V640c138.752 0 256-117.248 256-256s-117.248-256-256-256-256 117.248-256 256zM640 384c0 71.210667-56.704 128-128 128s-128-56.789333-128-128 56.704-128 128-128 128 56.789333 128 128z" horiz-adv-x="1024" />
<glyph glyph-name="zhongzhi1" unicode="&#58889;" d="M511.99872 892.544C229.93792 892.544 1.28 664.86016 1.28 384.00256 1.28 103.13984 229.93792-124.544 511.99872-124.544 794.06592-124.544 1022.72 103.13984 1022.72 384.00256 1022.72 664.86016 794.06592 892.544 511.99872 892.544L511.99872 892.544zM520.3072 23.71968c-188.20096 0-341.3312 152.47616-341.3312 339.87584 0 187.3984 153.13024 339.87456 341.3312 339.87456l0.02816 0L520.33536 777.35552l178.08384-118.21696-178.08384-118.21952L520.33536 614.8096l-0.02816 0c-139.10784 0-252.28544-112.69376-252.28544-251.21536 0-138.5152 113.1776-251.21152 252.28544-251.21152s252.28672 112.69632 252.28672 251.21152c0 24.50432 19.91168 44.33152 44.52224 44.33152 24.60928 0 44.52224-19.8272 44.52224-44.33152C861.63712 176.19584 708.50304 23.71968 520.3072 23.71968L520.3072 23.71968zM520.3072 23.71968" horiz-adv-x="1024" />
<glyph glyph-name="guolvqi" unicode="&#59163;" d="M908.6 761.3c6.5-15.5 3.8-28.8-8-39.7L620.9 441.9V21c0-15.8-7.4-27.1-22.1-33.5-4.9-2-9.7-2.9-14.2-2.9-10.3 0-18.7 3.6-25.5 10.7L413.8 140.8c-7.2 7.2-10.7 15.7-10.7 25.5V441.9L123.4 721.6c-11.7 11-14.3 24.2-8 39.7 6.5 14.8 17.5 22.1 33.5 22.1H875c16 0.1 27.2-7.3 33.6-22.1z" horiz-adv-x="1024" />
<glyph glyph-name="congshulianjie" unicode="&#59118;" d="M844.8 230.4a128 128 0 0 1-125.44-102.4H358.4a102.4 102.4 0 0 0 0 204.8h307.2a153.6 153.6 0 0 1 0 307.2H304.64a128 128 0 1 1 0-51.2H665.6a102.4 102.4 0 0 0 0-204.8H358.4a153.6 153.6 0 0 1 0-307.2h360.96a128 128 0 1 1 125.44 153.6z m0-204.8a76.8 76.8 0 1 0 76.8 76.8 76.8 76.8 0 0 0-76.8-76.8z" horiz-adv-x="1024" />
<glyph glyph-name="default" unicode="&#59007;" d="M512.020 822.323c-239.75 0-434.093-195.721-434.093-437.159s194.342-437.159 434.093-437.159 434.112 195.721 434.112 437.159-194.362 437.159-434.112 437.159zM729.087 372.55c0-18.589-14.961-33.649-33.397-33.649h-367.321c-18.434 0-33.377 15.058-33.377 33.649v33.61c0 18.59 14.941 33.649 33.377 33.649h367.321c18.435 0 33.397-15.058 33.397-33.649v-33.61z" horiz-adv-x="1024" />
@ -986,6 +989,12 @@ Created by iconfont
<glyph glyph-name="wenjianjia" unicode="&#58944;" d="M957.3 464.4v56.7c0 57.8-47 104.8-104.8 104.8H510.1v46.8c0 57.8-47 104.8-104.8 104.8H172.6c-57.8 0-104.8-47-104.8-104.8v-208.3h889.5zM67.8 394.8v-304.5c0-57.8 47-104.8 104.8-104.8h680c57.8 0 104.8 47 104.8 104.8V394.8H67.8z" horiz-adv-x="1024" />
<glyph glyph-name="chushihua" unicode="&#59164;" d="M511.682434-128A468.457376 468.457376 0 0 0 44.559694 340.457376a66.73182 66.73182 0 0 0 133.46364 0A333.6591 333.6591 0 1 1 511.682434 675.451113a330.989827 330.989827 0 0 1-235.785764-98.095776 66.73182 66.73182 0 0 0-111.2197 66.73182l60.503517 203.309612a66.798552 66.798552 0 1 0 128.125094-37.814698l-9.564894-31.808835A468.234937 468.234937 0 1 0 511.682434-128zM600.658194 183.41516h-133.46364a66.73182 66.73182 0 0 0-66.73182 66.73182V472.58638a66.73182 66.73182 0 0 0 133.46364 0v-155.70758h66.73182a66.73182 66.73182 0 0 0 0-133.46364z" horiz-adv-x="1024" />
<glyph glyph-name="ceshiji" unicode="&#59166;" d="M536.332172 333.97898a75.330291 75.330291 0 0 0-29.985844 6.338471l-463.195967 207.95061a73.136205 73.136205 0 0 0 0 133.351681l463.195967 207.95061a73.136205 73.136205 0 0 0 59.971688 0l463.195966-207.95061a73.136205 73.136205 0 0 0 0-133.351681l-463.195966-207.95061a75.330291 75.330291 0 0 0-29.985844-6.338471zM251.832333 614.822008L536.332172 487.321224l284.499838 127.500784L536.332172 742.56658zM536.332172 102.868571a73.136205 73.136205 0 0 0-31.204781 7.069834l-463.195967 219.408615a73.184963 73.184963 0 0 0 62.409562 132.376532L536.332172 257.429752l431.259823 215.020443a73.136205 73.136205 0 0 0 65.33501-130.913807l-463.195966-230.866621a73.136205 73.136205 0 0 0-33.398867-7.801196zM536.332172-127.99805a73.136205 73.136205 0 0 0-31.204781 7.069833l-463.195967 219.408616a73.136205 73.136205 0 0 0 62.409562 131.888957L536.332172 26.319343l431.259823 215.264231a73.136205 73.136205 0 0 0 65.33501-130.913807l-463.195966-230.866621A73.136205 73.136205 0 0 0 536.332172-127.99805z" horiz-adv-x="1073" />
</font>

Before

Width:  |  Height:  |  Size: 394 KiB

After

Width:  |  Height:  |  Size: 396 KiB

Loading…
Cancel
Save