Merge branches 'competitions' and 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into ysmCompetitions

competitions
杨树明 5 years ago
commit 6bd83ef694

@ -0,0 +1,11 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-competitions-index-page').length > 0) {
$('.modal.admin-upload-file-modal').on('upload:success', function(e, data){
var $imageElement = $('.competition-image-' + data.source_id);
$imageElement.attr('src', data.url);
$imageElement.show();
$imageElement.next().html('重新上传');
})
}
});

@ -11,6 +11,7 @@ class Admins::CompetitionsController < Admins::BaseController
ids = @competitions.map(&:id)
@member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count
@competition_hot = ModuleSetting.exists?(module_type: "Competition", property: "hot")
respond_to do |format|
format.js
format.html

@ -1,4 +1,63 @@
class Competitions::CompetitionTeamsController < Competitions::BaseController
before_action :tech_mode, only: [:shixun_detail, :course_detail]
def shixun_detail
start_time = current_competition.competition_mode_setting&.start_time || current_competition.start_time
end_time = current_competition.competition_mode_setting&.end_time || current_competition.end_time
team_user_ids = @team.team_members.pluck(:user_id)
shixuns = Shixun.where(user_id: team_user_ids, status: 2)
.where('shixuns.created_at > ? && shixuns.created_at <= ?', start_time, end_time)
shixuns = shixuns.joins('left join shixuns forked_shixuns on forked_shixuns.fork_from = shixuns.id and forked_shixuns.status = 2')
shixuns = shixuns.select('shixuns.id, shixuns.identifier, shixuns.user_id, shixuns.myshixuns_count, shixuns.name, shixuns.fork_from, sum(forked_shixuns.myshixuns_count) forked_myshixun_count')
@shixuns = shixuns.group('shixuns.id').order('shixuns.myshixuns_count desc').includes(:user)
shixun_ids = @shixuns.map(&:id)
@myshixun_count_map = get_valid_myshixun_count(shixun_ids)
@original_myshixun_count_map = @myshixun_count_map.clone
# forked shixun valid myshixun count
forked_shixun_map = Shixun.where(status: 2, fork_from: shixun_ids).select('id, fork_from')
forked_shixun_map = forked_shixun_map.each_with_object({}) { |sx, obj| obj[sx.id] = sx.fork_from }
@forked_myshixun_count_map = get_valid_myshixun_count(forked_shixun_map.keys)
@forked_myshixun_count_map.each { |k, v| @myshixun_count_map[forked_shixun_map[k]] += v }
@course_count_map = get_valid_course_count(shixun_ids)
@forked_map = get_valid_course_count(forked_shixun_map.keys)
@forked_course_count_map = {}
@forked_map.each do |forked_id, course_count|
@forked_course_count_map[forked_shixun_map[forked_id]] ||= 0
@forked_course_count_map[forked_shixun_map[forked_id]] += course_count
end
@forked_shixun_map = forked_shixun_map
end
def course_detail
start_time = current_competition.competition_mode_setting&.start_time || current_competition.start_time
end_time = current_competition.competition_mode_setting&.end_time || current_competition.end_time
@team_user_ids = @team.team_members.pluck(:user_id)
student_count_subquery = CourseMember.where('course_id = courses.id AND role = 4').select('count(*)').to_sql
subquery = StudentWork.where('homework_common_id = hcs.id')
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
course_ids = Course.where('courses.created_at > ?', start_time)
.where('courses.created_at <= ?', end_time)
.where("(#{student_count_subquery}) >= 3")
.where("exists(select 1 from homework_commons hcs where hcs.course_id = courses.id and hcs.publish_time is not null and hcs.publish_time < NOW() and hcs.homework_type = 4 and exists(#{subquery}))")
.joins('join course_members on course_members.course_id = courses.id and course_members.role in (1,2,3)')
.where(course_members: { user_id: @team_user_ids }).pluck(:id)
courses = Course.where(id: course_ids).joins(:practice_homeworks).where('homework_commons.publish_time < now()')
@courses = courses.select('courses.id, courses.name, courses.members_count, count(*) shixun_homework_count')
.group('courses.id').order('shixun_homework_count desc').having('shixun_homework_count > 0')
course_ids = @courses.map(&:id)
@course_myshixun_map = Myshixun.joins(student_works: :homework_common)
.where(homework_commons: { course_id: course_ids })
.where('exists(select 1 from games where games.myshixun_id = myshixuns.id and games.status = 2)')
.group('homework_commons.course_id').count
@course_shixun_count_map = get_valid_shixun_count(course_ids)
end
def index
admin_or_business? ? all_competition_teams : user_competition_teams
end
@ -67,4 +126,37 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController
def save_params
params.permit(:name, teacher_ids: [], member_ids: [])
end
def tech_mode
# render_not_found if current_competition.mode != 3
@team = current_competition.competition_teams.find_by(id: params[:id])
end
def get_valid_myshixun_count(ids)
Myshixun.where(shixun_id: ids)
.where('exists(select 1 from games where games.myshixun_id = myshixuns.id and games.status = 2)')
.group('shixun_id').count
end
def get_valid_course_count(ids)
percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < NOW()')
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
Course.joins(practice_homeworks: :homework_commons_shixun)
.where('shixun_id in (?)', ids)
.where("exists (#{percentage_sql})")
.group('shixun_id').count
end
def get_valid_shixun_count(ids)
percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < NOW()')
.select('sum(compelete_status !=0 ) as finish, count(*) as total')
.having('total != 0 and finish >= (total / 2)').to_sql
Shixun.joins(homework_commons_shixuns: :homework_common)
.where(homework_commons: { homework_type: 4 })
.where('course_id in (?)', ids)
.where("exists (#{percentage_sql})")
.group('course_id').count
end
end

@ -1,6 +1,10 @@
class Competitions::CompetitionsController < Competitions::BaseController
include CompetitionsHelper
skip_before_action :require_login
before_action :allow_visit, except: [:index]
before_action :require_admin, only: [:update, :update_inform]
before_action :chart_visible, only: [:charts, :chart_rules]
def index
# 已上架 或者 即将上架
@ -25,10 +29,108 @@ class Competitions::CompetitionsController < Competitions::BaseController
end
def show
@competition = current_competition
end
def update
@competition.update_attributes!(introduction: params[:introduction])
normal_status("更新成功")
end
def common_header
@competition = current_competition
@competition_modules = @competition.unhidden_competition_modules
@user = current_user
end
def informs
status = params[:status] || 1
@informs = current_competition.informs.where(status: status)
end
def update_inform
tip_exception("标题和内容不能为空") if params[:name].blank? || params[:description].blank?
tip_exception("status参数有误") if params[:status].blank? || ![1, 2].include?(params[:status].to_i)
ActiveRecord::Base.transaction do
if params[:inform_id]
inform = current_competition.informs.find_by!(id: params[:inform_id])
inform.update_attributes!(name: params[:name], description: params[:description])
else
inform = current_competition.informs.create!(name: params[:name], description: params[:description], status: params[:status])
end
Attachment.associate_container(params[:attachment_ids], inform.id, inform.class) if params[:attachment_ids]
normal_status("更新成功")
end
end
def md_content
@md_content = CompetitionModuleMdContent.find_by!(id: params[:md_content_id])
end
def update_md_content
tip_exception("标题和内容不能为空") if params[:name].blank? || params[:content].blank?
ActiveRecord::Base.transaction do
if params[:md_content_id]
md_content = CompetitionModuleMdContent.find_by!(id: params[:md_content_id])
md_content.update_attributes!(name: params[:name], content: params[:content])
else
md_content = CompetitionModuleMdContent.create!(name: params[:name], content: params[:content])
end
Attachment.associate_container(params[:attachment_ids], md_content.id, md_content.class) if params[:attachment_ids]
normal_status("更新成功")
end
end
def chart_rules
@competition = current_competition
@stages = @competition.competition_stages
@rule_contents = @competition.chart_rules
end
def update_chart_rules
tip_exception("内容不能为空") if params[:content].blank?
@competition = current_competition
@stage = @competition.competition_stages.find_by!(id: params[:stage_id]) if params[:stage_id]
chart_rule = @competition.chart_rules.where(competition_stage_id: @stage&.id).first
if chart_rule
chart_rule.update_attributes!(content: params[:content])
else
@competition.chart_rules.create!(competition_stage_id: @stage&.id, content: params[:content])
end
normal_status("更新成功")
end
def charts
@competition = current_competition
if params[:stage_id]
@stage = @competition.competition_stages.find_by(id: params[:stage_id])
end
if @competition.identifier == "gcc-annotation-2018"
@records = @competition.competition_teams.joins(:competition_scores)
.select("competition_teams.*, score, cost_time").order("score desc, cost_time desc")
else
@records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i})
.select("competition_teams.*, score, cost_time").order("score desc, cost_time desc")
end
current_team_ids = @competition.team_members.where(user_id: current_user.id).pluck(:competition_team_id).uniq
@user_ranks = @records.select{|com_team| current_team_ids.include?(com_team.id)}
@records = @records.where("score > 0")
if params[:format] == "xlsx"
@records = @records.includes(user: [user_extension: :school], team_members: :user)
respond_to do |format|
format.xlsx{
set_export_cookies
chart_to_xlsx(@records, @competition)
exercise_export_name = "#{@competition.name}比赛成绩"
render xlsx: "#{exercise_export_name.strip}",template: "competitions/competitions/chart_list.xlsx.axlsx",locals:
{table_columns: @competition_head_cells, chart_lists: @competition_cells_column}
}
end
else
@records = @records.includes(:user, :team_members).limit(@competition.awards_count)
end
end
private
@ -38,9 +140,60 @@ class Competitions::CompetitionsController < Competitions::BaseController
end
def allow_visit
unless current_competition.published? || admin_or_business?
render_forbidden
return
render_forbidden unless current_competition.published? || admin_or_business?
end
def chart_visible
chart_module = current_competition.competition_modules.find_by(name: "排行榜")
render_forbidden unless (chart_module.present? && !chart_module.hidden) || admin_or_business?
end
# 竞赛成绩导出
def chart_to_xlsx records, competition
@competition_head_cells = []
@competition_cells_column = []
max_staff = competition.competition_staffs.sum(:maximum)
if max_staff < 2 # 个人赛
@competition_head_cells = %w(序号 姓名 学校 学号)
else # 战队赛
@competition_head_cells = %w(序号 战队名 指导老师 队员 学校)
end
statistic_stages = competition.competition_stages.where("score_rate > 0")
statistic_stages.each do |stage|
@competition_head_cells += ["#{stage.name}得分", "#{stage.name}用时"]
end
@competition_head_cells += ["总得分", "总用时"] if statistic_stages.size > 1
competition_scores = competition.competition_scores
records.each_with_index do |record, index|
row_cells_column = []
row_cells_column << index + 1
record_user = record.user
if max_staff < 2
row_cells_column << record_user.real_name
row_cells_column << record_user.school_name
row_cells_column << record_user.student_id
else
row_cells_column << record.name
row_cells_column << record.teachers_name
row_cells_column << record.members_name
row_cells_column << chart_school_str(record.team_members.select{|member| !member.is_teacher}.pluck(:user_id))
end
statistic_stages.each do |stage|
stage_score = competition_scores.select{|score| score.competition_stage_id == stage.id && score.competition_team_id == record.id}.first
row_cells_column << stage_score&.score.to_f.round(2)
row_cells_column << com_spend_time(stage_score&.cost_time.to_i)
end
if statistic_stages.size > 1
row_cells_column << record&.score.to_f.round(2)
row_cells_column << com_spend_time(record&.cost_time.to_i)
end
@competition_cells_column.push(row_cells_column)
end
end
end

@ -55,12 +55,12 @@ class GamesController < ApplicationController
# 选择题和编程题公共部分
@base_date = {st: @st, discusses_count: discusses_count, game_count: game_count, myshixun: @myshixun,
challenge: game_challenge.attributes.except("answer"), game: @game.try(:attributes), shixun: @shixun.try(:attributes),
challenge: game_challenge.attributes.except("answer"), game: @game.try(:attributes), shixun: @shixun.attributes.except("vnc", "vnc_evaluate"),
record_onsume_time: record_onsume_time, prev_game: prev_game, next_game: next_game,
praise_count: praise_count, user_praise: user_praise, time_limit: time_limit,
tomcat_url: edu_setting('cloud_tomcat_php'), is_teacher: is_teacher,
myshixun_manager: myshixun_manager, git_url: (@shixun.vnc ? repo_url(@myshixun.repo_path) : "")}
if @shixun.vnc
if @shixun.vnc && @st == 0
get_vnc_link(@game)
end
@ -881,7 +881,7 @@ class GamesController < ApplicationController
end
# actual_output为空表示暂时没有评测答题不允许查看
actual_output = output.try(:actual_output).try(:strip)
#has_answer << choose.answer if choose.answer.present?
has_answer << choose.answer if choose.answer.present?
# 标准答案处理,错误的不让用户查看,用-1替代
standard_answer = (actual_output.blank? || !output.try(:result)) ? -1 : choose.standard_answer
result = output.try(:result)
@ -892,7 +892,7 @@ class GamesController < ApplicationController
@chooses << sin_choose
test_sets << sin_test_set
end
@has_answer = true # 选择题永远都有答案
@has_answer = has_answer.presence
@choose_test_cases = {:had_submmit => had_submmit, :challenge_chooses_count => challenge_chooses_count,
:choose_correct_num => choose_correct_num, :test_sets => test_sets}
end

@ -1058,8 +1058,8 @@ class HomeworkCommonsController < ApplicationController
tip_exception("截止时间不能晚于课堂结束时间(#{@course.end_date.end_of_day.strftime("%Y-%m-%d %H:%M")}") if
@course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
else
tip_exception("缺少分班截止时间参数") if params[:group_end_times].blank?
group_end_times = params[:group_end_times].reject(&:blank?).map{|time| time.to_time}
tip_exception("缺少截止时间参数") if group_end_times.blank?
tip_exception("截止时间和分班参数的个数不一致") if group_end_times.length != group_ids.length
group_end_times.each do |time|
tip_exception("分班截止时间不能早于当前时间") if time <= Time.now

@ -262,6 +262,11 @@ class ShixunsController < ApplicationController
:mirror_repository_id => config.mirror_repository_id)
end
# 同步高校限制
@shixun.shixun_schools.each do |school|
ShixunSchool.create!(shixun_id: @new_shixun.id, school_id: school.school_id)
end
# fork版本库
logger.info("###########fork_repo_path: ######{@repo_path}")
project_fork(@new_shixun, @repo_path, current_user.login)

@ -3,6 +3,7 @@ class Weapps::BaseController < ApplicationController
private
def require_wechat_login!
Rails.logger.info("[Weapp] unionid: #{session_unionid}, openid: #{session_openid}")
return if session_unionid.present?
render_error('请先进行微信授权')
@ -21,6 +22,7 @@ class Weapps::BaseController < ApplicationController
end
def set_session_openid(openid)
Rails.logger.info("[Weapp] set session openid: #{openid}")
session[:openid] = openid
end
@ -29,6 +31,7 @@ class Weapps::BaseController < ApplicationController
end
def set_session_unionid(unionid)
Rails.logger.info("[Weapp] set session unionid: #{unionid}")
session[:unionid] = unionid
end
end

@ -5,14 +5,11 @@ class Weapps::CodeSessionsController < Weapps::BaseController
result = Wechat::Weapp.jscode2session(params[:code])
set_session_openid(result['openid'])
set_weapp_session_key(result['session_key']) # weapp session_key写入缓存 后续解密需要
# 已授权,绑定过账号
open_user = OpenUsers::Wechat.find_by(uid: result['unionid'])
if open_user.present? && open_user.user
set_session_unionid(result['unionid'])
successful_authentication(open_user.user)
set_session_unionid(result['unionid'])
logged = true
else
# 新用户
@ -21,6 +18,9 @@ class Weapps::CodeSessionsController < Weapps::BaseController
set_session_unionid(user_info['unionId'])
end
set_session_openid(result['openid'])
set_weapp_session_key(result['session_key']) # weapp session_key写入缓存 后续解密需要
render_ok(openid: result['openid'], logged: logged)
end
end

@ -142,6 +142,14 @@ module ApplicationHelper
end
end
# 主页banner图
def banner_img(source_type)
if File.exist?(disk_filename(source_type, "banner"))
ctime = File.ctime(disk_filename(source_type, "banner")).to_i
File.join("images/avatars", ["#{source_type}", "banner"]) + "?t=#{ctime}"
end
end
def disk_filename(source_type,source_id,image_file=nil)
File.join(storage_path, "#{source_type}", "#{source_id}")
end

@ -0,0 +1,54 @@
module CompetitionsHelper
def chart_school_str user_ids
chart_school_name = ""
chart_school_name = School.where(id: UserExtension.where(user_id: user_ids).pluck(:school_id).uniq).pluck(:name).join("")
end
# 耗时:小时、分、秒 00:00:00
# 小于1秒钟则不显示
def com_spend_time time
hour = time / (60*60)
min = time % (60*60) / 60
sec = time % (60*60) % 60
hour_str = "00"
min_str = "00"
sec_str = "00"
if hour >= 1 && hour < 10
hour_str = "0#{hour}"
elsif hour >= 10
hour_str = "#{hour}"
end
if min >= 1 && min < 10
min_str = "0#{min}"
elsif min >= 10
min_str = "#{min}"
end
if sec >= 1 && sec < 10
sec_str = "0#{sec}"
elsif sec >= 10
sec_str = "#{sec}"
end
time = "#{hour_str} : #{min_str} : #{sec_str}"
return time
end
def chart_stages competition
stages = []
statistic_stages = competition.competition_stages.where("rate > 0")
if competition.end_time && competition.end_time < Time.now && statistic_stages.size > 1
stages << {id: nil, name: "总排行榜", rate: 1.0, start_time: competition.start_time, end_time: competition.end_time}
end
statistic_stages.each do |stage|
if stage.max_end_time && stage.max_end_time < Time.now
stages << {id: stage.id, name: "#{stage.name}排行榜", rate: stage.score_rate, start_time: stage.min_start_time, end_time: stage.max_end_time}
end
end
stages = stages.sort { |a, b| b[:end_time] <=> a[:end_time] } if stages.size > 0
return stages
end
end

@ -0,0 +1,6 @@
class ChartRule < ApplicationRecord
belongs_to :competition
belongs_to :competition_stage, optional: true
validates :content, length: { maximum: 1000 }
end

@ -9,12 +9,19 @@ class Competition < ApplicationRecord
has_many :competition_teams, dependent: :destroy
has_many :team_members, dependent: :destroy
has_many :chart_rules, dependent: :destroy
has_many :competition_scores, dependent: :destroy
has_many :competition_staffs, dependent: :destroy
has_one :teacher_staff, -> { where(category: :teacher) }, class_name: 'CompetitionStaff'
has_one :member_staff, -> { where.not(category: :teacher) }, class_name: 'CompetitionStaff'
has_one :competition_mode_setting, dependent: :destroy
has_many :informs, as: :container, dependent: :destroy
has_many :attachments, as: :container, dependent: :destroy
has_many :attachments, as: :container
has_many :competition_awards, dependent: :destroy
after_create :create_competition_modules
@ -81,6 +88,16 @@ class Competition < ApplicationRecord
member_staff.mutiple_limited?
end
def max_min_stage_time
CompetitionStageSection.find_by_sql("SELECT MAX(end_time) as max_end_time, MIN(start_time) as min_start_time,
competition_stage_id FROM competition_stage_sections WHERE competition_id = #{id}
GROUP BY competition_stage_id order by competition_stage_id")
end
def awards_count
competition_awards.pluck(:num)&.sum > 0 ? competition_awards.pluck(:num)&.sum : 20
end
private
def create_competition_modules

@ -0,0 +1,3 @@
class CompetitionAward < ApplicationRecord
belongs_to :competition
end

@ -1,3 +1,4 @@
class CompetitionModeSetting < ApplicationRecord
belongs_to :course
belongs_to :course, optional: true
belongs_to :competition
end

@ -4,4 +4,21 @@ class CompetitionModule < ApplicationRecord
belongs_to :competition
has_one :competition_module_md_content, dependent: :destroy
def module_url
case name
when "首页", "赛制介绍"
"/competitions/#{competition.identifier}"
when "通知公告"
"/competitions/#{competition.identifier}/informs?status=1"
when "参赛手册"
"/competitions/#{competition.identifier}/informs?status=2"
when "排行榜"
"/competitions/#{competition.identifier}/charts"
when "报名"
"/competitions/#{competition.identifier}/competition_teams"
else
url || "/competitions/#{competition.identifier}/md_content?md_content_id=#{competition_module_md_content&.id}"
end
end
end

@ -0,0 +1,6 @@
class CompetitionScore < ApplicationRecord
belongs_to :user
belongs_to :competition
belongs_to :competition_stage, optional: true
belongs_to :competition_team, optional: true
end

@ -3,5 +3,15 @@ class CompetitionStage < ApplicationRecord
has_many :competition_stage_sections, dependent: :destroy
has_many :competition_entries, dependent: :destroy
has_many :competition_scores, dependent: :destroy
has_one :chart_rule, dependent: :destroy
def min_start_time
competition_stage_sections.where("start_time is not null").pluck(:start_time).min
end
def max_end_time
competition_stage_sections.where("end_time is not null").pluck(:end_time).max
end
end

@ -7,6 +7,7 @@ class CompetitionTeam < ApplicationRecord
has_many :team_members, dependent: :destroy
has_many :users, through: :team_members, source: :user
has_many :competition_scores, dependent: :destroy
has_many :members, -> { without_teachers }, class_name: 'TeamMember'
has_many :teachers, -> { only_teachers }, class_name: 'TeamMember'
@ -30,4 +31,12 @@ class CompetitionTeam < ApplicationRecord
self.code = code
code
end
def teachers_name
teachers.map{|teacher| teacher.user.real_name}.join(",")
end
def members_name
members.map{|member| member.user.real_name}.join(",")
end
end

@ -3,4 +3,6 @@ class Inform < ApplicationRecord
validates :name, length: { maximum: 60 }
validates :description, length: { maximum: 5000 }
has_many :attachments, as: :container, dependent: :destroy
end

@ -43,7 +43,7 @@ class LaboratorySetting < ApplicationRecord
navbar: [
{ 'name' => '实践课程', 'link' => '/paths', 'hidden' => false },
{ 'name' => '翻转课堂', 'link' => '/courses', 'hidden' => false },
{ 'name' => '实项目', 'link' => '/shixuns', 'hidden' => false },
{ 'name' => '实项目', 'link' => '/shixuns', 'hidden' => false },
{ 'name' => '在线竞赛', 'link' => '/competitions', 'hidden' => false },
{ 'name' => '教学案例', 'link' => '/moop_cases', 'hidden' => false },
{ 'name' => '交流问答', 'link' => '/forums', 'hidden' => false },

@ -0,0 +1,2 @@
class ModuleSetting < ApplicationRecord
end

@ -4,6 +4,6 @@ class OpenUsers::Wechat < OpenUser
end
def en_type
'qq'
'wechat'
end
end

@ -27,6 +27,7 @@ class Shixun < ApplicationRecord
has_one :first_shixun_tag_repertoire, class_name: 'ShixunTagRepertoire'
has_one :first_tag_repertoire, through: :first_shixun_tag_repertoire, source: :tag_repertoire
has_many :homework_commons_shixuns, class_name: 'HomeworkCommonsShixun'
#实训的关卡
has_many :exercise_shixun_challenges, :dependent => :destroy
@ -48,7 +49,7 @@ class Shixun < ApplicationRecord
has_many :tidings, as: :container, dependent: :destroy
# 实训审核记录
has_many :shixun_reviews, -> {order("challenges.created_at desc")}, :dependent => :destroy
has_many :shixun_reviews, -> {order("shixun_reviews.created_at desc")}, :dependent => :destroy
scope :search_by_name, ->(keyword) { where("name like ? or description like ? ",
"%#{keyword}%", "%#{keyword}%") }

@ -0,0 +1,16 @@
<%
define_admin_breadcrumbs do
add_admin_breadcrumb('竞赛列表', admins_competitions_path)
add_admin_breadcrumb(@competition.name)
end
%>
<div class="card mb-5">
<div class="card-header d-flex justify-content-between align-items-center">
<span class="flex-1">基础设置</span>
</div>
<div class="card-body row">
</div>
</div>

@ -2,6 +2,25 @@
<% add_admin_breadcrumb('竞赛列表', admins_competitions_path) %>
<% end %>
<div class="box mb-5">
<div class="d-flex flex-column w-100">
<div class="d-flex">
<% imageExists = File.exist?(disk_filename("Competition", "banner")) %>
<% imageUrl = imageExists ? '/' + banner_img("Competition") + "?#{Time.now.to_i}" : '' %>
<span class="mr-3">竞赛主页banner</span>
<%= image_tag(imageUrl, width: 150, height: 50, class: "preview-image competition-image-banner mr-1", data: { toggle: 'tooltip', title: '点击预览' }) %>
<%= javascript_void_link imageExists ? '重新上传' : '上传图片', class: 'action upload-competition-image-action', data: { source_id: "banner", source_type: 'Competition', toggle: 'modal', target: '.admin-upload-file-modal' } %>
</div>
<div class="d-flex">
<label for="hot">
<%= check_box_tag :hot, (@competition_hot ? "1" : "0"), @competition_hot, class:"shixun-settings-select" %>
<span class="only_view">只看可ssh</span>
</label>
</div>
</div>
</div>
<div class="box competitions-list-container">
<%= render partial: 'admins/competitions/shared/list', locals: { competitions: @competitions } %>
</div>

@ -7,7 +7,7 @@
<td><%= @member_count_map&.fetch(competition.id, 0) || competition.team_members.count %></td>
<td><%= competition.teacher_staff_num %></td>
<td><%= competition.member_staff_num %></td>
<td class="shixun-setting-image">
<td class="competition-setting-image">
<% imageExists = File.exist?(disk_filename("Competition", competition.id)) %>
<% imageUrl = imageExists ? '/' + url_to_avatar(competition) + "?#{Time.now.to_i}" : '' %>
<%= image_tag(imageUrl, width: 60, height: 40, class: "preview-image competition-image-#{competition.id}", data: { toggle: 'tooltip', title: '点击预览' }, style: imageExists ? '' : 'display:none') %>

@ -4,16 +4,16 @@
<thead class="thead-light">
<tr>
<th width="8%">头像</th>
<th width="14%">创建者</th>
<th width="8%">创建者</th>
<th width="28%" class="text-left">实训名称</th>
<th width="10">审核情况(内容/性能)</th>
<th width="8%">审核情况</th>
<th width="12%">任务数</th>
<th width="16%">时间</th>
<% if is_processed %>
<th width="14%">拒绝原因</th>
<th width="12%">拒绝原因</th>
<th width="8%">状态</th>
<% else %>
<th width="22%">操作</th>
<th width="20%">操作</th>
<% end %>
</tr>
</thead>
@ -37,8 +37,8 @@
<% end %>
</td>
<td>
<%= check_box_tag :content, content_review&.status, content_review&.status.to_i == 1, class:"shixun-setting-form" ,title:"内容审核"%>
<%= check_box_tag :perference, perference_review&.status, perference_review&.status.to_i == 1, class:"shixun-setting-form" ,title:"性能审核"%>
<%= check_box_tag :content, content_review&.status, content_review&.status.to_i == 1, class:"shixun-setting-form" ,title:"内容审核", disabled: "disabled"%>
<%= check_box_tag :perference, perference_review&.status, perference_review&.status.to_i == 1, class:"shixun-setting-form" ,title:"性能审核", disabled: "disabled"%>
</td>
<td><%= shixun.challenges_count %></td>
<td><%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %></td>

@ -0,0 +1,28 @@
total_students_count = 0
total_shixun_homework_count = 0
total_course_score = 0
json.courses @courses.each do |course|
students_count = course.students.count
total_students_count += students_count
total_shixun_homework_count += course['shixun_homework_count'].to_i
score = 500 + 5 * @course_shixun_count_map.fetch(course.id, 0) * @course_myshixun_map.fetch(course.id, 0)
total_course_score += score
teacher = course.teachers.where(user_id: @team_user_ids).first.user
json.creator teacher&.real_name
json.creator_login teacher&.login
json.course_name course.name
json.course_id course.id
json.students_count students_count
json.shixun_homework_count course['shixun_homework_count']
json.valid_count @course_myshixun_map.fetch(course.id, 0)
json.score score
end
json.total_course_count @courses.size
json.total_students_count total_students_count
json.total_shixun_homework_count total_shixun_homework_count
json.total_valid_count @course_myshixun_map.values.reduce(:+)
json.total_course_score total_course_score

@ -0,0 +1,41 @@
total_myshixun_count = 0
total_forked_myshixun_count = 0
total_shixun_score = 0
json.shixuns @shixuns.each do |shixun|
total_myshixun_count += shixun.myshixuns_count
total_forked_myshixun_count += shixun['forked_myshixun_count'].to_i
valid_course_count = @course_count_map.fetch(shixun.id, 0)
valid_student_count = @original_myshixun_count_map.fetch(shixun.id, 0)
score =
if shixun.fork_from.blank?
500 + 50 * valid_course_count + 10 * valid_student_count
else
100 + 10 * valid_course_count + 5 * valid_student_count
end
@forked_shixun_map.each do |shixun_id, fork_from_id|
next if fork_from_id != shixun.id
score += 100 + 10 * @forked_map.fetch(shixun_id, 0) + 5 * @forked_myshixun_count_map.fetch(shixun_id, 0)
end
total_shixun_score += score
json.creator shixun.user.real_name
json.creator_login shixun.user.login
json.shixun_name shixun.name
json.shixun_identifier shixun.identifier
json.forked shixun.fork_from.present?
json.myshixuns_count shixun.myshixuns_count
json.forked_myshixun_count shixun['forked_myshixun_count'].to_i
json.valid_count @myshixun_count_map.fetch(shixun.id, 0)
json.score score
end
json.shixun_count @shixuns.size
json.total_myshixun_count total_myshixun_count
json.total_forked_myshixun_count total_forked_myshixun_count
json.total_valid_count @myshixun_count_map.values.reduce(:+)
json.total_shixun_score total_shixun_score

@ -0,0 +1,18 @@
wb = xlsx_package.workbook
# wb.use_autowidth = false
wb.styles do |s|
sz_all = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {:horizontal => :center}
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 20,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {:horizontal => :center}
wb.add_worksheet(:name => "比赛成绩") do |sheet|
sheet.sheet_view.show_grid_lines = false
sheet.add_row table_columns, :style => blue_cell
if chart_lists.count > 0
chart_lists.each do |user|
sheet.add_row user, :height => 20,:style => sz_all
end #each_widh_index
end
sheet.column_widths *([20]*sheet.column_info.count)
sheet.column_info.first.width = 12
end #add_worksheet
end

@ -0,0 +1,5 @@
json.rule_contents @rule_contents.each do |rule|
json.(rule, :id, :content, :competition_stage_id)
end
json.stages chart_stages @competition

@ -0,0 +1,21 @@
json.user_ranks @user_ranks.each do |user_rank|
rank = @records.map(&:id).index(user_rank.id)
rank = rank.present? ? (rank+1) : 0
json.rank rank == 0 ? "--" : user_rank.rank
json.team_name user_rank.name
json.user_name user_rank.user.real_name
json.cost_time rank == 0 && user_rank.cost_time ? "--" : com_spend_time(user_rank.cost_time)
json.score rank == 0 ? "--" : user_rank.score.round(2)
end
json.teams @records.each do |record|
record_user = record.user
json.team_name record.name
json.record_user_name record_user.real_name
json.user_image url_to_avatar(record_user)
json.user_login record_user.login
school_name = chart_school_str record.team_members.select{|member| !member.is_teacher}.pluck(:user_id)
json.school_name school_name
json.score record&.score&.round(2)
json.spend_time record.cost_time ? com_spend_time(record.cost_time) : "--"
end

@ -0,0 +1,24 @@
json.extract! @competition, :id, :name, :sub_title, :identifier, :bonus, :mode
json.visits_count @competition.visits
member_count = @competition.team_members.count
json.member_count member_count.zero? ? 268 : member_count
json.start_time @competition.start_time&.strftime("%Y-%m-%d")
json.end_time @competition.end_time&.strftime("%Y-%m-%d")
json.enroll_end_time @competition.enroll_end_time&.strftime("%Y-%m-%d %H:%M:%S")
json.published @competition.published?
json.nearly_published @competition.published_at.present?
json.competition_modules @competition_modules do |com_module|
json.(com_module, :name, :position)
json.module_url com_module.module_url
end
json.stages
if @competition.mode == 1
json.course_id @competition.competition_mode_setting&.course_id
json.member_of_course @user.member_of_course?(@competition.competition_mode_setting&.course)
end

@ -1,7 +1,7 @@
json.count @count
json.competitions do
json.array! @competitions.each do |competition|
json.extract! competition, :id, :identifier, :name, :sub_title, :bonus, :description
json.extract! competition, :id, :identifier, :name, :sub_title, :bonus, :description, :mode
json.visits_count competition.visits
member_count = @member_count_map&.fetch(competition.id, 0) || competition.team_members.count
@ -12,18 +12,18 @@ json.competitions do
json.nearly_published competition.published_at.present?
json.single_stage (@stage_count_map&.fetch(competition.id, 0) || competition.competition_stages.count) == 1
json.start_time competition.display_start_time
json.end_time competition.display_end_time
json.enroll_end_time competition.display_enroll_end_time
json.start_time competition.start_time&.strftime("%Y-%m-%d")
json.end_time competition.end_time&.strftime("%Y-%m-%d")
json.enroll_end_time competition.enroll_end_time&.strftime("%Y-%m-%d %H:%M:%S")
section = competition.current_stage_section
if section
json.current_stage do
json.name section.competition_stage.name
json.start_time section.display_start_time
json.end_time section.display_end_time
end
end
# section = competition.current_stage_section
# if section
# json.current_stage do
#
# json.name section.competition_stage.name
# json.start_time section.display_start_time
# json.end_time section.display_end_time
# end
# end
end
end

@ -0,0 +1,6 @@
json.informs @informs.each do |inform|
json.(inform, :id, :name, :description)
json.attachments inform.attachments do |atta|
json.partial! "attachments/attachment_simple", locals: {attachment: atta}
end
end

@ -0,0 +1,4 @@
json.(@md_content, :id, :name, :content)
json.attachments @md_content.attachments do |atta|
json.partial! "attachments/attachment_simple", locals: {attachment: atta}
end

@ -1,36 +1,2 @@
competition = current_competition
json.extract! competition, :id, :name, :sub_title, :identifier
json.start_time competition.display_start_time
json.end_time competition.display_end_time
json.enroll_end_time competition.display_enroll_end_time
json.images do
json.array! competition.attachments, partial: 'attachments/attachment_simple', as: :attachment
end
json.competition_stages do
stages = competition.competition_stages.includes(competition_stage_sections: :competition_entries)
json.array! stages.each do |stage|
json.extract! stage, :id, :name
json.sections do
json.array! stage.competition_stage_sections.each do |section|
json.extract! section, :id, :name
decorator_section = ActiveDecorator::Decorator.instance.decorate(section)
json.start_time decorator_section.display_start_time
json.end_time decorator_section.display_end_time
is_start = section.start_time > Time.now
json.entries do
json.array! section.competition_entries.each do |entry|
json.extract! entry, :id, :name
json.url is_start ? entry.url : ''
end
end
end
end
end
end
json.extract! @competition, :id, :introduction
json.image_url url_to_avatar(@competition)

@ -1,7 +1,7 @@
json.(@base_date, :st, :discusses_count, :game_count, :record_onsume_time, :prev_game, :next_game, :praise_count,
:user_praise, :time_limit, :tomcat_url, :is_teacher, :myshixun_manager, :game, :challenge,
:shixun, :myshixun, :git_url)
if @shixun.vnc
if @shixun.vnc && @st == 0
json.vnc_url @vnc_url
json.vnc_evaluate @vnc_evaluate
end

@ -1,12 +1,12 @@
if @content_record
json.content_info @content_record do
json.content_info do
json.status @content_record.status
json.time format_time(@content_record.created_at)
json.username @content_record.user&.real_name
end
end
if @perfer_record
json.perference_info @perfer_record do
json.perference_info do
json.status @perfer_record.status
json.time format_time(@perfer_record.created_at)
json.username @perfer_record.user&.real_name

@ -1,3 +1,4 @@
admins-mirror_scripts: 'admins-mirror_repositories'
admins-laboratory_settings: 'admins-laboratories'
admins-carousels: 'admins-laboratories'
admins-carousels: 'admins-laboratories'
admins-competition_settings: 'admins-competitions'

@ -784,18 +784,27 @@ Rails.application.routes.draw do
resources :repertoires, only: [:index]
scope module: :competitions do
resources :competitions, only: [:index, :show] do
resources :competitions, only: [:index, :show, :update] do
resources :competition_modules, only: [:index, :show, :update]
resource :competition_staff
resources :competition_teams, only: [:index, :show] do
post :join, on: :collection
post :leave, on: :member
get :course_detail, on: :member
get :shixun_detail, on: :member
end
resources :teachers, only: [:index]
resources :students, only: [:index]
member do
get :common_header
get :informs
post :update_inform
get :md_content
post :update_md_content
get :charts
get :chart_rules
post :update_chart_rules
end
end
end

@ -0,0 +1,7 @@
class AddCompetitionIdToModeSetting < ActiveRecord::Migration[5.2]
def change
add_column :competition_mode_settings, :competition_id, :integer
add_index :competition_mode_settings, :competition_id
end
end

@ -0,0 +1,29 @@
class MigrateCompetitionScore < ActiveRecord::Migration[5.2]
def change
CompetitionModule.where(name: "排行榜", hidden: 0).each do |com_module|
competition = com_module.competition
if competition.present?
puts competition.id
if competition.identifier == 'hn' || competition.identifier == 'gcc-task-2019'
p_rate = 0.2
f_rate = 0.8
else
p_rate = 0.15
f_rate = 0.85
end
pre_stage = competition.competition_stages.where(:name => "预赛").first
final_stage = competition.competition_stages.where(:name => "决赛").first
competition.competition_teams.each do |team|
f_score = team.competition_scores.where(:competition_stage_id => final_stage.try(:id)).first
# 预赛记录
p_score = team.competition_scores.where(:competition_stage_id => pre_stage.try(:id)).first
s_score = (f_score.try(:score).to_f * f_rate + p_score.try(:score).to_f * p_rate).try(:round, 2)
s_spend_time = f_score.try(:cost_time).to_i + p_score.try(:cost_time).to_i
CompetitionScore.create(:user_id => team.user_id, :competition_team_id => team.id, :competition_id => competition.id,
:competition_stage_id => 0, :score => s_score, :cost_time => s_spend_time)
end
end
end
end
end

@ -0,0 +1,12 @@
class CreateCompetitionAwards < ActiveRecord::Migration[5.2]
def change
create_table :competition_awards do |t|
t.references :competition, index: true
t.string :name
t.integer :num, default: 0
t.integer :award_type, default: 0
t.timestamps
end
end
end

@ -0,0 +1,5 @@
class AddRateToCompetitionStage < ActiveRecord::Migration[5.2]
def change
add_column :competition_stages, :rate, :float, default: 1.0
end
end

@ -0,0 +1,12 @@
class CreateModuleSettings < ActiveRecord::Migration[5.2]
def change
create_table :module_settings do |t|
t.string :module_type
t.string :property
t.timestamps
end
add_index :module_settings, :module_type
end
end

@ -0,0 +1,5 @@
class ChangeColumnCompetitionStage < ActiveRecord::Migration[5.2]
def change
rename_column :competition_stages, :rate, :score_rate
end
end

@ -370,73 +370,73 @@ class App extends Component {
isRender:false,
})
};
//获取数据为空的时候
gettablogourlnull = () => {
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
};
//获取数据的时候
gettablogourldata = (response) => {
document.title = response.data.setting.name;
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = '/' + response.data.setting.tab_logo_url;
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}
//获取当前定制信息
getAppdata=()=>{
let url = "/setting.json";
axios.get(url).then((response) => {
// console.log("app.js开始请求/setting.json");
// console.log("获取当前定制信息");
// console.log("获取当前定制信息");
if(response){
if(response.data){
this.setState({
mygetHelmetapi:response.data.setting
});
document.title = response.data.setting.name;
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = '/'+response.data.setting.tab_logo_url;
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}else {
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
try {
if (response.data.setting.tab_logo_url) {
this.gettablogourldata(response);
} else {
this.gettablogourlnull();
}
} catch (e) {
this.gettablogourlnull();
}
document.head.appendChild(link);
}
}else{
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
} else {
this.gettablogourlnull();
}
document.head.appendChild(link);
} else {
this.gettablogourlnull();
}
}).catch((error) => {
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
this.gettablogourlnull();
});
};

@ -435,6 +435,9 @@ pop_box_new(htmlvalue, 480, 182);
// TODO 测试
// resData.power = 0;
resData.shixun.vnc = !!resData.vnc_url
resData.shixun.vnc_evaluate = resData.vnc_evaluate
this.setState({
...resData,

@ -266,6 +266,9 @@ class CoursesNew extends Component {
})
}
}).catch((error) => {
this.setState({
bottonloading:false
})
console.log(error)
})
}else{
@ -339,6 +342,9 @@ class CoursesNew extends Component {
})
}
}).catch((error) => {
this.setState({
bottonloading:false
})
console.log(error)
})
}else{

@ -10,46 +10,144 @@ class Audit_situationComponent extends Component {
constructor(props) {
super(props)
this.state = {
datas:undefined,
value:undefined,
}
}
componentDidMount(){
componentDidMount() {
this.getdatas()
}
getdatas=()=>{
let url=`/shixuns/${this.props.match.params.shixunId}/review_newest_record.json`;
axios.get(url).then((response) => {
console.log(response)
if(response.data===undefined||JSON.stringify(response.data) == "{}"||response.data===null){
this.setState({
datas:[
{
name: '内容审核情况',
id:"Content",
},
{
name: '性能审核情况',
id:"Performance",
},
]
})
}else{
let newlist=[]
if(response.data.content_info!=undefined&&response.data.perference_info===undefined){
let arr=[
{
name: '内容审核情况',
id:"Content",
status:response.data.content_info.status,
username:response.data.content_info.username,
time:response.data.content_info.time,
},
{
name: '性能审核情况',
id:"Performance",
},
]
newlist=arr
}
if(response.data.content_info===undefined&&response.data.perference_info!=undefined){
let arr=[
{
name: '内容审核情况',
id:"Content",
},
{
name: '性能审核情况',
id:"Performance",
status:response.data.perference_info.status,
username:response.data.perference_info.username,
time:response.data.perference_info.time,
},
]
newlist=arr
}
if(response.data.content_info!=undefined&&response.data.perference_info!=undefined){
let arr=[
{
name: '内容审核情况',
id:"Content",
status:response.data.content_info.status,
username:response.data.content_info.username,
time:response.data.content_info.time,
},
{
name: '性能审核情况',
id:"Performance",
status:response.data.perference_info.status,
username:response.data.perference_info.username,
time:response.data.perference_info.time,
},
]
newlist=arr
}
this.setState({
datas:newlist
})
}
}).catch((error) => {
console.log(error)
});
}
showModal = () => {
showModal = (id,status) => {
debugger
this.setState({
visible: true,
editid:id,
value:status
});
};
handleOk = e => {
console.log(e);
this.setState({
visible: false,
handleOk=(id,editid)=>{
let url = `/shixuns/${this.props.match.params.shixunId}/review_shixun.json`;
axios.post(url, {
status: id===undefined?1:id,
review_type: editid,
}).then((response) => {
if(response.data.status===0){
this.props.showNotification(response.data.message);
this.setState({
visible: false,
});
this.getdatas()
}
}).catch((error) => {
console.log(error)
});
};
handleCancel = e => {
console.log(e);
this.setState({
visible: false,
});
};
onChange = e => {
console.log('radio checked', e.target.value);
this.setState({
value: e.target.value,
});
};
render() {
const { tpmLoading, shixun, user, match } = this.props;
let {value,editid,datas}=this.state;
console.log(this.props)
return (
<React.Fragment>
@ -77,14 +175,14 @@ class Audit_situationComponent extends Component {
}
</style>
<Radio.Group onChange={this.onChange} value={this.state.value}>
<Radio.Group onChange={this.onChange} value={this.state.value===undefined?1:this.state.value}>
<Radio value={1}>已完成</Radio>
<Radio value={2}>未完成</Radio>
<Radio value={0}>未完成</Radio>
</Radio.Group>
<div className={"mt30"}>
<a className="pop_close task-btn mr20 margin-tp26" onClick={()=>this.handleCancel()}>取消</a>
<a className="task-btn task-btn-orange margin-tp26" onClick={()=>this.handleOk()}>确定</a>
<a className="task-btn task-btn-orange margin-tp26" onClick={()=>this.handleOk(value,editid)}>确定</a>
</div>
</div>
@ -102,6 +200,7 @@ class Audit_situationComponent extends Component {
`
}
</style>
{ tpmLoading ? <div style={{ minHeight: '886px'}}></div> :
<div className="tpmComment educontent clearfix mt30 mb80">
@ -116,25 +215,14 @@ class Audit_situationComponent extends Component {
></TPMNav>
<div className="padding20 edu-back-white mt20" style={{minHeight: '640px'}}>
<List
dataSource={[
{
name: '内容审核情况',
id:1,
type:"未审核"
},
{
name: '性能审核情况',
id:2,
type:"未审核"
},
]}
{this.props.identity >2||this.props.identity===undefined?"":<List
dataSource={datas}
bordered
renderItem={(item,key) => (
<List.Item
key={item.id}
actions={[
<a onClick={()=>this.showModal(item.id)} key={key}>
<a onClick={()=>this.showModal(item.id,item.status)} key={key}>
<i className="iconfont icon-bianjidaibeijing font-22 color-green"></i>
</a>,
]}
@ -142,19 +230,18 @@ class Audit_situationComponent extends Component {
<List.Item.Meta
title={<div className={"font-16"}>
<div className={"Itemtitle"}>{item.name}</div>
<Tag color="#FF6800">已完成</Tag>
<Tag color="#bcbcbc">已完成</Tag>
{item.status===undefined?"":item.status===1?<Tag color="#FF6800">已完成</Tag>:<Tag color="#bcbcbc"></Tag>}
</div>}
description={
<div>
<span>审核时间: 2019-10-17 10:42</span>
<span className={"ml30"}>审核人 XXX</span>
{item.time===undefined?"":<span>审核时间: {item.time}</span>}
{item.username===undefined?"":<span className={"ml30"}>审核人: {item.username}</span>}
</div>
}
/>
</List.Item>
)}
/>
/>}
</div>
</div>

@ -657,76 +657,72 @@ submittojoinclass=(value)=>{
headtypesonClickbool:bool,
})
}
//获取数据为空的时候
gettablogourlnull = () => {
this.setState({
mygetHelmetapi2: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
};
//获取数据的时候
gettablogourldata = (response) => {
document.title = response.data.setting.name;
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = '/' + response.data.setting.tab_logo_url;
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}
getAppdata=()=>{
// console.log("开始刷新数据了")
let url = "/setting.json";
axios.get(url).then((response) => {
// console.log("axios.get");
// console.log(response);
// console.log("app.js开始请求/setting.json");
// console.log("获取当前定制信息");
if(response){
if(response.data){
this.setState({
mygetHelmetapi2:response.data.setting
});
document.title = response.data.setting.name;
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = '/'+response.data.setting.tab_logo_url;
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}else {
this.setState({
mygetHelmetapi2: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
try {
if (response.data.setting.tab_logo_url) {
this.gettablogourldata(response);
} else {
this.gettablogourlnull();
}
} catch (e) {
this.gettablogourlnull();
}
document.head.appendChild(link);
}
}else{
this.setState({
mygetHelmetapi2: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
} else {
this.gettablogourlnull();
}
document.head.appendChild(link);
} else {
this.gettablogourlnull();
}
}).catch((error) => {
console.log("开始刷新定制数据了但报错了");
console.log(error);
this.setState({
mygetHelmetapi2: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
this.gettablogourlnull();
});
};
render() {

@ -283,74 +283,72 @@ export function TPMIndexHOC(WrappedComponent) {
//
// }
//获取数据为空的时候
gettablogourlnull = () => {
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
};
//获取数据的时候
gettablogourldata = (response) => {
document.title = response.data.setting.name;
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = '/' + response.data.setting.tab_logo_url;
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}
//获取当前定制信息
//获取当前定制信息
getAppdata=()=>{
getAppdata = () => {
let url = "/setting.json";
axios.get(url).then((response) => {
// console.log("app.js开始请求/setting.json");
// console.log("获取当前定制信息");
if(response){
if(response.data){
if (response) {
if (response.data) {
this.setState({
mygetHelmetapi:response.data.setting
mygetHelmetapi: response.data.setting
});
document.title = response.data.setting.name;
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = '/'+response.data.setting.tab_logo_url;
if (oldLink) {
document.head.removeChild(oldLink);
try {
if (response.data.setting.tab_logo_url) {
this.gettablogourldata(response);
} else {
this.gettablogourlnull();
}
} catch (e) {
this.gettablogourlnull();
}
document.head.appendChild(link);
}else {
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
}
}else{
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
} else {
this.gettablogourlnull();
}
document.head.appendChild(link);
} else {
this.gettablogourlnull();
}
}).catch((error) => {
this.setState({
mygetHelmetapi: undefined
});
document.title = "EduCoder";
var link = document.createElement('link'),
oldLink = document.getElementById('dynamic-favicon');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = "/react/build/./favicon.ico";
if (oldLink) {
document.head.removeChild(oldLink);
}
document.head.appendChild(link);
this.gettablogourlnull();
});
};
/**

@ -698,7 +698,7 @@ export default class TPMquestion extends Component {
let newnewanswerMDvalue = this.editanswersRef.current.getValue().trim();
console.log(newnewanswerMDvalue)
if(newnewanswerMDvalue===""||newnewanswerMDvalue===" "){
newnewanswerMDvalue=newlist
newnewanswerMDvalue=undefined
}
url="/shixuns/" + id + "/challenges/" + challenge_id + "/update_choose_question.json?choose_id="+challenge_choose_id;
@ -747,7 +747,7 @@ export default class TPMquestion extends Component {
let newnewanswerMDvalue = this.newquestioMDMdCont.current.getValue().trim();
if(newnewanswerMDvalue===""||newnewanswerMDvalue===" "){
newnewanswerMDvalue=newlist
newnewanswerMDvalue=undefined
}
url="/shixuns/" + id + "/challenges/" + challenge_id + "/create_choose_question.json";
axios.post(url, {

@ -28,11 +28,9 @@ class TPMNav extends Component {
>背景知识</Link>
}
<Link to={`/shixuns/${shixunId}/repository`}
style={{display: this.props.identity >4||this.props.identity===undefined ? "none" : 'block'}}
className={`${match.url.indexOf('/repository') != -1 ? 'active' : ''} fl mr40`}>版本库</Link>
{secret_repository && <Link to={`/shixuns/${shixunId}/secret_repository`}
style={{display: this.props.identity >4||this.props.identity===undefined ? "none" : 'block'}}
{ this.props.identity >4||this.props.identity===undefined ?"":<Link to={`/shixuns/${shixunId}/repository`}
className={`${match.url.indexOf('/repository') != -1 ? 'active' : ''} fl mr40`}>版本库</Link>}
{this.props.identity >4||this.props.identity===undefined ?"": secret_repository && <Link to={`/shixuns/${shixunId}/secret_repository`}
className={`${match.url.indexOf('secret_repository') != -1 ? 'active' : ''} fl mr40`}>私密版本库</Link>}
<Link to={`/shixuns/${shixunId}/collaborators`}
@ -44,8 +42,8 @@ class TPMNav extends Component {
<Link to={`/shixuns/${shixunId}/ranking_list`}
className={`${match.url.indexOf('ranking_list') != -1 ? 'active' : ''} fl mr40`}>排行榜</Link>
<Link to={`/shixuns/${shixunId}/audit_situation`}
className={`${match.url.indexOf('audit_situation') != -1 ? 'active' : ''} fl`}>审核情况</Link>
{this.props.identity >2||this.props.identity===undefined?"":<Link to={`/shixuns/${shixunId}/audit_situation`}
className={`${match.url.indexOf('audit_situation') != -1 ? 'active' : ''} fl`}>审核情况</Link>}
<a
href={`/shixuns/${shixunId}/settings`} className="edu-default-btn edu-blueline-btn ml20 fr"

@ -98,23 +98,24 @@ class AccountPage extends Component {
padding-bottom: 30px;
margin-bottom:30px;
margin-right:20px;
// height:418px;
height: 460px;
}
`}</style>
<AccountNav {...this.props} {...common}></AccountNav>
<div className="basicFormWrap">
<Switch {...this.props}>
<Route path="/account/profile/edit"
render={
(props) => (<AccountBasicEdit {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/account/profile"
render={
(props) => (<AccountBasic {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/account/profile/edit"
render={
(props) => (<AccountBasicEdit {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/account/certification"
render={
(props) => (<AccountCertification {...this.props} {...props} {...this.state} {...common} />)
@ -135,7 +136,7 @@ class AccountPage extends Component {
<Route exact path="/account"
render={
(props) => (<AccountBasic {...this.props} {...props} {...this.state} {...common} />)
(props) => (<AccountBasic getBasicInfo={()=>this.getBasicInfo()} {...this.props} {...props} {...this.state} {...common} />)
}
></Route>

@ -48,7 +48,8 @@ class AccountSecure extends Component {
axios.delete(url).then((result)=>{
if(result.data.status===0){
this.props.showNotification('解绑成功');
this.props.history.push(`/account/binding`)
this.Cancelundologins()
this.props.getBasicInfo()
}
}).catch((error)=>{
console.log(error)
@ -144,7 +145,7 @@ class AccountSecure extends Component {
padding-top: 19px;
}
`}</style>
<div className="title">绑定登账号</div>
<div className="title">绑定登账号</div>
<Form>
<div className="flexTable">
<div className="flexTable">
@ -158,7 +159,7 @@ class AccountSecure extends Component {
</div>
<div className="description lineheight60">
{basicInfo===undefined||JSON.stringify(basicInfo) == "{}"?"":basicInfo&&basicInfo.open_users.length===0?"":<span className={"color-grey-9"}>{basicInfo===undefined||JSON.stringify(basicInfo) == "{}"?"":basicInfo&&basicInfo.open_users[0].nickname}</span>}
{basicInfo===undefined||JSON.stringify(basicInfo) == "{}"?"":basicInfo&&basicInfo.open_users.length===0?"":<span className={"color-grey-9 ml80"}>{basicInfo===undefined||JSON.stringify(basicInfo) == "{}"?"":basicInfo&&basicInfo.open_users[0].nickname}</span>}
</div>
<div className="status pt19">
@ -166,7 +167,7 @@ class AccountSecure extends Component {
onClick={
basicInfo===undefined||JSON.stringify(basicInfo) == "{}"?"":basicInfo&&basicInfo.open_users.length===0 ?() => this.showModal("wechat"):() => this.undologin("wechat",basicInfo===undefined||JSON.stringify(basicInfo) == "{}"?"":basicInfo&&basicInfo.open_users[0].id)
}
>{basicInfo===undefined||JSON.stringify(basicInfo) == "{}"?"":basicInfo&&basicInfo.open_users.length===0 ?"立即绑定":"解绑"}</WordsBtn>
>{basicInfo===undefined||JSON.stringify(basicInfo) == "{}"?"":basicInfo&&basicInfo.open_users.length===0 ?"绑定":"解绑"}</WordsBtn>
</div>
</div>

@ -110,7 +110,7 @@ class AccountNav extends Component {
<i className="iconfont icon-anquanshezhi color-grey-9 font-16"></i>
</li>
<li className={`navItem ${isBinding ? 'active' : ''}`} onClick={this.isBinding}>
<i className="iconfont icon-lianjie color-grey-9 font-16"></i>
<i className="iconfont icon-lianjie color-grey-9 font-16"></i>
</li>
</ul>
</div>

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe ChartRule, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe CompetitionAward, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe CompetitionScore, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe ModuleSetting, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading…
Cancel
Save